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:
Jian Cao
2023-12-29 07:51:18 +00:00
committed by gerrit autosubmit
parent 09b8bb6fe3
commit cac0610c87
3 changed files with 174 additions and 3 deletions
+100
View File
@@ -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(&params, " ");
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(&para, 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");
+49 -3
View File
@@ -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;
+25
View File
@@ -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