gdc: add endian support [1/1]

PD#SWPL-116164

Problem:
add endian support

Solution:
add this support

Verify:
t7

Change-Id: Id6934ccd7bbfb98dc95f157704f7763808f7373a
Signed-off-by: Jian Cao <jian.cao@amlogic.com>
This commit is contained in:
Jian Cao
2023-03-31 13:04:52 +08:00
committed by gerrit autosubmit
parent 29655631ae
commit 2796ae1550
4 changed files with 265 additions and 4 deletions
+90 -4
View File
@@ -27,6 +27,8 @@
#include <linux/kasan.h>
#include <linux/of_address.h>
#include <linux/ctype.h>
#include <api/gdc_api.h>
#include "system_log.h"
@@ -45,6 +47,12 @@
//#define DEBUG
int gdc_log_level;
int gdc_debug_enable;
int gdc_in_swap_endian;
int gdc_out_swap_endian;
int gdc_in_swap_64bit;
int gdc_out_swap_64bit;
struct gdc_manager_s gdc_manager;
static int kthread_created;
static struct gdc_irq_handle_wq irq_handle_wq[CORE_NUM];
@@ -1453,10 +1461,12 @@ int gdc_process_phys(struct gdc_context_s *context,
}
}
gdc_log(LOG_DEBUG, "input, format:%d, width:%d, height:%d y_stride:%d c_stride:%d\n",
format, i_width, i_height, i_y_stride, i_c_stride);
gdc_log(LOG_DEBUG, "output, format:%d, width:%d, height:%d y_stride:%d c_stride:%d\n",
format, o_width, o_height, o_y_stride, o_c_stride);
gdc_log(LOG_DEBUG,
"input, format:%d, width:%d, height:%d y_stride:%d c_stride:%d endian:0x%x\n",
format, i_width, i_height, i_y_stride, i_c_stride, gs->in_endian);
gdc_log(LOG_DEBUG,
"output, format:%d, width:%d, height:%d y_stride:%d c_stride:%d endian:0x%x\n",
format, o_width, o_height, o_y_stride, o_c_stride, gs->out_endian);
gdc_cmd->gdc_config.format = format;
gdc_cmd->gdc_config.input_width = i_width;
@@ -1471,6 +1481,8 @@ int gdc_process_phys(struct gdc_context_s *context,
gdc_cmd->gdc_config.config_size = gs->config_size;
gdc_cmd->outplane = gs->out_plane_num;
gdc_cmd->use_sec_mem = gs->use_sec_mem;
gdc_cmd->in_endian = gs->in_endian;
gdc_cmd->out_endian = gs->out_endian;
/* set config_paddr MSB val */
context->dma_cfg.config_cfg.paddr_8g_msb = (u64)gs->config_paddr >> 32;
@@ -1924,6 +1936,45 @@ static const struct file_operations meson_gdc_fops = {
.mmap = meson_gdc_mmap,
};
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_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -2065,6 +2116,39 @@ static ssize_t config_out_path_store(struct device *dev,
static DEVICE_ATTR_RW(config_out_path);
static ssize_t debug_endian_show(struct device *device,
struct device_attribute *attr,
char *buf)
{
return snprintf(buf, 80, "%d %d %d %d %d\n",
gdc_debug_enable,
gdc_in_swap_endian,
gdc_out_swap_endian,
gdc_in_swap_64bit,
gdc_out_swap_64bit);
}
static ssize_t debug_endian_store(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
int parsed[5];
if (likely(parse_para(buf, 5, parsed) == 5)) {
gdc_debug_enable = parsed[0];
gdc_in_swap_endian = parsed[1];
gdc_out_swap_endian = parsed[2];
gdc_in_swap_64bit = parsed[3];
gdc_out_swap_64bit = parsed[4];
} else {
pr_err("wrong params\n");
}
return count;
}
static DEVICE_ATTR_RW(debug_endian);
void irq_handle_func(struct work_struct *work)
{
struct gdc_irq_handle_wq *irq_handle_wq =
@@ -2309,6 +2393,8 @@ static int gdc_platform_probe(struct platform_device *pdev)
&dev_attr_trace_mode);
device_create_file(gdc_dev->misc_dev.this_device,
&dev_attr_config_out_path);
device_create_file(gdc_dev->misc_dev.this_device,
&dev_attr_debug_endian);
platform_set_drvdata(pdev, gdc_dev);
dev_set_drvdata(gdc_dev->misc_dev.this_device, gdc_dev);
+58
View File
@@ -111,6 +111,12 @@ struct gdc_irq_data_s {
extern struct gdc_manager_s gdc_manager;
extern int gdc_debug_enable;
extern int gdc_in_swap_endian;
extern int gdc_out_swap_endian;
extern int gdc_in_swap_64bit;
extern int gdc_out_swap_64bit;
#define GDC_DEVICE(dev_type) ((dev_type) == ARM_GDC ? \
&gdc_manager.gdc_dev->pdev->dev : \
&gdc_manager.aml_gdc_dev->pdev->dev)
@@ -142,6 +148,10 @@ extern struct gdc_manager_s gdc_manager;
#define ISP_DWAP_TOP_DST_V_CTRL0 ((0x17 << 2) | ISP_DWAP_REG_MARK)
#define ISP_DWAP_TOP_DST_V_CTRL1 ((0x18 << 2) | ISP_DWAP_REG_MARK)
#define ISP_DWAP_CMD_SWAP ((0x2b << 2) | ISP_DWAP_REG_MARK)
#define ISP_DWAP_WMIF_CTRL1 ((0x40 << 2) | ISP_DWAP_REG_MARK)
#define ISP_DWAP_RMIF_CTRL1 ((0x50 << 2) | ISP_DWAP_REG_MARK)
#define ISP_DWAP_GAMMA_CTRL ((0x60 << 2) | ISP_DWAP_REG_MARK)
#define ISP_DWAP_GAMMA_OFST ((0x61 << 2) | ISP_DWAP_REG_MARK)
#define ISP_DWAP_GAMMA_NUM ((0x62 << 2) | ISP_DWAP_REG_MARK)
@@ -383,6 +393,54 @@ static inline u32 gdc_config_size_read(void)
return system_gdc_read_32(0x14L, 0);
}
// args: enable (1-swap endian 0-do not swap)
static inline void gdc_datain_swap_endian_write(u32 enable, u32 core_id)
{
u32 curr = system_gdc_read_32(ISP_DWAP_CMD_SWAP, core_id);
curr &= ~(1 << 6);
curr |= (enable << 6);
system_gdc_write_32(ISP_DWAP_CMD_SWAP, curr, core_id);
}
static inline void gdc_dataout_swap_endian_write(u32 enable, u32 core_id)
{
u32 curr = system_gdc_read_32(ISP_DWAP_WMIF_CTRL1, core_id);
curr &= ~(1 << 6);
curr |= ((enable ? 0 : 1) << 6);
system_gdc_write_32(ISP_DWAP_WMIF_CTRL1, curr, core_id);
curr = system_gdc_read_32(ISP_DWAP_CMD_SWAP, core_id);
curr &= ~(1 << 8);
curr |= (enable << 8);
system_gdc_write_32(ISP_DWAP_CMD_SWAP, curr, core_id);
}
// args: enable (1-swap 64bit of 128bit 0-do not swap)
static inline void gdc_datain_swap_64bit_write(u32 enable, u32 core_id)
{
u32 curr = system_gdc_read_32(ISP_DWAP_RMIF_CTRL1, core_id);
curr &= ~(1 << 7);
curr |= (enable << 7);
/* for coef and mesh, in case of swap_64bit */
curr &= ~(1 << 6);
curr |= ((enable ? 0 : 1) << 6);
system_gdc_write_32(ISP_DWAP_RMIF_CTRL1, curr, core_id);
}
static inline void gdc_dataout_swap_64bit_write(u32 enable, u32 core_id)
{
u32 curr = system_gdc_read_32(ISP_DWAP_WMIF_CTRL1, core_id);
curr &= ~(1 << 7);
curr |= (enable << 7);
system_gdc_write_32(ISP_DWAP_WMIF_CTRL1, curr, core_id);
}
// ----------------------------------- //
// Register: datain width
// ----------------------------------- //
+105
View File
@@ -96,6 +96,106 @@ void gdc_stop(struct gdc_cmd_s *gdc_cmd, u32 core_id)
* @param gdc_cmd - overall gdc settings and state
*
*/
static void gdc_endian_config(struct gdc_cmd_s *gdc_cmd, u32 core_id)
{
u32 dev_type = gdc_cmd->dev_type;
if (dev_type == ARM_GDC)
return;
if (gdc_debug_enable) {
gdc_datain_swap_64bit_write(gdc_in_swap_64bit, core_id);
gdc_dataout_swap_64bit_write(gdc_out_swap_64bit, core_id);
gdc_datain_swap_endian_write(gdc_in_swap_endian, core_id);
gdc_dataout_swap_endian_write(gdc_out_swap_endian, core_id);
} else {
u32 in_swap_64bit = 0, out_swap_64bit = 0;
u32 in_swap_endian = 0, out_swap_endian = 0;
u32 in_endian = gdc_cmd->in_endian;
u32 out_endian = gdc_cmd->out_endian;
if (in_endian == GDC_ENDIAN_LITTLE) {
switch (out_endian) {
case GDC_ENDIAN_LITTLE:
in_swap_64bit = 0;
out_swap_64bit = 0;
in_swap_endian = 0;
out_swap_endian = 0;
break;
case GDC_ENDIAN_BIG_8BYTES:
in_swap_64bit = 0;
out_swap_64bit = 1;
in_swap_endian = 0;
out_swap_endian = 1;
break;
case GDC_ENDIAN_BIG_16BYTES:
in_swap_64bit = 0;
out_swap_64bit = 0;
in_swap_endian = 0;
out_swap_endian = 1;
break;
}
} else if (in_endian == GDC_ENDIAN_BIG_8BYTES) {
switch (out_endian) {
case GDC_ENDIAN_LITTLE:
in_swap_64bit = 1;
out_swap_64bit = 0;
in_swap_endian = 1;
out_swap_endian = 0;
break;
case GDC_ENDIAN_BIG_8BYTES:
in_swap_64bit = 1;
out_swap_64bit = 1;
in_swap_endian = 1;
out_swap_endian = 1;
break;
case GDC_ENDIAN_BIG_16BYTES:
in_swap_64bit = 1;
out_swap_64bit = 0;
in_swap_endian = 1;
out_swap_endian = 1;
break;
}
} else if (in_endian == GDC_ENDIAN_BIG_16BYTES) {
switch (out_endian) {
case GDC_ENDIAN_LITTLE:
in_swap_64bit = 0;
out_swap_64bit = 0;
in_swap_endian = 1;
out_swap_endian = 0;
break;
case GDC_ENDIAN_BIG_8BYTES:
in_swap_64bit = 0;
out_swap_64bit = 1;
in_swap_endian = 1;
out_swap_endian = 1;
break;
case GDC_ENDIAN_BIG_16BYTES:
in_swap_64bit = 0;
out_swap_64bit = 0;
in_swap_endian = 1;
out_swap_endian = 1;
break;
}
}
gdc_datain_swap_64bit_write(in_swap_64bit, core_id);
gdc_dataout_swap_64bit_write(out_swap_64bit, core_id);
gdc_datain_swap_endian_write(in_swap_endian, core_id);
gdc_dataout_swap_endian_write(out_swap_endian, core_id);
gdc_log(LOG_DEBUG, "in_endian:%d, out_endian:%d",
in_endian, out_endian);
gdc_log(LOG_DEBUG,
"in_swap_64bit:%d out_swap_64_bit:%d in_swap_endian:%d, out_swap_endian:%d",
in_swap_64bit, out_swap_64bit,
in_swap_endian, out_swap_endian);
}
}
void gdc_start(struct gdc_cmd_s *gdc_cmd, u32 core_id)
{
/* do a stop for sync */
@@ -213,6 +313,7 @@ int gdc_process(struct gdc_cmd_s *gdc_cmd,
if (GDC_DEV_T(dev_type)->ext_msb_8g)
set_ext_8g_msb(dma_cfg, 2);
gdc_endian_config(gdc_cmd, core_id);
gdc_start(gdc_cmd, core_id);
return 0;
@@ -308,6 +409,7 @@ int gdc_process_yuv420p(struct gdc_cmd_s *gdc_cmd,
if (GDC_DEV_T(dev_type)->ext_msb_8g)
set_ext_8g_msb(dma_cfg, 3);
gdc_endian_config(gdc_cmd, core_id);
gdc_start(gdc_cmd, core_id);
return 0;
@@ -365,6 +467,7 @@ int gdc_process_y_grey(struct gdc_cmd_s *gdc_cmd,
if (GDC_DEV_T(dev_type)->ext_msb_8g)
set_ext_8g_msb(dma_cfg, 1);
gdc_endian_config(gdc_cmd, core_id);
gdc_start(gdc_cmd, core_id);
return 0;
@@ -454,6 +557,7 @@ int gdc_process_yuv444p(struct gdc_cmd_s *gdc_cmd,
if (GDC_DEV_T(dev_type)->ext_msb_8g)
set_ext_8g_msb(dma_cfg, 3);
gdc_endian_config(gdc_cmd, core_id);
gdc_start(gdc_cmd, core_id);
return 0;
@@ -545,6 +649,7 @@ int gdc_process_rgb444p(struct gdc_cmd_s *gdc_cmd,
if (GDC_DEV_T(dev_type)->ext_msb_8g)
set_ext_8g_msb(dma_cfg, 3);
gdc_endian_config(gdc_cmd, core_id);
gdc_start(gdc_cmd, core_id);
return 0;
+12
View File
@@ -30,6 +30,13 @@ enum {
GDC_MAX_FW
};
enum {
GDC_ENDAIN_DEFAULT = 0, /* no endian operation */
GDC_ENDIAN_LITTLE = BIT(0),
GDC_ENDIAN_BIG_8BYTES = BIT(1),
GDC_ENDIAN_BIG_16BYTES = BIT(2)
};
struct aml_dma_cfg {
int fd;
void *dev;
@@ -112,6 +119,9 @@ struct gdc_cmd_s {
u32 dev_type;
/* secure mem access */
u32 use_sec_mem;
/* endian setting */
u32 in_endian;
u32 out_endian;
};
struct gdc_context_s {
@@ -186,6 +196,8 @@ struct gdc_phy_setting {
ulong config_paddr;
u32 config_size; /* in 32bit */
u32 use_sec_mem; /* secure mem access */
u32 in_endian;
u32 out_endian;
};
struct firmware_load_s {