lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250930040348.3702923-21-h.dewangan@samsung.com>
Date: Tue, 30 Sep 2025 09:33:39 +0530
From: Himanshu Dewangan <h.dewangan@...sung.com>
To: mchehab@...nel.org, robh@...nel.org, krzk+dt@...nel.org,
	conor+dt@...nel.org, sumit.semwal@...aro.org, christian.koenig@....com,
	alim.akhtar@...sung.com, manjun@...sung.com, nagaraju.s@...sung.com,
	ih0206.lee@...sung.com, jehyung.lee@...sung.com
Cc: linux-arm-kernel@...ts.infradead.org, linux-media@...r.kernel.org,
	devicetree@...r.kernel.org, linux-samsung-soc@...r.kernel.org,
	linux-kernel@...r.kernel.org, dri-devel@...ts.freedesktop.org,
	linaro-mm-sig@...ts.linaro.org, Himanshu Dewangan <h.dewangan@...sung.com>
Subject: [PATCH 20/29] media: mfc: Add H264 decoder support

From: Nagaraju Siddineni <nagaraju.s@...sung.com>

- Extend device‑tree with properties for secure firmware, DRM, codec
  capabilities, format/stride, resolution checks, and security controls.
- Introduce per‑codec and device‑wide bitrate limits.
- Implement runtime management: scheduler workers, dedicated workqueues,
  and required mutex/spinlock synchronization.
- Refine decoder‑context handling (full init/cleanup, CRC dump,
  DPB handling, vb2 queue setup, QoS parsing).
- Add polling with error‑state handling.
- Expand DebugFS to expose core‑balance, feature flags, format support,
  QoS data, and queue metrics.
- Update macros, include missing headers, improve logging, adjust
  scheduler/PBS configuration, and revise buffer‑size structures.

Signed-off-by: Nagaraju Siddineni <nagaraju.s@...sung.com>
Signed-off-by: Himanshu Dewangan <h.dewangan@...sung.com>
---
 .../dts/exynos/exynosautov920-evt2-mfc.dtsi   | 443 ++++++++++++++++++
 .../media/platform/samsung/exynos-mfc/mfc.c   | 420 ++++++++++++++++-
 .../platform/samsung/exynos-mfc/mfc_debugfs.c |  60 ++-
 3 files changed, 915 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/boot/dts/exynos/exynosautov920-evt2-mfc.dtsi b/arch/arm64/boot/dts/exynos/exynosautov920-evt2-mfc.dtsi
