obj-$(CONFIG_VIDEO_EXYNOS_MFC) := s5p-mfc.o
s5p-mfc-y += s5p_mfc.o s5p_mfc_irq.o s5p_mfc_dec.o s5p_mfc_dec_vb2_ops.o s5p_mfc_enc.o s5p_mfc_enc_vb2_ops.o
s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_hwlock.o s5p_mfc_nal_q.o s5p_mfc_watchdog.o s5p_mfc_opr.o s5p_mfc_sync.o
-s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_inst.o s5p_mfc_cmd.o s5p_mfc_cal.o s5p_mfc_reg.o
+s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_inst.o s5p_mfc_cmd.o s5p_mfc_cal.o s5p_mfc_reg.o s5p_mfc_perf_measure.o
s5p-mfc-y += s5p_mfc_dec_ops.o s5p_mfc_enc_ops.o s5p_mfc_enc_param.o
s5p-mfc-y += s5p_mfc_queue.o s5p_mfc_buf.o s5p_mfc_utils.o s5p_mfc_qos.o s5p_mfc_mem.o
s5p-mfc-y += s5p_mfc_debugfs.o s5p_mfc_otf.o
#include "s5p_mfc_inst.h"
#include "s5p_mfc_pm.h"
#include "s5p_mfc_cal.h"
+#include "s5p_mfc_perf_measure.h"
#include "s5p_mfc_reg.h"
#include "s5p_mfc_qos.h"
goto err_init_inst;
}
+ s5p_mfc_perf_init(dev);
trace_mfc_node_open(ctx->num, dev->num_inst, ctx->type, ctx->is_drm);
mfc_info_ctx("MFC open completed [%d:%d] dev = 0x%p, ctx = 0x%p, version = %d\n",
dev->num_drm_inst, dev->num_inst, dev, ctx, MFC_DRIVER_INFO);
dev->ctx[ctx->num] = 0;
kfree(ctx);
+ s5p_mfc_perf_print();
+
mfc_info_dev("mfc driver release finished [%d:%d], dev = 0x%p\n",
dev->num_drm_inst, dev->num_inst, dev);
struct resource *res;
int ret;
+ s5p_mfc_perf_register(dev);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(&pdev->dev, "failed to get memory region resource\n");
struct dentry *nal_q_disable;
struct dentry *nal_q_parallel_disable;
struct dentry *otf_dump;
+ struct dentry *perf_measure_option;
};
/**
};
/********************************************************************/
+struct s5p_mfc_perf {
+ void __iomem *regs_base0;
+ void __iomem *regs_base1;
+
+ struct timeval begin;
+ struct timeval end;
+
+ int new_start;
+ int count;
+ int drv_margin;
+};
+
/**
* struct s5p_mfc_dev - The struct containing driver internal parameters.
*/
#endif
struct s5p_mfc_debugfs debugfs;
+
+ struct s5p_mfc_perf perf;
};
/**
unsigned int nal_q_disable;
unsigned int nal_q_parallel_disable;
unsigned int otf_dump;
+unsigned int perf_measure_option;
static int mfc_info_show(struct seq_file *s, void *unused)
{
0644, debugfs->root, &nal_q_parallel_disable);
debugfs->otf_dump = debugfs_create_u32("otf_dump",
0644, debugfs->root, &otf_dump);
+ debugfs->perf_measure_option = debugfs_create_u32("perf_measure_option",
+ 0644, debugfs->root, &perf_measure_option);
}
#include "s5p_mfc_cmd.h"
#include "s5p_mfc_enc_param.h"
#include "s5p_mfc_cal.h"
+#include "s5p_mfc_perf_measure.h"
#include "s5p_mfc_reg.h"
#include "s5p_mfc_utils.h"
* is the last frame or not. */
switch (last_frame) {
case 0:
+ s5p_mfc_perf_measure_on(dev);
+
s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_NAL_START);
break;
case 1:
* is the last frame or not. */
switch (last_frame) {
case 0:
+ s5p_mfc_perf_measure_on(dev);
+
s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_NAL_START);
break;
case 1:
#include "s5p_mfc_pm.h"
#include "s5p_mfc_cal.h"
+#include "s5p_mfc_perf_measure.h"
#include "s5p_mfc_reg.h"
#include "s5p_mfc_qos.h"
dev->curr_ctx, reason, err);
MFC_TRACE_CTX("<< INT(top): %d\n", reason);
+ s5p_mfc_perf_measure_off(dev);
+
return IRQ_WAKE_THREAD;
}
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.c
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "s5p_mfc_perf_measure.h"
+
+#ifndef PERF_MEASURE
+
+void s5p_mfc_perf_register(struct s5p_mfc_dev *dev) {}
+void mfc_measure_init(void) {}
+void mfc_measure_on(struct s5p_mfc_dev *dev) {}
+void mfc_measure_off(struct s5p_mfc_dev *dev) {}
+void mfc_measure_store(struct s5p_mfc_dev *dev, int diff) {}
+void s5p_mfc_perf_print(void) {}
+
+#else
+
+#endif
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.h
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __S5P_MFC_PERF_MEASURE_H
+#define __S5P_MFC_PERF_MEASURE_H __FILE__
+
+#include <linux/clk.h>
+
+#include "s5p_mfc_reg.h"
+
+void s5p_mfc_perf_register(struct s5p_mfc_dev *dev);
+void mfc_measure_init(void);
+void mfc_measure_on(struct s5p_mfc_dev *dev);
+void mfc_measure_off(struct s5p_mfc_dev *dev);
+void mfc_measure_store(struct s5p_mfc_dev *dev, int diff);
+void s5p_mfc_perf_print(void);
+
+//#define PERF_MEASURE
+
+#ifndef PERF_MEASURE
+
+static inline void s5p_mfc_perf_init(struct s5p_mfc_dev *dev) {}
+static inline void s5p_mfc_perf_cancel_drv_margin(struct s5p_mfc_dev *dev) {}
+static inline void s5p_mfc_perf_measure_on(struct s5p_mfc_dev *dev) {}
+static inline void s5p_mfc_perf_measure_off(struct s5p_mfc_dev *dev) {}
+
+#else
+
+extern unsigned int perf_measure_option;
+
+static inline void s5p_mfc_perf_init(struct s5p_mfc_dev *dev)
+{
+ dev->perf.new_start = 0;
+ dev->perf.count = 0;
+ dev->perf.drv_margin = 0;
+
+ mfc_measure_init();
+
+ mfc_info_dev("MFC frequency : %ld\n", clk_get_rate(dev->pm.clock));
+}
+
+static inline void s5p_mfc_perf_cancel_drv_margin(struct s5p_mfc_dev *dev)
+{
+ dev->perf.drv_margin = 0;
+}
+
+static inline void s5p_mfc_perf_measure_on(struct s5p_mfc_dev *dev)
+{
+ int diff;
+
+ if (dev->perf.drv_margin) {
+ do_gettimeofday(&dev->perf.end);
+
+ diff = (dev->perf.end.tv_sec * 1000000 + dev->perf.end.tv_usec)
+ - (dev->perf.begin.tv_sec * 1000000 + dev->perf.begin.tv_usec);
+
+ mfc_info_dev("IRQ -> NAL_START time(ms) = %03d.%03d\n", diff / 1000, diff % 1000);
+
+ dev->perf.drv_margin = 0;
+ }
+
+ do_gettimeofday(&dev->perf.begin);
+
+ mfc_measure_on(dev);
+
+ dev->perf.new_start = 1;
+ dev->perf.count++;
+}
+
+static inline void s5p_mfc_perf_measure_off(struct s5p_mfc_dev *dev)
+{
+ unsigned int diff;
+
+ if ((dev->perf.new_start) && (dev->perf.count > 0)) {
+ mfc_measure_off(dev);
+
+ do_gettimeofday(&dev->perf.end);
+
+ diff = (dev->perf.end.tv_sec * 1000000 + dev->perf.end.tv_usec)
+ - (dev->perf.begin.tv_sec * 1000000 + dev->perf.begin.tv_usec);
+
+ mfc_measure_store(dev, diff);
+
+ mfc_debug(3, "uDECtype :%d, uENCtype :%d, codectype :%d\n",
+ s5p_mfc_get_dec_frame_type(), s5p_mfc_get_enc_slice_type(), MFC_READL(S5P_FIMV_CODEC_TYPE));
+
+ dev->perf.drv_margin = 1;
+
+ do_gettimeofday(&dev->perf.begin);
+ }
+
+ dev->perf.new_start = 0;
+}
+
+#endif
+
+#endif /* __S5P_MFC_PERF_MEASURE_H */
#include "s5p_mfc_sync.h"
+#include "s5p_mfc_perf_measure.h"
+
#include "s5p_mfc_queue.h"
#define R2H_BIT(x) (((x) > 0) ? (1 << ((x) - 1)) : 0)
src_buf_queue_greater_than_0)
return 1;
+ s5p_mfc_perf_cancel_drv_margin(dev);
mfc_debug(2, "ctx is not ready.\n");
return 0;
src_buf_queue_greater_than_0 && dst_buf_queue_greater_than_0)
return 1;
+ s5p_mfc_perf_cancel_drv_margin(dev);
mfc_debug(2, "ctx is not ready.\n");
return 0;