| // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| /* |
| * Copyright (c) 2019 Amlogic, Inc. All rights reserved. |
| */ |
| #include <linux/slab.h> |
| #include <linux/amlogic/media/gdc/gdc.h> |
| |
| #include "auto_gdc.h" |
| #include "auto_write.h" |
| |
| static void *auto_gdc_init(void) |
| { |
| struct gdc_context_s *g_ctx = NULL; |
| |
| g_ctx = create_gdc_work_queue(); |
| if (!g_ctx) |
| pr_err("Failed to init gdc context\n"); |
| |
| return g_ctx; |
| } |
| |
| static int auto_gdc_process(void *g_ctx, void *g_set) |
| { |
| s32 rtn = -1; |
| |
| if (!g_ctx || !g_set) { |
| pr_err("Error input param\n"); |
| return rtn; |
| } |
| |
| rtn = gdc_process_phys(g_ctx, g_set); |
| |
| return rtn; |
| } |
| |
| static int auto_gdc_deinit(void *g_ctx) |
| { |
| s32 rtn = -1; |
| |
| if (!g_ctx) { |
| pr_err("Error input param\n"); |
| return rtn; |
| } |
| |
| rtn = destroy_gdc_work_queue(g_ctx); |
| if (rtn < 0) |
| pr_err("Failed to deinit auto gdc\n"); |
| |
| return rtn; |
| } |
| |
| static void auto_gdc_cfg_addr(void *base, void *frm_info) |
| { |
| struct autowr_dev_base *dev_base = NULL; |
| struct autowr_frm_info *f_info = NULL; |
| struct gdc_phy_setting *g_set = NULL; |
| |
| if (!base || !frm_info) { |
| pr_err("Error input param\n"); |
| return; |
| } |
| |
| dev_base = base; |
| f_info = frm_info; |
| |
| switch (f_info->path_type) { |
| case AUTOWR_FR_PATH: |
| g_set = dev_base->fr_g_set; |
| break; |
| case AUTOWR_DS1_PATH: |
| g_set = dev_base->ds1_g_set; |
| break; |
| case AUTOWR_DS2_PATH: |
| g_set = dev_base->ds2_g_set; |
| break; |
| default: |
| pr_err("Error input path type\n"); |
| return; |
| } |
| |
| g_set->in_paddr[0] = f_info->input_addr; |
| g_set->out_paddr[0] = f_info->output_addr; |
| } |
| |
| void auto_gdc_cfg_setting(void *base, void *cfg_info) |
| { |
| struct autowr_dev_base *dev_base = NULL; |
| struct gdc_phy_setting *g_set = NULL; |
| struct autowr_gdc_cfg *gdc_cfg = NULL; |
| |
| if (!base || !cfg_info) { |
| pr_err("Error input param\n"); |
| return; |
| } |
| |
| dev_base = base; |
| gdc_cfg = cfg_info; |
| |
| switch (gdc_cfg->path_type) { |
| case AUTOWR_FR_PATH: |
| g_set = dev_base->fr_g_set; |
| break; |
| case AUTOWR_DS1_PATH: |
| g_set = dev_base->ds1_g_set; |
| break; |
| case AUTOWR_DS2_PATH: |
| g_set = dev_base->ds2_g_set; |
| break; |
| default: |
| pr_err("Error input path type\n"); |
| return; |
| } |
| |
| g_set->format = gdc_cfg->format; |
| g_set->in_plane_num = 1; |
| g_set->in_width = gdc_cfg->i_width; |
| g_set->in_height = gdc_cfg->i_height; |
| g_set->out_plane_num = 1; |
| g_set->out_width = gdc_cfg->o_width; |
| g_set->out_height = gdc_cfg->o_height; |
| g_set->use_builtin_fw = 1; |
| memcpy(g_set->config_name, |
| gdc_cfg->cfg_name, |
| sizeof(gdc_cfg->cfg_name)); |
| |
| pr_info("Success cfg path %u\n", gdc_cfg->path_type); |
| } |
| |
| int autowr_gdc_init(void *base, void *cfg_info) |
| { |
| s32 rtn = 0; |
| void *g_ctx = NULL; |
| void *g_set = NULL; |
| struct autowr_dev_base *dev_base = NULL; |
| struct autowr_gdc_cfg *gdc_cfg = NULL; |
| |
| if (!base || !cfg_info) { |
| pr_err("Error input param\n"); |
| return -1; |
| } |
| |
| dev_base = base; |
| gdc_cfg = cfg_info; |
| |
| switch (gdc_cfg->path_type) { |
| case AUTOWR_FR_PATH: |
| if (!dev_base->fr_g_ctx) { |
| dev_base->fr_g_ctx = auto_gdc_init(); |
| dev_base->fr_g_set = |
| kzalloc(sizeof(struct gdc_phy_setting), GFP_KERNEL); |
| } |
| g_ctx = dev_base->fr_g_ctx; |
| g_set = dev_base->fr_g_set; |
| break; |
| case AUTOWR_DS1_PATH: |
| if (!dev_base->ds1_g_ctx) { |
| dev_base->ds1_g_ctx = auto_gdc_init(); |
| dev_base->ds1_g_set = |
| kzalloc(sizeof(struct gdc_phy_setting), GFP_KERNEL); |
| } |
| g_ctx = dev_base->ds1_g_ctx; |
| g_set = dev_base->ds1_g_set; |
| break; |
| case AUTOWR_DS2_PATH: |
| if (!dev_base->ds2_g_ctx) { |
| dev_base->ds2_g_ctx = auto_gdc_init(); |
| dev_base->ds2_g_set = |
| kzalloc(sizeof(struct gdc_phy_setting), GFP_KERNEL); |
| } |
| g_ctx = dev_base->ds2_g_ctx; |
| g_set = dev_base->ds2_g_set; |
| break; |
| default: |
| rtn = -1; |
| pr_err("Error input path type\n"); |
| break; |
| } |
| |
| if (!g_ctx && !g_set) { |
| pr_err("Failed to init autowr gdc\n"); |
| return -1; |
| } |
| |
| pr_info("Success init path %u\n", gdc_cfg->path_type); |
| |
| return rtn; |
| } |
| |
| int autowr_gdc_process(void *base, void *frm_info) |
| { |
| s32 rtn = -1; |
| void *g_ctx = NULL; |
| void *g_set = NULL; |
| struct autowr_frm_info *f_info = NULL; |
| struct autowr_dev_base *dev_base = NULL; |
| |
| if (!base || !frm_info) { |
| pr_err("Error input param\n"); |
| return rtn; |
| } |
| |
| dev_base = base; |
| f_info = frm_info; |
| |
| if (f_info->input_addr == 0x0 && f_info->output_addr == 0x0) |
| return rtn; |
| |
| auto_gdc_cfg_addr(base, frm_info); |
| |
| switch (f_info->path_type) { |
| case AUTOWR_FR_PATH: |
| g_ctx = dev_base->fr_g_ctx; |
| g_set = dev_base->fr_g_set; |
| break; |
| case AUTOWR_DS1_PATH: |
| g_ctx = dev_base->ds1_g_ctx; |
| g_set = dev_base->ds1_g_set; |
| break; |
| case AUTOWR_DS2_PATH: |
| g_ctx = dev_base->ds2_g_ctx; |
| g_set = dev_base->ds2_g_set; |
| break; |
| default: |
| pr_err("Error input path type\n"); |
| return rtn; |
| } |
| |
| rtn = auto_gdc_process(g_ctx, g_set); |
| if (rtn < 0) |
| pr_err("Failed to gdc process\n"); |
| |
| return rtn; |
| } |
| |
| void autowr_gdc_deinit(void *base, void *frm_info) |
| { |
| void **g_ctx = NULL; |
| void **g_set = NULL; |
| struct autowr_frm_info *f_info = NULL; |
| struct autowr_dev_base *dev_base = NULL; |
| |
| if (!base || !frm_info) { |
| pr_err("Error input param\n"); |
| return; |
| } |
| |
| dev_base = base; |
| f_info = frm_info; |
| |
| switch (f_info->path_type) { |
| case AUTOWR_FR_PATH: |
| g_ctx = &dev_base->fr_g_ctx; |
| g_set = &dev_base->fr_g_set; |
| break; |
| case AUTOWR_DS1_PATH: |
| g_ctx = &dev_base->ds1_g_ctx; |
| g_set = &dev_base->ds1_g_set; |
| break; |
| case AUTOWR_DS2_PATH: |
| g_ctx = &dev_base->ds2_g_ctx; |
| g_set = &dev_base->ds2_g_set; |
| break; |
| default: |
| pr_err("Error input path type\n"); |
| return; |
| } |
| |
| if (g_ctx && *g_ctx) { |
| auto_gdc_deinit(*g_ctx); |
| *g_ctx = NULL; |
| } |
| |
| if (g_set && *g_set) { |
| kfree(*g_set); |
| *g_set = NULL; |
| } |
| |
| pr_info("Success deinit path %u\n", f_info->path_type); |
| } |