gdc: support phy addr configuration [1/1]

PD#SWPL-15157

Problem:
GDC Driver Support physical address configuration

Solution:
add this support

Verify:
verified on g12b

Change-Id: I8aee517a13bb2a65c021279cc3b54bd9861fc20c
Signed-off-by: Cao Jian <jian.cao@amlogic.com>
This commit is contained in:
Cao Jian
2019-10-19 18:30:55 +08:00
committed by Chris
parent 3cdb821e1b
commit dfd7a2da8e
7 changed files with 388 additions and 202 deletions

View File

@@ -21,7 +21,7 @@
#include <linux/mm_types.h>
#include <linux/mutex.h>
#include <linux/dma-buf.h>
#include <linux/amlogic/media/gdc/gdc.h>
#define AML_MAX_DMABUF 32
@@ -53,17 +53,6 @@ struct aml_dma_buffer {
struct aml_dma_buf_priv gd_buffer[AML_MAX_DMABUF];
};
struct aml_dma_cfg {
int fd;
void *dev;
void *vaddr;
struct dma_buf *dbuf;
struct dma_buf_attachment *attach;
struct sg_table *sg;
enum dma_data_direction dir;
};
void *gdc_dma_buffer_create(void);
void gdc_dma_buffer_destroy(struct aml_dma_buffer *buffer);
int gdc_dma_buffer_alloc(struct aml_dma_buffer *buffer,

View File

@@ -55,7 +55,6 @@ int trace_mode_enable;
char *config_out_file;
int config_out_path_defined;
#define CONFIG_PATH_LENG 128
#define CORE_CLK_RATE 800000000
#define AXI_CLK_RATE 800000000
@@ -154,9 +153,9 @@ static int meson_gdc_release(struct inode *inode, struct file *file)
return ret;
}
static long meson_gdc_set_buff(struct gdc_context_s *context,
struct page *cma_pages,
unsigned long len)
static int meson_gdc_set_buff(struct gdc_context_s *context,
struct page *cma_pages,
unsigned long len)
{
int ret = 0;
@@ -204,8 +203,8 @@ static long meson_gdc_set_buff(struct gdc_context_s *context,
return ret;
}
static long meson_gdc_set_input_addr(uint32_t start_addr,
struct gdc_cmd_s *gdc_cmd)
static int meson_gdc_set_input_addr(u32 start_addr,
struct gdc_cmd_s *gdc_cmd)
{
struct gdc_config_s *gc = NULL;
@@ -281,9 +280,9 @@ static void meson_gdc_cache_flush(struct device *dev,
dma_sync_single_for_cpu(dev, addr, size, DMA_FROM_DEVICE);
}
static long meson_gdc_dma_map(struct gdc_dma_cfg *cfg)
static int meson_gdc_dma_map(struct gdc_dma_cfg *cfg)
{
long ret = -1;
int ret = -1;
int fd = -1;
struct dma_buf *dbuf = NULL;
struct dma_buf_attachment *d_att = NULL;
@@ -389,11 +388,11 @@ static void meson_gdc_dma_unmap(struct gdc_dma_cfg *cfg)
dma_buf_put(dbuf);
}
static long meson_gdc_init_dma_addr(
static int meson_gdc_init_dma_addr(
struct gdc_context_s *context,
struct gdc_settings *gs)
{
long ret = -1;
int ret = -1;
struct gdc_dma_cfg *dma_cfg = NULL;
struct gdc_cmd_s *gdc_cmd = &context->cmd;
struct gdc_config_s *gc = &gdc_cmd->gdc_config;
@@ -548,7 +547,7 @@ static int gdc_get_buffer_fd(int plane_id, struct gdc_buffer_info *buf_info)
}
static int gdc_set_output_addr(int plane_id,
uint32_t addr,
u32 addr,
struct gdc_cmd_s *gdc_cmd)
{
switch (plane_id) {
@@ -569,9 +568,9 @@ static int gdc_set_output_addr(int plane_id,
return 0;
}
static long gdc_set_input_addr(int plane_id,
uint32_t addr,
struct gdc_cmd_s *gdc_cmd)
static int gdc_set_input_addr(int plane_id,
u32 addr,
struct gdc_cmd_s *gdc_cmd)
{
struct gdc_config_s *gc = NULL;
long size;
@@ -643,7 +642,7 @@ static long gdc_set_input_addr(int plane_id,
return 0;
}
static long gdc_get_input_size(struct gdc_cmd_s *gdc_cmd)
static int gdc_get_input_size(struct gdc_cmd_s *gdc_cmd)
{
struct gdc_config_s *gc = NULL;
long size;
@@ -674,10 +673,10 @@ static long gdc_get_input_size(struct gdc_cmd_s *gdc_cmd)
return 0;
}
static long gdc_process_input_dma_info(struct gdc_context_s *context,
struct gdc_settings_ex *gs_ex)
static int gdc_process_input_dma_info(struct gdc_context_s *context,
struct gdc_settings_ex *gs_ex)
{
long ret = -1;
int ret = -1;
unsigned long addr;
long size;
struct aml_dma_cfg *cfg = NULL;
@@ -748,10 +747,10 @@ dma_buf_unmap:
return ret;
}
static long gdc_process_output_dma_info(struct gdc_context_s *context,
struct gdc_settings_ex *gs_ex)
static int gdc_process_output_dma_info(struct gdc_context_s *context,
struct gdc_settings_ex *gs_ex)
{
long ret = -1;
int ret = -1;
unsigned long addr;
struct aml_dma_cfg *cfg = NULL;
struct gdc_cmd_s *gdc_cmd = &context->cmd;
@@ -811,10 +810,10 @@ dma_buf_unmap:
}
static long gdc_process_ex_info(struct gdc_context_s *context,
struct gdc_settings_ex *gs_ex)
static int gdc_process_ex_info(struct gdc_context_s *context,
struct gdc_settings_ex *gs_ex)
{
long ret;
int ret;
unsigned long addr = 0;
struct aml_dma_cfg *cfg = NULL;
struct gdc_cmd_s *gdc_cmd = &context->cmd;
@@ -828,7 +827,7 @@ static long gdc_process_ex_info(struct gdc_context_s *context,
mutex_lock(&context->d_mutext);
memcpy(&(gdc_cmd->gdc_config), &(gs_ex->gdc_config),
sizeof(struct gdc_config_s));
for (i = 0; i < MAX_PLANE; i++) {
for (i = 0; i < GDC_MAX_PLANE; i++) {
context->dma_cfg.input_cfg[i].dma_used = 0;
context->dma_cfg.output_cfg[i].dma_used = 0;
}
@@ -888,38 +887,38 @@ unlock_return:
return ret;
}
static void release_config_firmware(struct gdc_settings_with_fw *gs_with_fw)
static void release_config_firmware(struct fw_info_s *fw_info,
struct gdc_config_s *gdc_config)
{
if (!fw_info || !gdc_config) {
gdc_log(LOG_ERR, "NULL param, %s (%d)\n", __func__, __LINE__);
return;
}
if (gs_with_fw->fw_info.virt_addr)
unmap_virt_from_phys(gs_with_fw->fw_info.virt_addr);
if (gs_with_fw->fw_info.cma_pages) {
dma_release_from_contiguous(
&gdc_manager.gdc_dev->pdev->dev,
gs_with_fw->fw_info.cma_pages,
PAGE_ALIGN(gs_with_fw->gdc_config.config_size * 4)
>> PAGE_SHIFT);
gs_with_fw->fw_info.cma_pages = NULL;
if (fw_info->virt_addr &&
gdc_config->config_size && gdc_config->config_addr) {
dma_free_coherent(&gdc_manager.gdc_dev->pdev->dev,
gdc_config->config_size * 4,
fw_info->virt_addr,
gdc_config->config_addr);
}
}
static int load_firmware_by_name(struct gdc_settings_with_fw *gs_with_fw)
static int load_firmware_by_name(struct fw_info_s *fw_info,
struct gdc_config_s *gdc_config)
{
int ret = -1;
const struct firmware *fw = NULL;
char *path = NULL;
struct fw_info_s *current_fw = &gs_with_fw->fw_info;
struct page *cma_pages = NULL;
void __iomem *virt_addr = NULL;
phys_addr_t phys_addr = 0;
if (!current_fw->fw_name) {
gdc_log(LOG_ERR, "current firmware name is NULL, invalid\n");
if (!fw_info || !fw_info->fw_name || !gdc_config) {
gdc_log(LOG_ERR, "NULL param, %s (%d)\n", __func__, __LINE__);
return -EINVAL;
}
gdc_log(LOG_DEBUG, "Try to load %s ...\n", current_fw->fw_name);
gdc_log(LOG_DEBUG, "Try to load %s ...\n", fw_info->fw_name);
path = kzalloc(CONFIG_PATH_LENG, GFP_KERNEL);
if (!path) {
@@ -927,7 +926,7 @@ static int load_firmware_by_name(struct gdc_settings_with_fw *gs_with_fw)
return -ENOMEM;
}
snprintf(path, (CONFIG_PATH_LENG - 1), "%s/%s",
FIRMWARE_DIR, current_fw->fw_name);
FIRMWARE_DIR, fw_info->fw_name);
ret = request_firmware(&fw, path, &gdc_manager.gdc_dev->pdev->dev);
if (ret < 0) {
@@ -943,35 +942,23 @@ static int load_firmware_by_name(struct gdc_settings_with_fw *gs_with_fw)
goto release;
}
cma_pages = dma_alloc_from_contiguous(&gdc_manager.gdc_dev->pdev->dev,
PAGE_ALIGN(fw->size) >> PAGE_SHIFT, 0);
if (cma_pages != NULL) {
phys_addr = page_to_phys(cma_pages);
virt_addr = map_virt_from_phys(phys_addr,
PAGE_ALIGN(fw->size));
if (!virt_addr) {
gdc_log(LOG_ERR, "map_virt_from_phys failed\n");
dma_release_from_contiguous(
&gdc_manager.gdc_dev->pdev->dev,
cma_pages,
PAGE_ALIGN(fw->size) >> PAGE_SHIFT);
ret = -ENOMEM;
goto release;
}
} else {
gdc_log(LOG_ERR, "Failed to alloc dma buff\n");
virt_addr = dma_alloc_coherent(&gdc_manager.gdc_dev->pdev->dev, fw->size,
&phys_addr, GFP_DMA | GFP_KERNEL);
if (!virt_addr) {
gdc_log(LOG_ERR, "alloc config buffer failed\n");
ret = -ENOMEM;
goto release;
}
memcpy(virt_addr, (char *)fw->data, fw->size);
gdc_log(LOG_DEBUG,
"current firmware virt_addr: 0x%p, fw->data: 0x%p.\n",
virt_addr, fw->data);
gs_with_fw->gdc_config.config_addr = phys_addr;
gs_with_fw->gdc_config.config_size = fw->size / 4;
gs_with_fw->fw_info.cma_pages = cma_pages;
gdc_config->config_addr = phys_addr;
gdc_config->config_size = fw->size / 4;
fw_info->virt_addr = virt_addr;
gdc_log(LOG_DEBUG, "load firmware size : %zd, Name : %s.\n",
fw->size, path);
@@ -984,10 +971,10 @@ release:
return ret;
}
static long gdc_process_with_fw(struct gdc_context_s *context,
struct gdc_settings_with_fw *gs_with_fw)
static int gdc_process_with_fw(struct gdc_context_s *context,
struct gdc_settings_with_fw *gs_with_fw)
{
long ret = -1;
int ret = -1;
struct gdc_cmd_s *gdc_cmd = &context->cmd;
char *fw_name = NULL;
struct gdc_queue_item_s *pitem = NULL;
@@ -1034,7 +1021,8 @@ static long gdc_process_with_fw(struct gdc_context_s *context,
/* load firmware */
if (gs_with_fw->fw_info.fw_name != NULL) {
ret = load_firmware_by_name(gs_with_fw);
ret = load_firmware_by_name(&gs_with_fw->fw_info,
&gs_with_fw->gdc_config);
if (ret <= 0) {
gdc_log(LOG_ERR, "line %d,load FW %s failed\n",
__LINE__, gs_with_fw->fw_info.fw_name);
@@ -1144,7 +1132,8 @@ static long gdc_process_with_fw(struct gdc_context_s *context,
gs_with_fw->fw_info.fw_name = fw_name;
}
ret = load_firmware_by_name(gs_with_fw);
ret = load_firmware_by_name(&gs_with_fw->fw_info,
&gs_with_fw->gdc_config);
if (ret <= 0) {
gdc_log(LOG_ERR, "line %d,load FW %s failed\n",
__LINE__, gs_with_fw->fw_info.fw_name);
@@ -1168,13 +1157,12 @@ static long gdc_process_with_fw(struct gdc_context_s *context,
}
mutex_unlock(&context->d_mutext);
gdc_wq_add_work(context, pitem);
release_config_firmware(gs_with_fw);
release_config_firmware(&gs_with_fw->fw_info, &gs_with_fw->gdc_config);
kfree(fw_name);
return 0;
release_fw:
release_config_firmware(gs_with_fw);
release_config_firmware(&gs_with_fw->fw_info, &gs_with_fw->gdc_config);
release_fw_name:
mutex_unlock(&context->d_mutext);
kfree(fw_name);
@@ -1183,10 +1171,157 @@ release_fw_name:
}
EXPORT_SYMBOL(gdc_process_with_fw);
int gdc_process_phys(struct gdc_context_s *context,
struct gdc_phy_setting *gs)
{
int ret = -1, i;
struct gdc_cmd_s *gdc_cmd = NULL;
struct gdc_queue_item_s *pitem = NULL;
struct fw_info_s fw_info;
u32 plane_number;
u32 format = 0;
u32 i_width = 0, i_height = 0;
u32 o_width = 0, o_height = 0;
u32 i_y_stride = 0, i_c_stride = 0;
u32 o_y_stride = 0, o_c_stride = 0;
if (!context || !gs) {
gdc_log(LOG_ERR, "NULL param, %s (%d)\n", __func__, __LINE__);
return -EINVAL;
}
mutex_lock(&context->d_mutext);
gdc_cmd = &context->cmd;
memset(gdc_cmd, 0, sizeof(struct gdc_cmd_s));
/* set gdc_config */
format = gs->format;
i_width = gs->in_width;
i_height = gs->in_height;
o_width = gs->out_width;
o_height = gs->out_height;
if (format == NV12 || format == YUV444_P || format == RGB444_P) {
i_y_stride = AXI_WORD_ALIGN(i_width);
o_y_stride = AXI_WORD_ALIGN(o_width);
i_c_stride = AXI_WORD_ALIGN(i_width);
o_c_stride = AXI_WORD_ALIGN(o_width);
} else if (format == YV12) {
i_c_stride = AXI_WORD_ALIGN(i_width / 2);
o_c_stride = AXI_WORD_ALIGN(o_width / 2);
i_y_stride = i_c_stride * 2;
o_y_stride = o_c_stride * 2;
} else if (format == Y_GREY) {
i_y_stride = AXI_WORD_ALIGN(i_width);
o_y_stride = AXI_WORD_ALIGN(o_width);
i_c_stride = 0;
o_c_stride = 0;
} else {
gdc_log(LOG_ERR, "Error unknown format\n");
mutex_unlock(&context->d_mutext);
return -EINVAL;
}
gdc_cmd->gdc_config.format = format;
gdc_cmd->gdc_config.input_width = i_width;
gdc_cmd->gdc_config.input_height = i_height;
gdc_cmd->gdc_config.input_y_stride = i_y_stride;
gdc_cmd->gdc_config.input_c_stride = i_c_stride;
gdc_cmd->gdc_config.output_width = o_width;
gdc_cmd->gdc_config.output_height = o_height;
gdc_cmd->gdc_config.output_y_stride = o_y_stride;
gdc_cmd->gdc_config.output_c_stride = o_c_stride;
gdc_cmd->gdc_config.config_addr = gs->config_paddr;
gdc_cmd->gdc_config.config_size = gs->config_size;
gdc_cmd->outplane = gs->out_plane_num;
/* output_addr */
plane_number = gs->out_plane_num;
if (plane_number < 1 || plane_number > 3) {
plane_number = 1;
gdc_log(LOG_ERR, "%s, input plane_number=%d invalid\n",
__func__, plane_number);
}
for (i = 0; i < plane_number; i++) {
if (plane_number == 1) {
gdc_cmd->buffer_addr = gs->out_paddr[0];
gdc_cmd->current_addr = gdc_cmd->buffer_addr;
} else {
ret = gdc_set_output_addr(i, gs->out_paddr[i], gdc_cmd);
if (ret < 0) {
gdc_log(LOG_ERR, "set input addr err\n");
mutex_unlock(&context->d_mutext);
return -EINVAL;
}
}
gdc_log(LOG_DEBUG, "plane[%d] get output paddr=0x%x\n",
i, gs->out_paddr[i]);
}
/* input_addr */
plane_number = gs->in_plane_num;
if (plane_number < 1 || plane_number > 3) {
plane_number = 1;
gdc_log(LOG_ERR, "%s, output plane_number=%d invalid\n",
__func__, plane_number);
}
for (i = 0; i < plane_number; i++) {
if (plane_number == 1) {
ret = meson_gdc_set_input_addr(gs->in_paddr[0],
gdc_cmd);
if (ret != 0) {
gdc_log(LOG_ERR, "set input addr err\n");
mutex_unlock(&context->d_mutext);
return -EINVAL;
}
} else {
ret = gdc_set_input_addr(i, gs->in_paddr[i], gdc_cmd);
if (ret < 0) {
gdc_log(LOG_ERR, "set input addr err\n");
mutex_unlock(&context->d_mutext);
return -EINVAL;
}
}
gdc_log(LOG_DEBUG, "plane[%d] get input addr=0x%x\n",
i, gs->in_paddr[i]);
}
/* config_addr */
if (gs->use_builtin_fw) {
fw_info.fw_name = gs->config_name;
ret = load_firmware_by_name(&fw_info, &gdc_cmd->gdc_config);
if (ret <= 0) {
gdc_log(LOG_ERR, "line %d,load FW %s failed\n",
__LINE__, fw_info.fw_name);
ret = -EINVAL;
mutex_unlock(&context->d_mutext);
goto release_fw;
}
}
/* set block mode */
context->cmd.wait_done_flag = 1;
pitem = gdc_prepare_item(context);
if (!pitem) {
gdc_log(LOG_ERR, "get item error\n");
ret = -ENOMEM;
mutex_unlock(&context->d_mutext);
goto release_fw;
}
mutex_unlock(&context->d_mutext);
gdc_wq_add_work(context, pitem);
release_fw:
release_config_firmware(&fw_info, &gdc_cmd->gdc_config);
return ret;
}
EXPORT_SYMBOL(gdc_process_phys);
static long meson_gdc_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
long ret = -1;
int ret = -1;
size_t len;
struct gdc_context_s *context = NULL;
struct gdc_settings gs;
@@ -1661,7 +1796,7 @@ static int gdc_platform_probe(struct platform_device *pdev)
struct resource *gdc_res;
struct meson_gdc_dev_t *gdc_dev = NULL;
void *pd_cntl = NULL;
uint32_t reg_value = 0;
u32 reg_value = 0;
// Initialize irq
gdc_res = platform_get_resource(pdev,

View File

@@ -225,7 +225,7 @@ static int gdc_process_work_queue(struct gdc_context_s *wq)
list_move_tail(&pitem->list, &wq->free_queue);
spin_unlock(&wq->lock);
/* if dma buf detach it */
for (i = 0; i < MAX_PLANE; i++) {
for (i = 0; i < GDC_MAX_PLANE; i++) {
if (pitem->dma_cfg.input_cfg[i].dma_used) {
gdc_dma_buffer_unmap_info(gdc_manager.buffer,
&pitem->dma_cfg.input_cfg[i].dma_cfg);

View File

@@ -19,64 +19,25 @@
#define _GDC_WQ_H_
#include <linux/types.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/semaphore.h>
#include <linux/amlogic/media/gdc/gdc.h>
#include <gdc_config.h>
#include <gdc_api.h>
struct gdc_cmd_s;
#define MAX_GDC_CMD 32 /* 64 */
#define MAX_PLANE 3
#define GDC_STATE_IDLE 0
#define GDC_STATE_RUNNING 1
#define GDC_PROCESS_QUEUE_START 0
#define GDC_PROCESS_QUEUE_STOP 1
struct gdc_dmabuf_cfg_s {
int dma_used;
struct aml_dma_cfg dma_cfg;
};
struct gdc_dma_cfg_t {
struct gdc_dmabuf_cfg_s config_cfg;
struct gdc_dmabuf_cfg_s input_cfg[MAX_PLANE];
struct gdc_dmabuf_cfg_s output_cfg[MAX_PLANE];
};
struct gdc_queue_item_s {
struct list_head list;
struct gdc_cmd_s cmd;
struct gdc_dma_cfg_t dma_cfg;
};
struct gdc_context_s {
/* connect all process in one queue for RR process. */
struct list_head list;
/* current wq configuration */
uint32_t mmap_type;
dma_addr_t i_paddr;
dma_addr_t o_paddr;
dma_addr_t c_paddr;
void *i_kaddr;
void *o_kaddr;
void *c_kaddr;
unsigned long i_len;
unsigned long o_len;
unsigned long c_len;
struct gdc_dma_cfg y_dma_cfg;
struct gdc_dma_cfg uv_dma_cfg;
struct gdc_dma_cfg_t dma_cfg;
struct mutex d_mutext;
struct gdc_cmd_s cmd;
struct list_head work_queue;
struct list_head free_queue;
wait_queue_head_t cmd_complete;
int gdc_request_exit;
spinlock_t lock;/* for get and release item. */
};
extern unsigned int gdc_reg_store_mode;
extern int trace_mode_enable;
extern char *config_out_file;
@@ -90,6 +51,4 @@ int gdc_wq_deinit(void);
void *gdc_prepare_item(struct gdc_context_s *wq);
int gdc_wq_add_work(struct gdc_context_s *wq,
struct gdc_queue_item_s *pitem);
struct gdc_context_s *create_gdc_work_queue(void);
int destroy_gdc_work_queue(struct gdc_context_s *gdc_work_queue);
#endif

View File

@@ -19,7 +19,7 @@
#define __GDC_API_H__
#include <linux/of_address.h>
#include <linux/dma-direction.h>
#include <linux/amlogic/media/gdc/gdc.h>
enum gdc_memtype_s {
AML_GDC_MEM_ION,
@@ -32,21 +32,6 @@ struct gdc_buf_cfg {
unsigned long len;
};
// each configuration addresses and size
struct gdc_config_s {
uint32_t format;
uint32_t config_addr; //gdc config address
uint32_t config_size; //gdc config size in 32bit
uint32_t input_width; //gdc input width resolution
uint32_t input_height; //gdc input height resolution
uint32_t input_y_stride; //gdc input y stride resolution
uint32_t input_c_stride; //gdc input uv stride
uint32_t output_width; //gdc output width resolution
uint32_t output_height; //gdc output height resolution
uint32_t output_y_stride; //gdc output y stride
uint32_t output_c_stride; //gdc output uv stride
};
struct gdc_buffer_info {
unsigned int mem_alloc_type;
unsigned int plane_number;
@@ -153,15 +138,6 @@ enum {
GDC_BUFF_TYPE_MAX
};
enum {
NV12 = 1,
YV12,
Y_GREY,
YUV444_P,
RGB444_P,
FMT_MAX
};
enum {
EQUISOLID = 1,
CYLINDER,
@@ -171,52 +147,6 @@ enum {
FW_TYPE_MAX
};
struct gdc_dma_cfg {
int fd;
void *dev;
void *vaddr;
struct dma_buf *dbuf;
struct dma_buf_attachment *attach;
struct sg_table *sg;
enum dma_data_direction dir;
};
struct gdc_cmd_s {
uint32_t outplane;
//writing/reading to gdc base address, currently not read by api
uint32_t base_gdc;
//array of gdc configuration and sizes
struct gdc_config_s gdc_config;
//update this index for new config
//int gdc_config_total;
//start memory to write gdc output framse
uint32_t buffer_addr;
//size of memory output frames to determine
//if it is enough and can do multiple write points
uint32_t buffer_size;
//current output address of gdc
uint32_t current_addr;
//output address for u, v planes
union {
uint32_t uv_out_base_addr;
uint32_t u_out_base_addr;
};
uint32_t v_out_base_addr;
//set when expecting an interrupt from gdc
int32_t is_waiting_gdc;
//input address for y and u, v planes
uint32_t y_base_addr;
union {
uint32_t uv_base_addr;
uint32_t u_base_addr;
};
uint32_t v_base_addr;
unsigned char wait_done_flag;
};
/* path: "/vendor/lib/firmware/gdc/" */
#define FIRMWARE_DIR "gdc"

View File

@@ -23,8 +23,8 @@
extern int gdc_log_level;
enum log_level_e {
LOG_CRIT,
LOG_ERR,
LOG_CRIT = 0,
LOG_ERR = 0,
LOG_INFO = 0,
LOG_WARNING,
LOG_DEBUG,

View File

@@ -0,0 +1,173 @@
/*
* include/linux/amlogic/media/gdc/gdc.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* 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.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#ifndef _GDC_H_
#define _GDC_H_
#include <linux/types.h>
#include <linux/wait.h>
#include <linux/dma-direction.h>
#include <linux/dma-buf.h>
#define CONFIG_PATH_LENG 128
#define GDC_MAX_PLANE 3
#define WORD_SIZE 16
#define WORD_MASK (~(WORD_SIZE - 1))
#define AXI_WORD_ALIGN(size) (((size) + WORD_SIZE - 1) & WORD_MASK)
struct aml_dma_cfg {
int fd;
void *dev;
void *vaddr;
struct dma_buf *dbuf;
struct dma_buf_attachment *attach;
struct sg_table *sg;
enum dma_data_direction dir;
};
struct gdc_dmabuf_cfg_s {
int dma_used;
struct aml_dma_cfg dma_cfg;
};
struct gdc_dma_cfg_t {
struct gdc_dmabuf_cfg_s config_cfg;
struct gdc_dmabuf_cfg_s input_cfg[GDC_MAX_PLANE];
struct gdc_dmabuf_cfg_s output_cfg[GDC_MAX_PLANE];
};
struct gdc_dma_cfg {
int fd;
void *dev;
void *vaddr;
struct dma_buf *dbuf;
struct dma_buf_attachment *attach;
struct sg_table *sg;
enum dma_data_direction dir;
};
/* each configuration addresses and size */
struct gdc_config_s {
u32 format;
u32 config_addr; /* gdc config address */
u32 config_size; /* gdc config size in 32bit */
u32 input_width; /* gdc input width resolution */
u32 input_height; /* gdc input height resolution */
u32 input_y_stride; /* gdc input y stride resolution */
u32 input_c_stride; /* gdc input uv stride */
u32 output_width; /* gdc output width resolution */
u32 output_height; /* gdc output height resolution */
u32 output_y_stride; /* gdc output y stride */
u32 output_c_stride; /* gdc output uv stride */
};
struct gdc_cmd_s {
u32 outplane;
/* writing/reading to gdc base address, currently not read by api */
u32 base_gdc;
/* array of gdc configuration and sizes */
struct gdc_config_s gdc_config;
/* update this index for new config */
/* int gdc_config_total; */
/* start memory to write gdc output framse */
u32 buffer_addr;
/* size of memory output frames to determine */
/* if it is enough and can do multiple write points */
u32 buffer_size;
/* current output address of gdc */
u32 current_addr;
/* output address for u, v planes */
union {
u32 uv_out_base_addr;
u32 u_out_base_addr;
};
u32 v_out_base_addr;
/* set when expecting an interrupt from gdc */
s32 is_waiting_gdc;
/* input address for y and u, v planes */
u32 y_base_addr;
union {
u32 uv_base_addr;
u32 u_base_addr;
};
u32 v_base_addr;
unsigned char wait_done_flag;
};
struct gdc_context_s {
/* connect all process in one queue for RR process. */
struct list_head list;
/* current wq configuration */
u32 mmap_type;
dma_addr_t i_paddr;
dma_addr_t o_paddr;
dma_addr_t c_paddr;
void *i_kaddr;
void *o_kaddr;
void *c_kaddr;
unsigned long i_len;
unsigned long o_len;
unsigned long c_len;
struct gdc_dma_cfg y_dma_cfg;
struct gdc_dma_cfg uv_dma_cfg;
struct gdc_dma_cfg_t dma_cfg;
struct mutex d_mutext; /* for config context */
struct gdc_cmd_s cmd;
struct list_head work_queue;
struct list_head free_queue;
wait_queue_head_t cmd_complete;
int gdc_request_exit;
spinlock_t lock; /* for get and release item. */
};
enum {
NV12 = 1,
YV12,
Y_GREY,
YUV444_P,
RGB444_P,
FMT_MAX
};
/*
* two ways to load config bin.
* 1. loaded already, set use_builtin_fw 0, set config_paddr and config_size.
* 2. load through gdc driver, set use_builtin_fw 1, set config_name.
*/
struct gdc_phy_setting {
u32 format;
u32 in_width;
u32 in_height;
u32 out_width;
u32 out_height;
u32 in_plane_num;
u32 out_plane_num;
u32 in_paddr[GDC_MAX_PLANE];
u32 out_paddr[GDC_MAX_PLANE];
u32 config_paddr;
u32 config_size; /* in 32bit */
u32 use_builtin_fw;
char config_name[CONFIG_PATH_LENG];
};
int gdc_process_phys(struct gdc_context_s *context,
struct gdc_phy_setting *gs);
struct gdc_context_s *create_gdc_work_queue(void);
int destroy_gdc_work_queue(struct gdc_context_s *gdc_work_queue);
#endif