ret = mfc_init_instance(dev, ctx);
if (ret)
goto err_init_inst;
+
+ if (perf_boost_mode)
+ s5p_mfc_perf_boost_enable(dev);
}
#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
if (dev->num_inst == 0) {
s5p_mfc_deinit_hw(dev);
+
+ if (perf_boost_mode)
+ s5p_mfc_perf_boost_disable(dev);
+
del_timer_sync(&dev->watchdog_timer);
flush_workqueue(dev->butler_wq);
of_property_read_u32(np_qos, "freq_mfc", &qosdata->freq_mfc);
of_property_read_u32(np_qos, "freq_int", &qosdata->freq_int);
of_property_read_u32(np_qos, "freq_mif", &qosdata->freq_mif);
- of_property_read_u32(np_qos, "freq_cpu", &qosdata->freq_cpu);
- of_property_read_u32(np_qos, "freq_kfc", &qosdata->freq_kfc);
of_property_read_u32(np_qos, "mo_value", &qosdata->mo_value);
of_property_read_u32(np_qos, "mo_10bit_value", &qosdata->mo_10bit_value);
of_property_read_u32(np_qos, "mo_uhd_enc60_value", &qosdata->mo_uhd_enc60_value);
{
struct s5p_mfc_platdata *pdata = mfc->pdata;
#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+ struct device_node *np_qos;
char node_name[50];
int i;
#endif
snprintf(node_name, sizeof(node_name), "mfc_qos_variant_%d", i);
mfc_parse_mfc_qos_platdata(np, node_name, &pdata->qos_table[i]);
}
+
+ /* performance boost mode */
+ pdata->qos_boost_table = devm_kzalloc(mfc->device,
+ sizeof(struct s5p_mfc_qos_boost), GFP_KERNEL);
+ np_qos = of_find_node_by_name(np, "mfc_perf_boost_table");
+ if (!np_qos) {
+ pr_err("%s: could not find mfc_perf_boost_table node\n", node_name);
+ return;
+ }
+ of_property_read_u32(np_qos, "num_cluster", &pdata->qos_boost_table->num_cluster);
+ of_property_read_u32(np_qos, "freq_mfc", &pdata->qos_boost_table->freq_mfc);
+ of_property_read_u32(np_qos, "freq_int", &pdata->qos_boost_table->freq_int);
+ of_property_read_u32(np_qos, "freq_mif", &pdata->qos_boost_table->freq_mif);
+ of_property_read_u32_array(np_qos, "freq_cluster", &pdata->qos_boost_table->freq_cluster[0],
+ pdata->qos_boost_table->num_cluster);
#endif
}
#define MAX_NUM_IMAGES_IN_VB 8
#define MAX_NUM_BUFCON_BUFS 32
+#define MAX_NUM_CLUSTER 3
/*
* MFC region id for smc
struct dentry *sfr_dump;
struct dentry *mmcache_dump;
struct dentry *mmcache_disable;
+ struct dentry *perf_boost_mode;
};
/**
unsigned int freq_mfc;
unsigned int freq_int;
unsigned int freq_mif;
- unsigned int freq_cpu;
- unsigned int freq_kfc;
unsigned int mo_value;
unsigned int mo_10bit_value;
unsigned int mo_uhd_enc60_value;
unsigned int time_fw;
};
+
+struct s5p_mfc_qos_boost {
+ unsigned int num_cluster;
+ unsigned int freq_mfc;
+ unsigned int freq_int;
+ unsigned int freq_mif;
+ unsigned int freq_cluster[MAX_NUM_CLUSTER];
+};
#endif
struct s5p_mfc_feature {
unsigned int mo_control;
unsigned int bw_control;
struct s5p_mfc_qos *qos_table;
+ struct s5p_mfc_qos_boost *qos_boost_table;
#endif
};
struct pm_qos_request qos_req_mfc;
struct pm_qos_request qos_req_int;
struct pm_qos_request qos_req_mif;
-#ifdef CONFIG_ARM_EXYNOS_MP_CPUFREQ
- struct pm_qos_request qos_req_cluster1;
- struct pm_qos_request qos_req_cluster0;
-#endif
+ struct pm_qos_request qos_req_cluster[MAX_NUM_CLUSTER];
int qos_has_enc_ctx;
#endif
int id;
extern unsigned int sfr_dump;
extern unsigned int mmcache_dump;
extern unsigned int mmcache_disable;
+extern unsigned int perf_boost_mode;
#define mfc_debug(level, fmt, args...) \
do { \
unsigned int sfr_dump;
unsigned int mmcache_dump;
unsigned int mmcache_disable;
+unsigned int perf_boost_mode;
static int mfc_info_show(struct seq_file *s, void *unused)
{
seq_printf(s, "[MMCACHE] %s(%s)\n",
dev->has_mmcache ? "supported" : "not supported",
dev->mmcache.is_on_status ? "enabled" : "disabled");
+ seq_printf(s, "[PERF BOOST] %s\n", perf_boost_mode ? "enabled" : "disabled");
seq_printf(s, "[FEATURES] nal_q: %d(0x%x), skype: %d(0x%x), black_bar: %d(0x%x)\n",
dev->pdata->nal_q.support, dev->pdata->nal_q.version,
dev->pdata->skype.support, dev->pdata->skype.version,
seq_puts(s, "64 (1 << 6): ERR interrupt\n");
seq_puts(s, "128 (1 << 7): WARN interrupt\n");
+ seq_puts(s, "-----Performance boost options (bit setting)\n");
+ seq_puts(s, "ex) echo 7 > /d/mfc/perf_boost_mode (max freq)\n");
+ seq_puts(s, "1 (1 << 0): DVFS (INT/MFC/MIF)\n");
+ seq_puts(s, "2 (1 << 1): MO value\n");
+ seq_puts(s, "4 (1 << 2): CPU frequency\n");
+
return 0;
}
0644, debugfs->root, &mmcache_dump);
debugfs->mmcache_disable = debugfs_create_u32("mmcache_disable",
0644, debugfs->root, &mmcache_disable);
+ debugfs->perf_boost_mode = debugfs_create_u32("perf_boost_mode",
+ 0644, debugfs->root, &perf_boost_mode);
}
MFC_QOS_BW,
};
+enum {
+ MFC_PERF_BOOST_DVFS = (1 << 0),
+ MFC_PERF_BOOST_MO = (1 << 1),
+ MFC_PERF_BOOST_CPU = (1 << 2),
+};
+
+void s5p_mfc_perf_boost_enable(struct s5p_mfc_dev *dev)
+{
+ struct s5p_mfc_platdata *pdata = dev->pdata;
+ struct s5p_mfc_qos_boost *qos_boost_table = pdata->qos_boost_table;
+ int i;
+
+ if (perf_boost_mode & MFC_PERF_BOOST_DVFS) {
+ if (pdata->mfc_freq_control)
+ pm_qos_add_request(&dev->qos_req_mfc, PM_QOS_MFC_THROUGHPUT,
+ qos_boost_table->freq_mfc);
+ pm_qos_add_request(&dev->qos_req_int, PM_QOS_DEVICE_THROUGHPUT,
+ qos_boost_table->freq_int);
+ pm_qos_add_request(&dev->qos_req_mif, PM_QOS_BUS_THROUGHPUT,
+ qos_boost_table->freq_mif);
+ mfc_debug(3, "[QoS][perf_boost] DVFS mfc: %d, int:%d, mif:%d\n",
+ qos_boost_table->freq_mfc, qos_boost_table->freq_int,
+ qos_boost_table->freq_mif);
+ }
+
+#ifdef CONFIG_EXYNOS_BTS
+ if (perf_boost_mode & MFC_PERF_BOOST_MO) {
+ if (pdata->mo_control) {
+ bts_update_scen(BS_MFC_UHD_10BIT, 1);
+ mfc_debug(3, "[QoS][perf_boost] BTS(MO): UHD_10BIT\n");
+ }
+ }
+#endif
+
+ if (perf_boost_mode & MFC_PERF_BOOST_CPU) {
+ for (i = 0; i < qos_boost_table->num_cluster; i++) {
+ pm_qos_add_request(&dev->qos_req_cluster[i], PM_QOS_CLUSTER0_FREQ_MIN + (i * 2),
+ qos_boost_table->freq_cluster[i]);
+ mfc_debug(3, "[QoS][perf_boost] CPU cluster[%d]: %d\n",
+ i, qos_boost_table->freq_cluster[i]);
+ }
+ }
+}
+
+void s5p_mfc_perf_boost_disable(struct s5p_mfc_dev *dev)
+{
+ struct s5p_mfc_platdata *pdata = dev->pdata;
+ int i;
+
+ if (perf_boost_mode & MFC_PERF_BOOST_DVFS) {
+ if (pdata->mfc_freq_control)
+ pm_qos_remove_request(&dev->qos_req_mfc);
+ pm_qos_remove_request(&dev->qos_req_int);
+ pm_qos_remove_request(&dev->qos_req_mif);
+ mfc_debug(3, "[QoS][perf_boost] DVFS off\n");
+ }
+
+#ifdef CONFIG_EXYNOS_BTS
+ if (perf_boost_mode & MFC_PERF_BOOST_MO) {
+ if (pdata->mo_control) {
+ bts_update_scen(BS_MFC_UHD_10BIT, 0);
+ mfc_debug(3, "[QoS][perf_boost] BTS(MO) off\n");
+ }
+ }
+#endif
+
+ if (perf_boost_mode & MFC_PERF_BOOST_CPU) {
+ for (i = 0; i < pdata->qos_boost_table->num_cluster; i++) {
+ pm_qos_remove_request(&dev->qos_req_cluster[i]);
+ mfc_debug(3, "[QoS][perf_boost] CPU cluster[%d] off\n", i);
+ }
+ }
+}
+
static void mfc_qos_operate(struct s5p_mfc_ctx *ctx, int opr_type, int idx)
{
struct s5p_mfc_dev *dev = ctx->dev;
PM_QOS_BUS_THROUGHPUT,
qos_table[idx].freq_mif);
-#ifdef CONFIG_ARM_EXYNOS_MP_CPUFREQ
- pm_qos_add_request(&dev->qos_req_cluster1,
- PM_QOS_CLUSTER1_FREQ_MIN,
- qos_table[idx].freq_cpu);
- pm_qos_add_request(&dev->qos_req_cluster0,
- PM_QOS_CLUSTER0_FREQ_MIN,
- qos_table[idx].freq_kfc);
-#endif
-
#ifdef CONFIG_EXYNOS_BTS
if (pdata->mo_control) {
bts_update_scen(BS_MFC_UHD_ENC60, qos_table[idx].mo_uhd_enc60_value);
pm_qos_update_request(&dev->qos_req_mif,
qos_table[idx].freq_mif);
-#ifdef CONFIG_ARM_EXYNOS_MP_CPUFREQ
- pm_qos_update_request(&dev->qos_req_cluster1,
- qos_table[idx].freq_cpu);
- pm_qos_update_request(&dev->qos_req_cluster0,
- qos_table[idx].freq_kfc);
-#endif
-
#ifdef CONFIG_EXYNOS_BTS
if (pdata->mo_control) {
bts_update_scen(BS_MFC_UHD_ENC60, qos_table[idx].mo_uhd_enc60_value);
pm_qos_remove_request(&dev->qos_req_int);
pm_qos_remove_request(&dev->qos_req_mif);
-#ifdef CONFIG_ARM_EXYNOS_MP_CPUFREQ
- pm_qos_remove_request(&dev->qos_req_cluster1);
- pm_qos_remove_request(&dev->qos_req_cluster0);
-#endif
-
#ifdef CONFIG_EXYNOS_BTS
if (pdata->mo_control) {
bts_update_scen(BS_MFC_UHD_ENC60, 0);
struct bts_bw mfc_bw, mfc_bw_ctx;
#endif
+ if (perf_boost_mode) {
+ mfc_info_ctx("[QoS][perf_boost] skip control\n");
+ return;
+ }
+
list_for_each_entry(qos_ctx, &dev->qos_queue, qos_list)
if (qos_ctx == ctx)
found = 1;
struct bts_bw mfc_bw, mfc_bw_ctx;
#endif
+ if (perf_boost_mode) {
+ mfc_info_ctx("[QoS][perf_boost] skip control\n");
+ return;
+ }
+
if (list_empty(&dev->qos_queue)) {
if (atomic_read(&dev->qos_req_cur) != 0) {
mfc_err_ctx("MFC request count is wrong!\n");
#define MFC_QOS_WEIGHT_NUM_OF_TILE 75
#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+void s5p_mfc_perf_boost_enable(struct s5p_mfc_dev *dev);
+void s5p_mfc_perf_boost_disable(struct s5p_mfc_dev *dev);
void s5p_mfc_qos_on(struct s5p_mfc_ctx *ctx);
void s5p_mfc_qos_off(struct s5p_mfc_ctx *ctx);
#else
-#define s5p_mfc_qos_on(ctx) do {} while (0)
-#define s5p_mfc_qos_off(ctx) do {} while (0)
+#define s5p_mfc_perf_boost_enable(dev) do {} while (0)
+#define s5p_mfc_perf_boost_disable(dev) do {} while (0)
+#define s5p_mfc_qos_on(ctx) do {} while (0)
+#define s5p_mfc_qos_off(ctx) do {} while (0)
#endif
void s5p_mfc_qos_update_framerate(struct s5p_mfc_ctx *ctx);
dev->hwlock.bits, dev->hwlock.dev,
dev->curr_ctx, dev->curr_ctx_is_drm,
dev->preempt_ctx, s5p_mfc_get_bits(&dev->work_bits));
+ pr_err("options debug_level:%d, debug_mode:%d, mmcache:%d, perf_boost:%d\n",
+ debug_level, dev->pdata->debug_mode, dev->mmcache.is_on_status, perf_boost_mode);
pr_err("NAL-Q state:%d, exception:%d, in_exe_cnt: %d, out_exe_cnt: %d\n",
nal_q_handle->nal_q_state, nal_q_handle->nal_q_exception,
nal_q_handle->nal_q_in_handle->in_exe_count,