index 49c61958467e..40cac2b20804 100644
--- a/arch/arm64/boot/dts/exynos/exynosautov920-evt2-mfc.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynosautov920-evt2-mfc.dtsi
@@ -67,25 +67,142 @@ mfc: mfc@...d0000 {
 		/* MFC version */
 		ip_ver = <0x1600010C>;
 
+		/* Secure Firmware Loading */
+		secure_fw_loading = <1>;
+
 		/* MFC firmware name */
 		fw_name = "mfc_fw_v16.0.bin";
 
 		/* Debug mode */
 		debug_mode = <1>;
 
+		max_num_drm_inst = <3>;
+
+		/* NAL-Q size */
+		nal_q_entry_size = <768>;
+		nal_q_dump_size = <376>;
+
 		/* Features <on/off version> */
+		skype = <1 0x0>;
+		black_bar = <1 0x0>;
+		color_aspect_dec = <1 0x0>;
+		static_info_dec = <1 0x0>;
+		color_aspect_enc = <1 0x0>;
+		static_info_enc = <1 0x180314>;
+		vp9_stride_align = <1 0x0>;
 		mem_clear = <1 0x0>;
 		/* Support from v11.0 (except 11.2) */
 		wait_fw_status = <1 0x190122>;
+		/* DRM switch predict for cache flush */
+		drm_switch_predict = <1 0x0>;
+		/* Use metadata interface */
+		metadata_interface = <1 0x200910>;
+		/* Average QP of encoder per frame */
+		average_qp = <1 0x201030>;
+		/* MV search mode */
+		mv_search_mode = <1 0x201118>;
+		/* Encoder IDR flag */
+		enc_idr_flag = <1 0x210611>;
+		/* Encoder min quality mode */
+		min_quality_mode = <1 0x210705>;
+		/* Encoder time stamp delta */
+		enc_ts_delta = <1 0x211027>;
+		/* Encoder I limit RC mode for WFD */
+		wfd_rc_mode = <1 0x211229>;
 
 		/* Scheduler 0: round-robin, 1: PBS */
 		scheduler = <1>;
 		/* The number of priority in PBS */
 		pbs_num_prio = <1>;
 
+		/* Support AV1 Film Grain Feature */
+		av1_film_grain = <1 0x200717>;
+
+		/* Decoder stride align (default: 16, AMD GPU: 256) */
+		stride_align = <256>;
+		/* Decoder stride calculation type (new: 1, old: 0) */
+		stride_type = <1>;
+
+		/* Formats */
+		support_10bit = <1>;
+		support_422 = <0>;
+		support_rgb = <1>;
+
+		/* Resolution check (0: do not check, 1: FHD, 2: 4K, 3: 8K) */
+		support_check_res = <3>;
+
+		/* error type for sync_point display */
+		/* (1: concealment display, 2: error display, 3: error no display) */
+		display_err_type = <2>;
+
+		/* FW base security ctrl */
+		security_ctrl = <1>;
+		/* output buffer Q framerate */
+		display_framerate = <0>;
+
+		/* Encoder default parameter: max number is 100 */
+		enc_param_num = <25>;
+		enc_param_addr = <0xF7B4 0xF7B8 0xF7B0 0xF798 0xFA2C
+				0xF790 0xFA34 0xFA38 0xFA3C 0xF7C0
+				0xF7C8 0xF7CC 0xFA60 0xFDD4 0xFDDC
+				0xFB54 0xFB58 0xFBA8 0xFD90 0xFD94
+				0xFD40 0xFD48 0xFD4C 0xFD50 0xFD80>;
+		enc_param_val = <0x80 0x80 0x0 0x4000 0x3FD00
+				0x0 0x0 0x2710 0x3E8 0x0
+				0x0 0x0 0x0 0x8050D211 0x0
+				0x3011 0x0 0x0 0x2D 0xA00
+				0x1D 0xF4240 0x33003300 0x2 0x1>;
+
+		/* BW <peak, read, write> : KB/UHD frame */
+		bw_enc_h264		= <45456 56112 11170>;
+		bw_enc_hevc		= <46756 52766 9763>;
+		bw_enc_hevc_10bit	= <53865 64753 12556>;
+		bw_enc_vp8		= <64000 67318 22518>;
+		bw_enc_vp9		= <72326 59726 16530>;
+		bw_enc_vp9_10bit	= <149085 114928 31419>;
+		bw_enc_mpeg4		= <44647 55324 9531>;
+		bw_dec_h264		= <32605 34381 21263>;
+		bw_dec_hevc		= <29973 28851 17538>;
+		bw_dec_hevc_10bit	= <52859 46245 31351>;
+		bw_dec_vp8		= <28672 30468 22324>;
+		bw_dec_vp9		= <18351 18947 16877>;
+		bw_dec_vp9_10bit	= <42384 34452 31766>;
+		bw_dec_av1		= <23787 19570 15856>;
+		bw_dec_av1_10bit	= <41407 35490 29699>;
+		bw_dec_mpeg4		= <31540 25368 15770>;
+
+		/* QoS bitrate */
+		num_mfc_freq = <7>;
+		mfc_freqs = <160000 267000 332000 400000 533000 664000 800000>;
+
+		/* QoS weight (%) */
+		dynamic_weight = <1>;
+		qos_weight_h264_hevc = <100>;
+		qos_weight_vp8_vp9 = <100>;
+		qos_weight_av1 = <70>;
+		qos_weight_other_codec = <25>;
+		qos_weight_3plane = <80>;
+		qos_weight_10bit = <75>;
+		qos_weight_422 = <70>;
+		qos_weight_bframe = <50>;
+		qos_weight_num_of_ref = <60>;
+		qos_weight_gpb = <50>;
+		qos_weight_num_of_tile = <75>;
+		qos_weight_super64_bframe = <60>;
+		qos_weight_mbaff = <60>;
+
+		/* core balance(%) for resource managing */
+		core_balance = <54>;
+
 		/* MFC IOVA threshold (MB) */
 		iova_threshold = <1700>;
 
+		/* need control for mfc idle clock */
+		idle_clk_ctrl = <1>;
+
+		/* QoS level for pm_qos dynamic control */
+		qos_ctrl_level = <1>;
+
 		/* Sub nodes for MFC core */
 		#address-cells = <2>;
 		#size-cells = <2>;
@@ -135,6 +252,15 @@ mfc_core0: MFC-0@...d0000 {
 			axid_mask = <0xFFFF>;
 			tsmux_axid = <0x1>;
 
+			/* QoS */
+			num_default_qos_steps = <10>;
+			num_encoder_qos_steps = <7>;
+			max_mb = <5093269>;
+			max_hw_mb = <3888000>;
+			mfc_freq_control = <1>;
+			mo_control = <1>;
+			bw_control = <1>;
+
 			/* mem-log buffer size */
 			memlog_size = <0x80000>;
 			memlog_sfr_size = <0x1000>;
@@ -148,6 +274,160 @@ mfc_core0: MFC-0@...d0000 {
 			iommu@...70000 {
 				reg = <0x0 0x19C70000 0x0 0x9000>;
 			};
+
+			/* Default QoS table */
+			mfc_default_qos_table {
+				mfc_d_qos_variant_0 {
+					thrd_mb = <0>;
+					freq_mfc = <133000>;
+					freq_int = <133000>;
+					freq_mif = <421000>;
+					bts_scen = "default";
+					time_fw = <1238>;
+				};
+				mfc_d_qos_variant_1 {
+					thrd_mb = <546599>;
+					freq_mfc = <267000>;
+					freq_int = <133000>;
+					freq_mif = <546000>;
+					bts_scen = "default";
+					time_fw = <842>;
+				};
+				mfc_d_qos_variant_2 {
+					thrd_mb = <1167159>;
+					freq_mfc = <332000>;
+					freq_int = <200000>;
+					freq_mif = <676000>;
+					bts_scen = "default";
+					time_fw = <667>;
+				};
+				mfc_d_qos_variant_3 {
+					thrd_mb = <1859381>;
+					freq_mfc = <332000>;
+					freq_int = <200000>;
+					freq_mif = <845000>;
+					bts_scen = "default";
+					time_fw = <578>;
+				};
+				mfc_d_qos_variant_4 {
+					thrd_mb = <2078433>;
+					freq_mfc = <468000>;
+					freq_int = <200000>;
+					freq_mif = <1014000>;
+					bts_scen = "default";
+					time_fw = <483>;
+				};
+				mfc_d_qos_variant_5 {
+					thrd_mb = <2563082>;
+					freq_mfc = <533000>;
+					freq_int = <332000>;
+					freq_mif = <1352000>;
+					bts_scen = "default";
+					time_fw = <362>;
+				};
+				mfc_d_qos_variant_6 {
+					thrd_mb = <3173773>;
+					freq_mfc = <663000>;
+					freq_int = <400000>;
+					freq_mif = <1352000>;
+					bts_scen = "default";
+					time_fw = <306>;
+				};
+				mfc_d_qos_variant_7 {
+					thrd_mb = <3716529>;
+					freq_mfc = <745000>;
+					freq_int = <533000>;
+					freq_mif = <1539000>;
+					bts_scen = "default";
+					time_fw = <267>;
+				};
+				mfc_d_qos_variant_8 {
+					thrd_mb = <4282126>;
+					freq_mfc = <745000>;
+					freq_int = <663000>;
+					freq_mif = <2028000>;
+					bts_scen = "default";
+					time_fw = <235>;
+				};
+				mfc_d_qos_variant_9 {
+					thrd_mb = <4855818>;
+					freq_mfc = <800000>;
+					freq_int = <800000>;
+					freq_mif = <3172000>;
+					bts_scen = "mfc_uhd_10bit";
+					time_fw = <175>;
+				};
+			};
+
+			/* Encoder only QoS table */
+			mfc_encoder_qos_table {
+				mfc_e_qos_variant_0 {
+					thrd_mb = <0>;
+					freq_mfc = <133000>;
+					freq_int = <133000>;
+					freq_mif = <421000>;
+					bts_scen = "default";
+					time_fw = <1238>;
+				};
+				mfc_e_qos_variant_1 {
+					thrd_mb = <546599>;
+					freq_mfc = <267000>;
+					freq_int = <133000>;
+					freq_mif = <546000>;
+					bts_scen = "default";
+					time_fw = <842>;
+				};
+				mfc_e_qos_variant_2 {
+					thrd_mb = <1167159>;
+					freq_mfc = <332000>;
+					freq_int = <200000>;
+					freq_mif = <676000>;
+					bts_scen = "default";
+					time_fw = <667>;
+				};
+				mfc_e_qos_variant_3 {
+					thrd_mb = <1859381>;
+					freq_mfc = <332000>;
+					freq_int = <200000>;
+					freq_mif = <845000>;
+					bts_scen = "default";
+					time_fw = <578>;
+				};
+				mfc_e_qos_variant_4 {
+					thrd_mb = <2078433>;
+					freq_mfc = <533000>;
+					freq_int = <400000>;
+					freq_mif = <845000>;
+					bts_scen = "default";
+					time_fw = <471>;
+				};
+				mfc_e_qos_variant_5 {
+					thrd_mb = <2553457>;
+					freq_mfc = <468000>;
+					freq_int = <332000>;
+					freq_mif = <1539000>;
+					bts_scen = "mfc_uhd";
+					time_fw = <359>;
+				};
+				mfc_e_qos_variant_6 {
+					thrd_mb = <3175870>;
+					freq_mfc = <663000>;
+					freq_int = <663000>;
+					freq_mif = <1716000>;
+					bts_scen = "default";
+					time_fw = <287>;
+				};
+			};
+
+			/* QoS table for performance boost mode */
+			mfc_perf_boost_table {
+				num_cluster = <3>;
+				freq_cluster = <1742000 1898000 1456000>;
+				freq_mfc = <666000>;
+				freq_int = <534000>;
+				freq_mif = <2730000>;
+				bts_scen = "mfc_uhd_10bit";
+			};
 		};
 
 		mfc_core1: MFC-1@...d0000 {
@@ -173,6 +453,15 @@ mfc_core1: MFC-1@...d0000 {
 			share_sysmmu = <0>;
 			axid_mask = <0xFFFF>;
 
+			/* QoS */
+			num_default_qos_steps = <10>;
+			num_encoder_qos_steps = <7>;
+			max_mb = <5315425>;
+			max_hw_mb = <3888000>;
+			mfc_freq_control = <1>;
+			mo_control = <1>;
+			bw_control = <1>;
+
 			/* Device virtual address */
 			#dma-address-cells = <1>;
 			#dma-size-cells = <1>;
@@ -182,6 +471,160 @@ mfc_core1: MFC-1@...d0000 {
 			iommu@...70000 {
 				reg = <0x0 0x19E70000 0x0 0x9000>;
 			};
+
+			/* Default QoS table */
+			mfc_default_qos_table {
+				mfc_d_qos_variant_0 {
+					thrd_mb = <0>;
+					freq_mfc = <133000>;
+					freq_int = <133000>;
+					freq_mif = <421000>;
+					bts_scen = "default";
+					time_fw = <1238>;
+				};
+				mfc_d_qos_variant_1 {
+					thrd_mb = <546599>;
+					freq_mfc = <234000>;
+					freq_int = <133000>;
+					freq_mif = <546000>;
+					bts_scen = "default";
+					time_fw = <842>;
+				};
+				mfc_d_qos_variant_2 {
+					thrd_mb = <1167159>;
+					freq_mfc = <332000>;
+					freq_int = <200000>;
+					freq_mif = <676000>;
+					bts_scen = "default";
+					time_fw = <667>;
+				};
+				mfc_d_qos_variant_3 {
+					thrd_mb = <1859381>;
+					freq_mfc = <332000>;
+					freq_int = <200000>;
+					freq_mif = <845000>;
+					bts_scen = "default";
+					time_fw = <578>;
+				};
+				mfc_d_qos_variant_4 {
+					thrd_mb = <2078433>;
+					freq_mfc = <468000>;
+					freq_int = <200000>;
+					freq_mif = <1014000>;
+					bts_scen = "default";
+					time_fw = <483>;
+				};
+				mfc_d_qos_variant_5 {
+					thrd_mb = <2563082>;
+					freq_mfc = <533000>;
+					freq_int = <332000>;
+					freq_mif = <1352000>;
+					bts_scen = "default";
+					time_fw = <362>;
+				};
+				mfc_d_qos_variant_6 {
+					thrd_mb = <3173773>;
+					freq_mfc = <663000>;
+					freq_int = <400000>;
+					freq_mif = <1352000>;
+					bts_scen = "default";
+					time_fw = <306>;
+				};
+				mfc_d_qos_variant_7 {
+					thrd_mb = <3716529>;
+					freq_mfc = <745000>;
+					freq_int = <533000>;
+					freq_mif = <1539000>;
+					bts_scen = "default";
+					time_fw = <267>;
+				};
+				mfc_d_qos_variant_8 {
+					thrd_mb = <4282126>;
+					freq_mfc = <745000>;
+					freq_int = <663000>;
+					freq_mif = <2028000>;
+					bts_scen = "default";
+					time_fw = <235>;
+				};
+				mfc_d_qos_variant_9 {
+					thrd_mb = <4855818>;
+					freq_mfc = <800000>;
+					freq_int = <800000>;
+					freq_mif = <3172000>;
+					bts_scen = "mfc_8k_dec30";
+					time_fw = <175>;
+				};
+			};
+
+			/* Encoder only QoS table */
+			mfc_encoder_qos_table {
+				mfc_e_qos_variant_0 {
+					thrd_mb = <0>;
+					freq_mfc = <133000>;
+					freq_int = <133000>;
+					freq_mif = <421000>;
+					bts_scen = "default";
+					time_fw = <1238>;
+				};
+				mfc_e_qos_variant_1 {
+					thrd_mb = <546599>;
+					freq_mfc = <267000>;
+					freq_int = <133000>;
+					freq_mif = <546000>;
+					bts_scen = "default";
+					time_fw = <842>;
+				};
+				mfc_e_qos_variant_2 {
+					thrd_mb = <1167159>;
+					freq_mfc = <332000>;
+					freq_int = <200000>;
+					freq_mif = <676000>;
+					bts_scen = "default";
+					time_fw = <667>;
+				};
+				mfc_e_qos_variant_3 {
+					thrd_mb = <1859381>;
+					freq_mfc = <332000>;
+					freq_int = <200000>;
+					freq_mif = <845000>;
+					bts_scen = "default";
+					time_fw = <578>;
+				};
+				mfc_e_qos_variant_4 {
+					thrd_mb = <2078433>;
+					freq_mfc = <533000>;
+					freq_int = <400000>;
+					freq_mif = <845000>;
+					bts_scen = "default";
+					time_fw = <471>;
+				};
+				mfc_e_qos_variant_5 {
+					thrd_mb = <2553457>;
+					freq_mfc = <468000>;
+					freq_int = <332000>;
+					freq_mif = <1539000>;
+					bts_scen = "mfc_uhd";
+					time_fw = <359>;
+				};
+				mfc_e_qos_variant_6 {
+					thrd_mb = <3175870>;
+					freq_mfc = <663000>;
+					freq_int = <663000>;
+					freq_mif = <1716000>;
+					bts_scen = "default";
+					time_fw = <287>;
+				};
+			};
+
+			/* QoS table for performance boost mode */
+			mfc_perf_boost_table {
+				num_cluster = <3>;
+				freq_cluster = <1742000 1898000 1456000>;
+				freq_mfc = <666000>;
+				freq_int = <534000>;
+				freq_mif = <2730000>;
+				bts_scen = "mfc_uhd_10bit";
+			};
 		};
 	};
 };
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc.c b/drivers/media/platform/samsung/exynos-mfc/mfc.c
index b5b66083cc8b..fb9a7317e812 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc.c
@@ -21,6 +21,8 @@
 #include <linux/poll.h>
 #include <linux/iommu.h>
 
+#include "mfc_dec_v4l2.h"
+#include "mfc_dec_vb2.h"
 #include "mfc_rm.h"
 #include "mfc_debugfs.h"
 
@@ -29,6 +31,9 @@
 
 #include "mfc_core_hw_reg_api.h"
 
+#include "base/mfc_qos.h"
+
+#include "base/mfc_queue.h"
 #include "base/mfc_utils.h"
 #include "base/mfc_buf.h"
 #include "base/mfc_mem.h"
@@ -41,6 +46,188 @@ struct _mfc_trace g_mfc_trace[MFC_TRACE_COUNT_MAX];
 struct _mfc_trace g_mfc_trace_rm[MFC_TRACE_COUNT_MAX];
 struct _mfc_trace g_mfc_trace_longterm[MFC_TRACE_COUNT_MAX];
 
+static void mfc_butler_worker(struct work_struct *work)
+{
+	struct mfc_dev *dev;
+	struct mfc_ctx *ctx;
+	int i;
+
+	dev = container_of(work, struct mfc_dev, butler_work);
+
+	/* If there is multi core instance, it has high priority */
+	if (dev->multi_core_inst_bits) {
+		bool is_switch_to_single;
+		bool is_multi_mode;
+
+		i = __ffs(dev->multi_core_inst_bits);
+		ctx = dev->ctx[i];
+		if (!ctx) {
+			mfc_dev_err("[RM] There is no ctx\n");
+			return;
+		}
+
+		/* [DRC] In the case of MFC_OP_SWITCH_TO_SINGLE,
+		 * also need to request with MFC_WORK_TRY.
+		 * Because op_mode is maintained as MFC_OP_SWITCH_TO_SINGLE before subcore_deinit.
+		 * And, subcore_deinit can be started by MFC_WORK_TRY.
+		 */
+		is_multi_mode = IS_MULTI_MODE(ctx);
+		is_switch_to_single =
+			(ctx->op_mode == MFC_OP_SWITCH_TO_SINGLE && ctx->handle_drc_multi_mode);
+		if (!is_multi_mode && !is_switch_to_single)
+			return;
+
+		mfc_rm_request_work(dev, MFC_WORK_TRY, ctx);
+	} else {
+		mfc_rm_request_work(dev, MFC_WORK_BUTLER, NULL);
+	}
+}
+
+static void __mfc_deinit_dec_ctx(struct mfc_ctx *ctx)
+{
+	struct mfc_dec *dec = ctx->dec_priv;
+	unsigned int size;
+
+	if (dec->crc && (ctx->dev->debugfs.sfr_dump & MFC_DUMP_DEC_CRC)) {
+		if (dec->crc_idx * 4 > SZ_1K)
+			size = SZ_1K;
+		else
+			size = dec->crc_idx * 4;
+		print_hex_dump
+			(KERN_ERR, "CRC: ", DUMP_PREFIX_OFFSET, 32, 1,
+			dec->crc, size, false);
+		vfree(dec->crc);
+	}
+
+	mfc_cleanup_iovmm(ctx);
+
+	mfc_delete_queue(&ctx->src_buf_ready_queue);
+	mfc_delete_queue(&ctx->dst_buf_queue);
+	mfc_delete_queue(&ctx->err_buf_queue);
+	mfc_delete_queue(&ctx->meminfo_inbuf_q);
+
+	mfc_mem_cleanup_user_shared_handle(ctx, &dec->sh_handle_dpb);
+	if (dec->ref_info)
+		vfree(dec->ref_info);
+
+	kfree(dec);
+}
+
+static int __mfc_init_dec_ctx(struct mfc_ctx *ctx)
+{
+	struct mfc_dec *dec;
+	int ret = 0;
+	int i;
+
+	dec = kzalloc(sizeof(*dec), GFP_KERNEL);
+	if (!dec)
+		return -ENOMEM;
+
+	ctx->dec_priv = dec;
+
+	ctx->subcore_inst_no = MFC_NO_INSTANCE_SET;
+	ctx->curr_src_index = -1;
+	ctx->user_prio = -1;
+
+	mfc_create_queue(&ctx->src_buf_ready_queue);
+	mfc_create_queue(&ctx->dst_buf_queue);
+	mfc_create_queue(&ctx->err_buf_queue);
+	mfc_create_queue(&ctx->meminfo_inbuf_q);
+
+	for (i = 0; i < MFC_MAX_BUFFERS; i++) {
+		INIT_LIST_HEAD(&ctx->src_ctrls[i]);
+		INIT_LIST_HEAD(&ctx->dst_ctrls[i]);
+	}
+	bitmap_zero(ctx->src_ctrls_avail, MFC_MAX_BUFFERS);
+	bitmap_zero(ctx->dst_ctrls_avail, MFC_MAX_BUFFERS);
+
+	ctx->capture_state = QUEUE_FREE;
+	ctx->output_state = QUEUE_FREE;
+
+	ctx->type = MFCINST_DECODER;
+	ctx->c_ops = &mfc_ctrls_ops;
+	ctx->b_ops = &mfc_bufs_ops;
+
+	mfc_dec_set_default_format(ctx);
+	mfc_rate_reset_framerate(ctx);
+
+	ctx->qos_ratio = 100;
+	INIT_LIST_HEAD(&ctx->bitrate_list);
+	INIT_LIST_HEAD(&ctx->src_ts.ts_list);
+
+	dec->display_delay = -1;
+	dec->is_interlaced = 0;
+	dec->immediate_display = 0;
+	dec->is_dts_mode = 0;
+	dec->inter_res_change = 0;
+	dec->disp_drc.disp_res_change = 0;
+	dec->disp_drc.push_idx = 0;
+	dec->disp_drc.pop_idx = 0;
+
+	dec->is_dynamic_dpb = 1;
+	dec->dynamic_used = 0;
+	dec->is_dpb_full = 0;
+	dec->queued_dpb = 0;
+	dec->display_index = -1;
+	dec->dpb_table_used = 0;
+	dec->sh_handle_dpb.fd = -1;
+	mutex_init(&dec->dpb_mutex);
+
+	mfc_init_dpb_table(ctx);
+
+	dec->sh_handle_dpb.data_size = sizeof(struct dec_dpb_ref_info) * MFC_MAX_BUFFERS;
+	dec->ref_info = vmalloc(dec->sh_handle_dpb.data_size);
+	if (!dec->ref_info) {
+		mfc_ctx_err("failed to allocate decoder information data\n");
+		ret = -ENOMEM;
+		goto fail_dec_init;
+	}
+	for (i = 0; i < MFC_MAX_BUFFERS; i++)
+		dec->ref_info[i].dpb[0].fd[0] = MFC_INFO_INIT_FD;
+
+	if (ctx->dev->debugfs.sfr_dump & MFC_DUMP_DEC_CRC) {
+		dec->crc = vmalloc(SZ_1K);
+		if (!dec->crc) {
+			ret = -ENOMEM;
+			goto fail_dec_init;
+		}
+		dec->crc_idx = 0;
+	}
+
+	/* Init videobuf2 queue for OUTPUT */
+	ctx->vq_src.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	ctx->vq_src.drv_priv = ctx;
+	ctx->vq_src.buf_struct_size = (unsigned int)sizeof(struct mfc_buf);
+	ctx->vq_src.io_modes = VB2_USERPTR | VB2_DMABUF;
+	ctx->vq_src.ops = mfc_get_dec_vb2_ops();
+	ctx->vq_src.mem_ops = mfc_mem_ops();
+	ctx->vq_src.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	ret = vb2_queue_init(&ctx->vq_src);
+	if (ret) {
+		mfc_ctx_err("Failed to initialize videobuf2 queue(output)\n");
+		goto fail_dec_init;
+	}
+	/* Init videobuf2 queue for CAPTURE */
+	ctx->vq_dst.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	ctx->vq_dst.drv_priv = ctx;
+	ctx->vq_dst.buf_struct_size = (unsigned int)sizeof(struct mfc_buf);
+	ctx->vq_dst.io_modes = VB2_USERPTR | VB2_DMABUF;
+	ctx->vq_dst.ops = mfc_get_dec_vb2_ops();
+	ctx->vq_dst.mem_ops = mfc_mem_ops();
+	ctx->vq_dst.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	ret = vb2_queue_init(&ctx->vq_dst);
+	if (ret) {
+		mfc_ctx_err("Failed to initialize videobuf2 queue(capture)\n");
+		goto fail_dec_init;
+	}
+
+	return ret;
+
+fail_dec_init:
+	__mfc_deinit_dec_ctx(ctx);
+	return ret;
+}
+
 /* Open an MFC node */
 static int mfc_open(struct file *file)
 {
@@ -49,6 +236,7 @@ static int mfc_open(struct file *file)
 	int i, ret = 0;
 	enum mfc_node_type node;
 	struct video_device *vdev = NULL;
+	unsigned long total_mb = 0, max_hw_mb = 0;
 
 	if (!dev) {
 		mfc_pr_err("no mfc device to run\n");
@@ -60,6 +248,26 @@ static int mfc_open(struct file *file)
 	if (mutex_lock_interruptible(&dev->mfc_mutex))
 		return -ERESTARTSYS;
 
+	/* Check mfc_open() of spec over */
+	for (i = 0; i < dev->num_core; i++)
+		max_hw_mb += dev->core[i]->core_pdata->max_hw_mb;
+	for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
+		if (!dev->ctx[i])
+			continue;
+		total_mb += dev->ctx[i]->weighted_mb;
+		mfc_show_ctx_info(dev->ctx[i]);
+	}
+	if (total_mb >= max_hw_mb) {
+		mfc_dev_info
+			("[RM] now MFC work with full spec(mb: %lu / %lu)\n",
+			total_mb, max_hw_mb);
+		for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
+			if (!dev->ctx[i])
+				continue;
+			mfc_print_ctx_info(dev->ctx[i]);
+		}
+	}
+
 	node = mfc_get_node_type(file);
 	if (node == MFCNODE_INVALID) {
 		mfc_dev_err("cannot specify node type\n");
@@ -109,20 +317,32 @@ static int mfc_open(struct file *file)
 		}
 	}
 
+	spin_lock_init(&ctx->buf_queue_lock);
+	spin_lock_init(&ctx->meminfo_queue_lock);
 	spin_lock_init(&ctx->corelock.lock);
+	spin_lock_init(&ctx->src_ts.ts_lock);
+	spin_lock_init(&ctx->dst_q_ts.ts_lock);
+	spin_lock_init(&ctx->dst_dq_ts.ts_lock);
+	spin_lock_init(&ctx->src_q_ts.ts_lock);
 	mutex_init(&ctx->intlock.core_mutex);
 	mutex_init(&ctx->op_mode_mutex);
+	mutex_init(&ctx->drc_wait_mutex);
 	init_waitqueue_head(&ctx->corelock.wq);
+	init_waitqueue_head(&ctx->corelock.migrate_wq);
+	INIT_LIST_HEAD(&ctx->dst_q_ts.ts_list);
+	INIT_LIST_HEAD(&ctx->dst_dq_ts.ts_list);
+	INIT_LIST_HEAD(&ctx->src_q_ts.ts_list);
 
 	mfc_ctx_change_idle_mode(ctx, MFC_IDLE_MODE_NONE);
 
 	if (mfc_is_decoder_node(node)) {
-		ctx->type = MFCINST_DECODER;
+		ret = __mfc_init_dec_ctx(ctx);
 		dev->num_dec_inst++;
 	} else {
-		ctx->type = MFCINST_ENCODER;
 		dev->num_enc_inst++;
 	}
+	if (ret)
+		goto err_ctx_init;
 
 	if (dev->num_inst == 1) {
 		/* all of the ctx list */
@@ -131,6 +351,12 @@ static int mfc_open(struct file *file)
 		/* idle mode */
 		spin_lock_init(&dev->idle_bits_lock);
 	}
+	if (mfc_is_decoder_node(node))
+		ret = call_cop(ctx, init_ctx_ctrls, ctx);
+	if (ret) {
+		mfc_ctx_err("failed in init_ctx_ctrls\n");
+		goto err_ctx_init;
+	}
 
 	mfc_ctx_info
 		("NORMAL %s instance is opened [%d]\n",
@@ -155,11 +381,16 @@ static int mfc_open(struct file *file)
 		("[INFO] %s opened (ctx:%d, total:%d)\n",
 		mfc_is_decoder_node(node) ? "DEC" : "ENC", ctx->num, dev->num_inst);
 
+	queue_work(dev->butler_wq, &dev->butler_work);
+
 	mutex_unlock(&dev->mfc_mutex);
 	return ret;
 
 	/* Deinit when failure occurred */
 err_inst_init:
+	call_cop(ctx, cleanup_ctx_ctrls, ctx);
+
+err_ctx_init:
 	if (mfc_is_decoder_node(node))
 		dev->num_dec_inst--;
 	else
@@ -192,10 +423,13 @@ static int mfc_release(struct file *file)
 {
 	struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
 	struct mfc_dev *dev = ctx->dev;
+	struct mfc_ctx *move_ctx;
 	int ret = 0;
+	int i;
 	unsigned long flags;
 
 	mutex_lock(&dev->mfc_mutex);
+	mutex_lock(&dev->mfc_migrate_mutex);
 
 	mfc_ctx_info
 		("%s instance release is called [%d]\n",
@@ -215,6 +449,12 @@ static int mfc_release(struct file *file)
 	 * So, we need to performed stop_streaming
 	 * before instance de-init(CLOSE_INSTANCE).
 	 */
+	if (ctx->type == MFCINST_DECODER) {
+		vb2_queue_release(&ctx->vq_src);
+		vb2_queue_release(&ctx->vq_dst);
+
+		call_cop(ctx, cleanup_ctx_ctrls, ctx);
+	}
 
 	ret = mfc_rm_instance_deinit(dev, ctx);
 	if (ret) {
@@ -224,13 +464,27 @@ static int mfc_release(struct file *file)
 
 	dev->num_inst--;
 
-	if (ctx->type == MFCINST_DECODER)
+	if (IS_MULTI_CORE_DEVICE(dev))
+		mfc_rm_load_balancing(ctx, MFC_RM_LOAD_DELETE_UPDATE);
+
+	if (ctx->type == MFCINST_DECODER) {
+		__mfc_deinit_dec_ctx(ctx);
 		dev->num_dec_inst--;
-	else if (ctx->type == MFCINST_ENCODER)
+	} else if (ctx->type == MFCINST_ENCODER) {
 		dev->num_enc_inst--;
+	}
 
 	MFC_TRACE_CTX_LT("[INFO] Release finished (ctx:%d, total:%d)\n", ctx->num, dev->num_inst);
 
+	/* If ctx is move_ctx in migration worker, clear move_ctx */
+	for (i = 0; i < dev->move_ctx_cnt; i++) {
+		move_ctx = dev->move_ctx[i];
+		if (move_ctx && move_ctx->num == ctx->num) {
+			dev->move_ctx[i] = NULL;
+			break;
+		}
+	}
+
 	spin_lock_irqsave(&dev->ctx_list_lock, flags);
 	dev->ctx[ctx->num] = NULL;
 	kfree(ctx);
@@ -238,17 +492,49 @@ static int mfc_release(struct file *file)
 
 	mfc_dev_info("mfc driver release finished [%d]\n", dev->num_inst);
 
+	queue_work(dev->butler_wq, &dev->butler_work);
+
 end_release:
+	mutex_unlock(&dev->mfc_migrate_mutex);
 	mutex_unlock(&dev->mfc_mutex);
 	return ret;
 }
 
+/* Poll */
+static __poll_t mfc_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+	unsigned long req_events = poll_requested_events(wait);
+	__poll_t ret = 0;
+
+	mfc_ctx_debug_enter();
+
+	if (mfc_rm_query_state(ctx, EQUAL, MFCINST_ERROR)) {
+		if (req_events & (POLLOUT | POLLWRNORM))
+			mfc_ctx_err("SRC: Call on POLL after unrecoverable error\n");
+		else
+			mfc_ctx_err("DST: Call on POLL after unrecoverable error\n");
+		return EPOLLERR;
+	}
+
+	if (req_events & (POLLOUT | POLLWRNORM)) {
+		mfc_ctx_debug(2, "wait source buffer\n");
+		ret = vb2_poll(&ctx->vq_src, file, wait);
+	} else if (req_events & (POLLIN | POLLRDNORM)) {
+		mfc_ctx_debug(2, "wait destination buffer\n");
+		ret = vb2_poll(&ctx->vq_dst, file, wait);
+	}
+
+	mfc_ctx_debug_leave();
+	return ret;
+}
+
 /* v4l2 ops */
 static const struct v4l2_file_operations mfc_fops = {
 	.owner = THIS_MODULE,
 	.open = mfc_open,
 	.release = mfc_release,
-	.poll = NULL,
+	.poll = mfc_poll,
 	.unlocked_ioctl = video_ioctl2,
 };
 
@@ -278,6 +564,9 @@ static void __mfc_parse_dt_resource(struct mfc_dev *dev, struct device_node *np)
 		of_property_read_u32_index(np_tmp, "info", idx++, &codec_mode);
 		resource = &dev->pdata->mfc_resource[codec_mode];
 		of_property_read_u32_index(np_tmp, "info", idx++, (u32 *)&resource->op_core_type);
+		of_property_read_u32_index(np_tmp, "info", idx++, &resource->max_kbps);
+		if (resource->max_kbps > dev->max_kbps)
+			dev->max_kbps = resource->max_kbps;
 	}
 }
 
@@ -309,17 +598,104 @@ static int __mfc_parse_dt(struct device_node *np, struct mfc_dev *mfc)
 	/* Resource of standard */
 	__mfc_parse_dt_resource(mfc, np);
 
+	/* Features */
+	of_property_read_u32_array(np, "skype", &pdata->skype.support, 2);
+	of_property_read_u32_array
+		(np, "black_bar",
+		&pdata->black_bar.support, 2);
+	of_property_read_u32_array
+		(np, "color_aspect_dec",
+		&pdata->color_aspect_dec.support, 2);
+	of_property_read_u32_array
+		(np, "static_info_dec",
+		&pdata->static_info_dec.support, 2);
+	of_property_read_u32_array
+		(np, "vp9_stride_align",
+		&pdata->vp9_stride_align.support, 2);
 	of_property_read_u32_array
 		(np, "mem_clear",
 		&pdata->mem_clear.support, 2);
 	of_property_read_u32_array
 		(np, "wait_fw_status",
 		&pdata->wait_fw_status.support, 2);
+	of_property_read_u32_array
+		(np, "hevc_pic_output_flag",
+		&pdata->hevc_pic_output_flag.support, 2);
+
+	/* H/W limitation or option */
+	of_property_read_u32(np, "stride_align", &pdata->stride_align);
+	of_property_read_u32(np, "stride_type", &pdata->stride_type);
+	of_property_read_u32(np, "stream_buf_limit", &pdata->stream_buf_limit);
+	of_property_read_u32(np, "support_8K_cavlc", &pdata->support_8K_cavlc);
+
+	/* Formats */
+	of_property_read_u32(np, "support_422", &pdata->support_422);
+
+	/* Resolution */
+	of_property_read_u32(np, "support_check_res", &pdata->support_check_res);
+
+	/* HWACG */
+	of_property_read_u32(np, "support_hwacg", &pdata->support_hwacg);
+
+	/* display_err_type */
+	of_property_read_u32(np, "display_err_type", &pdata->display_err_type);
+
+	/* output buffer Q framerate */
+	of_property_read_u32(np, "display_framerate", &pdata->display_framerate);
+
+	of_property_read_u32_array
+		(np, "bw_dec_h264",
+		&pdata->mfc_bw_info.bw_dec_h264.peak, 3);
+
+	/* QoS weight */
+	of_property_read_u32(np, "dynamic_weight", &pdata->dynamic_weight);
+	of_property_read_u32
+			(np, "qos_weight_h264_hevc",
+			&pdata->qos_weight.weight_h264_hevc);
+	of_property_read_u32
+			(np, "qos_weight_3plane",
+			&pdata->qos_weight.weight_3plane);
+	of_property_read_u32
+			(np, "qos_weight_num_of_tile",
+			&pdata->qos_weight.weight_num_of_tile);
+	of_property_read_u32
+			(np, "qos_weight_mbaff",
+			&pdata->qos_weight.weight_mbaff);
+
+	/* Bitrate control for QoS */
+	of_property_read_u32(np, "num_mfc_freq", &pdata->num_mfc_freq);
+	if (pdata->num_mfc_freq)
+		of_property_read_u32_array
+			(np, "mfc_freqs",
+			pdata->mfc_freqs, pdata->num_mfc_freq);
+
+	/* Core balance(%) for resource managing */
+	of_property_read_u32(np, "core_balance", &pdata->core_balance);
+
+	/* MFC IOVA threshold */
+	of_property_read_u32(np, "iova_threshold", &pdata->iova_threshold);
+
+	/* MFC idle clock control */
+	of_property_read_u32(np, "idle_clk_ctrl", &pdata->idle_clk_ctrl);
+
+	/* QoS level for pm_qos dynamic control */
+	of_property_read_u32(np, "qos_ctrl_level", &pdata->qos_ctrl_level);
+
+	/* Memlog size */
+	of_property_read_u32(np, "memlog_size", &pdata->memlog_size);
+	of_property_read_u32(np, "memlog_sfr_size", &pdata->memlog_sfr_size);
+
+	/* offset for saving result of regression */
+	of_property_read_u32
+			(np, "reg_h264_loop_filter_disable",
+			&pdata->reg_h264_loop_filter_disable);
 
 	/* Scheduler */
 	of_property_read_u32(np, "scheduler", &pdata->scheduler);
 	of_property_read_u32(np, "pbs_num_prio", &pdata->pbs_num_prio);
 
+	of_property_read_u32(np, "support_mv_hevc", &pdata->support_mv_hevc);
+
 	return 0;
 }
 
