259 lines
6.3 KiB
C
Executable file
259 lines
6.3 KiB
C
Executable file
#include <linux/module.h>
|
|
#include "vfe_os.h"
|
|
|
|
unsigned int vfe_dbg_en = 0;
|
|
unsigned int vfe_dbg_lv = 1;
|
|
EXPORT_SYMBOL_GPL(vfe_dbg_en);
|
|
EXPORT_SYMBOL_GPL(vfe_dbg_lv);
|
|
|
|
int os_gpio_request(struct vfe_gpio_cfg *gpio_list, __u32 group_count_max)
|
|
{
|
|
#ifdef VFE_GPIO
|
|
int ret = 0;
|
|
struct gpio_config pin_cfg;
|
|
if(gpio_list == NULL)
|
|
return -1;
|
|
|
|
if(gpio_list->gpio == GPIO_INDEX_INVALID)
|
|
return -1;
|
|
|
|
pin_cfg.gpio = gpio_list->gpio;
|
|
pin_cfg.mul_sel = gpio_list->mul_sel;
|
|
pin_cfg.pull = gpio_list->pull;
|
|
pin_cfg.drv_level = gpio_list->drv_level;
|
|
pin_cfg.data = gpio_list->data;
|
|
ret = gpio_request(pin_cfg.gpio, NULL);
|
|
if(0 != ret)
|
|
{
|
|
vfe_warn("os_gpio_request failed, gpio=%d, ret=0x%x, %d\n", gpio_list->gpio, ret, ret);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL_GPL(os_gpio_request);
|
|
int os_gpio_set(struct vfe_gpio_cfg *gpio_list, __u32 group_count_max)
|
|
{
|
|
#ifdef VFE_GPIO
|
|
struct gpio_config pin_cfg;
|
|
char pin_name[32];
|
|
__u32 config;
|
|
|
|
if(gpio_list == NULL)
|
|
return -1;
|
|
if(gpio_list->gpio == GPIO_INDEX_INVALID)
|
|
return -1;
|
|
|
|
pin_cfg.gpio = gpio_list->gpio;
|
|
pin_cfg.mul_sel = gpio_list->mul_sel;
|
|
pin_cfg.pull = gpio_list->pull;
|
|
pin_cfg.drv_level = gpio_list->drv_level;
|
|
pin_cfg.data = gpio_list->data;
|
|
|
|
if (!IS_AXP_PIN(pin_cfg.gpio)) {
|
|
/* valid pin of sunxi-pinctrl,
|
|
* config pin attributes individually.
|
|
*/
|
|
sunxi_gpio_to_name(pin_cfg.gpio, pin_name);
|
|
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, pin_cfg.mul_sel);
|
|
pin_config_set(SUNXI_PINCTRL, pin_name, config);
|
|
if (pin_cfg.pull != GPIO_PULL_DEFAULT) {
|
|
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_PUD, pin_cfg.pull);
|
|
pin_config_set(SUNXI_PINCTRL, pin_name, config);
|
|
}
|
|
if (pin_cfg.drv_level != GPIO_DRVLVL_DEFAULT) {
|
|
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DRV, pin_cfg.drv_level);
|
|
pin_config_set(SUNXI_PINCTRL, pin_name, config);
|
|
}
|
|
if (pin_cfg.data != GPIO_DATA_DEFAULT) {
|
|
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, pin_cfg.data);
|
|
pin_config_set(SUNXI_PINCTRL, pin_name, config);
|
|
}
|
|
} else if (IS_AXP_PIN(pin_cfg.gpio)) {
|
|
/* valid pin of axp-pinctrl,
|
|
* config pin attributes individually.
|
|
*/
|
|
sunxi_gpio_to_name(pin_cfg.gpio, pin_name);
|
|
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, pin_cfg.mul_sel);
|
|
pin_config_set(AXP_PINCTRL, pin_name, config);
|
|
if (pin_cfg.data != GPIO_DATA_DEFAULT) {
|
|
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, pin_cfg.data);
|
|
pin_config_set(AXP_PINCTRL, pin_name, config);
|
|
}
|
|
} else {
|
|
vfe_warn("invalid pin [%d] from sys-config\n", pin_cfg.gpio);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL_GPL(os_gpio_set);
|
|
|
|
int os_gpio_release(u32 p_handler, __s32 if_release_to_default_status)
|
|
{
|
|
#ifdef VFE_GPIO
|
|
if(p_handler != GPIO_INDEX_INVALID)
|
|
{
|
|
gpio_free(p_handler);
|
|
}
|
|
else
|
|
{
|
|
vfe_dbg(0, "os_gpio_release, hdl is INVALID\n");
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(os_gpio_release);
|
|
|
|
int os_gpio_write(u32 p_handler, __u32 value_to_gpio, const char *gpio_name, int force_value_flag)
|
|
{
|
|
#ifdef VFE_GPIO
|
|
if(1 == force_value_flag)
|
|
{
|
|
if(p_handler != GPIO_INDEX_INVALID)
|
|
{
|
|
__gpio_set_value(p_handler, value_to_gpio);
|
|
}
|
|
else
|
|
{
|
|
vfe_dbg(0,"os_gpio_write, hdl is INVALID\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(p_handler != GPIO_INDEX_INVALID)
|
|
{
|
|
if(value_to_gpio == 0)
|
|
{
|
|
os_gpio_set_status(p_handler, 1, gpio_name);
|
|
__gpio_set_value(p_handler, value_to_gpio);
|
|
}
|
|
else
|
|
{
|
|
os_gpio_set_status(p_handler, 0, gpio_name);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vfe_dbg(0,"os_gpio_write, hdl is INVALID\n");
|
|
}
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(os_gpio_write);
|
|
|
|
|
|
int os_gpio_set_status(u32 p_handler, __u32 if_set_to_output_status, const char *gpio_name)
|
|
{
|
|
int ret = 0;
|
|
#ifdef VFE_GPIO
|
|
if(p_handler != GPIO_INDEX_INVALID)
|
|
{
|
|
if(if_set_to_output_status)
|
|
{
|
|
ret = gpio_direction_output(p_handler, 0);
|
|
if(ret != 0)
|
|
{
|
|
vfe_warn("gpio_direction_output fail!\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret = gpio_direction_input(p_handler);
|
|
if(ret != 0)
|
|
{
|
|
vfe_warn("gpio_direction_input fail!\n");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vfe_warn("os_gpio_set_status, hdl is INVALID\n");
|
|
ret = -1;
|
|
}
|
|
#endif
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(os_gpio_set_status);
|
|
|
|
int os_mem_alloc(struct vfe_mm *mem_man)
|
|
{
|
|
#ifdef SUNXI_MEM
|
|
int ret = -1;
|
|
char *ion_name = "ion_vfe";
|
|
mem_man->client = sunxi_ion_client_create(ion_name);
|
|
if (IS_ERR_OR_NULL(mem_man->client))
|
|
{
|
|
vfe_err("sunxi_ion_client_create failed!!");
|
|
goto err_client;
|
|
}
|
|
mem_man->handle = ion_alloc(mem_man->client, mem_man->size, PAGE_SIZE,
|
|
/*ION_HEAP_CARVEOUT_MASK|*/ION_HEAP_TYPE_DMA_MASK, 0);
|
|
if (IS_ERR_OR_NULL(mem_man->handle))
|
|
{
|
|
vfe_err("ion_alloc failed!!");
|
|
goto err_alloc;
|
|
}
|
|
mem_man->vir_addr = ion_map_kernel( mem_man->client, mem_man->handle);
|
|
if (IS_ERR_OR_NULL(mem_man->vir_addr))
|
|
{
|
|
vfe_err("ion_map_kernel failed!!");
|
|
goto err_map_kernel;
|
|
}
|
|
ret = ion_phys( mem_man->client, mem_man->handle, (ion_phys_addr_t *)&mem_man->phy_addr, &mem_man->size );
|
|
if( ret )
|
|
{
|
|
vfe_err("ion_phys failed!!");
|
|
goto err_phys;
|
|
}
|
|
mem_man->dma_addr = mem_man->phy_addr + HW_DMA_OFFSET-CPU_DRAM_PADDR_ORG;
|
|
return 0;
|
|
err_phys:
|
|
ion_unmap_kernel( mem_man->client, mem_man->handle);
|
|
err_map_kernel:
|
|
ion_free(mem_man->client, mem_man->handle);
|
|
err_alloc:
|
|
ion_client_destroy(mem_man->client);
|
|
err_client:
|
|
return -1;
|
|
#else
|
|
mem_man->vir_addr = dma_alloc_coherent(NULL, (size_t)mem_man->size,
|
|
(dma_addr_t*)&mem_man->phy_addr, GFP_KERNEL);
|
|
if (!mem_man->vir_addr) {
|
|
vfe_err("dma_alloc_coherent memory alloc size %d failed\n", mem_man->size);
|
|
return -ENOMEM;
|
|
}
|
|
mem_man->dma_addr = mem_man->phy_addr + HW_DMA_OFFSET-CPU_DRAM_PADDR_ORG;
|
|
return 0;
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL_GPL(os_mem_alloc);
|
|
|
|
void os_mem_free(struct vfe_mm *mem_man)
|
|
{
|
|
#ifdef SUNXI_MEM
|
|
if (IS_ERR_OR_NULL(mem_man->client)||IS_ERR_OR_NULL(mem_man->handle)||IS_ERR_OR_NULL(mem_man->vir_addr))
|
|
return ;
|
|
ion_unmap_kernel(mem_man->client, mem_man->handle);
|
|
ion_free(mem_man->client, mem_man->handle);
|
|
ion_client_destroy(mem_man->client);
|
|
#else
|
|
if(mem_man->vir_addr)
|
|
dma_free_coherent(NULL, mem_man->size, mem_man->vir_addr, (dma_addr_t)mem_man->phy_addr);
|
|
#endif
|
|
mem_man->phy_addr = NULL;
|
|
mem_man->dma_addr = NULL;
|
|
mem_man->vir_addr = NULL;
|
|
}
|
|
EXPORT_SYMBOL_GPL(os_mem_free);
|
|
|
|
MODULE_AUTHOR("raymonxiu");
|
|
MODULE_LICENSE("Dual BSD/GPL");
|
|
MODULE_DESCRIPTION("Video front end OSAL for sunxi");
|
|
|
|
|