From dfd7a2da8e43fcdfeede4bda3948193b8c44d21f Mon Sep 17 00:00:00 2001 From: Cao Jian Date: Sat, 19 Oct 2019 18:30:55 +0800 Subject: [PATCH] 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 --- drivers/amlogic/media/gdc/app/gdc_dmabuf.h | 13 +- drivers/amlogic/media/gdc/app/gdc_module.c | 281 +++++++++++++----- drivers/amlogic/media/gdc/app/gdc_wq.c | 2 +- drivers/amlogic/media/gdc/app/gdc_wq.h | 45 +-- drivers/amlogic/media/gdc/inc/api/gdc_api.h | 72 +---- .../amlogic/media/gdc/inc/sys/system_log.h | 4 +- include/linux/amlogic/media/gdc/gdc.h | 173 +++++++++++ 7 files changed, 388 insertions(+), 202 deletions(-) create mode 100644 include/linux/amlogic/media/gdc/gdc.h diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.h b/drivers/amlogic/media/gdc/app/gdc_dmabuf.h index 1fc7ae04854b..5f56a5233813 100644 --- a/drivers/amlogic/media/gdc/app/gdc_dmabuf.h +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.h @@ -21,7 +21,7 @@ #include #include #include - +#include #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, diff --git a/drivers/amlogic/media/gdc/app/gdc_module.c b/drivers/amlogic/media/gdc/app/gdc_module.c index 5d9b4c857767..1dd5eb9bf573 100644 --- a/drivers/amlogic/media/gdc/app/gdc_module.c +++ b/drivers/amlogic/media/gdc/app/gdc_module.c @@ -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, diff --git a/drivers/amlogic/media/gdc/app/gdc_wq.c b/drivers/amlogic/media/gdc/app/gdc_wq.c index e5b53f3713a1..f2fb62f7ee2b 100644 --- a/drivers/amlogic/media/gdc/app/gdc_wq.c +++ b/drivers/amlogic/media/gdc/app/gdc_wq.c @@ -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); diff --git a/drivers/amlogic/media/gdc/app/gdc_wq.h b/drivers/amlogic/media/gdc/app/gdc_wq.h index 265ac276a5de..ee1d17cd1a04 100644 --- a/drivers/amlogic/media/gdc/app/gdc_wq.h +++ b/drivers/amlogic/media/gdc/app/gdc_wq.h @@ -19,64 +19,25 @@ #define _GDC_WQ_H_ #include -#include #include #include +#include #include +#include -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 diff --git a/drivers/amlogic/media/gdc/inc/api/gdc_api.h b/drivers/amlogic/media/gdc/inc/api/gdc_api.h index 5aa1c3165dbd..a57efe101366 100644 --- a/drivers/amlogic/media/gdc/inc/api/gdc_api.h +++ b/drivers/amlogic/media/gdc/inc/api/gdc_api.h @@ -19,7 +19,7 @@ #define __GDC_API_H__ #include -#include +#include 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" diff --git a/drivers/amlogic/media/gdc/inc/sys/system_log.h b/drivers/amlogic/media/gdc/inc/sys/system_log.h index cee79b4c956a..83b3bd4d3a45 100644 --- a/drivers/amlogic/media/gdc/inc/sys/system_log.h +++ b/drivers/amlogic/media/gdc/inc/sys/system_log.h @@ -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, diff --git a/include/linux/amlogic/media/gdc/gdc.h b/include/linux/amlogic/media/gdc/gdc.h new file mode 100644 index 000000000000..15c9faa9f07b --- /dev/null +++ b/include/linux/amlogic/media/gdc/gdc.h @@ -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 +#include +#include +#include + +#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