=============================
struct camera2_shot {
/*google standard area*/
struct camera2_ctl ctl;
struct camera2_dm dm;
/*user defined area*/
struct camera2_uctl uctl;
struct camera2_udm udm;
/*magic : 23456789*/
uint32_t magicNumber;
};
struct camera2_ctl {
struct camera2_request_ctl request;
struct camera2_lens_ctl lens;
struct camera2_sensor_ctl sensor;
struct camera2_flash_ctl flash;
struct camera2_hotpixel_ctl hotpixel;
struct camera2_demosaic_ctl demosaic;
struct camera2_noisereduction_ctl noise;
struct camera2_shading_ctl shading;
struct camera2_geometric_ctl geometric;
struct camera2_colorcorrection_ctl color;
struct camera2_tonemap_ctl tonemap;
struct camera2_edge_ctl edge;
struct camera2_scaler_ctl scaler;
struct camera2_jpeg_ctl jpeg;
struct camera2_stats_ctl stats;
struct camera2_aa_ctl aa;
struct camera2_entry_ctl entry;
};
<6>[ 93.536725] [0] [@]fimc_is_fw2.bin version : E5260 4098-2014/02/05 16:19:19]C08LSHB01AJ
<6>[ 93.537416] [0] [@]Camera: the default FW were applied successfully.
<6>[ 93.537430] [0] [@][0][ISC:D] imemory.base(dvaddr) : 0x50000000
<6>[ 93.537441] [0] [@][0][ISC:D] imemory.base(kvaddr) : 0xE1C01000
frame 버퍼 6개를 만든다.
plane 4개중에 2개를 사용한다.
<6>[ 93.604983] [1] [@][0][ISP:V] fimc_is_isp_video_set_format_mplane
<6>[ 93.604998] [1] [@][VID:V] set_format(1936 x 1090)
<6>[ 93.605020] [1] [@][0][ISP:V] fimc_is_isp_video_reqbufs(buffers : 6)
<6>[ 93.605036] [1] [@][0][ISP:V] fimc_is_isp_queue_setup
<6>[ 93.605049] [1] [@][VID:V] queue[0] size : 3383360
<6>[ 93.605059] [1] [@][VID:V] queue[1] size : 32768
<6>[ 93.537732] [0] [@][ISC:D:0] fimc_is_ischain_open(0)
<6>[ 93.538127] [0] [@][SCC:V:0] fimc_is_scc_video_open
<6>[ 93.538364] [0] [@][SCP:V:0] fimc_is_scp_video_open
<6>[ 93.539165] [0] [@][1][SS0:V] fimc_is_sen_video_set_format_mplane
<6>[ 93.539178] [0] [@][VID:V] set_format(1936 x 1090)
<6>[ 93.539193] [0] [@][1][FRT:D] csi_s_format(1936x1090, 32314742)
<6>[ 93.539206] [0] [@][1][BAK:D] flite_s_format(1936x1090, 32314742)
<6>[ 93.539218] [0] sensor mode(1936x1090@30) = 0
<6>[ 93.539240] [0] [@][1][SS0:V] fimc_is_sen_video_reqbufs(buffers : 6)
<6>[ 93.539256] [0] [@][1][SS0:V] fimc_is_sen_queue_setup
<6>[ 93.539269] [0] [@][VID:V] queue[0] size : 3383360
<6>[ 93.539279] [0] [@][VID:V] queue[1] size : 32768
=============================================
Terms
=============================================
AFS (auto-focus single shot)
AFC (auto-focus continuous)
DNR (Digital Noise Reduction)
FD (Face Detection)
=============================================
source files
=============================================
.. fimc-is-interface.c
- 5260 과 ISP CPU 와의 인터페이스를 담당한다.
1. 레지스터 셋팅
=============================================
Linux Driver
=============================================
>>>>> module_platform_driver
platform_driver_register 와
platform_driver_unregister 를 등록해주는
매크로일 뿐이다.
=============================================
V4L2
=============================================
>>>>> void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
struct v4l2_subdev 구조체에 0또는 null 로 초기화 하고
두번째 파라미터를 연결시켜주는 작업을 한다.
>>>>> int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
struct v4l2_subdev *sd)
v4l2 서브 디바이스로 등록한다.
그러므로 위의 함수는 초기화만 담당하기 때문 서브 디바이스로의 역할을 하기 위해서는
레지스터가 되어야 한다.
core.c v4l2 의 디바이스로 등록됨.
(flite.c, csi.c, sensor.c)
>>>>> static inline void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p)
{
sd->dev_priv = p; // 포인터 연결만 해줌.
}
>>>>> static inline void v4l2_set_subdev_hostdata(struct v4l2_subdev *sd, void *p)
{
sd->host_priv = p; // 포인터 연결만 해줌.
}
setup-fimc-is-sensor.c
GPIO, CLK,
board-mv5260-camera.c*
static struct exynos_platform_fimc_is_sensor s5k3h7 = {
.scenario = SENSOR_SCENARIO_NORMAL, //0
.mclk_ch = 0,
.csi_ch = CSI_ID_A, // 0
.flite_ch = FLITE_ID_A, // 0
.i2c_ch = SENSOR_CONTROL_I2C0, // 0
.i2c_addr = 0x20,
.is_bns = 0,
.flash_first_gpio = 5,
.flash_second_gpio = 8,
};
struct fimc_is_device_sensor {
struct v4l2_device v4l2_dev;
struct platform_device *pdev;
struct fimc_is_mem mem;
u32 instance;
struct fimc_is_image image;
struct fimc_is_video_ctx *vctx;
struct fimc_is_video video;
struct fimc_is_device_ischain *ischain;
struct fimc_is_resourcemgr *resourcemgr;
struct fimc_is_module_enum module_enum[SENSOR_MAX_ENUM/*20*/];
/* current control value */
struct camera2_sensor_ctl sensor_ctl;
struct camera2_lens_ctl lens_ctl;
struct camera2_flash_ctl flash_ctl;
struct work_struct control_work;
struct fimc_is_frame *control_frame;
u32 fcount;
u32 instant_cnt;
int instant_ret;
wait_queue_head_t instant_wait;
struct work_struct instant_work;
unsigned long state;
spinlock_t slock_state;
/* hardware configuration */
struct v4l2_subdev *subdev_module;
struct v4l2_subdev *subdev_csi;
struct v4l2_subdev *subdev_flite;
int mode;
/* gain boost */
int min_target_fps;
int max_target_fps;
int scene_mode;
/* for vision control */
int exposure_time;
u64 frame_duration;
/* ENABLE_DTP */
bool dtp_check;
struct timer_list dtp_timer;
struct exynos_platform_fimc_is_sensor *pdata;
static struct exynos_platform_fimc_is_sensor s5k3h7 = {
.scenario = SENSOR_SCENARIO_NORMAL,
.mclk_ch = 0,
.csi_ch = CSI_ID_A,
.flite_ch = FLITE_ID_A,
.i2c_ch = SENSOR_CONTROL_I2C0,
.i2c_addr = 0x20,
.is_bns = 0,
.flash_first_gpio = 5,
.flash_second_gpio = 8,
};
void *private_data;
};
하나가 생성됨.
struct fimc_is_core {
struct platform_device *pdev;
struct resource *regs_res;
void __iomem *regs;
int irq;
u32 id;
u32 debug_cnt;
atomic_t rsccount;
unsigned long state;
/* depended on isp */
struct exynos_platform_fimc_is *pdata;
struct fimc_is_resourcemgr resourcemgr;
struct fimc_is_groupmgr groupmgr;
struct fimc_is_minfo minfo;
struct fimc_is_mem mem;
struct fimc_is_interface interface;
struct fimc_is_device_sensor sensor[FIMC_IS_MAX_NODES/*3*/];
struct fimc_is_device_ischain ischain[FIMC_IS_MAX_NODES/*3*/];
struct v4l2_device v4l2_dev;
/* 0-bayer, 1-scalerC, 2-3DNR, 3-scalerP */
struct fimc_is_video video_3a0;
struct fimc_is_video video_3a1;
struct fimc_is_video video_isp;
struct fimc_is_video video_scc;
struct fimc_is_video video_scp;
struct fimc_is_video video_vdc;
struct fimc_is_video video_vdo;
struct fimc_is_video video_3a0c;
struct fimc_is_video video_3a1c;
/* spi */
struct spi_device *spi0;
struct spi_device *spi1;
struct spi_device *t_spi;
};
struct fimc_is_core {
struct platform_device *pdev;
struct resource *regs_res;
void __iomem *regs;
int irq;
u32 id;
u32 debug_cnt;
atomic_t rsccount;
unsigned long state;
/* depended on isp */
struct exynos_platform_fimc_is *pdata;
맨 아래 문서에 있음.
struct fimc_is_resourcemgr resourcemgr;
struct fimc_is_groupmgr groupmgr;
struct fimc_is_minfo minfo;
offset = FW_SHARED_OFFSET; //0x013C0000
minfo.dvaddr_fshared = this->minfo.dvaddr + offset;
minfo.kvaddr_fshared = this->minfo.kvaddr + offset;
offset = FIMC_IS_A5_MEM_SIZE - FIMC_IS_REGION_SIZE; //0x01400000 - 0x00005000 = 0x13FB000
minfo.dvaddr_region = this->minfo.dvaddr + offset;
minfo.kvaddr_region = this->minfo.kvaddr + offset;
offset = FIMC_IS_A5_MEM_SIZE;
minfo.dvaddr_odc = 0;
minfo.kvaddr_odc = 0;
minfo.dvaddr_dis = 0;
minfo.kvaddr_dis = 0;
minfo.dvaddr_3dnr = 0;
minfo.kvaddr_3dnr = 0;
fimc_is_mem_probe()
struct fimc_is_mem mem;
vb2.ops = &vb2_ion_memops,
vb2.init = fimc_is_ion_init,
vb2.cleanup = vb2_ion_destroy_context,
vb2.plane_addr = plane_addr,
vb2.plane_kvaddr = plane_kvaddr,
vb2.resume = vb2_ion_attach_iommu,
vb2.suspend = vb2_ion_detach_iommu,
vb2.set_cacheable = vb2_ion_set_cached,
ctx->dev = dev;
ctx->client = ion_client_create(ion_exynos, dev_name(dev));
ctx->flags = VB2ION_CTX_IOMMU |VB2ION_CTX_VMCONTIG|VB2ION_CTX_KVA_ONDEMAND;
struct fimc_is_interface interface;
struct fimc_is_interface {
void __iomem *regs; //MCUCTLR address
struct is_common_reg __iomem *com_regs; //ISSR0 address
bool need_iflag;
unsigned long state;
spinlock_t process_barrier;//init_process_barrier(this);
struct mutex request_barrier;//init_request_barrier(this);
atomic_t lock_pid;
wait_queue_head_t lock_wait_queue;
wait_queue_head_t init_wait_queue;
wait_queue_head_t idle_wait_queue;
struct fimc_is_msg reply;
#ifdef MEASURE_TIME
#ifdef INTERFACE_TIME
struct fimc_is_interface_time time[HIC_COMMAND_END];
#endif
#endif
struct workqueue_struct *workqueue;
struct work_struct work_wq[INTR_MAX_MAP/*8*/];
인터럽트 함수 등록
struct fimc_is_work_list work_list[INTR_MAX_MAP/*8*/];
struct fimc_is_work_list {
u32 id;
struct fimc_is_work work[MAX_WORK_COUNT];
spinlock_t slock_free;
spinlock_t slock_request;
struct list_head work_free_head;
u32 work_free_cnt;
struct list_head work_request_head;
u32 work_request_cnt;
wait_queue_head_t wait_queue;
};
/* sensor streaming flag */
enum streaming_state streaming[FIMC_IS_MAX_NODES];
/* firmware processing flag */
enum processing_state processing[FIMC_IS_MAX_NODES];
/* frrmware power down ready flag */
enum pdown_ready_state pdown_ready;
struct fimc_is_framemgr *framemgr;
struct fimc_is_work_list nblk_cam_ctrl;
/* shot timeout check */
spinlock_t shot_check_lock;
atomic_t shot_check[FIMC_IS_MAX_NODES];
atomic_t shot_timeout[FIMC_IS_MAX_NODES];
/* sensor timeout check */
atomic_t sensor_check[FIMC_IS_MAX_NODES];
atomic_t sensor_timeout[FIMC_IS_MAX_NODES];
struct timer_list timer;
struct camera2_uctl isp_peri_ctl;
void *core;
};
struct fimc_is_device_sensor sensor[FIMC_IS_MAX_NODES/*3*/];
struct fimc_is_device_ischain ischain[FIMC_IS_MAX_NODES/*3*/];
struct v4l2_device v4l2_dev;
/* 0-bayer, 1-scalerC, 2-3DNR, 3-scalerP */
struct fimc_is_video video_3a0;
struct fimc_is_video video_3a1;
struct fimc_is_video video_isp;
video->id = FIMC_IS_VIDEO_ISP_NUM; //30
video->vb2 = mem->vb2;
video->alloc_ctx = mem->alloc_ctx;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
video->vd.vfl_dir = VFL_DIR_M2M;
#endif
video->vd.v4l2_dev = v4l2_dev;
video->vd.fops = fops;
video->vd.ioctl_ops = ioctl_ops;
video->vd.minor = -1;
video->vd.release = video_device_release;
video->vd.lock = lock;
video->vd.name = FIMC_IS_VIDEO_ISP_NAME; //"exynos5-fimc-is-isp"
const struct v4l2_file_operations fimc_is_isp_video_fops = {
.owner = THIS_MODULE,
.open = fimc_is_isp_video_open,
.release = fimc_is_isp_video_close,
.poll = fimc_is_isp_video_poll,
.unlocked_ioctl = video_ioctl2,
.mmap = fimc_is_isp_video_mmap,
};
const struct v4l2_ioctl_ops fimc_is_isp_video_ioctl_ops = {
.vidioc_querycap = fimc_is_isp_video_querycap,
.vidioc_enum_fmt_vid_out_mplane = fimc_is_isp_video_enum_fmt_mplane,
.vidioc_g_fmt_vid_out_mplane = fimc_is_isp_video_get_format_mplane,
.vidioc_s_fmt_vid_out_mplane = fimc_is_isp_video_set_format_mplane,
.vidioc_cropcap = fimc_is_isp_video_cropcap,
.vidioc_g_crop = fimc_is_isp_video_get_crop,
.vidioc_s_crop = fimc_is_isp_video_set_crop,
.vidioc_reqbufs = fimc_is_isp_video_reqbufs,
.vidioc_querybuf = fimc_is_isp_video_querybuf,
.vidioc_qbuf = fimc_is_isp_video_qbuf,
.vidioc_dqbuf = fimc_is_isp_video_dqbuf,
.vidioc_streamon = fimc_is_isp_video_streamon,
.vidioc_streamoff = fimc_is_isp_video_streamoff,
.vidioc_enum_input = fimc_is_isp_video_enum_input,
.vidioc_g_input = fimc_is_isp_video_g_input,
.vidioc_s_input = fimc_is_isp_video_s_input,
.vidioc_s_ctrl = fimc_is_isp_video_s_ctrl,
.vidioc_g_ctrl = fimc_is_isp_video_g_ctrl,
.vidioc_g_ext_ctrls = fimc_is_isp_video_g_ext_ctrl,
};
const struct vb2_ops fimc_is_isp_qops = {
.queue_setup = fimc_is_isp_queue_setup,
.buf_prepare = fimc_is_isp_buffer_prepare,
.buf_queue = fimc_is_isp_buffer_queue,
.buf_finish = fimc_is_isp_buffer_finish,
.wait_prepare = fimc_is_isp_wait_prepare,
.wait_finish = fimc_is_isp_wait_finish,
.start_streaming = fimc_is_isp_start_streaming,
.stop_streaming = fimc_is_isp_stop_streaming,
};
struct fimc_is_video video_scc;
struct fimc_is_video video_scp;
struct fimc_is_video video_vdc;
struct fimc_is_video video_vdo;
struct fimc_is_video video_3a0c;
struct fimc_is_video video_3a1c;
/* spi */
struct spi_device *spi0;
struct spi_device *spi1;
struct spi_device *t_spi;
};
******* ischain *******
********************************
static const struct sensor_param init_sensor_param = {
.config = {
#ifdef FIXED_FPS_DEBUG //X
.framerate = FIXED_FPS_VALUE,
.min_target_fps = FIXED_FPS_VALUE,
.max_target_fps = FIXED_FPS_VALUE,
#else
.framerate = 30,
.min_target_fps = 15,
.max_target_fps = 30,
#endif
},
};
******* CORE Memory Info *******
********************************
struct fimc_is_minfo {
dma_addr_t base; /* buffer base */
size_t size; /* total length */
dma_addr_t vaddr_base; /* buffer base */
dma_addr_t vaddr_curr; /* current addr */
void *bitproc_buf;
void *fw_cookie;
u32 dvaddr; // Device Virtual Address
u32 kvaddr; // Kernel Virtual Address
u32 dvaddr_debug;
u32 kvaddr_debug;
u32 dvaddr_fshared;
u32 kvaddr_fshared;
u32 dvaddr_region;
u32 kvaddr_region;
u32 dvaddr_shared; /*shared region of is region*/
u32 kvaddr_shared;
u32 dvaddr_odc;
u32 kvaddr_odc;
u32 dvaddr_dis;
u32 kvaddr_dis;
u32 dvaddr_3dnr;
u32 kvaddr_3dnr;
};
struct fimc_is_mem {
struct platform_device *pdev;
struct vb2_alloc_ctx *alloc_ctx;
const struct fimc_is_vb2 *vb2;
};
const struct fimc_is_vb2 fimc_is_vb2_ion = {
.ops = &vb2_ion_memops,
.init = fimc_is_ion_init,
.cleanup = vb2_ion_destroy_context,
.plane_addr = plane_addr,
.plane_kvaddr = plane_kvaddr,
.resume = vb2_ion_attach_iommu,
.suspend = vb2_ion_detach_iommu,
.set_cacheable = vb2_ion_set_cached,
};
struct vb2_ion_context {
struct device *dev;
struct ion_client *client;
unsigned long alignment;
long flags;
/* protects iommu_active_cnt and protected */
struct mutex lock;
int iommu_active_cnt;
bool protected;
};
struct fimc_is_minfo minfo;
offset = FW_SHARED_OFFSET; //0x013C0000
this->minfo.dvaddr_fshared = this->minfo.dvaddr + offset;
this->minfo.kvaddr_fshared = this->minfo.kvaddr + offset;
offset = FIMC_IS_A5_MEM_SIZE - FIMC_IS_REGION_SIZE; //0x01400000 - 0x00005000 = 0x13FB000
this->minfo.dvaddr_region = this->minfo.dvaddr + offset;
this->minfo.kvaddr_region = this->minfo.kvaddr + offset;
offset = FIMC_IS_A5_MEM_SIZE;
this->minfo.dvaddr_odc = 0;
this->minfo.kvaddr_odc = 0;
this->minfo.dvaddr_dis = 0;
this->minfo.kvaddr_dis = 0;
this->minfo.dvaddr_3dnr = 0;
this->minfo.kvaddr_3dnr = 0;
******* ISP Video Function *******
**********************************
ret = fimc_is_video_probe(video,
FIMC_IS_VIDEO_ISP_NAME,
FIMC_IS_VIDEO_ISP_NUM,
VFL_DIR_M2M,
&core->mem,
&core->v4l2_dev,
&video->lock,
&fimc_is_isp_video_fops,
&fimc_is_isp_video_ioctl_ops);
if (ret)
dev_err(&core->pdev->dev, "%s is fail(%d)\n", __func__, ret);
struct fimc_is_mem {
struct platform_device *pdev;
struct vb2_alloc_ctx *alloc_ctx;
const struct fimc_is_vb2 *vb2;
};
fimc-is-device-3h7.c
struct fimc_is_module_enum module_enum[SENSOR_MAX_ENUM/*20*/];
========================================
platform data
========================================
pdata->cfg_gpio = exynos5260_fimc_is_cfg_gpio;
pdata->clk_cfg = exynos5260_fimc_is_cfg_clk;
pdata->clk_on = exynos5260_fimc_is_clk_on;
pdata->clk_off = exynos5260_fimc_is_clk_off;
pdata->print_clk = exynos5260_fimc_is_print_clk;
pdata->print_cfg = exynos5260_fimc_is_print_cfg;
pdata->gate_info->user_clk_gate = exynos5260_fimc_is_set_user_clk_gate;
pdata->gate_info->clk_on_off = exynos5260_fimc_is_clk_gate;
pdata->subip_info
static struct exynos_fimc_is_subip_info subip_info = {
._mcuctl = {
.valid = 1,
.full_bypass = 0,
.version = 161,
.base_addr = 0,
},
._3a0 = {
.valid = 0,
.full_bypass = 0,
.version = 0,
.base_addr = 0,
},
._3a1 = {
.valid = 0,
.full_bypass = 0,
.version = 0,
.base_addr = 0,
},
._isp = {
.valid = 1,
.full_bypass = 0,
.version = 0,
.base_addr = 0,
},
._drc = {
.valid = 1,
.full_bypass = 0,
.version = 0,
.base_addr = 0,
},
._scc = {
.valid = 1,
.full_bypass = 0,
.version = 0,
.base_addr = 0,
},
._odc = {
.valid = 0,
.full_bypass = 0,
.version = 0,
.base_addr = 0,
},
._dis = {
.valid = 0,
.full_bypass = 0,
.version = 0,
.base_addr = 0,
},
._dnr = {
.valid = 0,
.full_bypass = 0,
.version = 0,
.base_addr = 0,
},
._scp = {
.valid = 1,
.full_bypass = 0,
.version = 0,
.base_addr = 0,
},
._fd = {
.valid = 1,
.full_bypass = 0,
.version = 0,
.base_addr = 0,
},
._pwm = {
.valid = 1,
.full_bypass = 0,
.version = 0,
.base_addr = 0x13160000,
},
};
pdata->gate_info
struct exynos_fimc_is_clk_gate_info gate_info = {
.groups = {
[FIMC_IS_GRP_3A0] = {
.mask_clk_on_org = 0,
.mask_clk_on_mod = 0,
.mask_clk_off_self_org = 0,
.mask_clk_off_self_mod = 0,
.mask_clk_off_depend = 0,
.mask_cond_for_depend = 0,
},
[FIMC_IS_GRP_3A1] = {
.mask_clk_on_org = 0,
.mask_clk_on_mod = 0,
.mask_clk_off_self_org = 0,
.mask_clk_off_self_mod = 0,
.mask_clk_off_depend = 0,
.mask_cond_for_depend = 0,
},
[FIMC_IS_GRP_ISP] = {
.mask_clk_on_org =
(1 << FIMC_IS_GATE_ISP_IP) |
(1 << FIMC_IS_GATE_DRC_IP) |
(1 << FIMC_IS_GATE_SCC_IP) |
(1 << FIMC_IS_GATE_SCP_IP) |
(1 << FIMC_IS_GATE_FD_IP),
.mask_clk_on_mod = 0,
.mask_clk_off_self_org =
(1 << FIMC_IS_GATE_ISP_IP) |
(1 << FIMC_IS_GATE_DRC_IP) |
(1 << FIMC_IS_GATE_SCC_IP) |
(1 << FIMC_IS_GATE_SCP_IP) |
(1 << FIMC_IS_GATE_FD_IP),
.mask_clk_off_self_mod = 0,
.mask_clk_off_depend = 0,
.mask_cond_for_depend = 0,
},
[FIMC_IS_GRP_DIS] = {
.mask_clk_on_org = 0,
.mask_clk_on_mod = 0,
.mask_clk_off_self_org = 0,
.mask_clk_off_self_mod = 0,
.mask_clk_off_depend = 0,
.mask_cond_for_depend = 0,
},
},
};
'Hello Android' 카테고리의 다른 글
리눅스에서 쉘 ftp (0) | 2015.08.20 |
---|---|
install jenkins on ubuntu 12.04 (0) | 2015.07.27 |
[eclipse] java version 변경 (0) | 2014.08.05 |
your project contains errors) please fix them before running your application (0) | 2014.08.05 |
[우분투] 환경설정 (0) | 2014.07.11 |