mirror of
https://github.com/hardkernel/kernel_common_drivers.git
synced 2026-06-25 12:03:48 +09:00
ge2d: add support for bandwidth adjustment [1/1]
PD#SWPL-151150 Problem: flickering screen occurs while playing images during rotation. Solution: use ge2d on and off mode to control the ratio between hardware processing and idle states Verify: t5 Change-Id: I4b45e5d9636310630092f09ddc5946a298277e1d Signed-off-by: Jian Cao <jian.cao@amlogic.com>
This commit is contained in:
committed by
gerrit autosubmit
parent
09b8bb6fe3
commit
cac0610c87
@@ -102,6 +102,12 @@ static ssize_t dump_reg_cnt_show(struct class *cla,
|
||||
static ssize_t dump_reg_cnt_store(struct class *cla,
|
||||
struct class_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
static ssize_t onoff_mode_show(struct class *cla,
|
||||
struct class_attribute *attr,
|
||||
char *buf);
|
||||
static ssize_t onoff_mode_store(struct class *cla,
|
||||
struct class_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
|
||||
static const struct file_operations ge2d_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
@@ -118,6 +124,7 @@ static CLASS_ATTR_RO(free_queue_status);
|
||||
static CLASS_ATTR_RW(log_level);
|
||||
static CLASS_ATTR_RW(dump_reg_enable);
|
||||
static CLASS_ATTR_RW(dump_reg_cnt);
|
||||
static CLASS_ATTR_RW(onoff_mode);
|
||||
|
||||
static struct attribute *ge2d_class_attrs[] = {
|
||||
&class_attr_work_queue_status.attr,
|
||||
@@ -125,6 +132,7 @@ static struct attribute *ge2d_class_attrs[] = {
|
||||
&class_attr_log_level.attr,
|
||||
&class_attr_dump_reg_enable.attr,
|
||||
&class_attr_dump_reg_cnt.attr,
|
||||
&class_attr_onoff_mode.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(ge2d_class);
|
||||
@@ -146,6 +154,45 @@ static struct timer_data_s timer_data;
|
||||
#define TIMER_MS (2000)
|
||||
#endif
|
||||
|
||||
static int parse_para(const char *para, int para_num, int *result)
|
||||
{
|
||||
char *token = NULL;
|
||||
char *params, *params_base;
|
||||
int *out = result;
|
||||
int len = 0, count = 0;
|
||||
int res = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!para)
|
||||
return 0;
|
||||
|
||||
params = kstrdup(para, GFP_KERNEL);
|
||||
params_base = params;
|
||||
token = params;
|
||||
if (!token)
|
||||
return 0;
|
||||
len = strlen(token);
|
||||
do {
|
||||
token = strsep(¶ms, " ");
|
||||
while (token && (isspace(*token) ||
|
||||
!isgraph(*token)) && len) {
|
||||
token++;
|
||||
len--;
|
||||
}
|
||||
if (len == 0 || !token)
|
||||
break;
|
||||
ret = kstrtoint(token, 0, &res);
|
||||
if (ret < 0)
|
||||
break;
|
||||
len = strlen(token);
|
||||
*out++ = res;
|
||||
count++;
|
||||
} while ((token) && (count < para_num) && (len > 0));
|
||||
|
||||
kfree(params_base);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t dump_reg_enable_show(struct class *cla,
|
||||
struct class_attribute *attr,
|
||||
char *buf)
|
||||
@@ -209,6 +256,35 @@ static ssize_t log_level_store(struct class *cla,
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t onoff_mode_show(struct class *cla,
|
||||
struct class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
u32 onoff_mode, on_cnt, off_cnt;
|
||||
|
||||
ge2d_get_onoff_mode(&onoff_mode, &on_cnt, &off_cnt);
|
||||
|
||||
return snprintf(buf, 80, "onoff_mode:%u on_cnt:%u off_cnt:%u\n",
|
||||
onoff_mode, on_cnt, off_cnt);
|
||||
}
|
||||
|
||||
static ssize_t onoff_mode_store(struct class *cla,
|
||||
struct class_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
u32 parsed[3];
|
||||
|
||||
if (likely(parse_para(buf, 3, parsed) == 3)) {
|
||||
ge2d_set_onoff_mode(parsed[0], parsed[1], parsed[2]);
|
||||
ge2d_log_info("onoff_mode:%u on_cnt:%u off_cnt:%u\n",
|
||||
parsed[0], parsed[1], parsed[2]);
|
||||
} else {
|
||||
ge2d_log_err("usage: echo onoff_mode on_cnt off_cnt > onoff_mode\n");
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int ge2d_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct ge2d_context_s *context = NULL;
|
||||
@@ -447,6 +523,7 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
|
||||
struct config_para_ex_ion_s *ge2d_config_ex_ion;
|
||||
struct ge2d_dmabuf_req_s ge2d_req_buf;
|
||||
struct ge2d_dmabuf_exp_s ge2d_exp_buf;
|
||||
struct ge2d_onoff_mode_para_s ge2d_onoff_mode;
|
||||
int ret = 0;
|
||||
#ifdef CONFIG_COMPAT
|
||||
struct compat_config_para_s __user *uf;
|
||||
@@ -475,6 +552,7 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
|
||||
memset(&ge2d_config, 0, sizeof(struct config_para_s));
|
||||
memset(&ge2d_req_buf, 0, sizeof(struct ge2d_dmabuf_req_s));
|
||||
memset(&ge2d_exp_buf, 0, sizeof(struct ge2d_dmabuf_exp_s));
|
||||
memset(&ge2d_onoff_mode, 0, sizeof(struct ge2d_onoff_mode_para_s));
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_GE2D_MORE_SECURITY
|
||||
switch (cmd) {
|
||||
case GE2D_CONFIG:
|
||||
@@ -864,6 +942,15 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
|
||||
pr_err("ioctl not support yed.\n");
|
||||
ret = -EINVAL;
|
||||
goto release1;
|
||||
case GE2D_SET_ONOFF_MODE:
|
||||
ret = copy_from_user(&ge2d_onoff_mode, argp,
|
||||
sizeof(struct ge2d_onoff_mode_para_s));
|
||||
if (ret < 0) {
|
||||
pr_err("Error user param, %s %d\n", __func__, __LINE__);
|
||||
ret = -EINVAL;
|
||||
goto release1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = copy_from_user(¶, argp, sizeof(struct ge2d_para_s));
|
||||
break;
|
||||
@@ -1097,6 +1184,19 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
|
||||
case GE2D_DETACH_DMA_FD:
|
||||
ge2d_ioctl_detach_dma_fd(context, data_type);
|
||||
break;
|
||||
case GE2D_SET_ONOFF_MODE:
|
||||
ret = ge2d_set_onoff_mode(ge2d_onoff_mode.onoff_mode,
|
||||
ge2d_onoff_mode.on_cnt,
|
||||
ge2d_onoff_mode.off_cnt);
|
||||
break;
|
||||
case GE2D_GET_ONOFF_MODE:
|
||||
ge2d_get_onoff_mode(&ge2d_onoff_mode.onoff_mode,
|
||||
&ge2d_onoff_mode.on_cnt,
|
||||
&ge2d_onoff_mode.off_cnt);
|
||||
|
||||
ret = copy_to_user(argp, &ge2d_onoff_mode,
|
||||
sizeof(struct ge2d_onoff_mode_para_s));
|
||||
break;
|
||||
/* enqueue one cmd */
|
||||
case GE2D_FILLRECTANGLE_ENQUEUE:
|
||||
ge2d_log_dbg("fill rect enqueue\t");
|
||||
|
||||
@@ -51,11 +51,13 @@
|
||||
|
||||
#define GE2D_NO_POWER_OFF_OP 0x8
|
||||
#define GE2D_NO_POWER_ON_OP 0x4
|
||||
#define GE2D_ONOFF_MODE_MAX_COUNT 32767
|
||||
|
||||
static struct ge2d_manager_s ge2d_manager;
|
||||
static int ge2d_irq = -ENXIO;
|
||||
static struct clk *ge2d_clk;
|
||||
static int backup_init_regs = 1;
|
||||
static DEFINE_MUTEX(dp_ctrl_mutex);
|
||||
|
||||
static const int bpp_type_lut[] = {
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_FB
|
||||
@@ -125,14 +127,58 @@ static const int default_ge2d_color_lut[] = {
|
||||
static int ge2d_buffer_get_phys(struct aml_dma_cfg *cfg,
|
||||
unsigned long *addr);
|
||||
|
||||
static u32 ge2d_onoff_mode, ge2d_on_cnt, ge2d_off_cnt;
|
||||
|
||||
/* onoff_mode:
|
||||
* 0. on_counter means how many pixels will output before ge2d turns off.
|
||||
* 1. on_counter means how many clocks will ge2d turn on before ge2d turns off.
|
||||
*
|
||||
* on_cnt: on counter, range (0, 32767].
|
||||
* off_cnt: off counter, range (0, 32767].
|
||||
*/
|
||||
int ge2d_set_onoff_mode(u32 onoff_mode, u32 on_cnt, u32 off_cnt)
|
||||
{
|
||||
if ((onoff_mode != 0 && onoff_mode != 1) ||
|
||||
on_cnt > GE2D_ONOFF_MODE_MAX_COUNT ||
|
||||
off_cnt > GE2D_ONOFF_MODE_MAX_COUNT) {
|
||||
ge2d_log_err("%s out of range, %u %u %u\n",
|
||||
__func__, onoff_mode, on_cnt, off_cnt);
|
||||
return -EINVAL;
|
||||
}
|
||||
mutex_lock(&dp_ctrl_mutex);
|
||||
ge2d_onoff_mode = onoff_mode;
|
||||
ge2d_on_cnt = on_cnt;
|
||||
ge2d_off_cnt = off_cnt;
|
||||
ge2d_log_dbg("%s, onoff_mode:%d on_cnt:%d off_cnt:%d\n",
|
||||
__func__, onoff_mode, on_cnt, off_cnt);
|
||||
mutex_unlock(&dp_ctrl_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ge2d_set_onoff_mode);
|
||||
|
||||
void ge2d_get_onoff_mode(u32 *onoff_mode, u32 *on_cnt, u32 *off_cnt)
|
||||
{
|
||||
if (!onoff_mode || !on_cnt || !off_cnt) {
|
||||
ge2d_log_err("%s err, onoff_mode:%p on_cnt:%p off_cnt:%p\n",
|
||||
__func__, onoff_mode, on_cnt, off_cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
*onoff_mode = ge2d_onoff_mode;
|
||||
*on_cnt = ge2d_on_cnt;
|
||||
*off_cnt = ge2d_off_cnt;
|
||||
}
|
||||
EXPORT_SYMBOL(ge2d_get_onoff_mode);
|
||||
|
||||
static void ge2d_pre_init(void)
|
||||
{
|
||||
struct ge2d_gen_s ge2d_gen_cfg;
|
||||
|
||||
ge2d_gen_cfg.interrupt_ctrl = 0x02;
|
||||
ge2d_gen_cfg.dp_on_cnt = 0;
|
||||
ge2d_gen_cfg.dp_off_cnt = 0;
|
||||
ge2d_gen_cfg.dp_onoff_mode = 0;
|
||||
ge2d_gen_cfg.dp_on_cnt = ge2d_on_cnt;
|
||||
ge2d_gen_cfg.dp_off_cnt = ge2d_off_cnt;
|
||||
ge2d_gen_cfg.dp_onoff_mode = ge2d_onoff_mode;
|
||||
ge2d_gen_cfg.vfmt_onoff_en = 0;
|
||||
/* fifo size control, 00: 512, 01: 256, 10: 128 11: 96 */
|
||||
ge2d_gen_cfg.fifo_size = 0;
|
||||
|
||||
@@ -1210,6 +1210,23 @@ struct ge2d_device_data_s {
|
||||
unsigned int cmd_queue_mode; /* cmd queue mode */
|
||||
};
|
||||
|
||||
/* To enable onoff_mode, set the following values for onoff_mode/on_cnt/off_cnt.
|
||||
* onoff_mode:
|
||||
* 0. on_counter means how many pixels will output before ge2d turns off.
|
||||
* 1. on_counter means how many clocks will ge2d turn on before ge2d turns off.
|
||||
*
|
||||
* on_cnt: on counter value, range (0, 32767].
|
||||
* off_cnt: off counter value, range (0, 32767].
|
||||
*
|
||||
* To disable onoff_mode, set all 0 for onoff_mode/on_cnt/off_cnt.
|
||||
*
|
||||
*/
|
||||
struct ge2d_onoff_mode_para_s {
|
||||
u32 onoff_mode;
|
||||
u32 on_cnt;
|
||||
u32 off_cnt;
|
||||
};
|
||||
|
||||
extern struct ge2d_device_data_s ge2d_meson_dev;
|
||||
|
||||
#define GE2D_IOC_MAGIC 'G'
|
||||
@@ -1281,6 +1298,11 @@ extern struct ge2d_device_data_s ge2d_meson_dev;
|
||||
#define GE2D_POST_QUEUE_NOBLOCK \
|
||||
_IO(GE2D_IOC_MAGIC, 0x15)
|
||||
|
||||
#define GE2D_SET_ONOFF_MODE \
|
||||
_IOW(GE2D_IOC_MAGIC, 0x16, struct ge2d_onoff_mode_para_s)
|
||||
#define GE2D_GET_ONOFF_MODE \
|
||||
_IOR(GE2D_IOC_MAGIC, 0x17, struct ge2d_onoff_mode_para_s)
|
||||
|
||||
void ge2d_set_src1_data(struct ge2d_src1_data_s *cfg, u32 mask);
|
||||
void ge2d_set_src1_gen(struct ge2d_src1_gen_s *cfg, u32 mask);
|
||||
void ge2d_set_src2_dst_data(struct ge2d_src2_dst_data_s *cfg, u32 mask);
|
||||
@@ -1336,6 +1358,9 @@ void start_cmd_queue_process(u32 queue_cnt);
|
||||
void stop_cmd_queue_process(void);
|
||||
void dump_cmd_queue_regs(u32 queue_index);
|
||||
|
||||
int ge2d_set_onoff_mode(u32 onoff_mode, u32 on_cnt, u32 off_cnt);
|
||||
void ge2d_get_onoff_mode(u32 *onoff_mode, u32 *on_cnt, u32 *off_cnt);
|
||||
|
||||
#include "ge2d_func.h"
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user