From nobody Thu Oct 2 02:18:05 2025 Received: from mailout1.samsung.com (mailout1.samsung.com [203.254.224.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3947727E071 for ; Tue, 30 Sep 2025 03:56:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=203.254.224.24 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759204624; cv=none; b=UIGL6MZq5JAJ7koQT32MNlSa+bVEu9/BW5RPShkxwEplXgDNp3NUrw1KmcfhsI7brU1cPUzqa7JXZ8KlzBvHx8Pf3GwvzpFEsqMGRKH6J2JXr6f+H5M8kZaNeNfSd0I8UTs7FGvtb+Gc/HEkYFkEZkeCfglWWy2r42djV8LkZWU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759204624; c=relaxed/simple; bh=lKh/aujwQc86B3wWTLTo74qOfkou6uPIN9jIjUdlqCY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:MIME-Version: Content-Type:References; b=l1z9XAzLLN2+eIrw1JRe9vEjX9R4GAhrDf/KDSTWGboF223NrIzOu6Z+iYxaoG+ypHK/5KL6aF/MRxv/xMQrGwMOfoK+nCSGRSue3NvK6eOcfJIOxNw/WRcSVzzsJsonKS5bXoaY/fiB0dEBPYx13KCvUg+VLQ9ENMkqFIKjhRI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=samsung.com; spf=pass smtp.mailfrom=samsung.com; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b=HKeTS5a8; arc=none smtp.client-ip=203.254.224.24 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=samsung.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=samsung.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="HKeTS5a8" Received: from epcas5p1.samsung.com (unknown [182.195.41.39]) by mailout1.samsung.com (KnoxPortal) with ESMTP id 20250930035656epoutp01aa0ef60d3bd081f26465299db55f562b~p80c3SAa33202032020epoutp01j for ; Tue, 30 Sep 2025 03:56:56 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.samsung.com 20250930035656epoutp01aa0ef60d3bd081f26465299db55f562b~p80c3SAa33202032020epoutp01j DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1759204616; bh=ETNz1qi8jzlIkhnJIGvK2dh55eK+c1AzYhvuRmECjc4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HKeTS5a8LJLYe6PMFk2uh5NSYdYkEtZX42+XyrlKYo4xNRCVRNjhHhXZGi0zZbmWk fHXC5m49myfEoOHg9mFCWrtUmhCW7i1/jcHxQTqSluGfdcWXr+tfUhCUjNNu1qXwHu YtDMh25SwGm61fRSSZfQQbTDlfyBZCzsDhRtVUCA= Received: from epsnrtp02.localdomain (unknown [182.195.42.154]) by epcas5p1.samsung.com (KnoxPortal) with ESMTPS id 20250930035656epcas5p1e07ca6fe54967c2515c169f609a4e41d~p80cakZGG2306123061epcas5p18; Tue, 30 Sep 2025 03:56:56 +0000 (GMT) Received: from epcas5p3.samsung.com (unknown [182.195.38.86]) by epsnrtp02.localdomain (Postfix) with ESMTP id 4cbPPz0rxjz2SSKf; Tue, 30 Sep 2025 03:56:55 +0000 (GMT) Received: from epsmtip1.samsung.com (unknown [182.195.34.30]) by epcas5p1.samsung.com (KnoxPortal) with ESMTPA id 20250930035654epcas5p1cbb6f3d0fe0dd25758085d041f020846~p80a4O6FG1575615756epcas5p1b; Tue, 30 Sep 2025 03:56:54 +0000 (GMT) Received: from bose.samsungds.net (unknown [107.108.83.9]) by epsmtip1.samsung.com (KnoxPortal) with ESMTPA id 20250930035651epsmtip111276e49f91b36a99e9a1ea266ec2280~p80YQC8ka2938529385epsmtip1k; Tue, 30 Sep 2025 03:56:51 +0000 (GMT) From: Himanshu Dewangan To: mchehab@kernel.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, sumit.semwal@linaro.org, christian.koenig@amd.com, alim.akhtar@samsung.com, manjun@samsung.com, nagaraju.s@samsung.com, ih0206.lee@samsung.com, jehyung.lee@samsung.com Cc: linux-arm-kernel@lists.infradead.org, linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-samsung-soc@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, Himanshu Dewangan Subject: [PATCH 23/29] media: mfc: Add encoder parameters, ROI & QoS support Date: Tue, 30 Sep 2025 09:33:42 +0530 Message-Id: <20250930040348.3702923-24-h.dewangan@samsung.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250930040348.3702923-1-h.dewangan@samsung.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CMS-MailID: 20250930035654epcas5p1cbb6f3d0fe0dd25758085d041f020846 X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" CMS-TYPE: 105P cpgsPolicy: CPGSC10-542,Y X-CFilter-Loop: Reflected X-CMS-RootMailID: 20250930035654epcas5p1cbb6f3d0fe0dd25758085d041f020846 References: <20250930040348.3702923-1-h.dewangan@samsung.com> From: Nagaraju Siddineni - Introduce a generic encoder=E2=80=91parameter framework (slice mode, ASO order, QP config, timestamp delta). - Expose full V4L2 encoder controls (frame tag, RC limits, level/profile, ROI, weighted prediction, hierarchical coding). - Implemente ROI handling by building ROI registers from per=E2=80=91buffer data. - Update encoder resource manager: fixed core integration, excluded from migration/load=E2=80=91balancing, ensured proper finalization per buffer type, and add encoder=E2=80=91specific QoS step table. - Disable bitrate=E2=80=91driven load=E2=80=91balancing for encoders; framerate updates now apply only to non=E2=80=91encoder contexts. Signed-off-by: Nagaraju Siddineni Signed-off-by: Himanshu Dewangan --- .../platform/samsung/exynos-mfc/Makefile | 2 +- .../samsung/exynos-mfc/mfc_core_enc_param.c | 848 ++++++++++++++++++ .../samsung/exynos-mfc/mfc_core_enc_param.h | 23 + .../samsung/exynos-mfc/mfc_ctx_ctrl.c | 803 +++++++++++++++++ .../platform/samsung/exynos-mfc/mfc_rm.c | 89 +- .../platform/samsung/exynos-mfc/mfc_rm.h | 2 + 6 files changed, 1755 insertions(+), 12 deletions(-) create mode 100644 drivers/media/platform/samsung/exynos-mfc/mfc_core_enc_= param.c create mode 100644 drivers/media/platform/samsung/exynos-mfc/mfc_core_enc_= param.h diff --git a/drivers/media/platform/samsung/exynos-mfc/Makefile b/drivers/m= edia/platform/samsung/exynos-mfc/Makefile index b6b312ae7f22..a257d5b0a576 100644 --- a/drivers/media/platform/samsung/exynos-mfc/Makefile +++ b/drivers/media/platform/samsung/exynos-mfc/Makefile @@ -13,7 +13,7 @@ exynos_mfc-y +=3D mfc_core_hwlock.o mfc_core_intlock.o mf= c_core_run.o exynos_mfc-y +=3D mfc_core_pm.o exynos_mfc-y +=3D mfc_core_sync.o mfc_core_sched_prio.o #Core HW access layer -exynos_mfc-y +=3D mfc_core_buf_ctrl.o mfc_core_cmd.o +exynos_mfc-y +=3D mfc_core_enc_param.o mfc_core_buf_ctrl.o mfc_core_cmd.o exynos_mfc-y +=3D mfc_core_hw_reg_api.o mfc_core_reg_api.o #Plugin interface layer #Plugin control layer diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_core_enc_param.c= b/drivers/media/platform/samsung/exynos-mfc/mfc_core_enc_param.c new file mode 100644 index 000000000000..9ff949df04ab --- /dev/null +++ b/drivers/media/platform/samsung/exynos-mfc/mfc_core_enc_param.c @@ -0,0 +1,848 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * mfc_core_enc_param.c file + * + * Nagaraju Siddineni, + * Himanshu Dewangan, + */ + +#include "mfc_core_enc_param.h" + +#include "mfc_core_reg_api.h" + +/* Definition */ +#define VBR_BIT_SAVE 20 +#define CBR_FIX_MAX 10 +#define CBR_I_LIMIT_WFD 6 +#define CBR_I_LIMIT_MAX 5 + +static int mfc_transfer_to_rgb_format_ctrl[][2] =3D { + { MFC_TRANSFER_RESERVED, 1}, + { MFC_TRANSFER_BT709, 1}, + { MFC_TRANSFER_UNSPECIFIED, 1}, + { MFC_TRANSFER_RESERVED, 1}, + { MFC_TRANSFER_GAMMA_22, 1}, + { MFC_TRANSFER_GAMMA_28, 1}, + { MFC_TRANSFER_SMPTE_170M, 0}, + { MFC_TRANSFER_SMPTE_240M, 1}, + { MFC_TRANSFER_LINEAR, 1}, + { MFC_TRANSFER_LOGARITHMIC, 1}, + { MFC_TRANSFER_LOGARITHMIC_S, 1}, + { MFC_TRANSFER_XvYCC, 1}, + { MFC_TRANSFER_BT1361, 1}, + { MFC_TRANSFER_SRGB, 1}, + { MFC_TRANSFER_BT2020_1, 1}, + { MFC_TRANSFER_BT2020_2, 1}, + { MFC_TRANSFER_ST2084, 1}, + { MFC_TRANSFER_ST428, 1}, + { MFC_TRANSFER_HLG, 1}, +}; + +void mfc_core_set_slice_mode(struct mfc_core *core, struct mfc_ctx *ctx) +{ + struct mfc_enc *enc =3D ctx->enc_priv; + + /* multi-slice control */ + if (enc->slice_mode =3D=3D V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) + MFC_CORE_RAW_WRITEL((enc->slice_mode + 0x4), MFC_REG_E_MSLICE_MODE); + else if (enc->slice_mode =3D=3D V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_R= OW) + MFC_CORE_RAW_WRITEL((enc->slice_mode - 0x2), MFC_REG_E_MSLICE_MODE); + else if (enc->slice_mode =3D=3D V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXE= D_BYTES) + MFC_CORE_RAW_WRITEL((enc->slice_mode + 0x3), MFC_REG_E_MSLICE_MODE); + else + MFC_CORE_RAW_WRITEL(enc->slice_mode, MFC_REG_E_MSLICE_MODE); + + /* multi-slice MB number or bit size */ + if (enc->slice_mode =3D=3D V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB || + enc->slice_mode =3D=3D V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW) { + MFC_CORE_RAW_WRITEL(enc->slice_size_mb, MFC_REG_E_MSLICE_SIZE_MB); + } else if (enc->slice_mode =3D=3D V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BY= TES || + enc->slice_mode =3D=3D V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYT= ES) { + MFC_CORE_RAW_WRITEL(enc->slice_size_bits, MFC_REG_E_MSLICE_SIZE_BITS); + } else { + MFC_CORE_RAW_WRITEL(0x0, MFC_REG_E_MSLICE_SIZE_MB); + MFC_CORE_RAW_WRITEL(0x0, MFC_REG_E_MSLICE_SIZE_BITS); + } +} + +void mfc_core_set_aso_slice_order_h264(struct mfc_core *core, + struct mfc_ctx *ctx) +{ + struct mfc_enc *enc =3D ctx->enc_priv; + struct mfc_enc_params *p =3D &enc->params; + struct mfc_h264_enc_params *p_264 =3D &p->codec.h264; + int i; + + if (p_264->aso_enable) { + for (i =3D 0; i < 8; i++) + MFC_CORE_RAW_WRITEL + (p_264->aso_slice_order[i], + MFC_REG_E_H264_ASO_SLICE_ORDER_0 + i * 4); + } +} + +void mfc_core_set_enc_config_qp(struct mfc_core *core, struct mfc_ctx *ctx) +{ + struct mfc_enc *enc =3D ctx->enc_priv; + struct mfc_enc_params *p =3D &enc->params; + unsigned int reg =3D 0; + + if (!p->rc_frame && !p->rc_mb && p->dynamic_qp) { + reg =3D MFC_CORE_READL(MFC_REG_E_FIXED_PICTURE_QP); + reg &=3D ~(0xFF000000); + reg |=3D (enc->config_qp & 0xFF) << 24; + MFC_CORE_WRITEL(reg, MFC_REG_E_FIXED_PICTURE_QP); + } +} + +void mfc_core_set_enc_ts_delta(struct mfc_core *core, struct mfc_ctx *ctx) +{ + struct mfc_enc *enc =3D ctx->enc_priv; + struct mfc_enc_params *p =3D &enc->params; + unsigned int reg =3D 0; + int ts_delta; + + ts_delta =3D mfc_enc_get_ts_delta(ctx); + + reg =3D MFC_CORE_READL(MFC_REG_E_TIME_STAMP_DELTA); + reg &=3D ~(0xFFFF); + reg |=3D (ts_delta & 0xFFFF); + MFC_CORE_WRITEL(reg, MFC_REG_E_TIME_STAMP_DELTA); + if (ctx->src_ts.ts_last_interval) + mfc_ctx_debug(3, "[DFR] fps %d -> %ld, delta: %d, reg: %#x\n", + p->rc_framerate, USEC_PER_SEC / ctx->src_ts.ts_last_interval, + ts_delta, reg); + else + mfc_ctx_debug(3, "[DFR] fps %d -> 0, delta: %d, reg: %#x\n", + p->rc_framerate, ts_delta, reg); +} + +static void __mfc_set_gop_size(struct mfc_core *core, + struct mfc_ctx *ctx, + int ctrl_mode) +{ + struct mfc_enc *enc =3D ctx->enc_priv; + struct mfc_enc_params *p =3D &enc->params; + unsigned int reg =3D 0; + + if (ctrl_mode) { + p->i_frm_ctrl_mode =3D 1; + /* + * gop_ctrl 1: gop_size means the I frame interval + * gop_ctrl 0: gop_size means the number of P frames. + */ + if (p->gop_ctrl) { + p->i_frm_ctrl =3D p->gop_size; + } else { + p->i_frm_ctrl =3D p->gop_size * (p->num_b_frame + 1); + if (p->i_frm_ctrl >=3D 0x3FFFFFFF) { + mfc_ctx_info("I frame interval is bigger than max: %d\n", + p->i_frm_ctrl); + p->i_frm_ctrl =3D 0x3FFFFFFF; + } + } + } else { + p->i_frm_ctrl_mode =3D 0; + p->i_frm_ctrl =3D p->gop_size; + } + + mfc_ctx_debug(2, "I frame interval: %d, (P: %d, B: %d), ctrl mode: %d, go= p ctrl: %d\n", + p->i_frm_ctrl, + p->gop_ctrl ? (p->gop_size / (p->num_b_frame + 1)) : p->gop_size, + p->num_b_frame, p->i_frm_ctrl_mode, p->gop_ctrl); + + /* pictype : IDR period, number of B */ + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_GOP_CONFIG); + mfc_clear_set_bits(reg, 0xFFFF, 0, p->i_frm_ctrl); + mfc_clear_set_bits(reg, 0x1, 19, p->i_frm_ctrl_mode); + /* if B frame is used, the performance falls by half */ + mfc_clear_set_bits(reg, 0x3, 16, p->num_b_frame); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_GOP_CONFIG); + + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_GOP_CONFIG2); + mfc_clear_set_bits(reg, 0x3FFF, 0, (p->i_frm_ctrl >> 16)); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_GOP_CONFIG2); +} + +static void __mfc_set_default_params(struct mfc_core *core, struct mfc_ctx= *ctx) +{ + struct mfc_dev *dev =3D ctx->dev; + int i; + + mfc_ctx_debug(2, "Set default param - enc_param_num: %d\n", + dev->pdata->enc_param_num); + for (i =3D 0; i < dev->pdata->enc_param_num; i++) { + if (i >=3D MFC_MAX_DEFAULT_PARAM) { + mfc_ctx_err("enc_param_num(%d) is over max number(%d)\n", + dev->pdata->enc_param_num, + MFC_MAX_DEFAULT_PARAM); + break; + } + MFC_CORE_RAW_WRITEL + (dev->pdata->enc_param_val[i], dev->pdata->enc_param_addr[i]); + mfc_ctx_debug(2, "Set default param[%d] - addr:0x%x, val:0x%x\n", + i, dev->pdata->enc_param_addr[i], + dev->pdata->enc_param_val[i]); + } +} + +static void __mfc_init_regs(struct mfc_core *core, struct mfc_ctx *ctx) +{ + /* Register initialization */ + MFC_CORE_RAW_WRITEL(0x0, MFC_REG_E_FRAME_INSERTION); + MFC_CORE_RAW_WRITEL(0x0, MFC_REG_E_ROI_BUFFER_ADDR); + MFC_CORE_RAW_WRITEL(0x0, MFC_REG_E_PARAM_CHANGE); + MFC_CORE_RAW_WRITEL(0x0, MFC_REG_E_PICTURE_TAG); + MFC_CORE_RAW_WRITEL(0x0, MFC_REG_E_METADATA_BUFFER_ADDR); + MFC_CORE_RAW_WRITEL(0x0, MFC_REG_E_METADATA_BUFFER_SIZE); +} + +static int __mfc_get_rgb_format_ctrl(struct mfc_ctx *ctx, struct mfc_enc_p= arams *p) +{ + int ret =3D 0; + + /* + * User set color VUI information as below regardless of the standard. + * --------------------------------------------- + * VP9 | others + * ----------------------|---------------------- + * color space only | primaries, transfer + * (primaries interface) | ,matrix + * --------------------------------------------- + * However, in case of RGB encoding, the F/W need to know + * which to use RGB pixel format transform characteristic. + * So, driver converts it based on the user's VUI information. + * Return value + * 0: ITU-R BT.601 + * 1: ITU-R BT.709 + * If Set to 3, use the coefficients of CSC formula determined by firmware + * on COLOR_SPACE and COLOUR_PRIMARIES of E_VIDEO_SIGNAL_TYPE. + * 3: Determined by firmware + */ + + if (ctx->dev->pdata->enc_rgb_csc_by_fw) { + ret =3D 3; + mfc_ctx_debug(2, "[RGB] coefficients of CSC formula using VUI by F/W\n"); + } else { + ret =3D mfc_transfer_to_rgb_format_ctrl[p->transfer_characteristics][1]; + mfc_ctx_debug(2, "[RGB] transfer %d converts to RGB format ctrl %s\n", + p->transfer_characteristics, ret ? "BT.709" : "BT.601"); + } + + return ret; +} + +static void __mfc_set_video_signal_type(struct mfc_core *core, struct mfc_= ctx *ctx) +{ + struct mfc_dev *dev =3D ctx->dev; + struct mfc_enc *enc =3D ctx->enc_priv; + struct mfc_enc_params *p =3D &enc->params; + unsigned int reg =3D 0; + + if ((ctx->src_fmt->type & MFC_FMT_RGB) && !dev->pdata->enc_rgb_csc_by_fw)= { + /* VIDEO_SIGNAL_TYPE_FLAG */ + mfc_set_bits(reg, 0x1, 31, 0x1); + /* COLOUR_DESCRIPTION_PRESENT_FLAG */ + mfc_set_bits(reg, 0x1, 24, 0x1); + } else if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_enc) && + p->check_color_range) { + /* VIDEO_SIGNAL_TYPE_FLAG */ + mfc_set_bits(reg, 0x1, 31, 0x1); + /* COLOR_RANGE */ + if (!(ctx->src_fmt->type & MFC_FMT_RGB)) + mfc_set_bits(reg, 0x1, 25, p->color_range); + + if (p->colour_primaries && + p->transfer_characteristics && + p->matrix_coefficients !=3D 3) { + /* COLOUR_DESCRIPTION_PRESENT_FLAG */ + mfc_set_bits(reg, 0x1, 24, 0x1); + /* COLOUR_PRIMARIES */ + mfc_set_bits(reg, 0xFF, 16, p->colour_primaries); + /* TRANSFER_CHARACTERISTICS */ + mfc_set_bits(reg, 0xFF, 8, p->transfer_characteristics); + /* MATRIX_COEFFICIENTS */ + mfc_set_bits(reg, 0xFF, 0, p->matrix_coefficients); + } + mfc_ctx_debug(2, "[HDR] %s ENC Color aspect: range(%s), pri(%d), trans(%= d), mat(%d)\n", + "H264", + p->color_range ? "Full" : "Limited", p->colour_primaries, + p->transfer_characteristics, p->matrix_coefficients); + } + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_VIDEO_SIGNAL_TYPE); +} + +static void __mfc_set_enc_params(struct mfc_core *core, struct mfc_ctx *ct= x) +{ + struct mfc_dev *dev =3D ctx->dev; + struct mfc_enc *enc =3D ctx->enc_priv; + struct mfc_enc_params *p =3D &enc->params; + unsigned int reg =3D 0; + unsigned int fps =3D ctx->operating_framerate / 1000; + + mfc_ctx_debug_enter(); + + __mfc_init_regs(core, ctx); + __mfc_set_default_params(core, ctx); + + /* width */ + MFC_CORE_RAW_WRITEL(ctx->crop_width, MFC_REG_E_CROPPED_FRAME_WIDTH); + /* height */ + MFC_CORE_RAW_WRITEL(ctx->crop_height, MFC_REG_E_CROPPED_FRAME_HEIGHT); + /* cropped offset */ + mfc_set_bits(reg, MFC_REG_E_FRAME_CROP_OFFSET_MASK, + MFC_REG_E_FRAME_CROP_OFFSET_LEFT, ctx->crop_left); + mfc_set_bits(reg, MFC_REG_E_FRAME_CROP_OFFSET_MASK, + MFC_REG_E_FRAME_CROP_OFFSET_TOP, ctx->crop_top); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_FRAME_CROP_OFFSET); + + /* multi-slice control */ + /* multi-slice MB number or bit size */ + enc->slice_mode =3D p->slice_mode; + + if (p->slice_mode =3D=3D V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) { + enc->slice_size_mb =3D p->slice_mb; + } else if (p->slice_mode =3D=3D V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTE= S || + p->slice_mode =3D=3D V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES= ) { + enc->slice_size_bits =3D p->slice_bit; + } else if (p->slice_mode =3D=3D V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_R= OW) { + enc->slice_size_mb =3D p->slice_mb_row * ((ctx->crop_width + 15) / 16); + } else { + enc->slice_size_mb =3D 0; + enc->slice_size_bits =3D 0; + } + + mfc_core_set_slice_mode(core, ctx); + + /* config qp */ + enc->config_qp =3D p->config_qp; + + /* cyclic intra refresh */ + MFC_CORE_RAW_WRITEL(p->intra_refresh_mb, MFC_REG_E_IR_SIZE); + + mfc_core_set_pixel_format(core, ctx, ctx->src_fmt->fourcc); + + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_ENC_OPTIONS); + /* frame skip mode */ + mfc_clear_set_bits(reg, 0x3, 0, p->frame_skip_mode); + /* seq header ctrl */ + mfc_clear_set_bits(reg, 0x1, 2, p->seq_hdr_mode); + /* cyclic intra refresh */ + mfc_clear_bits(reg, 0x1, 4); + if (p->intra_refresh_mb) + mfc_set_bits(reg, 0x1, 4, 0x1); + /* disable seq header generation if OTF mode */ + mfc_clear_bits(reg, 0x1, 6); + + /* 'NON_REFERENCE_STORE_ENABLE' for debugging */ + mfc_clear_bits(reg, 0x1, 9); + + /* Predict motion search mode */ + mfc_clear_set_bits(reg, 0x3, 22, p->mv_search_mode); + + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_ENC_OPTIONS); + + if (p->mv_hor_range) { + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_MV_HOR_RANGE); + mfc_clear_set_bits(reg, 0x3fff, 0, p->mv_hor_range); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_MV_HOR_RANGE); + } + if (p->mv_ver_range) { + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_MV_VER_RANGE); + mfc_clear_set_bits(reg, 0x3fff, 0, p->mv_ver_range); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_MV_VER_RANGE); + } + + if (p->mv_search_mode =3D=3D 2) { + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_MV_HOR_RANGE); + mfc_clear_set_bits(reg, 0xff, 16, p->mv_hor_pos_l0); + mfc_clear_set_bits(reg, 0xff, 24, p->mv_hor_pos_l1); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_MV_HOR_RANGE); + + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_MV_VER_RANGE); + mfc_clear_set_bits(reg, 0xff, 16, p->mv_ver_pos_l0); + mfc_clear_set_bits(reg, 0xff, 24, p->mv_ver_pos_l1); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_MV_VER_RANGE); + mfc_ctx_debug(2, "MV search mode(%d), HOR (L0: %d, L1: %d), VER (L0: %d,= L1: %d)\n", + p->mv_search_mode, + p->mv_hor_pos_l0, p->mv_hor_pos_l1, + p->mv_ver_pos_l0, p->mv_ver_pos_l1); + } + + if (ctx->src_fmt->type & MFC_FMT_RGB) { + reg =3D MFC_CORE_RAW_READL(MFC_REG_PIXEL_FORMAT); + mfc_clear_set_bits(reg, 0x1, 8, p->color_range); + mfc_clear_set_bits(reg, 0x3, 6, __mfc_get_rgb_format_ctrl(ctx, p)); + mfc_ctx_debug(2, "[RGB] enc color_range %d, primaries %d, transfer %d\n", + p->color_range, p->colour_primaries, + p->transfer_characteristics); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_PIXEL_FORMAT); + } + + /* padding control & value */ + MFC_CORE_RAW_WRITEL(0x0, MFC_REG_E_PADDING_CTRL); + if (p->pad) { + reg =3D 0; + /** enable */ + mfc_set_bits(reg, 0x1, 31, 0x1); + /** cr value */ + mfc_set_bits(reg, 0xFF, 16, p->pad_cr); + /** cb value */ + mfc_set_bits(reg, 0xFF, 8, p->pad_cb); + /** y value */ + mfc_set_bits(reg, 0xFF, 0, p->pad_luma); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_PADDING_CTRL); + } + + /* rate control config. */ + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_RC_CONFIG); + /* macroblock level rate control */ + mfc_clear_set_bits(reg, 0x1, 8, p->rc_mb); + /* frame-level rate control */ + mfc_clear_set_bits(reg, 0x1, 9, p->rc_frame); + /* drop control */ + mfc_clear_set_bits(reg, 0x1, 10, p->drop_control); + if (MFC_FEATURE_SUPPORT(dev, dev->pdata->enc_ts_delta)) + mfc_clear_set_bits(reg, 0x1, 20, 1); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_RC_CONFIG); + + /* + * Delta value for framerate is timestamp(ms * 10) diff. + * ex) 30fps: 333, 60fps: 166 + * Resolution unit is most sophisticated value + * that can be determined within 16bit. + * F/W calculates fps through resolution / delta. + * ex) 10000 / 166 =3D 60fps + */ + p->rc_frame_delta =3D p->rc_framerate_res / p->rc_framerate; + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_RC_FRAME_RATE); + mfc_clear_set_bits(reg, 0xFFFF, 16, p->rc_framerate_res); + mfc_clear_set_bits(reg, 0xFFFF, 0, p->rc_frame_delta); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_RC_FRAME_RATE); + + /* bit rate */ + ctx->kbps =3D p->rc_bitrate / SZ_1K; + MFC_CORE_RAW_WRITEL(p->rc_bitrate, MFC_REG_E_RC_BIT_RATE); + + if (MFC_FEATURE_SUPPORT(dev, dev->pdata->max_i_frame_size)) { + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_RC_OPTIONS); + mfc_clear_set_bits(reg, 0xFFFF, 0, p->max_i_frame_size); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_RC_OPTIONS); + } + + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_RC_MODE); + mfc_clear_bits(reg, 0x7, 0); + mfc_clear_bits(reg, 0x3, 4); + mfc_clear_bits(reg, 0xFF, 8); + if (p->rc_frame) { + if (p->rc_reaction_coeff <=3D CBR_I_LIMIT_MAX) { + mfc_set_bits(reg, 0x7, 0, MFC_REG_E_RC_CBR_I_LIMIT_VT); + /* + * Ratio of intra for max frame size + * is controlled when only CBR_I_LIMIT_VT mode. + * And CBR_I_LIMIT_VT mode is valid for H.264, HEVC codec + */ + if (p->ratio_intra) + mfc_set_bits(reg, 0xFF, 8, p->ratio_intra); + } else if (p->rc_reaction_coeff <=3D CBR_FIX_MAX) { + if (MFC_FEATURE_SUPPORT(dev, dev->pdata->wfd_rc_mode) && + p->rc_reaction_coeff <=3D CBR_I_LIMIT_WFD) { + mfc_set_bits(reg, 0x7, 0, MFC_REG_E_RC_CBR_I_LIMIT_WFD); + } else { + mfc_set_bits(reg, 0x7, 0, MFC_REG_E_RC_CBR_FIX); + } + } else { + if (MFC_FEATURE_SUPPORT(dev, dev->pdata->wfd_rc_mode) && + p->rc_reaction_coeff <=3D VBR_BIT_SAVE) { + mfc_set_bits(reg, 0x7, 0, MFC_REG_E_RC_VBR_BS); + } else { + mfc_set_bits(reg, 0x7, 0, MFC_REG_E_RC_VBR); + } + } + + if (p->rc_mb) + mfc_set_bits(reg, 0x3, 4, p->rc_pvc); + } + + if (MFC_FEATURE_SUPPORT(dev, dev->pdata->min_quality_mode) && p->min_qual= ity_mode) { + mfc_set_bits(reg, 0x1, 7, p->min_quality_mode); + mfc_ctx_debug(2, "MIN quality mode is enabled\n"); + } + + mfc_ctx_debug(3, "RC_MODE) rc coeff: %d, wfd_rc_mode: %d, rc_mode: %#x, m= ax I size: %d\n", + p->rc_reaction_coeff, + MFC_FEATURE_SUPPORT(dev, dev->pdata->wfd_rc_mode), + reg, p->max_i_frame_size); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_RC_MODE); + + /* high quality mode */ + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_HIGH_QUALITY_MODE); + if (p->wp_two_pass_enable) { + mfc_clear_set_bits(reg, 0x1, 0, p->wp_two_pass_enable); + mfc_ctx_debug(2, "WP two pass encoding is enabled\n"); + } + if (p->adaptive_gop_enable) { + mfc_clear_set_bits(reg, 0x1, 4, p->adaptive_gop_enable); + mfc_ctx_debug(2, "Adaptive gop is enabled\n"); + } + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_HIGH_QUALITY_MODE); + + /* extended encoder ctrl */ + /** vbv buffer size */ + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_VBV_BUFFER_SIZE); + mfc_clear_bits(reg, 0xFF, 0); + if (p->frame_skip_mode =3D=3D V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_L= IMIT) + mfc_set_bits(reg, 0xFF, 0, p->vbv_buf_size); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_VBV_BUFFER_SIZE); + + /* Video signal type */ + __mfc_set_video_signal_type(core, ctx); + + /* Check performance decrease options */ + if (!fps) + fps =3D p->rc_framerate; + if (IS_MFC_MAX_PERF(ctx, fps)) { + if (mfc_is_enc_bframe(ctx)) { + p->num_b_frame =3D 0; + if (IS_H264_ENC(ctx)) + p->codec.h264.hier_qp_type =3D + V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P; + mfc_ctx_info("forcely can't be use B frame for 8K or 4K %d fps\n", fps); + } + if (p->num_refs_for_p > 1) { + p->num_refs_for_p =3D 1; + mfc_ctx_info("forcely use 1-ref frame for 8K or 4K %d fps\n", fps); + } + } + + mfc_ctx_debug_leave(); +} + +static void __mfc_set_temporal_svc_h264(struct mfc_core *core, + struct mfc_ctx *ctx, + struct mfc_h264_enc_params *p_264) +{ + struct mfc_enc *enc =3D ctx->enc_priv; + struct mfc_enc_params *p =3D &enc->params; + unsigned int reg =3D 0, reg2 =3D 0; + int i; + + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_H264_OPTIONS_2); + /* pic_order_cnt_type =3D 0 for backward compatibilities */ + mfc_clear_bits(reg, 0x3, 0); + /* Enable LTR */ + mfc_clear_bits(reg, 0x1, 2); + if ((p_264->enable_ltr & 0x1) || p_264->num_of_ltr > 0) + mfc_set_bits(reg, 0x1, 2, 0x1); + /* Number of LTR */ + mfc_clear_bits(reg, 0x3, 7); + if (p_264->num_of_ltr > 2) + mfc_set_bits(reg, 0x3, 7, (p_264->num_of_ltr - 2)); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_H264_OPTIONS_2); + + /* Temporal SVC - qp type, layer number */ + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_NUM_T_LAYER); + mfc_clear_set_bits(reg, 0x1, 3, p_264->hier_qp_type); + mfc_clear_set_bits(reg, 0x7, 0, p_264->num_hier_layer); + mfc_clear_bits(reg, 0x7, 4); + if (p_264->hier_ref_type) { + mfc_set_bits(reg, 0x1, 7, 0x1); + mfc_set_bits(reg, 0x7, 4, p->num_hier_max_layer); + } else { + mfc_clear_bits(reg, 0x1, 7); + mfc_set_bits(reg, 0x7, 4, p_264->num_hier_layer); + } + mfc_clear_set_bits(reg, 0x1, 8, p->hier_bitrate_ctrl); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_NUM_T_LAYER); + mfc_ctx_debug(3, "[HIERARCHICAL] hier_qp_enable %d, enable_ltr %d", + p_264->hier_qp_enable, p_264->enable_ltr); + mfc_ctx_debug(3, "num_hier_layer %d, max_layer %d, hier_ref_type %d, NUM_= T_LAYER 0x%x\n", + p_264->num_hier_layer, p->num_hier_max_layer, p_264->hier_ref_type= , reg); + + /* QP & Bitrate for each layer */ + for (i =3D 0; i < 7; i++) { + MFC_CORE_RAW_WRITEL + (p_264->hier_qp_layer[i], + MFC_REG_E_HIERARCHICAL_QP_LAYER0 + i * 4); + /* If hier_bitrate_ctrl is set to 1, this is meaningless */ + MFC_CORE_RAW_WRITEL + (p_264->hier_bit_layer[i], + MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4); + mfc_ctx_debug(3, "[HIERARCHICAL] layer[%d] QP: %#x, bitrate: %d(FW ctrl:= %d)\n", + i, p_264->hier_qp_layer[i], + p_264->hier_bit_layer[i], p->hier_bitrate_ctrl); + } + if (p_264->set_priority) { + reg =3D 0; + reg2 =3D 0; + for (i =3D 0; i < (p_264->num_hier_layer & 0x7); i++) { + if (i <=3D 4) + mfc_set_bits(reg, 0x3F, (6 * i), (p_264->base_priority + i)); + else + mfc_set_bits(reg2, 0x3F, (6 * (i - 5)), (p_264->base_priority + i)); + } + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_H264_HD_SVC_EXTENSION_0); + MFC_CORE_RAW_WRITEL(reg2, MFC_REG_E_H264_HD_SVC_EXTENSION_1); + mfc_ctx_debug(3, "[HIERARCHICAL] priority EXTENSION0: %#x, EXTENSION1: %= #x\n", + reg, reg2); + } +} + +static void __mfc_set_fmo_slice_map_h264(struct mfc_core *core, + struct mfc_ctx *ctx, + struct mfc_h264_enc_params *p_264) +{ + int i; + + if (p_264->fmo_enable) { + switch (p_264->fmo_slice_map_type) { + case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES: + if (p_264->fmo_slice_num_grp > 4) + p_264->fmo_slice_num_grp =3D 4; + for (i =3D 0; i < (p_264->fmo_slice_num_grp & 0xF); i++) + MFC_CORE_RAW_WRITEL + (p_264->fmo_run_length[i] - 1, + MFC_REG_E_H264_FMO_RUN_LENGTH_MINUS1_0 + i * 4); + break; + case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES: + if (p_264->fmo_slice_num_grp > 4) + p_264->fmo_slice_num_grp =3D 4; + break; + case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN: + case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN: + if (p_264->fmo_slice_num_grp > 2) + p_264->fmo_slice_num_grp =3D 2; + MFC_CORE_RAW_WRITEL + (p_264->fmo_sg_dir & 0x1, MFC_REG_E_H264_FMO_SLICE_GRP_CHANGE_DIR); + /* the valid range is 0 ~ number of macroblocks -1 */ + MFC_CORE_RAW_WRITEL(p_264->fmo_sg_rate, + MFC_REG_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1); + break; + default: + mfc_ctx_err("Unsupported map type for FMO: %d\n", + p_264->fmo_slice_map_type); + p_264->fmo_slice_map_type =3D 0; + p_264->fmo_slice_num_grp =3D 1; + break; + } + + MFC_CORE_RAW_WRITEL + (p_264->fmo_slice_map_type, MFC_REG_E_H264_FMO_SLICE_GRP_MAP_TYPE); + MFC_CORE_RAW_WRITEL + (p_264->fmo_slice_num_grp - 1, MFC_REG_E_H264_FMO_NUM_SLICE_GRP_MINUS1); + } else { + MFC_CORE_RAW_WRITEL(0, MFC_REG_E_H264_FMO_NUM_SLICE_GRP_MINUS1); + } +} + +static void __mfc_set_enc_params_h264(struct mfc_core *core, + struct mfc_ctx *ctx) +{ + struct mfc_dev *dev =3D ctx->dev; + struct mfc_enc *enc =3D ctx->enc_priv; + struct mfc_enc_params *p =3D &enc->params; + struct mfc_h264_enc_params *p_264 =3D &p->codec.h264; + unsigned int mb =3D 0; + unsigned int reg =3D 0; + + mfc_ctx_debug_enter(); + + p->rc_framerate_res =3D FRAME_RATE_RESOLUTION; + __mfc_set_enc_params(core, ctx); + + if (p_264->num_hier_layer & 0x7) { + /* set gop_size without i_frm_ctrl mode */ + __mfc_set_gop_size(core, ctx, 0); + } else { + /* set gop_size with i_frm_ctrl mode */ + __mfc_set_gop_size(core, ctx, 1); + } + + mb =3D WIDTH_MB((ctx)->crop_width) * HEIGHT_MB((ctx)->crop_height); + /* Level 6.0 case */ + if (IS_LV60_MB(mb)) { + if (p_264->level < 60) + mfc_ctx_info("This resolution(mb: %d) recommends level6.0\n", mb); + /* In case of profile is baseline or constrained baseline */ + if (p_264->profile =3D=3D 0x0 || p_264->profile =3D=3D 0x3) + mfc_ctx_info("This resolution(mb: %d) recommends high profile\n", mb); + if (!dev->pdata->support_8K_cavlc && p_264->entropy_mode !=3D 0x1) { + mfc_ctx_info("Set Entropy mode CABAC\n"); + p_264->entropy_mode =3D 1; + } + } + + /* Level 5.1 case */ + if (IS_LV51_MB(mb)) { + if (p_264->level < 51) + mfc_ctx_info("This resolution(mb: %d) recommends level5.1\n", mb); + /* In case of profile is baseline or constrained baseline */ + if (p_264->profile =3D=3D 0x0 || p_264->profile =3D=3D 0x3) + mfc_ctx_info("This resolution(mb: %d) recommends high profile\n", mb); + } + + /* profile & level */ + reg =3D 0; + /** level */ + mfc_clear_set_bits(reg, 0xFF, 8, p_264->level); + /** profile - 0 ~ 3 */ + mfc_clear_set_bits(reg, 0x3F, 0, p_264->profile); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_PICTURE_PROFILE); + + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_H264_OPTIONS); + /* entropy coding mode */ + mfc_clear_set_bits(reg, 0x1, 0, p_264->entropy_mode); + /* loop filter ctrl */ + mfc_clear_set_bits(reg, 0x3, 1, p_264->loop_filter_mode); + /* interlace */ + mfc_clear_set_bits(reg, 0x1, 3, p_264->interlace); + /* intra picture period for H.264 open GOP */ + mfc_clear_set_bits(reg, 0x1, 4, p_264->open_gop); + /* extended encoder ctrl */ + mfc_clear_set_bits(reg, 0x1, 5, p_264->ar_vui); + /* ASO enable */ + mfc_clear_set_bits(reg, 0x1, 6, p_264->aso_enable); + /* if num_refs_for_p is 2, the performance falls by half */ + mfc_clear_set_bits(reg, 0x1, 7, (p->num_refs_for_p - 1)); + /* Temporal SVC - hier qp enable */ + mfc_clear_set_bits(reg, 0x1, 8, p_264->hier_qp_enable); + /* Weighted Prediction enable */ + mfc_clear_set_bits(reg, 0x3, 9, p->weighted_enable); + if (p->weighted_enable) + mfc_ctx_debug(2, "WP mode is %d\n", p->weighted_enable); + /* 8x8 transform enable [12]: INTER_8x8_TRANS_ENABLE */ + mfc_clear_set_bits(reg, 0x1, 12, p_264->_8x8_transform); + /* 8x8 transform enable [13]: INTRA_8x8_TRANS_ENABLE */ + mfc_clear_set_bits(reg, 0x1, 13, p_264->_8x8_transform); + /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */ + mfc_clear_bits(reg, 0x1, 14); + /* sps pps control */ + mfc_clear_set_bits(reg, 0x1, 29, p_264->prepend_sps_pps_to_idr); + /* VUI parameter disable */ + mfc_clear_set_bits(reg, 0x1, 30, p_264->vui_enable); + /* Timing info */ + mfc_set_bits(reg, 0x1, 31, p->timing_info_enable); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_H264_OPTIONS); + + /* cropped height */ + if (p_264->interlace) + MFC_CORE_RAW_WRITEL(ctx->crop_height >> 1, MFC_REG_E_CROPPED_FRAME_HEIGH= T); + + /* loopfilter alpha offset */ + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_H264_LF_ALPHA_OFFSET); + mfc_clear_set_bits(reg, 0x1F, 0, p_264->loop_filter_alpha); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_H264_LF_ALPHA_OFFSET); + + /* loopfilter beta offset */ + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_H264_LF_BETA_OFFSET); + mfc_clear_set_bits(reg, 0x1F, 0, p_264->loop_filter_beta); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_H264_LF_BETA_OFFSET); + + /* rate control config. */ + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_RC_CONFIG); + /** frame QP */ + mfc_clear_set_bits(reg, 0xFF, 0, p_264->rc_frame_qp); + mfc_clear_bits(reg, 0x1, 11); + if (!p->rc_frame && !p->rc_mb && p->dynamic_qp) + mfc_set_bits(reg, 0x1, 11, 0x1); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_RC_CONFIG); + + /* max & min value of QP for I frame */ + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_RC_QP_BOUND); + /** max I frame QP */ + mfc_clear_set_bits(reg, 0xFF, 8, p_264->rc_max_qp); + /** min I frame QP */ + mfc_clear_set_bits(reg, 0xFF, 0, p_264->rc_min_qp); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_RC_QP_BOUND); + + /* max & min value of QP for P/B frame */ + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_RC_QP_BOUND_PB); + /** max B frame QP */ + mfc_clear_set_bits(reg, 0xFF, 24, p_264->rc_max_qp_b); + /** min B frame QP */ + mfc_clear_set_bits(reg, 0xFF, 16, p_264->rc_min_qp_b); + /** max P frame QP */ + mfc_clear_set_bits(reg, 0xFF, 8, p_264->rc_max_qp_p); + /** min P frame QP */ + mfc_clear_set_bits(reg, 0xFF, 0, p_264->rc_min_qp_p); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_RC_QP_BOUND_PB); + + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_FIXED_PICTURE_QP); + mfc_clear_set_bits(reg, 0xFF, 24, p->config_qp); + mfc_clear_set_bits(reg, 0xFF, 16, p_264->rc_b_frame_qp); + mfc_clear_set_bits(reg, 0xFF, 8, p_264->rc_p_frame_qp); + mfc_clear_set_bits(reg, 0xFF, 0, p_264->rc_frame_qp); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_FIXED_PICTURE_QP); + + /* chroma QP offset */ + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_H264_CHROMA_QP_OFFSET); + mfc_clear_set_bits(reg, 0x1F, 5, p->chroma_qp_offset_cr); + mfc_clear_set_bits(reg, 0x1F, 0, p->chroma_qp_offset_cb); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_H264_CHROMA_QP_OFFSET); + + MFC_CORE_RAW_WRITEL(0x0, MFC_REG_E_ASPECT_RATIO); + MFC_CORE_RAW_WRITEL(0x0, MFC_REG_E_EXTENDED_SAR); + if (p_264->ar_vui) { + /* aspect ration IDC */ + reg =3D 0; + mfc_set_bits(reg, 0xFF, 0, p_264->ar_vui_idc); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_ASPECT_RATIO); + if (p_264->ar_vui_idc =3D=3D 0xFF) { + /* sample AR info. */ + reg =3D 0; + mfc_set_bits(reg, 0xFFFF, 16, p_264->ext_sar_width); + mfc_set_bits(reg, 0xFFFF, 0, p_264->ext_sar_height); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_EXTENDED_SAR); + } + } + /* intra picture period for H.264 open GOP, value */ + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_H264_REFRESH_PERIOD); + mfc_clear_bits(reg, 0xFFFF, 0); + if (p_264->open_gop) + mfc_set_bits(reg, 0xFFFF, 0, p_264->open_gop_size); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_H264_REFRESH_PERIOD); + + /* Temporal SVC */ + __mfc_set_temporal_svc_h264(core, ctx, p_264); + + /* set frame pack sei generation */ + if (p_264->sei_gen_enable) { + /* frame packing enable */ + reg =3D MFC_CORE_RAW_READL(MFC_REG_E_H264_OPTIONS); + mfc_set_bits(reg, 0x1, 25, 0x1); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_H264_OPTIONS); + + /* set current frame0 flag & arrangement type */ + reg =3D 0; + /** current frame0 flag */ + mfc_set_bits(reg, 0x1, 2, p_264->sei_fp_curr_frame_0); + /** arrangement type */ + mfc_set_bits(reg, 0x3, 0, (p_264->sei_fp_arrangement_type - 3)); + MFC_CORE_RAW_WRITEL(reg, MFC_REG_E_H264_FRAME_PACKING_SEI_INFO); + } + + __mfc_set_fmo_slice_map_h264(core, ctx, p_264); + + mfc_ctx_debug_leave(); +} + +int mfc_core_set_enc_params(struct mfc_core *core, struct mfc_ctx *ctx) +{ + if (IS_H264_ENC(ctx)) { + __mfc_set_enc_params_h264(core, ctx); + } else { + mfc_ctx_err("Unknown codec for encoding (%x)\n", ctx->codec_mode); + return -EINVAL; + } + + mfc_ctx_debug(5, "RC) Bitrate: %d / framerate: %#x / config %#x / mode %#= x\n", + MFC_CORE_RAW_READL(MFC_REG_E_RC_BIT_RATE), + MFC_CORE_RAW_READL(MFC_REG_E_RC_FRAME_RATE), + MFC_CORE_RAW_READL(MFC_REG_E_RC_CONFIG), + MFC_CORE_RAW_READL(MFC_REG_E_RC_MODE)); + + return 0; +} diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_core_enc_param.h= b/drivers/media/platform/samsung/exynos-mfc/mfc_core_enc_param.h new file mode 100644 index 000000000000..ce15ae29abba --- /dev/null +++ b/drivers/media/platform/samsung/exynos-mfc/mfc_core_enc_param.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2025 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * mfc_enc_param.h file + * + * Nagaraju Siddineni, + * Himanshu Dewangan, + */ + +#ifndef __MFC_ENC_PARAM_H +#define __MFC_ENC_PARAM_H __FILE__ + +#include "base/mfc_common.h" + +void mfc_core_set_slice_mode(struct mfc_core *core, struct mfc_ctx *ctx); +void mfc_core_set_aso_slice_order_h264(struct mfc_core *core, + struct mfc_ctx *ctx); +void mfc_core_set_enc_config_qp(struct mfc_core *core, struct mfc_ctx *ctx= ); +void mfc_core_set_enc_ts_delta(struct mfc_core *core, struct mfc_ctx *ctx); +int mfc_core_set_enc_params(struct mfc_core *core, struct mfc_ctx *ctx); +#endif /* __MFC_ENC_PARAM_H */ diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_ctx_ctrl.c b/dri= vers/media/platform/samsung/exynos-mfc/mfc_ctx_ctrl.c index 8846230f1e20..4580aa3498cc 100644 --- a/drivers/media/platform/samsung/exynos-mfc/mfc_ctx_ctrl.c +++ b/drivers/media/platform/samsung/exynos-mfc/mfc_ctx_ctrl.c @@ -379,6 +379,768 @@ static struct mfc_ctrl_cfg mfc_dec_ctrl_list[] =3D { =20 #define NUM_DEC_CTRL_CFGS ARRAY_SIZE(mfc_dec_ctrl_list) =20 +static struct mfc_ctrl_cfg mfc_enc_ctrl_list[] =3D { + { /* set frame tag */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_PICTURE_TAG, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* get frame tag */ + .type =3D MFC_CTRL_TYPE_GET_DST, + .id =3D V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, + .is_volatile =3D 0, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RET_PICTURE_TAG, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* encoded y physical addr */ + .type =3D MFC_CTRL_TYPE_GET_DST, + .id =3D V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR, + .is_volatile =3D 0, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_ENCODED_SOURCE_FIRST_ADDR, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* encoded c physical addr */ + .type =3D MFC_CTRL_TYPE_GET_DST, + .id =3D V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR, + .is_volatile =3D 0, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_ENCODED_SOURCE_SECOND_ADDR, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* I, not coded frame insertion */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_FRAME_INSERTION, + .mask =3D 0x3, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* I period change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_GOP_CONFIG, + .mask =3D 0xFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 0, + }, + { /* frame rate change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_FRAME_RATE, + .mask =3D 0x0000FFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 1, + }, + { /* bit rate change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_BIT_RATE, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 2, + }, + { /* frame status (in slice or not) */ + .type =3D MFC_CTRL_TYPE_GET_DST, + .id =3D V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS, + .is_volatile =3D 0, + .mode =3D MFC_CTRL_MODE_NONE, + .addr =3D 0, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* H.264 I frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_H264_MAX_QP, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND, + .mask =3D 0xFF, + .shft =3D 8, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* H.264 I frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_H264_MIN_QP, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND, + .mask =3D 0xFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* H.263 I frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_H263_MAX_QP, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND, + .mask =3D 0xFF, + .shft =3D 8, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* H.263 I frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_H263_MIN_QP, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND, + .mask =3D 0xFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* MPEG4 I frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND, + .mask =3D 0xFF, + .shft =3D 8, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* MPEG4 I frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND, + .mask =3D 0xFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* VP8 I frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_VP8_MAX_QP, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND, + .mask =3D 0xFF, + .shft =3D 8, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* VP8 I frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_VP8_MIN_QP, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND, + .mask =3D 0xFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* VP9 I frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_VP9_MAX_QP, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND, + .mask =3D 0xFF, + .shft =3D 8, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* VP9 I frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_VP9_MIN_QP, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND, + .mask =3D 0xFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* HEVC I frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND, + .mask =3D 0xFF, + .shft =3D 8, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* HEVC I frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND, + .mask =3D 0xFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* H.264 P frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 8, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* H.264 P frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* H.263 P frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 8, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* H.263 P frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* MPEG4 P frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 8, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* MPEG4 P frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* VP8 P frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 8, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* VP8 P frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* VP9 P frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 8, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* VP9 P frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* HEVC P frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 8, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* HEVC P frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* H.264 B frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 24, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* H.264 B frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 16, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* MPEG4 B frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 24, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* MPEG4 B frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 16, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* HEVC B frame QP Max change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 24, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* HEVC B frame QP Min change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_QP_BOUND_PB, + .mask =3D 0xFF, + .shft =3D 16, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 4, + }, + { /* H.264 Dynamic Temporal Layer & bitrate change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 10, + }, + { /* HEVC Dynamic Temporal Layer & bitrate change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 10, + }, + { /* VP8 Dynamic Temporal Layer change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 10, + }, + { /* VP9 Dynamic Temporal Layer change */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 10, + }, + { /* set level */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_H264_LEVEL, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_PICTURE_PROFILE, + .mask =3D 0x000000FF, + .shft =3D 8, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 5, + }, + { /* set profile */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_H264_PROFILE, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_PICTURE_PROFILE, + .mask =3D 0x0000000F, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 5, + }, + { /* set store LTR */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_MFC_H264_MARK_LTR, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_H264_NAL_CONTROL, + .mask =3D 0x00000003, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* set use LTR */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_MFC_H264_USE_LTR, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_H264_NAL_CONTROL, + .mask =3D 0x00000003, + .shft =3D 2, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* set base layer priority */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_H264_HD_SVC_EXTENSION_0, + .mask =3D 0x0000003F, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 12, + }, + { /* set QP per each frame */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_MFC_CONFIG_QP, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_FIXED_PICTURE_QP, + .mask =3D 0x000000FF, + .shft =3D 24, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* Region-Of-Interest control */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_ROI_CONTROL, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_ROI_CTRL, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* set YSUM for weighted prediction */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_YSUM, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_WEIGHT_FOR_WEIGHTED_PREDICTION, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_shft =3D 0, + }, + { /* set base layer priority */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_MODE, + .mask =3D 0x000000FF, + .shft =3D 8, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 13, + }, + { /* sync the timestamp for drop control */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_DROP_CONTROL, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_FRAME_RATE, + .mask =3D 0x0000FFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* average QP of current frame */ + .type =3D MFC_CTRL_TYPE_GET_DST, + .id =3D V4L2_CID_MPEG_VIDEO_AVERAGE_QP, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_NAL_DONE_INFO, + .mask =3D 0x000000FF, + .shft =3D 12, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* HOR range position of current frame */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_MV_HOR_POSITION_L0, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_MV_HOR_RANGE, + .mask =3D 0x000000FF, + .shft =3D 16, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* HOR range position of current frame */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_MV_HOR_POSITION_L1, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_MV_HOR_RANGE, + .mask =3D 0x000000FF, + .shft =3D 24, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* VER range position of current frame */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_MV_VER_POSITION_L0, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_MV_VER_RANGE, + .mask =3D 0x000000FF, + .shft =3D 16, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* VER range position of current frame */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_MV_VER_POSITION_L1, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_MV_VER_RANGE, + .mask =3D 0x000000FF, + .shft =3D 24, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* Max I frame size */ + .type =3D MFC_CTRL_TYPE_SET_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_MAX_IFRAME_SIZE, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_RC_OPTIONS, + .mask =3D 0xFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_SFR, + .flag_addr =3D MFC_REG_E_PARAM_CHANGE, + .flag_shft =3D 20, + }, + { /* The number of skip MB */ + .type =3D MFC_CTRL_TYPE_GET_DST, + .id =3D V4L2_CID_MPEG_VIDEO_SUM_SKIP_MB, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_SUM_SKIP_MB, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* The number of intra MB */ + .type =3D MFC_CTRL_TYPE_GET_DST, + .id =3D V4L2_CID_MPEG_VIDEO_SUM_INTRA_MB, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_SUM_INTRA_MB, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* The number of intra MB */ + .type =3D MFC_CTRL_TYPE_GET_DST, + .id =3D V4L2_CID_MPEG_VIDEO_SUM_ZERO_MV_MB, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_SFR, + .addr =3D MFC_REG_E_SUM_ZERO_MV_MB, + .mask =3D 0xFFFFFFFF, + .shft =3D 0, + .flag_mode =3D MFC_CTRL_MODE_NONE, + .flag_addr =3D 0, + .flag_shft =3D 0, + }, + { /* buffer additional information */ + .type =3D MFC_CTRL_TYPE_SRC, + .id =3D V4L2_CID_MPEG_VIDEO_SRC_BUF_FLAG, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_NONE, + .flag_mode =3D MFC_CTRL_MODE_NONE, + }, + { /* buffer additional information */ + .type =3D MFC_CTRL_TYPE_DST, + .id =3D V4L2_CID_MPEG_VIDEO_DST_BUF_FLAG, + .is_volatile =3D 1, + .mode =3D MFC_CTRL_MODE_NONE, + .flag_mode =3D MFC_CTRL_MODE_NONE, + } +}; + +#define NUM_ENC_CTRL_CFGS ARRAY_SIZE(mfc_enc_ctrl_list) + static void mfc_ctrl_cleanup_ctx(struct mfc_ctx *ctx) { struct mfc_ctx_ctrl *ctx_ctrl; @@ -426,6 +1188,8 @@ static int mfc_ctrl_init_ctx(struct mfc_ctx *ctx) { if (ctx->type =3D=3D MFCINST_DECODER) return __mfc_ctrl_init_ctx(ctx, mfc_dec_ctrl_list, NUM_DEC_CTRL_CFGS); + else if (ctx->type =3D=3D MFCINST_ENCODER) + return __mfc_ctrl_init_ctx(ctx, mfc_enc_ctrl_list, NUM_ENC_CTRL_CFGS); =20 mfc_ctx_err("[CTRLS] invalid type %d\n", ctx->type); return -EINVAL; @@ -560,11 +1324,47 @@ static int mfc_ctrl_init_buf(struct mfc_ctx *ctx, en= um mfc_ctrl_type type, unsig { if (ctx->type =3D=3D MFCINST_DECODER) return __mfc_ctrl_init_buf(ctx, mfc_dec_ctrl_list, type, index, NUM_DEC_= CTRL_CFGS); + else if (ctx->type =3D=3D MFCINST_ENCODER) + return __mfc_ctrl_init_buf(ctx, mfc_enc_ctrl_list, type, index, NUM_ENC_= CTRL_CFGS); =20 mfc_ctx_err("[CTRLS] invalid type %d\n", ctx->type); return -EINVAL; } =20 +static void __mfc_enc_set_roi(struct mfc_ctx *ctx, struct mfc_buf_ctrl *bu= f_ctrl) +{ + struct mfc_enc *enc =3D ctx->enc_priv; + int index =3D 0; + unsigned int reg =3D 0; + + index =3D enc->roi_index; + if (enc->roi_info[index].enable) { + enc->roi_index =3D (index + 1) % MFC_MAX_EXTRA_BUF; + reg |=3D enc->roi_info[index].enable; + reg &=3D ~(0xFF << 8); + reg |=3D (enc->roi_info[index].lower_qp << 8); + reg &=3D ~(0xFFFF << 16); + reg |=3D (enc->roi_info[index].upper_qp << 16); + /* + * 2bit ROI + * - All codec type: upper_qp and lower_qp is valid + * 8bit ROI + * - H.264/HEVC/MPEG4: upper_qp and lower_qp is invalid + * - VP8/VP9: upper_qp and lower_qp is valid + */ + mfc_ctx_debug(3, "[ROI] buffer[%d] en %d QP lower %d upper %d reg %#x\n", + index, enc->roi_info[index].enable, + enc->roi_info[index].lower_qp, + enc->roi_info[index].upper_qp, + reg); + } else { + mfc_ctx_debug(3, "[ROI] buffer[%d] is not enabled\n", index); + } + + buf_ctrl->val =3D reg; + buf_ctrl->old_val2 =3D index; +} + static void mfc_ctrl_to_buf(struct mfc_ctx *ctx, struct list_head *head) { struct mfc_ctx_ctrl *ctx_ctrl; @@ -588,6 +1388,9 @@ static void mfc_ctrl_to_buf(struct mfc_ctx *ctx, struc= t list_head *head) =20 ctx_ctrl->set.has_new =3D 0; =20 + if (buf_ctrl->id =3D=3D V4L2_CID_MPEG_VIDEO_ROI_CONTROL) + __mfc_enc_set_roi(ctx, buf_ctrl); + break; } } diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_rm.c b/drivers/m= edia/platform/samsung/exynos-mfc/mfc_rm.c index a7db47e58589..4083d76640fd 100644 --- a/drivers/media/platform/samsung/exynos-mfc/mfc_rm.c +++ b/drivers/media/platform/samsung/exynos-mfc/mfc_rm.c @@ -685,12 +685,22 @@ static void __mfc_rm_migrate_all_to_one_core(struct m= fc_dev *dev) spin_unlock_irqrestore(&dev->ctx_list_lock, flags); return; } - - if (tmp_ctx->op_core_type =3D=3D MFC_OP_CORE_FIXED_0) - op_core_fixed0++; - else if (tmp_ctx->op_core_type =3D=3D MFC_OP_CORE_FIXED_1) - op_core_fixed1++; - + /* op core type */ + if (tmp_ctx->type =3D=3D MFCINST_ENCODER) { + /* + * instance of encoder cannot be moved to another core. + * So, treat main core as the fixed core. + */ + if (tmp_ctx->op_core_num[MFC_CORE_MAIN] =3D=3D MFC_DEC_DEFAULT_CORE) + op_core_fixed0++; + else if (tmp_ctx->op_core_num[MFC_CORE_MAIN] =3D=3D MFC_SURPLUS_CORE) + op_core_fixed1++; + } else { + if (tmp_ctx->op_core_type =3D=3D MFC_OP_CORE_FIXED_0) + op_core_fixed0++; + else if (tmp_ctx->op_core_type =3D=3D MFC_OP_CORE_FIXED_1) + op_core_fixed1++; + } /* op main core */ if (tmp_ctx->op_core_num[MFC_CORE_MAIN] =3D=3D MFC_DEC_DEFAULT_CORE) op_core0++; @@ -1344,6 +1354,14 @@ void mfc_rm_load_balancing(struct mfc_ctx *ctx, int = load_add) __mfc_rm_update_core_load(tmp_ctx, 0, 1); continue; } + + if (tmp_ctx->type =3D=3D MFCINST_ENCODER) { + mfc_ctx_debug(3, "[RMLB] encoder ctx[%d] can't be moved\n", + tmp_ctx->num); + __mfc_rm_update_core_load(tmp_ctx, 0, IS_MULTI_MODE(tmp_ctx)); + continue; + } + core_num =3D __mfc_rm_get_core_num_by_load(dev, tmp_ctx, MFC_DEC_DEFAULT= _CORE); if (IS_SWITCH_SINGLE_MODE(tmp_ctx) || core_num =3D=3D tmp_ctx->op_core_num[MFC_CORE_MAIN]) { @@ -1440,8 +1458,10 @@ int mfc_rm_instance_init(struct mfc_dev *dev, struct= mfc_ctx *ctx) * QoS portion data should be allocated * only once per instance after maincore is determined. */ - num_qos_steps =3D core->core_pdata->num_default_qos_steps; - + if (ctx->type =3D=3D MFCINST_ENCODER) + num_qos_steps =3D core->core_pdata->num_encoder_qos_steps; + else + num_qos_steps =3D core->core_pdata->num_default_qos_steps; ctx->mfc_qos_portion =3D vmalloc(sizeof(unsigned int) * num_qos_steps); if (!ctx->mfc_qos_portion) ret =3D -ENOMEM; @@ -1916,6 +1936,46 @@ void mfc_rm_instance_dec_stop(struct mfc_dev *dev, s= truct mfc_ctx *ctx, mfc_ctx_debug_leave(); } =20 +void mfc_rm_instance_enc_stop(struct mfc_dev *dev, struct mfc_ctx *ctx, + unsigned int type) +{ + struct mfc_core *core; + struct mfc_core *subcore; + + mfc_ctx_debug_enter(); + + mfc_get_corelock_ctx(ctx); + + core =3D mfc_get_main_core(dev, ctx); + if (!core) { + mfc_ctx_err("[RM] There is no main core\n"); + mfc_release_corelock_ctx(ctx); + return; + } + + if (type =3D=3D V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + core->core_ops->instance_q_flush(core, ctx); + } else if (type =3D=3D V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + if (IS_SWITCH_SINGLE_MODE(ctx)) { + subcore =3D mfc_get_sub_core(dev, ctx); + if (!subcore) { + mfc_ctx_err("[RM] There is no sub core for switch single\n"); + goto err_subcore_stop; + } + + core->core_ops->instance_finishing(core, ctx); + subcore->core_ops->instance_finishing(subcore, ctx); + } else { + core->core_ops->instance_finishing(core, ctx); + } + } + +err_subcore_stop: + mfc_release_corelock_ctx(ctx); + + mfc_ctx_debug_leave(); +} + int mfc_rm_subcore_seq_start(struct mfc_dev *dev, struct mfc_ctx *ctx) { struct mfc_core *core; @@ -2284,6 +2344,8 @@ void mfc_rm_qos_control(struct mfc_ctx *ctx, enum mfc= _qos_control qos_control) mfc_rm_load_balancing(ctx, MFC_RM_LOAD_ADD); =20 ctx->update_bitrate =3D false; + if (ctx->type =3D=3D MFCINST_ENCODER) + ctx->update_framerate =3D false; break; default: mfc_ctx_err("[RM] not supported QoS control type: %#x\n", @@ -2528,9 +2590,14 @@ void mfc_rm_update_real_time(struct mfc_ctx *ctx) } } else { if (new_prio =3D=3D 0) { - /* In case of google photo app, user sets priority 0 */ - new_prio =3D 1; - new_rt =3D MFC_RT_LOW; + if (ctx->type =3D=3D MFCINST_ENCODER && + ctx->enc_priv->params.rc_framerate) { + new_rt =3D MFC_RT; + } else { + /* In case of google photo app, user sets priority 0 */ + new_prio =3D 1; + new_rt =3D MFC_RT_LOW; + } } else if (new_prio >=3D 1) { new_rt =3D MFC_NON_RT; } else { diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_rm.h b/drivers/m= edia/platform/samsung/exynos-mfc/mfc_rm.h index b73ef905718a..39ec63392db3 100644 --- a/drivers/media/platform/samsung/exynos-mfc/mfc_rm.h +++ b/drivers/media/platform/samsung/exynos-mfc/mfc_rm.h @@ -94,6 +94,8 @@ int mfc_rm_instance_deinit(struct mfc_dev *dev, struct mf= c_ctx *ctx); int mfc_rm_instance_open(struct mfc_dev *dev, struct mfc_ctx *ctx); void mfc_rm_instance_dec_stop(struct mfc_dev *dev, struct mfc_ctx *ctx, unsigned int type); +void mfc_rm_instance_enc_stop(struct mfc_dev *dev, struct mfc_ctx *ctx, + unsigned int type); int mfc_rm_subcore_seq_start(struct mfc_dev *dev, struct mfc_ctx *ctx); int mfc_rm_instance_setup(struct mfc_dev *dev, struct mfc_ctx *ctx); void mfc_rm_request_work(struct mfc_dev *dev, enum mfc_request_work work, --=20 2.34.1