@@ -341,6 +717,11 @@ static struct video_device *__mfc_video_device_register
 	vfd->minor = -1;
 	vfd->release = video_device_release;
 
+	if (IS_DEC_NODE(node_num))
+		vfd->ioctl_ops = mfc_get_dec_v4l2_ioctl_ops();
+	else if (IS_ENC_NODE(node_num))
+		vfd->ioctl_ops = NULL;
+
 	vfd->lock = &dev->mfc_mutex;
 	vfd->v4l2_dev = &dev->v4l2_dev;
 	vfd->vfl_dir = VFL_DIR_M2M;
@@ -413,6 +794,7 @@ static int mfc_probe(struct platform_device *pdev)
 	dma_set_mask(&pdev->dev, DMA_BIT_MASK(dev->pdata->dma_bit_mask));
 
 	mutex_init(&dev->mfc_mutex);
+	mutex_init(&dev->mfc_migrate_mutex);
 
 	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
 	if (ret)
@@ -437,6 +819,24 @@ static int mfc_probe(struct platform_device *pdev)
 	}
 	/* end of node setting*/
 
+	/* instance migration worker */
+	dev->migration_wq = alloc_workqueue("mfc/inst_migration", WQ_UNBOUND
+					| WQ_MEM_RECLAIM | WQ_HIGHPRI, 1);
+	if (!dev->migration_wq) {
+		dev_err(&pdev->dev, "failed to create workqueue for migration wq\n");
+		goto err_migration_work;
+	}
+	INIT_WORK(&dev->migration_work, mfc_rm_migration_worker);
+
+	/* main butler worker */
+	dev->butler_wq = alloc_workqueue("mfc/butler", WQ_UNBOUND
+					| WQ_MEM_RECLAIM | WQ_HIGHPRI, 1);
+	if (!dev->butler_wq) {
+		dev_err(&pdev->dev, "failed to create workqueue for butler\n");
+		goto err_butler_wq;
+	}
+	INIT_WORK(&dev->butler_work, mfc_butler_worker);
+
 	/* for DVA reservation */
 	if (dev->pdata->reserved_start) {
 		dev->domain = iommu_get_domain_for_dev(dev->device);
@@ -461,6 +861,10 @@ static int mfc_probe(struct platform_device *pdev)
 
 /* Deinit MFC if probe had failed */
 err_iova_reserve:
+	destroy_workqueue(dev->butler_wq);
+err_butler_wq:
+	destroy_workqueue(dev->migration_wq);
+err_migration_work:
 	video_unregister_device(dev->vfd_enc);
 alloc_vdev_enc:
 	video_unregister_device(dev->vfd_dec);
@@ -468,6 +872,7 @@ static int mfc_probe(struct platform_device *pdev)
 	v4l2_device_unregister(&dev->v4l2_dev);
 err_v4l2_dev:
 	mutex_destroy(&dev->mfc_mutex);
+	mutex_destroy(&dev->mfc_migrate_mutex);
 err_res_mem:
 	return ret;
 }
