blob: 3119e6bbc2c86c45b8a5211dacea06d6b036a7e0 [file] [log] [blame]
// 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);
}