blob: d300258051f4fd37807d69c3a0beb37723c10903 [file] [log] [blame]
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#ifndef __GDC_API_H__
#define __GDC_API_H__
#include <linux/of_address.h>
#include <linux/amlogic/media/gdc/gdc.h>
enum gdc_memtype_s {
AML_GDC_MEM_ION,
AML_GDC_MEM_DMABUF,
AML_GDC_MEM_INVALID,
};
struct gdc_buf_cfg {
u32 type;
unsigned long len;
};
struct gdc_buffer_info {
unsigned int mem_alloc_type;
unsigned int plane_number;
union {
unsigned int y_base_fd;
unsigned int shared_fd;
};
union {
unsigned int uv_base_fd;
unsigned int u_base_fd;
};
unsigned int v_base_fd;
};
// overall gdc settings and state
struct gdc_settings {
u32 magic;
//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;
//set when expecting an interrupt from gdc
s32 is_waiting_gdc;
s32 in_fd; //input buffer's share fd
s32 out_fd; //output buffer's share fd
//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;
//opaque address in ddr added with offset to
//write the gdc config sequence
void *ddr_mem;
//when inititialised this callback will be called
//to update frame buffer addresses and offsets
void (*get_frame_buffer)(u32 y_base_addr,
u32 uv_base_addr,
u32 y_line_offset,
u32 uv_line_offset);
void *fh;
s32 y_base_fd;
union {
s32 uv_base_fd;
s32 u_base_fd;
};
s32 v_base_fd;
};
struct gdc_settings_ex {
u32 magic;
struct gdc_config_s gdc_config;
struct gdc_buffer_info input_buffer;
struct gdc_buffer_info config_buffer;
struct gdc_buffer_info output_buffer;
};
/* for gdc dma buf define */
struct gdc_dmabuf_req_s {
int index;
unsigned int len;
unsigned int dma_dir;
};
struct gdc_dmabuf_exp_s {
int index;
unsigned int flags;
int fd;
};
/* end of gdc dma buffer define */
#define GDC_IOC_MAGIC 'G'
#define GDC_PROCESS _IOW(GDC_IOC_MAGIC, 0x00, struct gdc_settings)
#define GDC_PROCESS_NO_BLOCK _IOW(GDC_IOC_MAGIC, 0x01, struct gdc_settings)
#define GDC_RUN _IOW(GDC_IOC_MAGIC, 0x02, struct gdc_settings)
#define GDC_REQUEST_BUFF _IOW(GDC_IOC_MAGIC, 0x03, struct gdc_settings)
#define GDC_HANDLE _IOW(GDC_IOC_MAGIC, 0x04, struct gdc_settings)
#define GDC_PROCESS_EX _IOW(GDC_IOC_MAGIC, 0x05, struct gdc_settings_ex)
#define GDC_REQUEST_DMA_BUFF _IOW(GDC_IOC_MAGIC, 0x06, struct gdc_dmabuf_req_s)
#define GDC_EXP_DMA_BUFF _IOW(GDC_IOC_MAGIC, 0x07, struct gdc_dmabuf_exp_s)
#define GDC_FREE_DMA_BUFF _IOW(GDC_IOC_MAGIC, 0x08, int)
#define GDC_SYNC_DEVICE _IOW(GDC_IOC_MAGIC, 0x09, int)
#define GDC_SYNC_CPU _IOW(GDC_IOC_MAGIC, 0x0a, int)
#define GDC_PROCESS_WITH_FW _IOW(GDC_IOC_MAGIC, 0x0b, \
struct gdc_settings_with_fw)
enum {
INPUT_BUFF_TYPE = 0x1000,
OUTPUT_BUFF_TYPE,
CONFIG_BUFF_TYPE,
GDC_BUFF_TYPE_MAX
};
/* format type and format bit width mask
* example: (NV12 | BIT_16) means nv12 16bit.
*/
#define FORMAT_TYPE_MASK 0xffff
#define FORMAT_IN_BITW_MASK 0x0f0000
#define FORMAT_OUT_BITW_MASK 0xf00000
enum {
NV12 = 1,
YV12,
Y_GREY,
YUV444_P,
RGB444_P,
FMT_MAX
};
enum {
IN_BITW_8 = 0, /* default input bit width */
IN_BITW_10 = (1 << 16),
IN_BITW_12 = (1 << 17),
IN_BITW_16 = (1 << 18),
OUT_BITW_8 = 0, /* default output bit width */
OUT_BITW_10 = (1 << 20),
OUT_BITW_12 = (1 << 21),
OUT_BITW_16 = (1 << 22)
};
enum {
EQUISOLID = 1,
CYLINDER,
EQUIDISTANT,
CUSTOM,
AFFINE,
FW_TYPE_MAX
};
/* path: "/vendor/lib/firmware/gdc/" */
#define FIRMWARE_DIR "gdc"
struct fw_equisolid_s {
/* float */
char strength_x[8];
/* float */
char strength_y[8];
int rotation;
};
struct fw_cylinder_s {
/* float */
char strength[8];
int rotation;
};
struct fw_equidistant_s {
/* float */
char azimuth[8];
int elevation;
int rotation;
int fov_width;
int fov_height;
bool keep_ratio;
int cylindricity_x;
int cylindricity_y;
};
struct fw_custom_s {
char *fw_name;
};
struct fw_affine_s {
int rotation;
};
struct fw_input_info_s {
int with;
int height;
int fov;
int diameter;
int offset_x;
int offset_y;
};
union transform_u {
struct fw_equisolid_s fw_equisolid;
struct fw_cylinder_s fw_cylinder;
struct fw_equidistant_s fw_equidistant;
struct fw_custom_s fw_custom;
struct fw_affine_s fw_affine;
};
struct fw_output_info_s {
int offset_x;
int offset_y;
int width;
int height;
union transform_u trans;
int pan;
int tilt;
/* float*/
char zoom[8];
};
struct firmware_info {
unsigned int format;
unsigned int trans_size_type;
char *file_name;
phys_addr_t phys_addr;
void __iomem *virt_addr;
unsigned int size;
struct page *cma_pages;
unsigned int loaded;
};
struct fw_info_s {
char *fw_name;
int fw_type;
struct page *cma_pages;
phys_addr_t phys_addr;
void __iomem *virt_addr;
struct fw_input_info_s fw_input_info;
struct fw_output_info_s fw_output_info;
};
struct gdc_settings_with_fw {
u32 magic;
struct gdc_config_s gdc_config;
struct gdc_buffer_info input_buffer;
struct gdc_buffer_info reserved;
struct gdc_buffer_info output_buffer;
struct fw_info_s fw_info;
};
struct gdc_pd {
/* powerdomain virtual device */
struct device *dev;
/* on:1 off:0 */
u32 status;
};
/**
* Configure the output gdc configuration
*
* address/size and buffer address/size; and resolution.
*
* More than one gdc settings can be accessed by index to a gdc_config_t.
*
* @param gdc_cmd_s - overall gdc settings and state
* @param gdc_config_num - selects the current gdc config to be applied
*
* @return 0 - success
* -1 - fail.
*/
int gdc_init(struct gdc_cmd_s *gdc_cmd, struct gdc_dma_cfg_t *dma_cfg,
u32 core_id);
/**
* This function stops the gdc block
*
* @param gdc_cmd_s - overall gdc settings and state
*
*/
void gdc_stop(struct gdc_cmd_s *gdc_cmd, u32 core_id);
/**
* This function starts the gdc block
*
* Writing 0->1 transition is necessary for trigger
*
* @param gdc_cmd_s - overall gdc settings and state
*
*/
void gdc_start(struct gdc_cmd_s *gdc_cmd, u32 core_id);
/**
* This function points gdc to
*
* its input resolution and yuv address and offsets
*
* Shown inputs to GDC are Y and UV plane address and offsets
*
* @param gdc_cmd_s - overall gdc settings and state
* @param active_width - input width resolution
* @param active_height - input height resolution
* @param y_base_addr - input Y base address
* @param uv_base_addr - input UV base address
* @param y_line_offset - input Y line buffer offset
* @param uv_line_offset- input UV line buffer offer
*
* @return 0 - success
* -1 - no interrupt from GDC.
*/
int gdc_process(struct gdc_cmd_s *gdc_cmd,
u32 y_base_addr,
u32 uv_base_addr,
struct gdc_dma_cfg_t *dma_cfg,
u32 core_id);
int gdc_process_yuv420p(struct gdc_cmd_s *gdc_cmd,
u32 y_base_addr,
u32 u_base_addr,
u32 v_base_addr,
struct gdc_dma_cfg_t *dma_cfg,
u32 core_id);
int gdc_process_y_grey(struct gdc_cmd_s *gdc_cmd,
u32 y_base_addr,
struct gdc_dma_cfg_t *dma_cfg,
u32 core_id);
int gdc_process_yuv444p(struct gdc_cmd_s *gdc_cmd,
u32 y_base_addr,
u32 u_base_addr,
u32 v_base_addr,
struct gdc_dma_cfg_t *dma_cfg,
u32 core_id);
int gdc_process_rgb444p(struct gdc_cmd_s *gdc_cmd,
u32 y_base_addr,
u32 u_base_addr,
u32 v_base_addr,
struct gdc_dma_cfg_t *dma_cfg,
u32 core_id);
/**
* This function gets the GDC output frame addresses
*
* and offsets and updates the frame buffer via callback
*
* if it is available Shown ouputs to GDC are
*
* Y and UV plane address and offsets
*
* @param gdc_cmd_s - overall gdc settings and state
*
* @return 0 - success
* -1 - unexpected interrupt from GDC.
*/
int gdc_get_frame(struct gdc_cmd_s *gdc_cmd);
/**
* This function points gdc to its input resolution
*
* and yuv address and offsets
*
* Shown inputs to GDC are Y and UV plane address and offsets
*
* @param gdc_cmd_s - overall gdc settings and state
*
* @return 0 - success
* -1 - no interrupt from GDC.
*/
int gdc_run(struct gdc_cmd_s *g, struct gdc_dma_cfg_t *dma_cfg, u32 core_id);
s32 init_gdc_io(struct device_node *dn, u32 dev_type);
int gdc_pwr_init(struct device *dev, struct gdc_pd *pd, u32 dev_type);
int gdc_pwr_config(bool enable, u32 dev_type, u32 core_id);
void gdc_pwr_remove(struct gdc_pd *pd);
#endif