@@ -482,6 +887,10 @@ static void mfc_remove(struct platform_device *pdev)
 	platform_driver_unregister(&mfc_core_driver);
 	mfc_unconfigure_dma_memory(dev);
 	of_reserved_mem_device_release(dev->device);
+	flush_workqueue(dev->butler_wq);
+	destroy_workqueue(dev->butler_wq);
+	flush_workqueue(dev->migration_wq);
+	destroy_workqueue(dev->migration_wq);
 
 	mfc_deinit_debugfs(dev);
 	video_unregister_device(dev->vfd_enc);
@@ -665,6 +1074,7 @@ static const struct dev_pm_ops mfc_pm_ops = {
 
 struct mfc_ctx_buf_size mfc_ctx_buf_size = {
 	.dev_ctx	= PAGE_ALIGN(0x7800),	/*  30KB */
+	.h264_dec_ctx	= PAGE_ALIGN(0x200000),	/* 1.6MB */
 	.dbg_info_buf	= PAGE_ALIGN(0x1000),	/* 4KB for DEBUG INFO */
 };
 
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_debugfs.c b/drivers/media/platform/samsung/exynos-mfc/mfc_debugfs.c
index 5baa76a6b405..59cd6f3945ff 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc_debugfs.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc_debugfs.c
@@ -14,18 +14,34 @@
 
 #include "mfc_debugfs.h"
 
+#include "base/mfc_queue.h"
+
 static int __mfc_info_show(struct seq_file *s, void *unused)
 {
 	struct mfc_dev *dev = s->private;
 	struct mfc_core *core = NULL;
+	struct mfc_ctx *ctx = NULL;
 	struct mfc_core_ctx *core_ctx = NULL;
 	int i, j;
+	char *codec_name = NULL, *fmt_name = NULL;
 
 	seq_puts(s, ">>> MFC common device information\n");
 	seq_printf(s, " [DEBUG MODE] dt: %s sysfs: %s\n",
 		   dev->pdata->debug_mode ? "enabled" : "disabled",
 		   dev->debugfs.debug_mode_en ? "enabled" : "disabled");
-
+	seq_printf(s, " [FEATURES] skype: %d(0x%x), black_bar: %d(0x%x)\n",
+		   dev->pdata->skype.support, dev->pdata->skype.version,
+		   dev->pdata->black_bar.support,
+		   dev->pdata->black_bar.version);
+	seq_printf(s, "           color_aspect_dec: %d(0x%x)\n",
+		   dev->pdata->color_aspect_dec.support,
+		   dev->pdata->color_aspect_dec.version);
+	seq_printf(s, "           static_info_dec: %d(0x%x)\n",
+		   dev->pdata->static_info_dec.support,
+		   dev->pdata->static_info_dec.version);
+	seq_printf(s, " [FORMATS] 10bit: %s, 422: %s\n",
+		   dev->pdata->support_10bit ? "supported" : "not supported",
+		   dev->pdata->support_422 ? "supported" : "not supported");
 	seq_printf(s, " [LOWMEM] is_low_mem: %d\n", IS_LOW_MEM);
 
 	for (j = 0; j < dev->num_core; j++) {
@@ -54,9 +70,46 @@ static int __mfc_info_show(struct seq_file *s, void *unused)
 		for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
 			core_ctx = core->core_ctx[i];
 			if (core_ctx) {
-				seq_printf(s, "    [CORECTX:%d] state: %d\n",
-					   i, core_ctx->state);
+				seq_printf(s, "    [CORECTX:%d] state: %d, queue(src: %d, dst: %d)\n",
+					   i, core_ctx->state,
+					   mfc_get_queue_count(&core_ctx->ctx->buf_queue_lock,
+							       &core_ctx->src_buf_queue),
+					   mfc_get_queue_count(&core_ctx->ctx->buf_queue_lock,
+							       &core_ctx->dst_buf_queue));
+			}
+		}
+	}
+	seq_puts(s, ">>> MFC instance information\n");
+	for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
+		ctx = dev->ctx[i];
+		if (ctx) {
+			if (ctx->type == MFCINST_DECODER) {
+				codec_name = ctx->src_fmt->name;
+				fmt_name = ctx->dst_fmt->name;
+			} else {
+				codec_name = ctx->dst_fmt->name;
+				fmt_name = ctx->src_fmt->name;
 			}
+
+			seq_printf(s, "  [CTX:%d] %s%s %s, size: %dx%d@...fps(ts: %lufps, tmu: %dfps, op: %lufps), crop: %d %d %d %d\n",
+				   ctx->num, codec_name, ctx->multi_view_enable ? "(MV-HEVC)" : "",
+				   fmt_name,
+				   ctx->img_width, ctx->img_height,
+				   ctx->framerate / 1000,
+				   ctx->last_framerate / 1000,
+				   ctx->dev->tmu_fps,
+				   ctx->operating_framerate,
+				   ctx->crop_width, ctx->crop_height,
+				   ctx->crop_left, ctx->crop_top);
+			seq_printf(s, "        main core: %d, op_mode: %d(stream: %d), idle_mode: %d, prio %d, rt %d, queue(src: %d, dst: %d, ref: %d)\n",
+				   ctx->op_core_num[MFC_CORE_MAIN],
+				   ctx->op_mode, ctx->stream_op_mode, ctx->idle_mode,
+				   ctx->prio, ctx->rt,
+				   mfc_get_queue_count(&ctx->buf_queue_lock,
+						       &ctx->src_buf_ready_queue),
+				   mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
+				   mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue));
+			seq_puts(s, "\n");
 		}
 	}
 
@@ -175,6 +228,7 @@ void mfc_init_debugfs(struct mfc_dev *dev)
 	debugfs_create_u32("sfr_dump", 0644, debugfs->root, &dev->debugfs.sfr_dump);
 
 	debugfs_create_u32("feature_option", 0644, debugfs->root, &dev->debugfs.feature_option);
+	debugfs_create_u32("core_balance", 0644, debugfs->root, &dev->debugfs.core_balance);
 	debugfs_create_u32("logging_option", 0644, debugfs->root, &dev->debugfs.logging_option);
 	debugfs_create_u32("sched_perf_disable", 0644,
 			   debugfs->root, &dev->debugfs.sched_perf_disable);
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