From 8602650d636b32c01fd11337dffc1df310f024e6 Mon Sep 17 00:00:00 2001 From: SW.LEE Date: Wed, 2 Jul 2008 22:36:46 +0100 Subject: [PATCH] introduce-samsung-camera-unit-driver.patch This is the kernel side of an old (2004) samsung camera driver for 2440 It doesn't compile on modern kernel yet, this patch introduces it into the kernel tree without gross mods, so it is broken code we can start to work on --- arch/arm/mach-s3c2440/Kconfig | 4 +- arch/arm/mach-s3c2440/Makefile | 26 +- arch/arm/mach-s3c2440/camera/Kconfig | 7 + arch/arm/mach-s3c2440/camera/Makefile | 9 + arch/arm/mach-s3c2440/camera/bits.h | 48 ++ arch/arm/mach-s3c2440/camera/cam_reg.h | 220 ++++++ arch/arm/mach-s3c2440/camera/camif.c | 978 +++++++++++++++++++++++++++ arch/arm/mach-s3c2440/camera/camif.h | 304 +++++++++ arch/arm/mach-s3c2440/camera/camif_fsm.c | 427 ++++++++++++ arch/arm/mach-s3c2440/camera/imgsensor.c | 255 +++++++ arch/arm/mach-s3c2440/camera/miscdevice.h | 18 + arch/arm/mach-s3c2440/camera/qt-driver.c | 169 +++++ arch/arm/mach-s3c2440/camera/qt.h | 18 + arch/arm/mach-s3c2440/camera/s5x532.h | 143 ++++ arch/arm/mach-s3c2440/camera/s5x532_rev36.h | 208 ++++++ arch/arm/mach-s3c2440/camera/sensor.h | 20 + arch/arm/mach-s3c2440/camera/sxga.h | 504 ++++++++++++++ arch/arm/mach-s3c2440/camera/userapp.h | 44 ++ arch/arm/mach-s3c2440/camera/v4l2_api.c | 311 +++++++++ arch/arm/mach-s3c2440/camera/video-driver.c | 591 ++++++++++++++++ arch/arm/mach-s3c2440/camera/videodev.c | 342 ++++++++++ arch/arm/mach-s3c2440/camera/videodev.h | 110 +++ arch/arm/mach-s3c2440/camera/videodev2.h | 938 +++++++++++++++++++++++++ 23 files changed, 5668 insertions(+), 26 deletions(-) create mode 100644 arch/arm/mach-s3c2440/camera/Kconfig create mode 100644 arch/arm/mach-s3c2440/camera/Makefile create mode 100644 arch/arm/mach-s3c2440/camera/bits.h create mode 100644 arch/arm/mach-s3c2440/camera/cam_reg.h create mode 100644 arch/arm/mach-s3c2440/camera/camif.c create mode 100644 arch/arm/mach-s3c2440/camera/camif.h create mode 100644 arch/arm/mach-s3c2440/camera/camif_fsm.c create mode 100644 arch/arm/mach-s3c2440/camera/imgsensor.c create mode 100644 arch/arm/mach-s3c2440/camera/miscdevice.h create mode 100644 arch/arm/mach-s3c2440/camera/qt-driver.c create mode 100644 arch/arm/mach-s3c2440/camera/qt.h create mode 100644 arch/arm/mach-s3c2440/camera/s5x532.h create mode 100644 arch/arm/mach-s3c2440/camera/s5x532_rev36.h create mode 100644 arch/arm/mach-s3c2440/camera/sensor.h create mode 100644 arch/arm/mach-s3c2440/camera/sxga.h create mode 100644 arch/arm/mach-s3c2440/camera/userapp.h create mode 100644 arch/arm/mach-s3c2440/camera/v4l2_api.c create mode 100644 arch/arm/mach-s3c2440/camera/video-driver.c create mode 100644 arch/arm/mach-s3c2440/camera/videodev.c create mode 100644 arch/arm/mach-s3c2440/camera/videodev.h create mode 100644 arch/arm/mach-s3c2440/camera/videodev2.h diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig index c40aaca..c350511 100644 --- a/arch/arm/mach-s3c2440/Kconfig +++ b/arch/arm/mach-s3c2440/Kconfig @@ -30,6 +30,9 @@ config S3C2440_C_FIQ Support for S3C2440 FIQ support in C -- see ./arch/arm/macs3c2440/fiq_c_isr.c +source "arch/arm/mach-s3c2440/camera/Kconfig" + + menu "S3C2440 Machines" config MACH_ANUBIS @@ -99,4 +102,3 @@ config NEO1973_GTA02_2440 of the FIC/Openmoko Neo1973 GTA02 GSM Phone. endmenu - diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile index e3ca9e3..7112231 100644 --- a/arch/arm/mach-s3c2440/Makefile +++ b/arch/arm/mach-s3c2440/Makefile @@ -1,26 +1,2 @@ -# arch/arm/mach-s3c2440/Makefile -# -# Copyright 2007 Simtec Electronics -# -# Licensed under GPLv2 +obj-y += camera/ -obj-y := -obj-m := -obj-n := -obj- := - -obj-$(CONFIG_CPU_S3C2440) += s3c2440.o dsc.o -obj-$(CONFIG_CPU_S3C2440) += irq.o -obj-$(CONFIG_CPU_S3C2440) += clock.o -obj-$(CONFIG_S3C2440_DMA) += dma.o -obj-$(CONFIG_S3C2440_C_FIQ) += fiq_c_isr.o - -# Machine support - -obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o -obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o -obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o -obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o -obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o -obj-$(CONFIG_MACH_HXD8) += mach-hxd8.o -obj-$(CONFIG_MACH_NEO1973_GTA02) += mach-gta02.o diff --git a/arch/arm/mach-s3c2440/camera/Kconfig b/arch/arm/mach-s3c2440/camera/Kconfig new file mode 100644 index 0000000..36f127d --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/Kconfig @@ -0,0 +1,7 @@ + +config S3C2440_CAMERA + bool "S3C24xx Camera interface" + depends on ARCH_S3C2410 + help + Camera driver for S3C2440 camera unit + diff --git a/arch/arm/mach-s3c2440/camera/Makefile b/arch/arm/mach-s3c2440/camera/Makefile new file mode 100644 index 0000000..a46d3be --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/Makefile @@ -0,0 +1,9 @@ +obj-$(CONFIG_S3C2440_CAMERA) += \ + videodev.o \ + imgsensor.o \ + videodrv.o \ + video-driver.o \ + camif.o \ + camif_fsm.o \ + qt-driver.o + diff --git a/arch/arm/mach-s3c2440/camera/bits.h b/arch/arm/mach-s3c2440/camera/bits.h new file mode 100644 index 0000000..8d83c2e --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/bits.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) Samsung Electroincs 2003 + * Author: SW.LEE + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#ifndef __SW_BITS_H +#define __SW_BITS_H + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#endif diff --git a/arch/arm/mach-s3c2440/camera/cam_reg.h b/arch/arm/mach-s3c2440/camera/cam_reg.h new file mode 100644 index 0000000..7247a4e --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/cam_reg.h @@ -0,0 +1,220 @@ + /*---------------------------------------------------------- + * (C) 2004 Samsung Electronics + * SW.LEE < hitchcar@samsung.com> + * + ----------------------------------------------------------- */ + +#ifndef __FIMC20_CAMERA_H__ +#define __FIMC20_CAMERA_H__ + + +#ifdef CONFIG_ARCH_S3C24A0 +#define CAM_BASE_ADD 0x48000000 +#else /* S3C2440A */ +#define CAM_BASE_ADD 0x4F000000 +#endif + + +/* + * CAMERA IP + * P-port is used as RGB Capturing device which including scale and crop + * those who want to see(preview ) the image on display needs RGB image. + * + * C-port is used as YCbCr(4:2:0, 4:2:2) Capturing device which including the scale and crop + * the prefix of C-port have the meaning of "Codec" ex. mpeg4, h263.. which requries the + YCBCB format not RGB + */ + +#define CISRCFMT __REG(CAM_BASE_ADD+0x00) // RW Input Source Format +#define CIWDOFST __REG(CAM_BASE_ADD+0x04) // Window offset register +#define CIGCTRL __REG(CAM_BASE_ADD+0x08) // Global control register +#define CICOYSA0 __REG(CAM_BASE_ADD+0x18) // Y 1 st frame start address +#define CICOYSA1 __REG(CAM_BASE_ADD+0x1C) // Y 2 nd frame start address +#define CICOYSA2 __REG(CAM_BASE_ADD+0x20) // Y 3 rd frame start address +#define CICOYSA3 __REG(CAM_BASE_ADD+0x24) // Y 4 th frame start address +#define CICOCBSA0 __REG(CAM_BASE_ADD+0x28) // Cb 1 st frame start address +#define CICOCBSA1 __REG(CAM_BASE_ADD+0x2C) // Cb 2 nd frame start address +#define CICOCBSA2 __REG(CAM_BASE_ADD+0x30) // Cb 3 rd frame start address +#define CICOCBSA3 __REG(CAM_BASE_ADD+0x34) // Cb 4 th frame start address +#define CICOCRSA0 __REG(CAM_BASE_ADD+0x38) // Cr 1 st frame start address +#define CICOCRSA1 __REG(CAM_BASE_ADD+0x3C) // Cr 2 nd frame start address +#define CICOCRSA2 __REG(CAM_BASE_ADD+0x40) // Cr 3 rd frame start address +#define CICOCRSA3 __REG(CAM_BASE_ADD+0x44) // Cr 4 th frame start address +#define CICOTRGFMT __REG(CAM_BASE_ADD+0x48) // Target image format of codec +#define CICOCTRL __REG(CAM_BASE_ADD+0x4C) // Codec DMA control related +#define CICOSCPRERATIO __REG(CAM_BASE_ADD+0x50) // Codec pre-scaler ratio control +#define CICOSCPREDST __REG(CAM_BASE_ADD+0x54) // Codec pre-scaler destination +#define CICOSCCTRL __REG(CAM_BASE_ADD+0x58) // Codec main-scaler control +#define CICOTAREA __REG(CAM_BASE_ADD+0x5C) // Codec pre-scaler destination +#define CICOSTATUS __REG(CAM_BASE_ADD+0x64) // Codec path status +#define CIPRCLRSA0 __REG(CAM_BASE_ADD+0x6C) // RGB 1 st frame start address +#define CIPRCLRSA1 __REG(CAM_BASE_ADD+0x70) // RGB 2 nd frame start address +#define CIPRCLRSA2 __REG(CAM_BASE_ADD+0x74) // RGB 3 rd frame start address +#define CIPRCLRSA3 __REG(CAM_BASE_ADD+0x78) // RGB 4 th frame start address +#define CIPRTRGFMT __REG(CAM_BASE_ADD+0x7C) // Target image format of preview +#define CIPRCTRL __REG(CAM_BASE_ADD+0x80) // Preview DMA control related +#define CIPRSCPRERATIO __REG(CAM_BASE_ADD+0x84) // Preview pre-scaler ratio control +#define CIPRSCPREDST __REG(CAM_BASE_ADD+0x88) // Preview pre-scaler destination +#define CIPRSCCTRL __REG(CAM_BASE_ADD+0x8C) // Preview main-scaler control +#define CIPRTAREA __REG(CAM_BASE_ADD+0x90) // Preview pre-scaler destination +#define CIPRSTATUS __REG(CAM_BASE_ADD+0x98) // Preview path status +#define CIIMGCPT __REG(CAM_BASE_ADD+0xA0) // Image capture enable command + +#define CICOYSA(__x) __REG(CAM_BASE_ADD+0x18 + (__x)*4 ) +#define CICOCBSA(__x) __REG(CAM_BASE_ADD+0x28 + (__x)*4 ) +#define CICOCRSA(__x) __REG(CAM_BASE_ADD+0x38 + (__x)*4 ) +#define CIPRCLRSA(__x) __REG(CAM_BASE_ADD+0x6C + (__x)*4 ) + +/* CISRCFMT BitField */ +#define SRCFMT_ITU601 BIT31 +#define SRCFMT_ITU656 0 +#define SRCFMT_UVOFFSET_128 BIT30 +#define fCAM_SIZE_H Fld(13, 16) +#define fCAM_SIZE_V Fld(13, 0) +#define SOURCE_HSIZE(x) FInsrt((x), fCAM_SIZE_H) +#define SOURCE_VSIZE(x) FInsrt((x), fCAM_SIZE_V) + + +/* Window Option Register */ +#define WINOFEN BIT31 +#define CO_FIFO_Y BIT30 +#define CO_FIFO_CB BIT15 +#define CO_FIFO_CR BIT14 +#define PR_FIFO_CB BIT13 +#define PR_FIFO_CR BIT12 +#define fWINHOR Fld(11, 16) +#define fWINVER Fld(11, 0) +#define WINHOROFST(x) FInsrt((x), fWINHOR) +#define WINVEROFST(x) FInsrt((x), fWINVER) + +/* Global Control Register */ +#define GC_SWRST BIT31 +#define GC_CAMRST BIT30 +#define GC_INVPOLPCLK BIT26 +#define GC_INVPOLVSYNC BIT25 +#define GC_INVPOLHREF BIT24 + +/*-------------------------------------------------- + REGISTER BIT FIELD DEFINITION TO + YCBCR and RGB +----------------------------------------------------*/ +/* Codec Target Format Register */ +#define IN_YCBCR420 0 +#define IN_YCBCR422 BIT31 +#define OUT_YCBCR420 0 +#define OUT_YCBCR422 BIT30 + +#if 0 +#define FLIP_NORMAL 0 +#define FLIP_X (BIT14) +#define FLIP_Y (BIT15) +#define FLIP_MIRROR (BIT14|BIT15) +#endif + +/** BEGIN ************************************/ +/* Cotents: Common in both P and C port */ +#define fTARGET_HSIZE Fld(13,16) +#define TARGET_HSIZE(x) FInsrt((x), fTARGET_HSIZE) +#define fTARGET_VSIZE Fld(13,0) +#define TARGET_VSIZE(x) FInsrt((x), fTARGET_VSIZE) +#define FLIP_X_MIRROR BIT14 +#define FLIP_Y_MIRROR BIT15 +#define FLIP_180_MIRROR (BIT14 | BIT15) +/** END *************************************/ + +/* Codec DMA Control Register */ +#define fYBURST_M Fld(5,19) +#define fYBURST_R Fld(5,14) +#define fCBURST_M Fld(5,9) +#define fCBURST_R Fld(5,4) +#define YBURST_M(x) FInsrt((x), fYBURST_M) +#define CBURST_M(x) FInsrt((x), fCBURST_M) +#define YBURST_R(x) FInsrt((x), fYBURST_R) +#define CBURST_R(x) FInsrt((x), fCBURST_R) +#define LAST_IRQ_EN BIT2 /* Common in both P and C port */ +/* + * Check the done signal of capturing image for JPEG + * !!! AutoClear Bit + */ + + +/* (Codec, Preview ) Pre-Scaler Control Register 1 */ +#define fSHIFT Fld(4,28) +#define PRE_SHIFT(x) FInsrt((x), fSHIFT) +#define fRATIO_H Fld(7,16) +#define PRE_HRATIO(x) FInsrt((x), fRATIO_H) +#define fRATIO_V Fld(7,0) +#define PRE_VRATIO(x) FInsrt((x), fRATIO_V) + +/* (Codec, Preview ) Pre-Scaler Control Register 2*/ +#define fDST_WIDTH Fld(12,16) +#define fDST_HEIGHT Fld(12,0) +#define PRE_DST_WIDTH(x) FInsrt((x), fDST_WIDTH) +#define PRE_DST_HEIGHT(x) FInsrt((x), fDST_HEIGHT) + + +/* (Codec, Preview) Main-scaler control Register */ +#define S_METHOD BIT31 /* Sampling method only for P-port */ +#define SCALERSTART BIT15 +/* Codec scaler bypass for upper 2048x2048 + where ImgCptEn_CoSC and ImgCptEn_PrSC should be 0 +*/ + +#define SCALERBYPASS BIT31 +#define RGB_FMT24 BIT30 +#define RGB_FMT16 0 + +/* +#define SCALE_UP_H BIT29 +#define SCALE_UP_V BIT28 +*/ + +#define fMAIN_HRATIO Fld(9, 16) +#define MAIN_HRATIO(x) FInsrt((x), fMAIN_HRATIO) + +#define SCALER_START BIT15 + +#define fMAIN_VRATIO Fld(9, 0) +#define MAIN_VRATIO(x) FInsrt((x), fMAIN_VRATIO) + +/* (Codec, Preview ) DMA Target AREA Register */ +#define fCICOTAREA Fld(26,0) +#define TARGET_DMA_AREA(x) FInsrt((x), fCICOTAREA) + +/* Preview DMA Control Register */ +#define fRGBURST_M Fld(5,19) +#define fRGBURST_R Fld(5,14) +#define RGBURST_M(x) FInsrt((x), fRGBURST_M) +#define RGBURST_R(x) FInsrt((x), fRGBURST_R) + + +/* (Codec, Preview) Status Register */ +#define CO_OVERFLOW_Y BIT31 +#define CO_OVERFLOW_CB BIT30 +#define CO_OVERFLOW_CR BIT29 +#define PR_OVERFLOW_CB BIT31 +#define PR_OVERFLOW_CR BIT30 + +#define VSYNC BIT28 + +#define fFRAME_CNT Fld(2,26) +#define FRAME_CNT(x) FExtr((x),fFRAME_CNT) + +#define WIN_OFF_EN BIT25 +#define fFLIP_MODE Fld(2,23) +#define FLIP_MODE(x) EExtr((x), fFLIP_MODE) +#define CAP_STATUS_CAMIF BIT22 +#define CAP_STATUS_CODEC BIT21 +#define CAP_STATUS_PREVIEW BIT21 +#define VSYNC_A BIT20 +#define VSYNC_B BIT19 + +/* Image Capture Enable Regiser */ +#define CAMIF_CAP_ON BIT31 +#define CAMIF_CAP_CODEC_ON BIT30 +#define CAMIF_CAP_PREVIEW_ON BIT29 + + + + +#endif /* S3C2440_CAMER_H */ diff --git a/arch/arm/mach-s3c2440/camera/camif.c b/arch/arm/mach-s3c2440/camera/camif.c new file mode 100644 index 0000000..36d4ccc --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/camif.c @@ -0,0 +1,978 @@ +/* + * Copyright (C) 2004 Samsung Electronics + * SW.LEE + * + * This file is subject to the terms and conditions of the GNU General Public + * License 2. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_ARCH_S3C24A0A +#include +#include +#else +#include +#include +#endif + +#include "cam_reg.h" +//#define SW_DEBUG +#include "camif.h" +#include "videodev.h" +#include "miscdevice.h" + + +static int camif_dma_burst(camif_cfg_t *); +static int camif_scaler(camif_cfg_t *); + +static const char *camif_version = + "$Id: camif.c,v 1.10 2004/06/04 04:24:14 swlee Exp $"; + +/* For SXGA Image */ +#define RESERVE_MEM 15*1024*1024 +#define YUV_MEM 10*1024*1024 +#define RGB_MEM (RESERVE_MEM - YUV_MEM) + +static int camif_malloc(camif_cfg_t *cfg) +{ + unsigned int t_size; + unsigned int daon = cfg->target_x *cfg->target_y; + + if(cfg->dma_type & CAMIF_CODEC) { + if (cfg->fmt & CAMIF_OUT_YCBCR420) { + t_size = daon * 3 / 2 ; + } + else { t_size = daon * 2; /* CAMIF_OUT_YCBCR422 */ } + t_size = t_size *cfg->pp_num; + +#ifndef SAMSUNG_SXGA_CAM + cfg->pp_virt_buf = consistent_alloc(GFP_KERNEL, t_size, &cfg->pp_phys_buf); +#else + printk(KERN_INFO "Reserving High RAM Addresses \n"); + cfg->pp_phys_buf = PHYS_OFFSET + (MEM_SIZE - RESERVE_MEM); + cfg->pp_virt_buf = ioremap_nocache(cfg->pp_phys_buf,YUV_MEM); +#endif + + if ( !cfg->pp_virt_buf ) { + printk(KERN_ERR"CAMERA:Failed to request YCBCR MEM\n"); + return -ENOMEM; + } + memset(cfg->pp_virt_buf, 0, t_size); + cfg->pp_totalsize = t_size; + return 0; + } + if ( cfg->dma_type & CAMIF_PREVIEW ) { + if (cfg->fmt & CAMIF_RGB16) + t_size = daon * 2; /* 4byte per two pixel*/ + else { + assert(cfg->fmt & CAMIF_RGB24); + t_size = daon * 4; /* 4byte per one pixel */ + } + t_size = t_size * cfg->pp_num; +#ifndef SAMSUNG_SXGA_CAM + cfg->pp_virt_buf = consistent_alloc(GFP_KERNEL, t_size, &cfg->pp_phys_buf); +#else + printk(KERN_INFO "Reserving High RAM Addresses \n"); + cfg->pp_phys_buf = PHYS_OFFSET + (MEM_SIZE - RESERVE_MEM ) + YUV_MEM; + cfg->pp_virt_buf = ioremap_nocache(cfg->pp_phys_buf,RGB_MEM); +#endif + if ( !cfg->pp_virt_buf ) { + printk(KERN_ERR"CAMERA:Failed to request RGB MEM\n"); + return -ENOMEM; + } + memset(cfg->pp_virt_buf, 0, t_size); + cfg->pp_totalsize = t_size; + return 0; + } + + return 0; /* Never come. */ +} + +static int camif_demalloc(camif_cfg_t *cfg) +{ +#ifndef SAMSUNG_SXGA_CAM + if ( cfg->pp_virt_buf ) { + consistent_free(cfg->pp_virt_buf,cfg->pp_totalsize,cfg->pp_phys_buf); + cfg->pp_virt_buf = 0; + } +#else + iounmap(cfg->pp_virt_buf); + cfg->pp_virt_buf = 0; +#endif + return 0; +} + +/* + * advise a person to use this func in ISR + * index value indicates the next frame count to be used + */ +int camif_g_frame_num(camif_cfg_t *cfg) +{ + int index = 0; + + if (cfg->dma_type & CAMIF_CODEC ) { + index = FRAME_CNT(CICOSTATUS); + DPRINTK("CAMIF_CODEC frame %d \n", index); + } + else { + assert(cfg->dma_type & CAMIF_PREVIEW ); + index = FRAME_CNT(CIPRSTATUS); + DPRINTK("CAMIF_PREVIEW frame %d 0x%08X \n", index, CIPRSTATUS); + } + cfg->now_frame_num = (index + 2) % 4; /* When 4 PingPong */ + return index; /* meaningless */ +} + +static int camif_pp_codec(camif_cfg_t *cfg) +{ + u32 i, c_size; /* Cb,Cr size */ + u32 one_p_size; + u32 daon = cfg->target_x * cfg->target_y; + if (cfg->fmt & CAMIF_OUT_YCBCR420) { + c_size = daon /4; + } + else { + assert(cfg->fmt & CAMIF_OUT_YCBCR422); + c_size = daon /2; + } + switch ( cfg->pp_num ) { + case 1 : + for ( i =0 ; i < 4; i=i+1) { + cfg->img_buf[i].virt_y = cfg->pp_virt_buf; + cfg->img_buf[i].phys_y = cfg->pp_phys_buf; + cfg->img_buf[i].virt_cb = cfg->pp_virt_buf + daon; + cfg->img_buf[i].phys_cb = cfg->pp_phys_buf + daon; + cfg->img_buf[i].virt_cr = cfg->pp_virt_buf + daon + c_size; + cfg->img_buf[i].phys_cr = cfg->pp_phys_buf + daon + c_size; + CICOYSA(i) = cfg->img_buf[i].phys_y; + CICOCBSA(i) = cfg->img_buf[i].phys_cb; + CICOCRSA(i) = cfg->img_buf[i].phys_cr; + } + break; + case 2: +#define TRY (( i%2 ) ? 1 :0) + one_p_size = daon + 2*c_size; + for (i = 0; i < 4 ; i++) { + cfg->img_buf[i].virt_y = cfg->pp_virt_buf + TRY * one_p_size; + cfg->img_buf[i].phys_y = cfg->pp_phys_buf + TRY * one_p_size; + cfg->img_buf[i].virt_cb = cfg->pp_virt_buf + daon + TRY * one_p_size; + cfg->img_buf[i].phys_cb = cfg->pp_phys_buf + daon + TRY * one_p_size; + cfg->img_buf[i].virt_cr = cfg->pp_virt_buf + daon + c_size + TRY * one_p_size; + cfg->img_buf[i].phys_cr = cfg->pp_phys_buf + daon + c_size + TRY * one_p_size; + CICOYSA(i) = cfg->img_buf[i].phys_y; + CICOCBSA(i) = cfg->img_buf[i].phys_cb; + CICOCRSA(i) = cfg->img_buf[i].phys_cr; + } + break; + case 4: + one_p_size = daon + 2*c_size; + for (i = 0; i < 4 ; i++) { + cfg->img_buf[i].virt_y = cfg->pp_virt_buf + i * one_p_size; + cfg->img_buf[i].phys_y = cfg->pp_phys_buf + i * one_p_size; + cfg->img_buf[i].virt_cb = cfg->pp_virt_buf + daon + i * one_p_size; + cfg->img_buf[i].phys_cb = cfg->pp_phys_buf + daon + i * one_p_size; + cfg->img_buf[i].virt_cr = cfg->pp_virt_buf + daon + c_size + i * one_p_size; + cfg->img_buf[i].phys_cr = cfg->pp_phys_buf + daon + c_size + i * one_p_size; + CICOYSA(i) = cfg->img_buf[i].phys_y; + CICOCBSA(i) = cfg->img_buf[i].phys_cb; + CICOCRSA(i) = cfg->img_buf[i].phys_cr; + } + break; + default: + printk("Invalid PingPong Number %d \n",cfg->pp_num); + panic("halt\n"); + } + return 0; +} + +/* RGB Buffer Allocation */ +static int camif_pp_preview(camif_cfg_t *cfg) +{ + int i; + u32 daon = cfg->target_x * cfg->target_y; + + if(cfg->fmt & CAMIF_RGB24) + daon = daon * 4 ; + else { + assert (cfg->fmt & CAMIF_RGB16); + daon = daon *2; + } + switch ( cfg->pp_num ) { + case 1: + for ( i = 0; i < 4 ; i++ ) { + cfg->img_buf[i].virt_rgb = cfg->pp_virt_buf ; + cfg->img_buf[i].phys_rgb = cfg->pp_phys_buf ; + CIPRCLRSA(i) = cfg->img_buf[i].phys_rgb; + } + break; + case 2: + for ( i = 0; i < 4 ; i++) { + cfg->img_buf[i].virt_rgb = cfg->pp_virt_buf + TRY * daon; + cfg->img_buf[i].phys_rgb = cfg->pp_phys_buf + TRY * daon; + CIPRCLRSA(i) = cfg->img_buf[i].phys_rgb; + } + break; + case 4: + for ( i = 0; i < 4 ; i++) { + cfg->img_buf[i].virt_rgb = cfg->pp_virt_buf + i * daon; + cfg->img_buf[i].phys_rgb = cfg->pp_phys_buf + i * daon; + CIPRCLRSA(i) = cfg->img_buf[i].phys_rgb; + } + break; + default: + printk("Invalid PingPong Number %d \n",cfg->pp_num); + panic("halt\n"); + } + return 0; +} + +static int camif_pingpong(camif_cfg_t *cfg) +{ + if (cfg->dma_type & CAMIF_CODEC ) { + camif_pp_codec(cfg); + } + + if ( cfg->dma_type & CAMIF_PREVIEW) { + camif_pp_preview(cfg); + } + return 0; +} + + +/*********** Image Convert *******************************/ +/* Return Format + * Supported by Hardware + * V4L2_PIX_FMT_YUV420, + * V4L2_PIX_FMT_YUV422P, + * V4L2_PIX_FMT_BGR32 (BGR4) + * ----------------------------------- + * V4L2_PIX_FMT_RGB565(X) + * Currenly 2byte --> BGR656 Format + * S3C2440A,S3C24A0 supports vairants with reversed FMT_RGB565 + i.e blue toward the least, red towards the most significant bit + -- by SW.LEE + */ + + +/* + * After calling camif_g_frame_num, + * this func must be called + */ +u8 * camif_g_frame(camif_cfg_t *cfg) +{ + u8 * ret = NULL; + int cnt = cfg->now_frame_num; + + if(cfg->dma_type & CAMIF_PREVIEW) { + ret = cfg->img_buf[cnt].virt_rgb; + } + if (cfg->dma_type & CAMIF_CODEC) { + ret = cfg->img_buf[cnt].virt_y; + } + return ret; +} + +/* This function must be called in module initial time */ +static int camif_source_fmt(camif_gc_t *gc) +{ + u32 cmd = 0; + + /* Configure CISRCFMT --Source Format */ + if (gc->itu_fmt & CAMIF_ITU601) { + cmd = CAMIF_ITU601; + } + else { + assert ( gc->itu_fmt & CAMIF_ITU656); + cmd = CAMIF_ITU656; + } + cmd |= SOURCE_HSIZE(gc->source_x)| SOURCE_VSIZE(gc->source_y); + /* Order422 */ + cmd |= gc->order422; + CISRCFMT = cmd; + + return 0 ; +} + + +/* + * Codec Input YCBCR422 will be Fixed + */ +static int camif_target_fmt(camif_cfg_t *cfg) +{ + u32 cmd = 0; + + if (cfg->dma_type & CAMIF_CODEC) { + /* YCBCR setting */ + cmd = TARGET_HSIZE(cfg->target_x)| TARGET_VSIZE(cfg->target_y); + if ( cfg->fmt & CAMIF_OUT_YCBCR420 ) { + cmd |= OUT_YCBCR420|IN_YCBCR422; + } + else { + assert(cfg->fmt & CAMIF_OUT_YCBCR422); + cmd |= OUT_YCBCR422|IN_YCBCR422; + } + CICOTRGFMT = cmd | cfg->flip; + } + else { + assert(cfg->dma_type & CAMIF_PREVIEW); + CIPRTRGFMT = + TARGET_HSIZE(cfg->target_x)|TARGET_VSIZE(cfg->target_y)|cfg->flip; + } + return 0; +} + +void camif_change_flip(camif_cfg_t *cfg) +{ + u32 cmd = 0; + + if (cfg->dma_type & CAMIF_CODEC ) { + /* YCBCR setting */ + cmd = CICOTRGFMT; + cmd &= ~(BIT14|BIT15); /* Clear FLIP Mode */ + cmd |= cfg->flip; + CICOTRGFMT = cmd; + } + else { + cmd = CIPRTRGFMT; + cmd &= ~(BIT14|BIT15); + cmd |= cfg->flip; + CICOTRGFMT = cmd; + } +} + + + +/* Must: + * Before calling this function, + * you must use "camif_dynamic_open" + * If you want to enable both CODEC and preview + * you must do it at the same time. + */ +int camif_capture_start(camif_cfg_t *cfg) +{ + u32 n_cmd = 0; /* Next Command */ + + switch(cfg->exec) { + case CAMIF_BOTH_DMA_ON: + camif_reset(CAMIF_RESET,0); /* Flush Camera Core Buffer */ + CIPRSCCTRL |= SCALERSTART; + CICOSCCTRL |= SCALERSTART; + n_cmd = CAMIF_CAP_PREVIEW_ON|CAMIF_CAP_CODEC_ON; + break; + case CAMIF_DMA_ON: + camif_reset(CAMIF_RESET,0); /* Flush Camera Core Buffer */ + if (cfg->dma_type&CAMIF_CODEC) { + CICOSCCTRL |= SCALERSTART; + n_cmd = CAMIF_CAP_CODEC_ON; + }else { + CIPRSCCTRL |= SCALERSTART; + n_cmd = CAMIF_CAP_PREVIEW_ON; + } + + /* wait until Sync Time expires */ + /* First settting, to wait VSYNC fall */ + /* By VESA spec,in 640x480 @60Hz + MAX Delay Time is around 64us which "while" has.*/ + while(VSYNC & CICOSTATUS); + break; + default: + break; + } + CIIMGCPT = n_cmd|CAMIF_CAP_ON; + return 0; +} + + +int camif_capture_stop(camif_cfg_t *cfg) +{ + u32 n_cmd = CIIMGCPT; /* Next Command */ + + switch(cfg->exec) { + case CAMIF_BOTH_DMA_OFF: + CIPRSCCTRL &= ~SCALERSTART; + CICOSCCTRL &= ~SCALERSTART; + n_cmd = 0; + break; + case CAMIF_DMA_OFF_L_IRQ: /* fall thru */ + case CAMIF_DMA_OFF: + if (cfg->dma_type&CAMIF_CODEC) { + CICOSCCTRL &= ~SCALERSTART; + n_cmd &= ~CAMIF_CAP_CODEC_ON; + if (!(n_cmd & CAMIF_CAP_PREVIEW_ON)) + n_cmd = 0; + }else { + CIPRSCCTRL &= ~SCALERSTART; + n_cmd &= ~CAMIF_CAP_PREVIEW_ON; + if (!(n_cmd & CAMIF_CAP_CODEC_ON)) + n_cmd = 0; + } + break; + default: + panic("Unexpected \n"); + } + CIIMGCPT = n_cmd; + if(cfg->exec == CAMIF_DMA_OFF_L_IRQ) { /* Last IRQ */ + if (cfg->dma_type & CAMIF_CODEC) + CICOCTRL |= LAST_IRQ_EN; + else + CIPRCTRL |= LAST_IRQ_EN; + } +#if 0 + else { /* to make internal state machine of CAMERA stop */ + camif_reset(CAMIF_RESET, 0); + } +#endif + return 0; +} + + +/* LastIRQEn is autoclear */ +void camif_last_irq_en(camif_cfg_t *cfg) +{ + if(cfg->exec == CAMIF_BOTH_DMA_ON) { + CIPRCTRL |= LAST_IRQ_EN; + CICOCTRL |= LAST_IRQ_EN; + } + else { + if (cfg->dma_type & CAMIF_CODEC) + CICOCTRL |= LAST_IRQ_EN; + else + CIPRCTRL |= LAST_IRQ_EN; + } +} + +static int +camif_scaler_internal(u32 srcWidth, u32 dstWidth, u32 *ratio, u32 *shift) +{ + if(srcWidth>=64*dstWidth){ + printk(KERN_ERR"CAMERA:out of prescaler range: srcWidth /dstWidth = %d(< 64)\n", + srcWidth/dstWidth); + return 1; + } + else if(srcWidth>=32*dstWidth){ + *ratio=32; + *shift=5; + } + else if(srcWidth>=16*dstWidth){ + *ratio=16; + *shift=4; + } + else if(srcWidth>=8*dstWidth){ + *ratio=8; + *shift=3; + } + else if(srcWidth>=4*dstWidth){ + *ratio=4; + *shift=2; + } + else if(srcWidth>=2*dstWidth){ + *ratio=2; + *shift=1; + } + else { + *ratio=1; + *shift=0; + } + return 0; +} + + +int camif_g_fifo_status(camif_cfg_t *cfg) +{ + u32 reg; + + if (cfg->dma_type & CAMIF_CODEC) { + u32 flag = CO_OVERFLOW_Y|CO_OVERFLOW_CB|CO_OVERFLOW_CR; + reg = CICOSTATUS; + if (reg & flag) { + printk("CODEC: FIFO error(0x%08x) and corrected\n",reg); + /* FIFO Error Count ++ */ + CIWDOFST |= CO_FIFO_Y|CO_FIFO_CB|CO_FIFO_CR; + CIWDOFST &= ~(CO_FIFO_Y|CO_FIFO_CB|CO_FIFO_CR); + return 1; /* Error */ + } + } + if (cfg->dma_type & CAMIF_PREVIEW) { + u32 flag = PR_OVERFLOW_CB|PR_OVERFLOW_CR; + reg = CIPRSTATUS; + if (reg & flag) { + printk("PREVIEW:FIFO error(0x%08x) and corrected\n",reg); + CIWDOFST |= PR_FIFO_CB|PR_FIFO_CR; + CIWDOFST &= ~(CO_FIFO_Y|CO_FIFO_CB|CO_FIFO_CR); + /* FIFO Error Count ++ */ + return 1; /* Error */ + } + } + return 0; /* No Error */ +} + + +/* Policy: + * if codec or preview define the win offset, + * other must follow that value. + */ +int camif_win_offset(camif_gc_t *gc ) +{ + u32 h = gc->win_hor_ofst; + u32 v = gc->win_ver_ofst; + + /*Clear Overflow */ + CIWDOFST = CO_FIFO_Y|CO_FIFO_CB|CO_FIFO_CR|PR_FIFO_CB|PR_FIFO_CB; + CIWDOFST = 0; /* ? Dummy */ + if (!h && !v) { + CIWDOFST = 0; + return 0; + } + CIWDOFST = WINOFEN | WINHOROFST(h) | WINVEROFST(v); + return 0; +} + +/* + * when you change the resolution in a specific camera, + * sometimes, it is necessary to change the polarity + * -- SW.LEE + */ +static void camif_polarity(camif_gc_t *gc) +{ + u32 cmd = CIGCTRL; + + cmd = cmd & ~(BIT26|BIT25|BIT24); /* clear polarity */ + if (gc->polarity_pclk) + cmd |= GC_INVPOLPCLK; + if (gc->polarity_vsync) + cmd |= GC_INVPOLVSYNC; + if (gc->polarity_href) + cmd |= GC_INVPOLHREF; + CIGCTRL |= cmd; +} + + +int camif_dynamic_open(camif_cfg_t *cfg) +{ + camif_win_offset(cfg->gc); + camif_polarity(cfg->gc); + + if(camif_scaler(cfg)) { + printk(KERN_ERR "CAMERA:Preview Scaler, Change WinHorOfset or Target Size\n"); + return 1; + } + camif_target_fmt(cfg); + if (camif_dma_burst(cfg)) { + printk(KERN_ERR "CAMERA:DMA Busrt Length Error \n"); + return 1; + } + if(camif_malloc(cfg) ) { + printk(KERN_ERR " Instead of using consistent_alloc()\n" + " lease use dedicated memory allocation for DMA memory\n"); + return -1; + } + camif_pingpong(cfg); + return 0; +} + +int camif_dynamic_close(camif_cfg_t *cfg) +{ + camif_demalloc(cfg); + return 0; +} + +static int camif_target_area(camif_cfg_t *cfg) +{ + u32 rect = cfg->target_x * cfg->target_y; + if (cfg->dma_type & CAMIF_CODEC ) { + CICOTAREA = rect; + } + if (cfg->dma_type & CAMIF_PREVIEW) { + CIPRTAREA = rect; + } + return 0; +} + +static int inline camif_hw_reg(camif_cfg_t *cfg) +{ + u32 cmd = 0; + + if (cfg->dma_type & CAMIF_CODEC) { + CICOSCPRERATIO = PRE_SHIFT(cfg->sc.shfactor) + |PRE_HRATIO(cfg->sc.prehratio)|PRE_VRATIO(cfg->sc.prevratio); + CICOSCPREDST = + PRE_DST_WIDTH(cfg->sc.predst_x)|PRE_DST_HEIGHT(cfg->sc.predst_y); + + /* Differ from Preview */ + if (cfg->sc.scalerbypass) + cmd |= SCALERBYPASS; + if (cfg->sc.scaleup_h & cfg->sc.scaleup_v) + cmd |= BIT30|BIT29; + CICOSCCTRL = cmd | MAIN_HRATIO(cfg->sc.mainhratio) + |MAIN_VRATIO(cfg->sc.mainvratio); + return 0; + } + else if (cfg->dma_type & CAMIF_PREVIEW) { + CIPRSCPRERATIO = PRE_SHIFT(cfg->sc.shfactor) + |PRE_HRATIO(cfg->sc.prehratio)|PRE_VRATIO(cfg->sc.prevratio); + CIPRSCPREDST = + PRE_DST_WIDTH(cfg->sc.predst_x)|PRE_DST_HEIGHT(cfg->sc.predst_y); + /* Differ from Codec */ + if (cfg->fmt & CAMIF_RGB24) { + cmd |= RGB_FMT24; + } + else { + /* RGB16 */; + } + if (cfg->sc.scaleup_h & cfg->sc.scaleup_v) + cmd |= BIT29|BIT28; + CIPRSCCTRL = cmd |MAIN_HRATIO(cfg->sc.mainhratio)|S_METHOD + |MAIN_VRATIO(cfg->sc.mainvratio); + }else { + panic("CAMERA:DMA_TYPE Wrong \n"); + } + + return 0; +} + + +/* Configure Pre-scaler control & main scaler control register */ +static int camif_scaler(camif_cfg_t *cfg) +{ + int tx = cfg->target_x,ty=cfg->target_y; + int sx, sy; + + if (tx <= 0 || ty<= 0) panic("CAMERA: Invalid target size \n"); + + sx = cfg->gc->source_x - 2*cfg->gc->win_hor_ofst; + sy = cfg->gc->source_y - 2*cfg->gc->win_ver_ofst; + if (sx <= 0 || sy<= 0) panic("CAMERA: Invalid source size \n"); + cfg->sc.modified_src_x = sx; + cfg->sc.modified_src_y = sy; + + /* Pre-scaler control register 1 */ + camif_scaler_internal(sx,tx,&cfg->sc.prehratio,&cfg->sc.hfactor); + camif_scaler_internal(sy,ty,&cfg->sc.prevratio,&cfg->sc.vfactor); + + if (cfg->dma_type & CAMIF_PREVIEW) { + if ( (sx /cfg->sc.prehratio) <= 640 ) {} + else { + printk(KERN_INFO "CAMERA: Internal Preview line buffer is 640 pixels\n"); + return 1; /* Error */ + } + } + + cfg->sc.shfactor = 10-(cfg->sc.hfactor+cfg->sc.vfactor); + /* Pre-scaler control register 2 */ + cfg->sc.predst_x = sx / cfg->sc.prehratio; + cfg->sc.predst_y = sy / cfg->sc.prevratio; + + /* Main-scaler control register */ + cfg->sc.mainhratio = (sx << 8)/(tx << cfg->sc.hfactor); + cfg->sc.mainvratio = (sy << 8)/(ty << cfg->sc.vfactor); + DPRINTK(" sx %d, sy %d tx %d ty %d \n",sx,sy,tx,ty); + DPRINTK(" hfactor %d vfactor %d \n",cfg->sc.hfactor,cfg->sc.vfactor); + + cfg->sc.scaleup_h = (sx <= tx) ? 1: 0; + cfg->sc.scaleup_v = (sy <= ty) ? 1: 0; + if ( cfg->sc.scaleup_h != cfg->sc.scaleup_v) + printk(KERN_ERR "scaleup_h must be same to scaleup_v \n"); + camif_hw_reg(cfg); + camif_target_area(cfg); + return 0; +} + +/****************************************************** + CalculateBurstSize - Calculate the busrt lengths + Description: + - dstHSize: the number of the byte of H Size. +********************************************************/ +static void camif_g_bsize(u32 hsize, u32 *mburst, u32 *rburst) +{ + u32 tmp; + + tmp = (hsize/4) % 16; + switch(tmp) { + case 0: + *mburst=16; + *rburst=16; + break; + case 4: + *mburst=16; + *rburst=4; + break; + case 8: + *mburst=16; + *rburst=8; + break; + default: + tmp=(hsize/4)%8; + switch(tmp) { + case 0: + *mburst=8; + *rburst=8; + break; + case 4: + *mburst=8; + *rburst=4; + default: + *mburst=4; + tmp=(hsize/4)%4; + *rburst= (tmp) ? tmp: 4; + break; + } + break; + } +} + +/* SXGA 1028x1024*/ +/* XGA 1024x768 */ +/* SVGA 800x600 */ +/* VGA 640x480 */ +/* CIF 352x288 */ +/* QVGA 320x240 */ +/* QCIF 176x144 */ +/* ret val + 1 : DMA Size Error +*/ +#define BURST_ERR 1 +static int camif_dma_burst(camif_cfg_t *cfg) +{ + int width = cfg->target_x; + + if (cfg->dma_type & CAMIF_CODEC ) { + u32 yburst_m, yburst_r; + u32 cburst_m, cburst_r; + /* CODEC DMA WIDHT is multiple of 16 */ + if (width %16 != 0 ) return BURST_ERR; /* DMA Burst Length Error */ + camif_g_bsize(width,&yburst_m,&yburst_r); + camif_g_bsize(width/2,&cburst_m,&cburst_r); + CICOCTRL =YBURST_M(yburst_m)|CBURST_M(cburst_m) + |YBURST_R(yburst_r)|CBURST_R(cburst_r); + } + + if (cfg->dma_type & CAMIF_PREVIEW) { + u32 rgburst_m, rgburst_r; + if(cfg->fmt == CAMIF_RGB24) { + if (width %2 != 0 ) return BURST_ERR; /* DMA Burst Length Error */ + camif_g_bsize(width*4,&rgburst_m,&rgburst_r); + } + else { /* CAMIF_RGB16 */ + if ((width/2) %2 != 0 ) return BURST_ERR; /* DMA Burst Length Error */ + camif_g_bsize(width*2,&rgburst_m,&rgburst_r); + } + CIPRCTRL = RGBURST_M(rgburst_m) | RGBURST_R(rgburst_r); + } + return 0; +} + +static int camif_gpio_init(void) +{ +#ifdef CONFIG_ARCH_S3C24A0A + /* S3C24A0A has the dedicated signal pins for Camera */ +#else + set_gpio_ctrl(GPIO_CAMDATA0); + set_gpio_ctrl(GPIO_CAMDATA1); + set_gpio_ctrl(GPIO_CAMDATA2); + set_gpio_ctrl(GPIO_CAMDATA3); + set_gpio_ctrl(GPIO_CAMDATA4); + set_gpio_ctrl(GPIO_CAMDATA5); + set_gpio_ctrl(GPIO_CAMDATA6); + set_gpio_ctrl(GPIO_CAMDATA7); + set_gpio_ctrl(GPIO_CAMPCLKIN); + set_gpio_ctrl(GPIO_CAMVSYNC); + set_gpio_ctrl(GPIO_CAMHREF); + set_gpio_ctrl(GPIO_CAMPCLKOUT); + set_gpio_ctrl(GPIO_CAMRESET); +#endif + return 0; +} + + +#define ROUND_ADD 0x100000 + +#ifdef CONFIG_ARCH_S3C24A0A +int camif_clock_init(camif_gc_t *gc) +{ + unsigned int upll, camclk_div, camclk; + + if (!gc) camclk = 24000000; + else { + camclk = gc->camclk; + if (camclk > 48000000) + printk(KERN_ERR "Wrong Camera Clock\n"); + } + + CLKCON |= CLKCON_CAM_UPLL | CLKCON_CAM_HCLK; + upll = get_bus_clk(GET_UPLL); + printk(KERN_INFO "CAMERA:Default UPLL %08d and Assing 96Mhz to UPLL\n",upll); + UPLLCON = FInsrt(56, fPLL_MDIV) | FInsrt(2, fPLL_PDIV)| FInsrt(1, fPLL_SDIV); + upll = get_bus_clk(GET_UPLL); + + camclk_div = (upll+ROUND_ADD) / camclk - 1; + CLKDIVN = (CLKDIVN & 0xFF) | CLKDIVN_CAM(camclk_div); + printk(KERN_INFO"CAMERA:upll %d MACRO 0x%08X CLKDIVN 0x%08X \n", + upll, CLKDIVN_CAM(camclk_div),CLKDIVN); + CIIMGCPT = 0; /* Dummy ? */ + return 0; +} +#else +int camif_clock_init(camif_gc_t *gc) +{ + unsigned int upll, camclk_div, camclk; + if (!gc) camclk = 24000000; + else { + camclk = gc->camclk; + if (camclk > 48000000) + printk(KERN_ERR "Wrong Camera Clock\n"); + } + + CLKCON |= CLKCON_CAMIF; + upll = elfin_get_bus_clk(GET_UPLL); + printk(KERN_INFO "CAMERA:Default UPLL %08d and Assing 96Mhz to UPLL\n",upll); + { + UPLLCON = FInsrt(60, fPLL_MDIV) | FInsrt(4, fPLL_PDIV)| FInsrt(1, fPLL_SDIV); + CLKDIVN |= DIVN_UPLL; /* For USB */ + upll = elfin_get_bus_clk(GET_UPLL); + } + + camclk_div = (upll+ROUND_ADD) /(camclk * 2) -1; + CAMDIVN = CAMCLK_SET_DIV|(camclk_div&0xf); + printk(KERN_INFO "CAMERA:upll %08d cam_clk %08d CAMDIVN 0x%08x \n",upll,camclk, CAMDIVN); + CIIMGCPT = 0; /* Dummy ? */ + return 0; +} +#endif + +/* + Reset Camera IP in CPU + Reset External Sensor + */ +void camif_reset(int is, int delay) +{ + switch (is) { + case CAMIF_RESET: + CIGCTRL |= GC_SWRST; + mdelay(1); + CIGCTRL &= ~GC_SWRST; + break; + case CAMIF_EX_RESET_AH: /*Active High */ + CIGCTRL &= ~GC_CAMRST; + udelay(200); + CIGCTRL |= GC_CAMRST; + udelay(delay); + CIGCTRL &= ~GC_CAMRST; + break; + case CAMIF_EX_RESET_AL: /*Active Low */ + CIGCTRL |= GC_CAMRST; + udelay(200); + CIGCTRL &= ~GC_CAMRST; + udelay(delay); + CIGCTRL |= GC_CAMRST; + break; + default: + break; + } +} + +/* For Camera Operation, + * we can give the high priority to REQ2 of ARBITER1 + */ + +/* Please move me into proper place + * camif_gc_t is not because "rmmod imgsenor" will delete the instance of camif_gc_t + */ +static u32 old_priority; + +static void camif_bus_priority(int flag) +{ + if (flag) { +#ifdef CONFIG_ARCH_S3C24A0A + old_priority = PRIORITY0; + PRIORITY0 = PRIORITY_I_FIX; + PRIORITY1 = PRIORITY_I_FIX; + +#else + old_priority = PRIORITY; + PRIORITY &= ~(3<<7); + PRIORITY |= (1<<7); /* Arbiter 1, REQ2 first */ + PRIORITY &= ~(1<<1); /* Disable Priority Rotate */ +#endif + } + else { +#ifdef CONFIG_ARCH_S3C24A0A + PRIORITY0 = old_priority; + PRIORITY1 = old_priority; +#else + PRIORITY = old_priority; +#endif + } +} + +static void inline camif_clock_off(void) +{ + CIIMGCPT = 0; +#if defined (CONFIG_ARCH_S3C24A0A) + CLKCON &= ~CLKCON_CAM_UPLL; + CLKCON &= ~CLKCON_CAM_HCLK; +#else + CLKCON &= ~CLKCON_CAMIF; +#endif +} + + +/* Init external image sensor + * Before make some value into image senor, + * you must set up the pixel clock. + */ +void camif_setup_sensor(void) +{ + camif_reset(CAMIF_RESET, 0); + camif_gpio_init(); + camif_clock_init(NULL); +/* Sometimes ,Before loading I2C module, we need the reset signal */ +#ifdef CONFIG_ARCH_S3C24A0A + camif_reset(CAMIF_EX_RESET_AL,1000); +#else + camif_reset(CAMIF_EX_RESET_AH,1000); +#endif +} + +void camif_hw_close(camif_cfg_t *cfg) +{ + camif_bus_priority(0); + camif_clock_off(); +} + +void camif_hw_open(camif_gc_t *gc) +{ + camif_source_fmt(gc); + camif_win_offset(gc); + camif_bus_priority(1); +} + + + +/* + * Local variables: + * tab-width: 8 + * c-indent-level: 8 + * c-basic-offset: 8 + * c-set-style: "K&R" + * End: + */ diff --git a/arch/arm/mach-s3c2440/camera/camif.h b/arch/arm/mach-s3c2440/camera/camif.h new file mode 100644 index 0000000..8b4f9aa --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/camif.h @@ -0,0 +1,304 @@ +/* + FIMC2.0 Camera Header File + + Copyright (C) 2003 Samsung Electronics (SW.LEE: hitchcar@samsung.com) + + Author : SW.LEE + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +* +*/ + + +#ifndef __FIMC20_CAMIF_H_ +#define __FIMC20_CAMIF_H_ + +#ifdef __KERNEL__ + +#include "bits.h" +#include "videodev.h" +#include +#include + +#endif /* __KERNEL__ */ + +#ifndef O_NONCAP +#define O_NONCAP O_TRUNC +#endif + +/* Codec or Preview Status */ +#define CAMIF_STARTED BIT1 +#define CAMIF_STOPPED BIT2 +#define CAMIF_INT_HAPPEN BIT3 + +/* Codec or Preview : Interrupt FSM */ +#define CAMIF_1nd_INT BIT7 +#define CAMIF_Xnd_INT BIT8 +#define CAMIF_Ynd_INT BIT9 +#define CAMIF_Znd_INT BIT10 +#define CAMIF_NORMAL_INT BIT11 +#define CAMIF_DUMMY_INT BIT12 +#define CAMIF_PENDING_INT 0 + + +/* CAMIF RESET Definition */ +#define CAMIF_RESET BIT0 +#define CAMIF_EX_RESET_AL BIT1 /* Active Low */ +#define CAMIF_EX_RESET_AH BIT2 /* Active High */ + + +enum camif_itu_fmt { + CAMIF_ITU601 = BIT31, + CAMIF_ITU656 = 0 +}; + +/* It is possbie to use two device simultaneously */ +enum camif_dma_type { + CAMIF_PREVIEW = BIT0, + CAMIF_CODEC = BIT1, +}; + +enum camif_order422 { + CAMIF_YCBYCR = 0, + CAMIF_YCRYCB = BIT14, + CAMIF_CBYCRY = BIT15, + CAMIF_CRYCBY = BIT14 | BIT15 +}; + +enum flip_mode { + CAMIF_FLIP = 0, + CAMIF_FLIP_X = BIT14, + CAMIF_FLIP_Y = BIT15, + CAMIF_FLIP_MIRROR = BIT14 |BIT15, +}; + +enum camif_codec_fmt { + /* Codec part */ + CAMIF_IN_YCBCR420 = BIT0, /* Currently IN_YCBCR format fixed */ + CAMIF_IN_YCBCR422 = BIT1, + CAMIF_OUT_YCBCR420 = BIT4, + CAMIF_OUT_YCBCR422 = BIT5, + /* Preview Part */ + CAMIF_RGB16 = BIT2, + CAMIF_RGB24 = BIT3, +}; + +enum camif_capturing { + CAMIF_BOTH_DMA_ON = BIT4, + CAMIF_DMA_ON = BIT3, + CAMIF_BOTH_DMA_OFF = BIT1, + CAMIF_DMA_OFF = BIT0, + /*------------------------*/ + CAMIF_DMA_OFF_L_IRQ= BIT5, +}; + +typedef struct camif_performance +{ + int frames; + int framesdropped; + __u64 bytesin; + __u64 bytesout; + __u32 reserved[4]; +} camif_perf_t; + + +typedef struct { + dma_addr_t phys_y; + dma_addr_t phys_cb; + dma_addr_t phys_cr; + u8 *virt_y; + u8 *virt_cb; + u8 *virt_cr; + dma_addr_t phys_rgb; + u8 *virt_rgb; +}img_buf_t; + + +/* this structure convers the CIWDOFFST, prescaler, mainscaler */ +typedef struct { + u32 modified_src_x; /* After windows applyed to source_x */ + u32 modified_src_y; + u32 hfactor; + u32 vfactor; + u32 shfactor; /* SHfactor = 10 - ( hfactor + vfactor ) */ + u32 prehratio; + u32 prevratio; + u32 predst_x; + u32 predst_y; + u32 scaleup_h; + u32 scaleup_v; + u32 mainhratio; + u32 mainvratio; + u32 scalerbypass; /* only codec */ +} scaler_t; + + +enum v4l2_status { + CAMIF_V4L2_INIT = BIT0, + CAMIF_v4L2_DIRTY = BIT1, +}; + + +/* Global Status Definition */ +#define PWANT2START BIT0 +#define CWANT2START BIT1 +#define BOTH_STARTED (PWANT2START|CWANT2START) +#define PNOTWORKING BIT4 +#define C_WORKING BIT5 + +typedef struct { + struct semaphore lock; + enum camif_itu_fmt itu_fmt; + enum camif_order422 order422; + u32 win_hor_ofst; + u32 win_ver_ofst; + u32 camclk; /* External Image Sensor Camera Clock */ + u32 source_x; + u32 source_y; + u32 polarity_pclk; + u32 polarity_vsync; + u32 polarity_href; + struct i2c_client *sensor; + u32 user; /* MAX 2 (codec, preview) */ + u32 old_priority; /* BUS PRIORITY register */ + u32 status; + u32 init_sensor;/* initializing sensor */ + void *other; /* Codec camif_cfg_t */ + u32 reset_type; /* External Sensor Reset Type */ + u32 reset_udelay; +} camif_gc_t; /* gobal control register */ + + +/* when App want to change v4l2 parameter, + * we instantly store it into v4l2_t v2 + * and then reflect it to hardware + */ +typedef struct v4l2 { + struct v4l2_fmtdesc *fmtdesc; + struct v4l2_pix_format fmt; /* current pixel format */ + struct v4l2_input input; + struct video_picture picture; + enum v4l2_status status; + int used_fmt ; /* used format index */ +} v4l2_t; + + +typedef struct camif_c_t { + struct video_device *v; + /* V4L2 param only for v4l2 driver */ + v4l2_t v2; + camif_gc_t *gc; /* Common between Codec and Preview */ + /* logical parameter */ + wait_queue_head_t waitq; + u32 status; /* Start/Stop */ + u32 fsm; /* Start/Stop */ + u32 open_count; /* duplicated */ + int irq; + char shortname[16]; + u32 target_x; + u32 target_y; + scaler_t sc; + enum flip_mode flip; + enum camif_dma_type dma_type; + /* 4 pingpong Frame memory */ + u8 *pp_virt_buf; + dma_addr_t pp_phys_buf; + u32 pp_totalsize; + u32 pp_num; /* used pingpong memory number */ + img_buf_t img_buf[4]; + enum camif_codec_fmt fmt; + enum camif_capturing exec; + camif_perf_t perf; + u32 now_frame_num; + u32 auto_restart; /* Only For Preview */ +} camif_cfg_t; + +#ifdef SW_DEBUG +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +#else +#define DPRINTK(fmt, args...) +#endif + + +#ifdef SW_DEBUG +#define assert(expr) \ + if(!(expr)) { \ + printk( "Assertion failed! %s,%s,%s,line=%d\n", \ + #expr,__FILE__,__FUNCTION__,__LINE__); \ + } +#else +#define assert(expr) +#endif + + + +extern int camif_capture_start(camif_cfg_t *); +extern int camif_capture_stop(camif_cfg_t *); +extern int camif_g_frame_num(camif_cfg_t *); +extern u8 * camif_g_frame(camif_cfg_t *); +extern int camif_win_offset(camif_gc_t *); +extern void camif_hw_open(camif_gc_t *); +extern void camif_hw_close(camif_cfg_t *); +extern int camif_dynamic_open(camif_cfg_t *); +extern int camif_dynamic_close(camif_cfg_t *); +extern void camif_reset(int,int); +extern void camif_setup_sensor(void); +extern int camif_g_fifo_status(camif_cfg_t *); +extern void camif_last_irq_en(camif_cfg_t *); +extern void camif_change_flip(camif_cfg_t *); + + +/* Todo + * API Interface function to both Character and V4L2 Drivers + */ +extern int camif_do_write(struct file *,const char *, size_t, loff_t *); +extern int camif_do_ioctl(struct inode *, struct file *,unsigned int, void *); + + +/* + * API for Decoder (S5x532, OV7620..) + */ +void camif_register_decoder(struct i2c_client *); +void camif_unregister_decoder(struct i2c_client*); + + + +/* API for FSM */ +#define INSTANT_SKIP 0 +#define INSTANT_GO 1 + +extern ssize_t camif_p_1fsm_start(camif_cfg_t *); +extern ssize_t camif_p_2fsm_start(camif_cfg_t *); +extern ssize_t camif_4fsm_start(camif_cfg_t *); +extern ssize_t camif_p_stop(camif_cfg_t *); +extern int camif_enter_p_4fsm(camif_cfg_t *); +extern int camif_enter_c_4fsm(camif_cfg_t *); +extern int camif_enter_2fsm(camif_cfg_t *); +extern int camif_enter_1fsm(camif_cfg_t *); +extern int camif_check_preview(camif_cfg_t *); +extern int camif_callback_start(camif_cfg_t *); +extern int camif_clock_init(camif_gc_t *); + +/* + * V4L2 Part + */ +#define VID_HARDWARE_SAMSUNG_FIMC20 236 + + + + + +#endif + + +/* + * Local variables: + * tab-width: 8 + * c-indent-level: 8 + * c-basic-offset: 8 + * c-set-style: "K&R" + * End: + */ diff --git a/arch/arm/mach-s3c2440/camera/camif_fsm.c b/arch/arm/mach-s3c2440/camera/camif_fsm.c new file mode 100644 index 0000000..3e2b71a --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/camif_fsm.c @@ -0,0 +1,427 @@ +/* + Copyright (C) 2004 Samsung Electronics + SW.LEE + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define SW_DEBUG + +#include "camif.h" +const char *fsm_version = + "$Id: camif_fsm.c,v 1.3 2004/04/27 10:26:28 swlee Exp $"; + + +/* + * FSM function is the place where Synchronization in not necessary + * because IRS calls this functions. + */ + +ssize_t camif_p_1fsm_start(camif_cfg_t *cfg) +{ + //camif_reset(CAMIF_RESET,0); + cfg->exec = CAMIF_DMA_ON; + camif_capture_start(cfg); + camif_last_irq_en(cfg); + cfg->status = CAMIF_STARTED; + cfg->fsm = CAMIF_1nd_INT; + return 0; +} + + +ssize_t camif_p_2fsm_start(camif_cfg_t *cfg) +{ + camif_reset(CAMIF_RESET,0);/* FIFO Count goes to zero */ + cfg->exec = CAMIF_DMA_ON; + camif_capture_start(cfg); + cfg->status = CAMIF_STARTED; + cfg->fsm = CAMIF_1nd_INT; + return 0; +} + + +ssize_t camif_4fsm_start(camif_cfg_t *cfg) +{ + camif_reset(CAMIF_RESET,0); /* FIFO Count goes to zero */ + cfg->exec = CAMIF_DMA_ON; + camif_capture_start(cfg); + cfg->status = CAMIF_STARTED; + cfg->fsm = CAMIF_1nd_INT; + cfg->perf.frames = 0; + return 0; +} + + +/* Policy: + cfg->perf.frames set in camif_fsm.c + cfg->status set in video-driver.c + */ + +/* + * Don't insert camif_reset(CAM_RESET, 0 ) into this func + */ +ssize_t camif_p_stop(camif_cfg_t *cfg) +{ + cfg->exec = CAMIF_DMA_OFF; +// cfg->status = CAMIF_STOPPED; + camif_capture_stop(cfg); + cfg->perf.frames = 0; /* Dupplicated ? */ + return 0; +} + +/* When C working, P asks C to play togehter */ +/* Only P must call this function */ +void camif_start_c_with_p (camif_cfg_t *cfg, camif_cfg_t *other) +{ +// cfg->gc->other = get_camif(CODEC_MINOR); + cfg->gc->other = other; + camif_start_p_with_c(cfg); +} + +static void camif_start_p_with_c(camif_cfg_t *cfg) +{ + camif_cfg_t *other = (camif_cfg_t *)cfg->gc->other; + /* Preview Stop */ + cfg->exec = CAMIF_DMA_OFF; + camif_capture_stop(cfg); + /* Start P and C */ + camif_reset(CAMIF_RESET, 0); + cfg->exec =CAMIF_BOTH_DMA_ON; + camif_capture_start(cfg); + cfg->fsm = CAMIF_1nd_INT; /* For Preview */ + if(!other) panic("Unexpected Error \n"); + other->fsm = CAMIF_1nd_INT; /* For Preview */ +} + +static void camif_auto_restart(camif_cfg_t *cfg) +{ +// if (cfg->dma_type & CAMIF_CODEC) return; + if (cfg->auto_restart) + camif_start_p_with_c(cfg); +} + + +/* Supposed that PREVIEW already running + * request PREVIEW to start with Codec + */ +static int camif_check_global(camif_cfg_t *cfg) +{ + int ret = 0; + + if (down_interruptible(&cfg->gc->lock)) + return -ERESTARTSYS; + if ( cfg->gc->status & CWANT2START ) { + cfg->gc->status &= ~CWANT2START; + cfg->auto_restart = 1; + ret = 1; + } + else { + ret = 0; /* There is no codec */ + cfg->auto_restart = 0; /* Duplicated ..Dummy */ + } + + up(&cfg->gc->lock); + + return ret; +} + +/* + * 1nd INT : Start Interrupt + * Xnd INT : enable Last IRQ : pingpong get the valid data + * Ynd INT : Stop Codec or Preview : pingpong get the valid data + * Znd INT : Last IRQ : valid data + */ +#define CHECK_FREQ 5 +int camif_enter_p_4fsm(camif_cfg_t *cfg) +{ + int ret = 0; + + cfg->perf.frames++; + if (cfg->fsm == CAMIF_NORMAL_INT) + if (cfg->perf.frames % CHECK_FREQ == 0) + ret = camif_check_global(cfg); + if (ret > 0) cfg->fsm = CAMIF_Xnd_INT; /* Codec wait for Preview */ + + switch (cfg->fsm) { + case CAMIF_1nd_INT: /* Start IRQ */ + cfg->fsm = CAMIF_NORMAL_INT; + ret = INSTANT_SKIP; + DPRINTK(KERN_INFO "1nd INT \n"); + break; + case CAMIF_NORMAL_INT: + cfg->status = CAMIF_INT_HAPPEN; + cfg->fsm = CAMIF_NORMAL_INT; + ret = INSTANT_GO; + DPRINTK(KERN_INFO "NORMAL INT \n"); + break; + case CAMIF_Xnd_INT: + camif_last_irq_en(cfg);/* IRQ for Enabling LAST IRQ */ + cfg->status = CAMIF_INT_HAPPEN; + cfg->fsm = CAMIF_Ynd_INT; + ret = INSTANT_GO; + DPRINTK(KERN_INFO "Xnd INT \n"); + break; + case CAMIF_Ynd_INT: /* Capture Stop */ + cfg->exec = CAMIF_DMA_OFF; + cfg->status = CAMIF_INT_HAPPEN; + camif_capture_stop(cfg); + cfg->fsm = CAMIF_Znd_INT; + ret = INSTANT_GO; + DPRINTK(KERN_INFO "Ynd INT \n"); + break; + case CAMIF_Znd_INT: /* LAST IRQ (Dummy IRQ */ + cfg->fsm = CAMIF_DUMMY_INT; + cfg->status = CAMIF_INT_HAPPEN; + ret = INSTANT_GO; + camif_auto_restart(cfg); /* Automatically Restart Camera */ + DPRINTK(KERN_INFO "Znd INT \n"); + break; + case CAMIF_DUMMY_INT: + cfg->status = CAMIF_STOPPED; /* Dupplicate ? */ + ret = INSTANT_SKIP; +// DPRINTK(KERN_INFO "Dummy INT \n"); + break; + default: + printk(KERN_INFO "Unexpect INT %d \n",cfg->fsm); + ret = INSTANT_SKIP; + break; + } + return ret; +} + + +/* + * NO autorestart included in this function + */ +int camif_enter_c_4fsm(camif_cfg_t *cfg) +{ + int ret; + + cfg->perf.frames++; +#if 0 + if ( (cfg->fsm==CAMIF_NORMAL_INT) + && (cfg->perf.frames>cfg->restart_limit-1) + ) + cfg->fsm = CAMIF_Xnd_INT; +#endif + switch (cfg->fsm) { + case CAMIF_1nd_INT: /* Start IRQ */ + cfg->fsm = CAMIF_NORMAL_INT; +// cfg->status = CAMIF_STARTED; /* need this to meet auto-restart */ + ret = INSTANT_SKIP; + DPRINTK(KERN_INFO "1nd INT \n"); + break; + case CAMIF_NORMAL_INT: + cfg->status = CAMIF_INT_HAPPEN; + cfg->fsm = CAMIF_NORMAL_INT; + ret = INSTANT_GO; + DPRINTK(KERN_INFO "NORMALd INT \n"); + break; + case CAMIF_Xnd_INT: + camif_last_irq_en(cfg);/* IRQ for Enabling LAST IRQ */ + cfg->status = CAMIF_INT_HAPPEN; + cfg->fsm = CAMIF_Ynd_INT; + ret = INSTANT_GO; + DPRINTK(KERN_INFO "Xnd INT \n"); + break; + case CAMIF_Ynd_INT: /* Capture Stop */ + cfg->exec = CAMIF_DMA_OFF; + cfg->status = CAMIF_INT_HAPPEN; + camif_capture_stop(cfg); + cfg->fsm = CAMIF_Znd_INT; + ret = INSTANT_GO; + DPRINTK(KERN_INFO "Ynd INT \n"); + break; + case CAMIF_Znd_INT: /* LAST IRQ (Dummy IRQ */ + cfg->fsm = CAMIF_DUMMY_INT; + cfg->status = CAMIF_INT_HAPPEN; + ret = INSTANT_GO; + DPRINTK(KERN_INFO "Znd INT \n"); + break; + case CAMIF_DUMMY_INT: + cfg->status = CAMIF_STOPPED; /* Dupplicate ? */ + ret = INSTANT_SKIP; + break; + default: + printk(KERN_INFO "Unexpect INT %d \n",cfg->fsm); + ret = INSTANT_SKIP; + break; + } + return ret; +} + +/* 4 Interrups State Machine is for two pingpong + * 1nd INT : Start Interrupt + * Xnd INT : enable Last IRQ : pingpong get the valid data + * Ynd INT : Stop Codec or Preview : pingpong get the valid data + * Znd INT : Last IRQ : valid data + * + * Note: + * Before calling this func, you must call camif_reset + */ + +int camif_enter_2fsm(camif_cfg_t *cfg) /* Codec FSM */ +{ + int ret; + + cfg->perf.frames++; + switch (cfg->fsm) { + case CAMIF_1nd_INT: /* Start IRQ */ + cfg->fsm = CAMIF_Xnd_INT; + ret = INSTANT_SKIP; +// printk(KERN_INFO "1nd INT \n"); + break; + case CAMIF_Xnd_INT: + camif_last_irq_en(cfg);/* IRQ for Enabling LAST IRQ */ + cfg->now_frame_num = 0; + cfg->status = CAMIF_INT_HAPPEN; + cfg->fsm = CAMIF_Ynd_INT; + ret = INSTANT_GO; +// printk(KERN_INFO "2nd INT \n"); + break; + case CAMIF_Ynd_INT: /* Capture Stop */ + cfg->exec = CAMIF_DMA_OFF; + cfg->now_frame_num = 1; + cfg->status = CAMIF_INT_HAPPEN; + camif_capture_stop(cfg); + cfg->fsm = CAMIF_Znd_INT; + ret = INSTANT_GO; +// printk(KERN_INFO "Ynd INT \n"); + break; + case CAMIF_Znd_INT: /* LAST IRQ (Dummy IRQ */ + cfg->now_frame_num = 0; +// cfg->fsm = CAMIF_DUMMY_INT; + cfg->status = CAMIF_INT_HAPPEN; + ret = INSTANT_GO; +// printk(KERN_INFO "Znd INT \n"); + break; + case CAMIF_DUMMY_INT: + cfg->status = CAMIF_STOPPED; /* Dupplicate ? */ + ret = INSTANT_SKIP; + printk(KERN_INFO "Dummy INT \n"); + break; + default: /* CAMIF_PENDING_INT */ + printk(KERN_INFO "Unexpect INT \n"); + ret = INSTANT_SKIP; + break; + } + return ret; +} + + +/* 2 Interrups State Machine is for one pingpong + * 1nd INT : Stop Codec or Preview : pingpong get the valid data + * 2nd INT : Last IRQ : dummy data + */ +int camif_enter_1fsm(camif_cfg_t *cfg) /* Codec FSM */ +{ + int ret; + + cfg->perf.frames++; + switch (cfg->fsm) { + case CAMIF_Ynd_INT: /* IRQ for Enabling LAST IRQ */ + cfg->exec = CAMIF_DMA_OFF; + camif_capture_stop(cfg); + cfg->fsm = CAMIF_Znd_INT; + ret = INSTANT_SKIP; + // printk(KERN_INFO "Ynd INT \n"); + break; + case CAMIF_Znd_INT: /* LAST IRQ (Dummy IRQ */ + cfg->fsm = CAMIF_DUMMY_INT; + cfg->status = CAMIF_INT_HAPPEN; + ret = INSTANT_GO; + // printk(KERN_INFO "Znd INT \n"); + break; + case CAMIF_DUMMY_INT: + cfg->status = CAMIF_STOPPED; /* Dupplicate ? */ + ret = INSTANT_SKIP; + printk(KERN_INFO "Dummy INT \n"); + break; + default: + printk(KERN_INFO "Unexpect INT \n"); + ret = INSTANT_SKIP; + break; + } + return ret; +} + + +/* + * GLOBAL STATUS CONTROL FUNCTION + * + */ + + +/* Supposed that PREVIEW already running + * request PREVIEW to start with Codec + */ +int camif_callback_start(camif_cfg_t *cfg) +{ + int doit = 1; + while (doit) { + if (down_interruptible(&cfg->gc->lock)) { + return -ERESTARTSYS; + } + cfg->gc->status = CWANT2START; + cfg->gc->other = cfg; + up(&cfg->gc->lock); + doit = 0; + } + return 0; +} + +/* + * Return status of Preview Machine + ret value : + 0: Preview is not working + X: Codec must follow PREVIEW start +*/ +int camif_check_preview(camif_cfg_t *cfg) +{ + int ret = 0; + + if (down_interruptible(&cfg->gc->lock)) { + ret = -ERESTARTSYS; + return ret; + } + if (cfg->gc->user == 1) ret = 0; + // else if (cfg->gc->status & PNOTWORKING) ret = 0; + else ret = 1; + up(&cfg->gc->lock); + return ret; +} + + + + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/arch/arm/mach-s3c2440/camera/imgsensor.c b/arch/arm/mach-s3c2440/camera/imgsensor.c new file mode 100644 index 0000000..44b7bee --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/imgsensor.c @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2004 Samsung Electronics + * SW.LEE + * + * Copyright (C) 2000 Russell King : pcf8583.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver for FIMC20 Camera Decoder + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef CONFIG_ARCH_S3C24A0A +#else +#include +#endif + +#define SW_DEBUG +#include "camif.h" +#include "sensor.h" + +#ifndef SAMSUNG_SXGA_CAM +#include "s5x532_rev36.h" +#else +#include "sxga.h" +#endif + +static const char *sensor_version = + "$Id: imgsensor.c,v 1.11 2004/06/10 12:45:40 swlee Exp $"; + + +static struct i2c_driver s5x532_driver; +static camif_gc_t data = { + itu_fmt: CAMIF_ITU601, + order422: CAMIF_YCBYCR, + camclk: 24000000, +#ifndef SAMSUNG_SXGA_CAM + source_x: 640, + source_y: 480, + win_hor_ofst: 112, + win_ver_ofst: 20, +#else + source_x: 1280, + source_y: 1024, + win_hor_ofst: 0, + win_ver_ofst: 0, +#endif + polarity_pclk:1, + polarity_href:0, +#ifdef CONFIG_ARCH_S3C24A0A + reset_type:CAMIF_EX_RESET_AL, /* Active Low */ +#else + reset_type:CAMIF_EX_RESET_AH, /* Ref board has inverted signal */ +#endif + reset_udelay:2000, +}; + +#define CAM_ID 0x5a + +static unsigned short ignore[] = { I2C_CLIENT_END }; +static unsigned short normal_addr[] = { (CAM_ID>>1), I2C_CLIENT_END }; +static struct i2c_client_address_data addr_data = { + normal_i2c: normal_addr, + normal_i2c_range: ignore, + probe: ignore, + probe_range: ignore, + ignore: ignore, + ignore_range: ignore, + force: ignore, +}; + +s5x532_t s5x532_regs_mirror[S5X532_REGS]; + +unsigned char +s5x532_read(struct i2c_client *client,unsigned char subaddr) +{ + int ret; + unsigned char buf[1]; + struct i2c_msg msg ={ client->addr, 0, 1, buf}; + buf[0] = subaddr; + + ret = i2c_transfer(client->adapter,&msg, 1) == 1 ? 0 : -EIO; + if (ret == -EIO) { + printk(" I2C write Error \n"); + return -EIO; + } + + msg.flags = I2C_M_RD; + ret = i2c_transfer(client->adapter, &msg, 1) == 1 ? 0 : -EIO; + + return buf[0]; +} + + +static int +s5x532_write(struct i2c_client *client, + unsigned char subaddr, unsigned char val) +{ + unsigned char buf[2]; + struct i2c_msg msg = { client->addr, 0, 2, buf}; + + buf[0]= subaddr; + buf[1]= val; + + return i2c_transfer(client->adapter, &msg, 1) == 1 ? 0 : -EIO; +} + +void inline s5x532_init(struct i2c_client *sam_client) +{ + int i; + + printk(KERN_ERR "s5x532_init \n"); + for (i = 0; i < S5X532_INIT_REGS; i++) { + s5x532_write(sam_client, + s5x532_reg[i].subaddr, s5x532_reg[i].value ); + } + +#ifdef YOU_WANT_TO_CHECK_IMG_SENSOR + for (i = 0; i < S5X532_INIT_REGS;i++) { + if ( s5x532_reg[i].subaddr == PAGE_ADDRESS ) { + s5x532_write(sam_client, + s5x532_reg[i].subaddr, s5x532_reg[i].value); + + printk(KERN_ERR "Page: Subaddr %02x = 0x%02x\n", + s5x532_reg[i].subaddr, s5x532_regs_mirror[i].value); + + + } else + { + s5x532_regs_mirror[i].subaddr = s5x532_reg[i].subaddr; + s5x532_regs_mirror[i].value = + s5x532_read(sam_client,s5x532_reg[i].subaddr); + printk(KERN_ERR "Subaddr %02x = 0x%02x\n", + s5x532_reg[i].subaddr, s5x532_regs_mirror[i].value); + } + } +#endif + +} + +static int +s5x532_attach(struct i2c_adapter *adap, int addr, unsigned short flags,int kind) +{ + struct i2c_client *c; + + c = kmalloc(sizeof(*c), GFP_KERNEL); + if (!c) return -ENOMEM; + + strcpy(c->name, "S5X532"); + c->id = s5x532_driver.id; + c->flags = I2C_CLIENT_ALLOW_USE; + c->addr = addr; + c->adapter = adap; + c->driver = &s5x532_driver; + c->data = &data; + data.sensor = c; + + camif_register_decoder(c); + return i2c_attach_client(c); +} + +static int s5x532_probe(struct i2c_adapter *adap) +{ + return i2c_probe(adap, &addr_data, s5x532_attach); +} + +static int s5x532_detach(struct i2c_client *client) +{ + i2c_detach_client(client); + camif_unregister_decoder(client); + return 0; +} + +static int +s5x532_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + switch (cmd) { + case SENSOR_INIT: + s5x532_init(client); + printk(KERN_INFO "CAMERA: S5X532 Sensor initialized\n"); + break; + case USER_ADD: + MOD_INC_USE_COUNT; + break; + case USER_EXIT: + MOD_DEC_USE_COUNT; + break; +/* Todo + case SENSOR_BRIGHTNESS: + change_sensor(); + break; +*/ + default: + panic("Unexpect Sensor Command \n"); + break; + } + return 0; +} + +static struct i2c_driver s5x532_driver = { + name: "S5X532", + id: I2C_ALGO_S3C, + flags: I2C_DF_NOTIFY, + attach_adapter: s5x532_probe, + detach_client: s5x532_detach, + command: s5x532_command +}; + +static void iic_gpio_port(void) +{ +#ifdef CONFIG_ARCH_S3C24A0A +#else + GPECON &= ~(0xf <<28); + GPECON |= 0xa <<28; +#endif +} + +static __init int camif_sensor_init(void) +{ + iic_gpio_port(); + return i2c_add_driver(&s5x532_driver); +} + + +static __init void camif_sensor_exit(void) +{ + i2c_del_driver(&s5x532_driver); +} + +module_init(camif_sensor_init) +module_exit(camif_sensor_exit) + +MODULE_AUTHOR("SW.LEE "); +MODULE_DESCRIPTION("I2C Client Driver For Fimc2.0 MISC Driver"); +MODULE_LICENSE("GPL"); + + + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/arch/arm/mach-s3c2440/camera/miscdevice.h b/arch/arm/mach-s3c2440/camera/miscdevice.h new file mode 100644 index 0000000..2e1cfbc --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/miscdevice.h @@ -0,0 +1,18 @@ + + /*---------------------------------------------------------- + * (C) 2004 Samsung Electronics + * SW.LEE < hitchcar@samsung.com> + * + ----------------------------------------------------------- */ + +#ifndef _LINUX_S3C_MISCDEVICE_H +#define _LINUX_S3C_MISCDEVICE_H + +#define CODEC_MINOR 212 +#define PREVIEW_MINOR 213 + + + + + +#endif diff --git a/arch/arm/mach-s3c2440/camera/qt-driver.c b/arch/arm/mach-s3c2440/camera/qt-driver.c new file mode 100644 index 0000000..0c5dd40 --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/qt-driver.c @@ -0,0 +1,169 @@ +/* + * SW.LEE + * + * This file is subject to the terms and conditions of the GNU General Public + * License 2. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define SW_DEBUG + +#include "camif.h" +#include "videodev.h" +#include "miscdevice.h" +#include "cam_reg.h" +#include "sensor.h" +#include "userapp.h" + + +/************************* Sharp Zarus API ************************** +* refering to Camera Driver API for SL-5000D/SL-5600 revision 1.00 +* April 11, 2002. + SW.LEE + I want to use Sharp Camera Application. +* +*/ + +#define READ_MODE_STATUS 0x1 +#define READ_MODE_IMAGE 0x0 +#define CAPTURE_SPEED +#define H_FLIP +#define V_FLIP +typedef enum sharp_readmode +{ + IMAGE = 0, STATUS = 1, + FASTER = 0, BETTER = 2, + XNOFLIP = 0, XFLIP = 4, + YNOFLIP = 0, YFLIP = 8, + AUTOMATICFLIP = -1 +} ReadMode_t; + + +static struct sharp_param_t { + ReadMode_t readMode; + char CameraStatus[4]; +} sharp_param = { STATUS, {'s','m','c','A'}}; + + +camif_param_t qt_parm = { 640,480,240,320,16,0}; + +static void setReadMode(const char *b,size_t count) +{ + int i = *(b+2) - 48 ; + if ( 4 == count ) { + i = (*(b+3) - 48) + i * 10; + } + + // DPRINTK(" setReadMode %s conversion value %d \n",b , i); + if ( i & STATUS ) { + // DPRINTK(" STATUS MODE \n"); + sharp_param.readMode = i; + } + else { + // DPRINTK(" IMAGE MODE \n"); + sharp_param.readMode = i; + } +} + + + + +extern ssize_t camif_p_read(struct file *, char *, size_t , loff_t *); + +ssize_t z_read(struct file *f, char *buf, size_t count, loff_t *pos) +{ + size_t end; + + if (sharp_param.readMode & STATUS ) { + buf[0] = sharp_param.CameraStatus[0]; + buf[1] = sharp_param.CameraStatus[1]; + buf[2] = sharp_param.CameraStatus[2]; + buf[3] = sharp_param.CameraStatus[3]; + end = 4; + return end; + } + else { /* Image ReadMode */ + /* + if (( sharp_param.readMode & (BETTER|X FLIP|YFLIP))) + DPRINTK(" Not Supporting BETTER|XFLIP|YFLIP\n"); + */ + return camif_p_read(f,buf,count,pos); + } +} + +static void z_config(camif_cfg_t *cfg,int x, int y) +{ + cfg->target_x = x; + cfg->target_y = y; + cfg->fmt = CAMIF_RGB16; + if (camif_dynamic_open(cfg)) { + panic(" Eror Happens \n"); + } +} + + +ssize_t z_write(struct file *f, const char *b, size_t c, loff_t *pos) +{ + int array[5]; + int zoom = 1; + camif_cfg_t *cfg; + + cfg = get_camif(MINOR(f->f_dentry->d_inode->i_rdev)); +// DPRINTK(" param %s count %d \n",b, c ); + + switch(*b) { + case 'M': + setReadMode(b, c); + break; + case 'B': /* Clear the latch flag of shutter button */ + DPRINTK(" clear latch flag of camera's shutter button\n"); + sharp_param.CameraStatus[0]='s'; + break; + case 'Y': /* I don't know how to set Shutter pressed */ + DPRINTK(" set latch flag n"); + sharp_param.CameraStatus[0]='S'; + break; + case 'S': /* Camera Image Resolution */ + case 'R': /* Donot support Rotation */ + DPRINTK(" param %s count %d \n",b, c ); + get_options((char *)(b+2), 5, array); + if ( array[3] == 512 ) zoom = 2; + z_config(cfg, array[1] * zoom , array[2] * zoom ); + camif_4fsm_start(cfg); + break; + case 'C': + DPRINTK(" param %s count %d \n",b, c ); + DPRINTK(" Start the camera to capture \n"); + sharp_param.CameraStatus[2]='C'; + camif_4fsm_start(cfg); + break; + default: + printk("Unexpected param %s count %d \n",b, c ); + } + + return c; +} + diff --git a/arch/arm/mach-s3c2440/camera/qt.h b/arch/arm/mach-s3c2440/camera/qt.h new file mode 100644 index 0000000..e58368a --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/qt.h @@ -0,0 +1,18 @@ +/* + * SW.LEE + * + * This file is subject to the terms and conditions of the GNU General Public + * License 2. See the file COPYING in the main directory of this archive + * for more details. + */ + +#ifndef __Z_API_H_ +#define __Z_API_H_ + +extern ssize_t z_read(struct file *f, char *buf, size_t count, loff_t *pos); +extern ssize_t z_write(struct file *f, const char *b, size_t c, loff_t *pos); + + + +#endif + diff --git a/arch/arm/mach-s3c2440/camera/s5x532.h b/arch/arm/mach-s3c2440/camera/s5x532.h new file mode 100644 index 0000000..12725f4 --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/s5x532.h @@ -0,0 +1,143 @@ +/* + * 2004 (C) Samsung Electronics + * SW.LEE + * This file is subject to the terms and conditions of the GNU General Public + * License 2. See the file COPYING in the main directory of this archive + * for more details. + */ + + +#ifndef _SMDK2440_S5X532_H_ +#define _SMDK2440_S5X532_H_ + + +#define CHIP_DELAY 0xFF + +typedef struct samsung_t{ + unsigned char subaddr; + unsigned char value; + unsigned char page; +} s5x532_t; + +s5x532_t s5x532_reg[] = { + // page 5 + {0xec,0x05}, + {0x08,0x55,0x5}, + {0x0a,0x75,0x5}, + {0x0c,0x90,0x5}, + {0x0e,0x18,0x5}, + {0x12,0x09,0x5}, + {0x14,0x9d,0x5}, + {0x16,0x90,0x5}, + {0x1a,0x18,0x5}, + {0x1c,0x0c,0x5}, + {0x1e,0x09,0x5}, + {0x20,0x06,0x5}, + {0x22,0x20,0x5}, + {0x2a,0x00,0x5}, + {0x2d,0x04,0x5}, + {0x12,0x24,0x5}, + // page 3 + {0xec,0x03,0x3}, + {0x0c,0x09,0x3}, + {0x6c,0x09,0x3}, + {0x2b,0x10,0x3}, // momo clock inversion + // page 2 + {0xec,0x02,0x2}, + {0x03,0x09,0x2}, + {0x05,0x08,0x2}, + {0x06,0x01,0x2}, + {0x07,0xf8,0x2}, + {0x15,0x25,0x2}, + {0x30,0x29,0x2}, + {0x36,0x12,0x2}, + {0x38,0x04,0x2}, + {0x1b,0x77,0x2}, // 24MHz : 0x77, 12MHz : 0x22 + {0x1c,0x77,0x2}, // 24MHz : 0x77, 12MHz : 0x22 + // page 1 + {0xec,0x01,0x1}, + {0x00,0x03,0x1}, // + {0x0a,0x08,0x1}, // 0x0-QQVGA, 0x06-CIF, 0x02-QCIF, 0x08-VGA, 0x04-QVGA, 0x0a-SXGA + {0x0c,0x00,0x1}, // Pattern selectio. 0-CIS, 1-Color bar, 2-Ramp, 3-Blue screen + {0x10,0x27,0x1}, + // 0x21-ITU-R656(CrYCbY), 0x25-ITU-R601(CrYCbY), 0x26-ITU-R601(YCbYCr) + {0x50,0x21,0x1}, // Hblank + {0x51,0x00,0x1}, // Hblank + {0x52,0xA1,0x1}, // Hblank + {0x53,0x02,0x1}, // Hblank + {0x54,0x01,0x1}, // Vblank + {0x55,0x00,0x1}, // Vblank + {0x56,0xE1,0x1}, // Vblank + {0x57,0x01,0x1}, // Vblank + {0x58,0x21,0x1}, // Hsync + {0x59,0x00,0x1}, // Hsync + {0x5a,0xA1,0x1}, // Hsync + {0x5b,0x02,0x1}, // Hsync + {0x5c,0x03,0x1}, // Vref + {0x5d,0x00,0x1}, // Vref + {0x5e,0x05,0x1}, // Vref + {0x5f,0x00,0x1}, // Vref + {0x70,0x0E,0x1}, + {0x71,0xD6,0x1}, + {0x72,0x30,0x1}, + {0x73,0xDB,0x1}, + {0x74,0x0E,0x1}, + {0x75,0xD6,0x1}, + {0x76,0x18,0x1}, + {0x77,0xF5,0x1}, + {0x78,0x0E,0x1}, + {0x79,0xD6,0x1}, + {0x7a,0x28,0x1}, + {0x7b,0xE6,0x1}, + {0x50,0x00,0x1}, + {0x5c,0x00,0x1}, + + // page 0 + {0xec,0x00,0x0}, + {0x79,0x01,0x0}, + {0x58,0x90,0x0}, + {0x59,0xA0,0x0}, + {0x5a,0x50,0x0}, + {0x5b,0x70,0x0}, + {0x5c,0xD0,0x0}, + {0x5d,0xC0,0x0}, + {0x5e,0x28,0x0}, + {0x5f,0x08,0x0}, + {0x50,0x90,0x0}, + {0x51,0xA0,0x0}, + {0x52,0x50,0x0}, + {0x53,0x70,0x0}, + {0x54,0xD0,0x0}, + {0x55,0xC0,0x0}, + {0x56,0x28,0x0}, + {0x57,0x00,0x0}, + {0x48,0x90,0x0}, + {0x49,0xA0,0x0}, + {0x4a,0x50,0x0}, + {0x4b,0x70,0x0}, + {0x4c,0xD0,0x0}, + {0x4d,0xC0,0x0}, + {0x4e,0x28,0x0}, + {0x4f,0x08,0x0}, + {0x72,0x82,0x0}, // main clock = 24MHz:0xd2, 16M:0x82, 12M:0x54 + {0x75,0x05,0x0} // absolute vertical mirror. junon + +}; + + +#define S5X532_INIT_REGS (sizeof(s5x532_reg)/sizeof(s5x532_reg[0])) +#define S5X532_RISC_REGS 0xEB +#define S5X532_ISP_REGS 0xFB /* S5C7323X */ +#define S5X532_CIS_REGS 0x2F /* S5K437LA03 */ + + +#define PAGE_ADDRESS 0xEC + +//#define S5X532_REGS (S5X532_RISC_REGS+S5X532_ISP_REGS+S5X532_CIS_REGS) +#define S5X532_REGS (0x1000) + + + +#endif + + diff --git a/arch/arm/mach-s3c2440/camera/s5x532_rev36.h b/arch/arm/mach-s3c2440/camera/s5x532_rev36.h new file mode 100644 index 0000000..b662e9c --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/s5x532_rev36.h @@ -0,0 +1,208 @@ +/* + * 2004 (C) Samsung Electronics + * SW.LEE + * This file is subject to the terms and conditions of the GNU General Public + * License 2. See the file COPYING in the main directory of this archive + * for more details. + */ + + +#ifndef _SMDK2440_S5X532_H_ +#define _SMDK2440_S5X532_H_ + + +#define CHIP_DELAY 0xFF + +typedef struct samsung_t{ + unsigned char subaddr; + unsigned char value; + unsigned char page; +} s5x532_t; + +s5x532_t s5x532_reg[] = { + + //=============== page0 ===============// + {0xec,0x00,0x00}, + {0x02,0x00,0x00}, + {0x14,0x60,0x00}, + {0x15,0x60,0x00}, + {0x16,0x60,0x00}, + {0x1b,0x20,0x00}, + {0x1c,0x20,0x00}, + {0x1d,0x20,0x00}, + {0x1e,0x20,0x00}, + {0x72,0xdc,0x00}, + {0x73,0x11,0x00}, + {0x76,0x82,0x00}, + {0x77,0x90,0x00}, + {0x78,0x6c,0x00}, + {0x0a,0x02,0x00}, + {0x34,0x0d,0x00}, + {0x35,0x0a,0x00}, + {0x36,0x05,0x00}, + {0x37,0x05,0x00}, + {0x38,0x06,0x00}, + {0x39,0x08,0x00}, + {0x3A,0x0d,0x00}, + {0x3B,0x0d,0x00}, + {0x3C,0x18,0x00}, + {0x3D,0xE0,0x00}, + {0x3E,0x20,0x00}, + {0x66,0x02,0x00}, + {0x6c,0x40,0x00}, + {0x7c,0x01,0x00}, + {0x0D,0x24,0x00}, + {0x40,0x1B,0x00}, + {0x41,0x4F,0x00}, + {0x42,0x24,0x00}, + {0x43,0x3E,0x00}, + {0x44,0x32,0x00}, + {0x45,0x30,0x00}, + {0x48,0xa0,0x00}, + {0x49,0xd0,0x00}, + {0x4A,0x28,0x00}, + {0x4B,0x7d,0x00}, + {0x4C,0xd0,0x00}, + {0x4D,0xe0,0x00}, + {0x4E,0x1a,0x00}, + {0x4F,0xa0,0x00}, + {0x50,0xc0,0x00}, + {0x51,0xc0,0x00}, + {0x52,0x42,0x00}, + {0x53,0x7e,0x00}, + {0x54,0xc0,0x00}, + {0x55,0xf0,0x00}, + {0x56,0x1e,0x00}, + {0x57,0xe0,0x00}, + {0x58,0xc0,0x00}, + {0x59,0xa0,0x00}, + {0x5A,0x4a,0x00}, + {0x5B,0x7e,0x00}, + {0x5C,0xc0,0x00}, + {0x5D,0xf0,0x00}, + {0x5E,0x2a,0x00}, + {0x5F,0x10,0x00}, + {0x79,0x00,0x00}, + {0x7a,0x00,0x00}, + {0xe0,0x0f,0x00}, + {0xe3,0x14,0x00}, + {0xe5,0x48,0x00}, + {0xe7,0x58,0x00}, + + //=============== page1 ===============// + {0xec,0x01,0x01}, + {0x10,0x05,0x01}, + {0x20,0xde,0x01}, + {0x0b,0x06,0x01}, + {0x30,0x00,0x01}, + {0x31,0x00,0x01}, + {0x32,0x00,0x01}, + {0x24,0x28,0x01}, + {0x25,0x3F,0x01}, + {0x26,0x65,0x01}, + {0x27,0xA1,0x01}, + {0x28,0xFF,0x01}, + {0x29,0x96,0x01}, + {0x2A,0x85,0x01}, + {0x2B,0xFF,0x01}, + {0x2C,0x00,0x01}, + {0x2D,0x1B,0x01}, + {0xB0,0x28,0x01}, + {0xB1,0x3F,0x01}, + {0xB2,0x65,0x01}, + {0xB3,0xA1,0x01}, + {0xB4,0xFF,0x01}, + {0xB5,0x96,0x01}, + {0xB6,0x85,0x01}, + {0xB7,0xFF,0x01}, + {0xB8,0x00,0x01}, + {0xB9,0x1B,0x01}, + {0x15,0x15,0x01}, + {0x18,0x85,0x01}, + {0x1f,0x05,0x01}, + {0x87,0x40,0x01}, + {0x37,0x60,0x01}, + {0x38,0xd5,0x01}, + {0x48,0xa0,0x01}, + {0x61,0x54,0x01}, + {0x62,0x54,0x01}, + {0x63,0x14,0x01}, + {0x64,0x14,0x01}, + {0x6d,0x12,0x01}, + {0x78,0x09,0x01}, + {0x79,0xD7,0x01}, + {0x7A,0x14,0x01}, + {0x7B,0xEE,0x01}, + + //=============== page2 ===============// + {0xec,0x02,0x02}, + {0x2c,0x76,0x02}, + {0x25,0x25,0x02}, + {0x27,0x27,0x02}, + {0x30,0x29,0x02}, + {0x36,0x08,0x02}, + {0x38,0x04,0x02}, + + //=============== page3 ===============// + {0xec,0x03,0x03}, + {0x08,0x00,0x03}, + {0x09,0x33,0x03}, + + //=============== page4 ===============// + {0xec,0x04,0x04}, + {0x00,0x21,0x04}, + {0x01,0x00,0x04}, + {0x02,0x9d,0x04}, + {0x03,0x02,0x04}, + {0x04,0x04,0x04}, + {0x05,0x00,0x04}, + {0x06,0x1f,0x04}, + {0x07,0x02,0x04}, + {0x08,0x21,0x04}, + {0x09,0x00,0x04}, + {0x0a,0x9d,0x04}, + {0x0b,0x02,0x04}, + {0x0c,0x04,0x04}, + {0x0d,0x00,0x04}, + {0x0e,0x20,0x04}, + {0x0f,0x02,0x04}, + {0x1b,0x3c,0x04}, + {0x1c,0x3c,0x04}, + + //=============== page5 ===============// + {0xec,0x05,0x05}, + {0x1f,0x00,0x05}, + {0x08,0x59,0x05}, + {0x0a,0x71,0x05}, + {0x1e,0x23,0x05}, + {0x0e,0x3c,0x05}, + + //=============== page7 ===============// + {0xec,0x07,0x07}, + {0x11,0xfe,0x07}, + + // added by junon + {0xec,0x01,0x07}, + {0x10,0x26,0x07}, + // 0x21-ITU-R656(CbYCrY), 0x25-ITU-R601(CbYCrY), 0x26-ITU-R601(YCrYCb) + + +}; + + +#define S5X532_INIT_REGS (sizeof(s5x532_reg)/sizeof(s5x532_reg[0])) +#define S5X532_RISC_REGS 0xEB +#define S5X532_ISP_REGS 0xFB /* S5C7323X */ +#define S5X532_CIS_REGS 0x2F /* S5K437LA03 */ + + +#define PAGE_ADDRESS 0xEC + +//#define S5X532_REGS (S5X532_RISC_REGS+S5X532_ISP_REGS+S5X532_CIS_REGS) +#define S5X532_REGS (0x1000) + + + +#endif + + diff --git a/arch/arm/mach-s3c2440/camera/sensor.h b/arch/arm/mach-s3c2440/camera/sensor.h new file mode 100644 index 0000000..e28d01c --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/sensor.h @@ -0,0 +1,20 @@ +/* + * + * Copyright (C) 2004 Samsung Electronics + * SW.LEE + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __SENSOR_CMD_H_ +#define __SENSOR_CMD_H_ + +#include "bits.h" + +#define SENSOR_INIT BIT0 +#define USER_ADD BIT1 +#define USER_EXIT BIT2 + +#endif diff --git a/arch/arm/mach-s3c2440/camera/sxga.h b/arch/arm/mach-s3c2440/camera/sxga.h new file mode 100644 index 0000000..b41305a --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/sxga.h @@ -0,0 +1,504 @@ +/* + * 2004 (C) Samsung Electronics + * SW.LEE + * This file is subject to the terms and conditions of the GNU General Public + * License 2. See the file COPYING in the main directory of this archive + * for more details. + */ + + +#ifndef _SAMSUNG_SXGA_H_ +#define _SAMSUNG_SXGA_H_ + + +#define CHIP_DELAY 0xFF + +typedef struct samsung_t{ + unsigned char subaddr; + unsigned char value; + unsigned char page; +} s5x532_t; + +s5x532_t s5x532_reg[] = { + // page 0 + {0xec,0x00,0x0}, + {0x0c,0x38,0x0}, + {0x0d,0x24,0x0}, + {0x13,0x10,0x0}, + {0x14,0x10,0x0}, + {0x15,0x10,0x0}, + {0x16,0x10,0x0}, + {0x17,0x20,0x0}, + {0x18,0x30,0x0}, + {0x19,0x30,0x0}, + {0x1a,0x10,0x0}, + {0x1b,0x10,0x0}, + + {0x2d,0x40,0x0}, + {0x3e,0x10,0x0}, + {0x34,0x0a,0x0}, + {0x39,0x04,0x0}, + {0x3a,0x02,0x0}, + {0x31,0x05,0x0}, + + {0x40,0x1d,0x0}, + {0x41,0x50,0x0}, + {0x42,0x24,0x0}, + {0x43,0x3f,0x0}, + {0x44,0x30,0x0}, + {0x45,0x31,0x0}, + + {0x48,0xa0,0x0}, + {0x49,0xc0,0x0}, + {0x4a,0x58,0x0}, + {0x4b,0x50,0x0}, + {0x4c,0xb0,0x0}, + {0x4d,0xc0,0x0}, + {0x4e,0x30,0x0}, + {0x4f,0x20,0x0}, + + {0x50,0xa0,0x0}, + {0x51,0xc0,0x0}, + {0x52,0x50,0x0}, + {0x53,0x60,0x0}, + {0x54,0xb0,0x0}, + {0x55,0xc0,0x0}, + {0x56,0x20,0x0}, + {0x57,0x08,0x0}, +// {0x72,0x50,0x0}, // Clock 16 + {0x72,0x78,0x0}, // Clock 24Mhz +// {0x72,0xf0,0x0}, // Clock 48Mhz + // page 1 + {0xec,0x01,0x1}, + {0x10,0x17,0x1}, // ITU-R601 + /* + [3:2] : out_sel + 00 : 656 + 01 : 601 + 10 : RGB + 11 : CIS + [1] : YC_SEL + [0] : CBCR_SEL + */ + + {0x0b,0x06,0x1}, // 6 + {0x20,0xa8,0x1}, //b0); // Highlight C Supp 040215 + {0x22,0x26,0x1}, //2f); 040225 + + {0x24,0x08,0x1}, //00); //1F); 040226 + {0x25,0x10,0x1}, //10); //34); + {0x26,0x40,0x1}, //56); + {0x27,0x80,0x1}, //8D); + {0x28,0x2c,0x1}, //E7); + {0x29,0xd6,0x1}, //7C); + {0x2A,0x0c,0x1}, //70); + {0x2B,0xFF,0x1}, //FF); + {0x2C,0x00,0x1}, //00); + {0x2D,0x5f,0x1}, //1B); + // + {0xB0,0x08,0x1}, //00); //1F); 040226 + {0xB1,0x10,0x1}, //10); //34);50 + {0xB2,0x40,0x1}, //36); + {0xB3,0x80,0x1}, //6D); + {0xB4,0x2c,0x1}, //b7); + {0xB5,0xd6,0x1}, //7C); + {0xB6,0x0c,0x1}, //70); + {0xB7,0xFF,0x1}, //FF); + {0xB8,0x00,0x1}, //00); + {0xB9,0x5f,0x1}, //1B); + + + {0xc2,0x01,0x1}, // shading On + {0xc3,0x80,0x1}, + {0xc4,0x02,0x1}, + {0xc5,0x00,0x1}, + {0xc6,0x01,0x1}, + {0xc7,0x00,0x1}, + {0xc8,0x05,0x1}, + {0xc9,0x00,0x1}, + {0xca,0x04,0x1}, + + // shading 5 + {0xd0,0xb5,0x1}, + {0xd1,0x9c,0x1}, + {0xd2,0x8d,0x1}, + {0xd3,0x84,0x1}, + {0xd4,0x84,0x1}, + {0xd5,0x91,0x1}, + {0xd6,0xa0,0x1}, + {0xd7,0xb5,0x1}, + + {0xd8,0xc0,0x1}, + {0xd9,0xa6,0x1}, + {0xda,0x93,0x1}, + {0xdb,0x85,0x1}, + {0xdc,0x85,0x1}, + {0xdd,0x90,0x1}, + {0xde,0xa0,0x1}, + {0xdf,0xb8,0x1}, + + // Page 2 + {0xec,0x02,0x02}, + + {0x2d,0x02,0x02}, + {0x20,0x13,0x02}, + {0x21,0x13,0x2}, + {0x22,0x13,0x2}, + {0x23,0x13,0x2}, + {0x2e,0x85,0x2}, + {0x2f,0x34,0x2}, + {0x30,0x00,0x2}, + {0x28,0x94,0x2}, + + + // page 3 + {0xec,0x03,0x03}, + {0x10,0x00,0x3}, + {0x20,0x00,0x3}, + {0x21,0x20,0x3}, + {0x22,0x00,0x3}, + {0x23,0x00,0x3}, + {0x40,0x20,0x3}, + {0x41,0x20,0x3}, + {0x42,0x20,0x3}, + {0x43,0x20,0x3}, + {0x60,0x00,0x3}, + {0x61,0x00,0x3}, + {0x62,0x00,0x3}, + {0x63,0x00,0x3}, + {0x64,0x04,0x3}, + {0x65,0x1C,0x3}, + {0x66,0x05,0x3}, + {0x67,0x1C,0x3}, + {0x68,0x00,0x3}, + {0x69,0x2D,0x3}, + {0x6a,0x00,0x3}, + {0x6b,0x72,0x3}, + {0x6c,0x00,0x3}, + {0x6d,0x00,0x3}, + {0x6e,0x16,0x3}, // 2.38 + {0x6f,0x16,0x3}, // 2.38 + {0x70,0x00,0x3}, + {0x71,0x00,0x3}, + {0x72,0x45,0x3}, + {0x73,0x00,0x3}, + {0x74,0x1C,0x3}, + {0x75,0x05,0x3}, + + {0x80,0x00,0x3}, //for 0.02 _ 44 + {0x81,0x00,0x3}, + {0x82,0x00,0x3}, + {0x83,0x00,0x3}, + {0x84,0x04,0x3}, + {0x85,0x1c,0x3}, + {0x86,0x05,0x3}, + {0x87,0x1c,0x3}, + {0x88,0x00,0x3}, + {0x89,0x2d,0x3}, + {0x8a,0x00,0x3}, + {0x8b,0xcc,0x3}, + {0x8c,0x00,0x3}, + {0x8d,0x00,0x3}, + {0x8e,0x08,0x3}, + {0x8f,0x08,0x3}, + {0x90,0x01,0x3}, + {0x91,0x00,0x3}, + {0x92,0x91,0x3}, + {0x93,0x00,0x3}, + {0x94,0x88,0x3}, + {0x95,0x02,0x3}, + + + + // page 4 + {0xec,0x04,0x04}, + {0x3f,0x09,0x04}, // VGA : old board :0x08 , new board ; 0X09 + {0x18,0x00,0x04}, // sxga + {0x1c,0x41,0x04}, + {0x20,0x41,0x04}, // vga center 040215 + {0x22,0xc1,0x04},// a1); + {0x23,0x02,0x04}, + {0x28,0x41,0x04}, + {0x2a,0xc1,0x04},// a1); + {0x2b,0x02,0x04}, + + {0x3c,0x0b,0x04}, //f); // vga + {0x58,0x11,0x04}, + {0x5c,0x14,0x04}, + {0x60,0x21,0x04}, + {0x61,0x00,0x04}, + {0x62,0xB1,0x04}, + {0x63,0x02,0x04}, + {0x64,0x01,0x04}, + {0x65,0x00,0x04}, + {0x66,0x01,0x04}, + {0x67,0x02,0x04}, + {0x68,0x21,0x04}, + {0x69,0x00,0x04}, + {0x6a,0xB1,0x04}, + {0x6b,0x02,0x04}, + {0x6c,0x01,0x04}, + {0x6d,0x00,0x04}, + {0x6e,0x01,0x04}, + {0x6f,0x02,0x04}, + {0x70,0x2D,0x04}, + {0x71,0x00,0x04}, + {0x72,0xd3,0x04}, // 14 + {0x73,0x05,0x04}, // 15 + {0x74,0x1C,0x04}, + {0x75,0x05,0x04}, + {0x76,0x1b,0x04}, // HendL + {0x77,0x0b,0x04}, // HendH + {0x78,0x01,0x04}, // 5.00 + {0x79,0x80,0x04}, // 5.2a + {0x7a,0x33,0x04}, + {0x7b,0x00,0x04}, + {0x7c,0x38,0x04}, // 5.0e + {0x7d,0x03,0x04}, + {0x7e,0x00,0x04}, + {0x7f,0x0A,0x04}, + + {0x80,0x2e,0x04}, + {0x81,0x00,0x04}, + {0x82,0xae,0x04}, + {0x83,0x02,0x04}, + {0x84,0x00,0x04}, + {0x85,0x00,0x04}, + {0x86,0x01,0x04}, + {0x87,0x02,0x04}, + {0x88,0x2e,0x04}, + {0x89,0x00,0x04}, + {0x8a,0xae,0x04}, + {0x8b,0x02,0x04}, + {0x8c,0x1c,0x04}, + {0x8d,0x00,0x04}, + {0x8e,0x04,0x04}, + {0x8f,0x02,0x04}, + {0x90,0x2d,0x04}, + {0x91,0x00,0x04}, + {0x92,0xa5,0x04}, + {0x93,0x00,0x04}, + {0x94,0x88,0x04}, + {0x95,0x02,0x04}, + {0x96,0xb3,0x04}, + {0x97,0x06,0x04}, + {0x98,0x01,0x04}, + {0x99,0x00,0x04}, + {0x9a,0x33,0x04}, + {0x9b,0x30,0x04}, + {0x9c,0x50,0x04}, + {0x9d,0x30,0x04}, + {0x9e,0x01,0x04}, + {0x9f,0x08,0x04}, + + // page 5 + {0xec,0x05,0x05}, + {0x5a,0x22,0x05}, + + // page 6 + {0xec,0x06,0x06}, + {0x14,0x1e,0x06}, + {0x15,0xb4,0x04}, + {0x16,0x25,0x04}, + {0x17,0x74,0x04}, + + {0x10,0x48,0x04}, + {0x11,0xa0,0x04}, + {0x12,0x40,0x04}, // 040216 AE1 window ÁÙÀÓ + {0x13,0x70,0x04}, + + {0x1a,0x29,0x04}, // 040217 AWB window ÁÙÀÓ + {0x30,0x40,0x04}, + {0x31,0xa2,0x04}, + {0x32,0x50,0x04}, + {0x33,0xbc,0x04}, + {0x34,0x10,0x04}, + {0x35,0xd2,0x04}, + {0x36,0x18,0x04}, + {0x37,0xf5,0x04}, + {0x38,0x10,0x04}, + {0x39,0xd3,0x04}, + {0x3a,0x1a,0x04}, + {0x3b,0xf0,0x04}, + + // page 7 + {0xec,0x07,0x07}, + {0x08,0xff,0x7}, + {0x38,0x01,0x7}, //07); 040315 + {0x39,0x01,0x7}, //02); //4); 040223 040315 + {0x11,0xfe,0x7}, //fe); // green -2 040303 + {0x2a,0x20,0x7}, + {0x2b,0x20,0x7}, + {0x2c,0x10,0x7}, + {0x2d,0x00,0x7}, + {0x2e,0xf0,0x7}, + {0x2f,0xd0,0x7}, + {0x3a,0xf0,0x7}, + {0x23,0x07,0x7}, // for ESD + + // page 0 + {0xec,0x00,0x00}, + {0x8a,0x04,0x00}, + + // page 1 + {0xec,0x01,0x01}, + {0xe5,0xb0,0x01}, + {0xe5,0xb0,0x01}, + {0xc2,0x01,0x01}, + + {0x61,0x7b,0x01}, + {0x62,0x7b,0x01}, + {0x63,0x1b,0x01}, + {0x64,0x1b,0x01}, + + // page 0 + {0xec,0x00,0x00}, + {0x7e,0x04,0x00}, + + // page 4 + {0xec,0x04,0x04}, + {0x04,0x02,0x04}, + {0x06,0x02,0x04}, + + // page 1 + {0xec,0x01,0x01}, + {0x10,0x05,0x01}, + {0x54,0x02,0x01}, + {0x56,0x02,0x01}, + + // page 3 + {0xec,0x03,0x03}, + {0x0e,0x08,0x03}, + {0x0f,0x08,0x03}, + + // page 4 + {0xec,0x04,0x04}, + {0x00,0x30,0x04}, + {0x0a,0x30,0x04}, + + // page 5 + {0xec,0x05,0x05}, + {0x08,0x33,0x05}, + + // page 0 + {0xec,0x00,0x00}, + {0x02,0x00,0x00}, + + // page 4 +//scale out + {0xec,0x04,0x04}, + {0x02,0x20,0x04}, + {0x1c,0x4f,0x04}, + + // page 1 + {0xec,0x01,0x01}, + {0x52,0x20,0x01}, + + // page 5 + {0xec,0x05,0x05}, + {0x0e,0x4f,0x05}, + +//ae speed + // page 0 + {0xec,0x00,0x00}, + {0x92,0x80,0x00}, + {0x93,0x02,0x00}, + {0x94,0x04,0x00}, + {0x95,0x04,0x00}, + {0x96,0x04,0x00}, + {0x97,0x04,0x00}, + {0x9b,0x47,0x00}, + + {0xec,0x00,0x00}, + {0x40,0x17,0x00}, + {0x41,0x4c,0x00}, + {0x42,0x1d,0x00}, + {0x43,0x3e,0x00}, + {0x44,0x2a,0x00}, + {0x45,0x2d,0x00}, + + {0xec,0x01,0x01}, + {0x20,0xd0,0x01}, //high light color reference + + {0xec,0x00,0x00}, + {0x7e,0x00,0x00}, + {0x73,0x11,0x00}, // 41 + {0x78,0x78,0x00}, + + {0xec,0x07,0x07}, + {0x1b,0x3e,0x07}, + + {0xec,0x00,0x00}, + {0x48,0xA0,0x00}, //s48C0 + {0x49,0xB0,0x00}, //s49B0 + {0x4a,0x30,0x00}, //s4a20 + {0x4b,0x70,0x00}, //s4b70 + {0x4c,0xD0,0x00}, //s4cA0 + {0x4d,0xB0,0x00}, //s4dB0 + {0x4e,0x30,0x00}, //s4e30 + {0x4f,0xF0,0x00}, //s4fF0 + {0x50,0xA0,0x00}, //s50D0 + {0x51,0xB0,0x00}, //s51B0 + {0x52,0x25,0x00}, //s5210 + {0x53,0x70,0x00}, //s5370 + {0x54,0xD0,0x00}, //s5490 + {0x55,0xD0,0x00}, //s55B0 + {0x56,0x3A,0x00}, //s5640 + {0x57,0xD0,0x00}, //s57D0 + {0x58,0xA0,0x00}, //s58D0 + {0x59,0xA0,0x00}, //s59B0 + {0x5a,0x32,0x00}, //s5a0A + {0x5b,0x7A,0x00}, //s5b7A + {0x5c,0xB0,0x00}, //s5c90 + {0x5d,0xC0,0x00}, //s5dC0 + {0x5e,0x3E,0x00}, //s5e4A + {0x5f,0xfa,0x00}, //s5fD0 + + // gamma + {0xec,0x01,0x01}, + {0x24,0x31,0x01}, + {0x25,0x4C,0x01}, + {0x26,0x75,0x01}, + {0x27,0xB5,0x01}, + {0x28,0x17,0x01}, + {0x29,0xAE,0x01}, + {0x2A,0x97,0x01}, + {0x2B,0xFF,0x01}, + {0x2C,0x00,0x01}, + {0x2D,0x5B,0x01}, + + {0xB0,0x31,0x01}, + {0xB1,0x4C,0x01}, + {0xB2,0x75,0x01}, + {0xB3,0xB5,0x01}, + {0xB4,0x17,0x01}, + {0xB5,0xAE,0x01}, + {0xB6,0x97,0x01}, + {0xB7,0xFF,0x01}, + {0xB8,0x00,0x01}, + {0xB9,0x5B,0x01}, + + {0xec,0x00,0x00}, + {0x77,0xb0,0x00}, + {0x39,0x06,0x00}, + {0x3a,0x08,0x00}, + +}; + + +#define S5X532_INIT_REGS (sizeof(s5x532_reg)/sizeof(s5x532_reg[0])) +#define S5X532_RISC_REGS 0xEB +#define S5X532_ISP_REGS 0xFB /* S5C7323X */ +#define S5X532_CIS_REGS 0x2F /* S5K437LA03 */ + + +#define PAGE_ADDRESS 0xEC + +//#define S5X532_REGS (S5X532_RISC_REGS+S5X532_ISP_REGS+S5X532_CIS_REGS) +#define S5X532_REGS (0x1000) + + + +#endif + + diff --git a/arch/arm/mach-s3c2440/camera/userapp.h b/arch/arm/mach-s3c2440/camera/userapp.h new file mode 100644 index 0000000..9203378 --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/userapp.h @@ -0,0 +1,44 @@ +/* + Character Driver API Interface + + Copyright (C) 2003 Samsung Electronics (SW.LEE: hitchcar@samsung.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + +*/ + +#ifndef __FIMC20_CAMIF_USR_APP_H_ +#define __FIMC20_CAMIF_USR_APP_H_ + + +/* + * IOCTL Command for Character Driver + */ + +#define CMD_CAMERA_INIT 0x23 +/* Test Application Usage */ +typedef struct { + int src_x; + int src_y; + int dst_x; + int dst_y; + int bpp; + int flip; +} camif_param_t; + + + +#endif + + +/* + * Local variables: + * tab-width: 8 + * c-indent-level: 8 + * c-basic-offset: 8 + * c-set-style: "K&R" + * End: + */ diff --git a/arch/arm/mach-s3c2440/camera/v4l2_api.c b/arch/arm/mach-s3c2440/camera/v4l2_api.c new file mode 100644 index 0000000..13aed36 --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/v4l2_api.c @@ -0,0 +1,311 @@ +/* + * . 2004-01-03: SW.LEE + * + * This file is subject to the terms and conditions of the GNU General Public + * License 2. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "camif.h" +#include "videodev.h" + +/* + Codec_formats/Preview_format[0] must be same to initial value of + preview_init_param/codec_init_param +*/ + +const struct v4l2_fmtdesc codec_formats[] = { + { + .index = 0, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, +// .flags = FORMAT_FLAGS_PLANAR, + .description = "4:2:2, planar, Y-Cb-Cr", + .pixelformat = V4L2_PIX_FMT_YUV422P, + + },{ + .index = 1, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, +// .flags = FORMAT_FLAGS_PLANAR, + .name = "4:2:0, planar, Y-Cb-Cr", + .fourcc = V4L2_PIX_FMT_YUV420, + } +}; + + +/* Todo + FIMC V4L2_PIX_FMT_RGB565 is not same to that of V4L2spec + and so we need image convert to FIMC V4l2_PIX_FMT_RGB565. +*/ +const struct v4l2_fmtdesc preview_formats[] = { + { + .index = 1, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .description = "16 bpp RGB, le", + .fourcc = V4L2_PIX_FMT_RGB565, +// .flags = FORMAT_FLAGS_PACKED, + }, + { + .index = 0, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, +// .flags = FORMAT_FLAGS_PACKED, + .description = "32 bpp RGB, le", + .fourcc = V4L2_PIX_FMT_BGR32, + } +} + +#define NUM_F ARRARY_SIZE(preview_formats) + + +/* + * This function and v4l2 structure made for V4L2 API functions + * App <--> v4l2 <--> logical param <--> hardware + */ +static int camif_get_v4l2(camif_cfg_t *cfg) +{ + return 0; +} + + +/* +** Gives the depth of a video4linux2 fourcc aka pixel format in bits. +*/ +static int pixfmt2depth(int pixfmt,int *fmtptr) +{ + int fmt, depth; + + switch (pixfmt) { + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_RGB565X: + fmt = CAMIF_RGB_16; + depth = 16; + break; + case V4L2_PIX_FMT_BGR24: /* Not tested */ + case V4L2_PIX_FMT_RGB24: + fmt = CAMIF_RGB_24; + depth = 24; + break; + case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_RGB32: + fmt = CAMIF_RGB_24; + depth 32; + break; + case V4L2_PIX_FMT_GREY: /* Not tested */ + fmt = CAMIF_OUT_YCBCR420; + depth = 8; + break; + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUV422P: + fmt = CAMIF_OUT_YCBCR422; + depth = 16; + break; + case V4L2_PIX_FMT_YUV420: + fmt = CAMIF_OUT_YCBCR420; + depth = 12; + break; + } + if (fmtptr) *fmtptr = fmt; + return depth; +} + + + +static int camif_s_v4l2(camif_cfg_t *cfg) +{ + int num = cfg->v2.used_fmt; + + if ( !(cfg->v2.status&CAMIF_V4L2_INIT)) { + int depth; + int fourcc = v2.fmtdesc[num].pixelformat; + + /* To define v4l2_fmtsdesc */ + if (cfg->dma_type == CAMIF_CODEC) + cfg->v2->fmtdesc = codec_formats; + else + cfg->v2->fmtdesc = preview_formats; + + /* To define v4l2_format used currently */ + cfg->v2.fmt.width = cfg->target_x; + cfg->v2.fmt.height = cfg->target_y; + cfg->v2.fmt.field = V4L2_FIELD_NONE; + cfg->v2.fmt.pixelformat = fourcc; + depth = pixfmt2depth(fourcc,NULL); + cfg->v2.fmt.bytesperline= cfg->v2.fmt.width*depth >> 3; + cfg->v2.fmt.sizeimage = + cfg->v2.fmt.height * cfg->v2.fmt.bytesperline; + + /* To define v4l2_input */ + cfg->v2.input.index = 0; + if (cfg->dma_type == CAMIF_CODEC) + snprintf(cfg->v2.input.name, 31, "CAMIF CODEC"); + else + snprintf(cfg->v2.input.name, 31, "CAMIF PREVIEW"); + cfg->v2.input.type = V4L2_INPUT_TYPE_CAMERA; + + /* Write the Status of v4l2 machine */ + cfg->v2.status |= CAMIF_V4L2_INIT; + } + return 0; +} + + +static int camif_g_fmt(camif_cfg_t *cfg, struct v4l2_format *f) +{ + int size = sizeof(struct v4l2_pix_format); + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + memset(&f->fmt.pix,0,size); + memcpy(&f->fmt.pix,&cfg->v2.fmt,size); + return 0; + default: + return -EINVAL; + } +} + + +/* Copy v4l2 parameter into other element of camif_cfg_t */ +static int camif_s_try(camif_cfg_t *cfg, int f) +{ + int fmt; + cfg->target_x = cfg->v2.fmt.width; + cfg->target_y = cfg->v2.fmt.height; + pixfmt2depth(cfg->v2.fmt.pixelformat,&fmt); + cfg->fmt = fmt; + camif_dynamic_conf(cfg); +} + + +static int camif_s_fmt(camif_cfg_t *cfg, struct v4l2_format *f) +{ + int retval; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + { + /* update our state informations */ +// down(&fh->cap.lock); + cfg->v2.fmt = f->pix; + cfg->v2.status |= CAMIF_v4L2_DIRTY; + camif_dynamic_conf(cfg); + cfg->v2.status &= ~CAMIF_v4L2_DIRTY; /* dummy ? */ +// up(&fh->cap.lock); + + return 0; + } + default: + return -EINVAL; + } + +} + +/* Refer ioctl of videodeX.c and bttv-driver.c */ +int camif_do_ioctl +(struct inode *inode, struct file *file,unsigned int cmd, void * arg) +{ + camif_cfg_t *cfg = file->private_data; + int ret = 0; + + switch (cmd) { + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *cap = arg; + + strcpy(cap->driver,"Fimc Camera"); + strlcpy(cap->card,cfg->v->name,sizeof(cap->card)); + sprintf(cap->bus_info,"FIMC 2.0 AHB Bus"); + cap->version = 0; + cap->capabilities = + V4L2_CAP_VIDEO_CAPTURE |V4L2_CAP_READWRITE; + return 0; + } + case VIDIOC_G_FMT: + { + struct v4l2_format *f = arg; + return camif_g_fmt(cfg,f); + } + case VIDIOC_S_FMT: + { + struct v4l2_format *f = arg; + return camif_s_fmt(cfg,f); + } + + case VIDIOC_ENUM_FMT: + { + struct v4l2_fmtdesc *f = arg; + enum v4l2_buf_type type = f->type; + int index = f->index; + + if (index >= NUM_F) + return -EINVAL; + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + break; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VBI_CAPTURE: + default: + return -EINVAL; + } + memset(f,0,sizeof(*f)); + memcpy(f,cfg->v2.fmtdesc+index,sizeof(*f)); + return 0; + } + case VIDIOC_G_INPUT: + { + u32 *i = arg; + *i = cfg->v2.input; + return 0; + } + case VIDIOC_S_INPUT: + { + int index = *((int *)arg); + if (index != 0) + return -EINVAL; + cfg->v2.input.index = index; + return 0; + } + + default: + return -ENOIOCTLCMD; /* errno.h */ + } /* End of Switch */ + + +} + + + + + + + +/* + * Local variables: + * tab-width: 8 + * c-indent-level: 8 + * c-basic-offset: 8 + * c-set-style: "K&R" + * End: + */ diff --git a/arch/arm/mach-s3c2440/camera/video-driver.c b/arch/arm/mach-s3c2440/camera/video-driver.c new file mode 100644 index 0000000..fe9130c --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/video-driver.c @@ -0,0 +1,591 @@ +/* + Copyright (C) 2004 Samsung Electronics + SW.LEE + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define SW_DEBUG + +#include "camif.h" +#include "videodev.h" +#include "miscdevice.h" +#include "cam_reg.h" +#include "sensor.h" +#include "userapp.h" + +#ifdef Z_API +#include "qt.h" +#endif + +/* Codec and Preview */ +#define CAMIF_NUM 2 +static camif_cfg_t fimc[CAMIF_NUM]; + +static const char *driver_version = + "$Id: video-driver.c,v 1.9 2004/06/02 03:10:36 swlee Exp $"; +extern const char *fimc_version; +extern const char *fsm_version; + + +camif_cfg_t * get_camif(int nr) +{ + camif_cfg_t *ret = NULL; + switch(nr) { + case CODEC_MINOR: + ret = &fimc[0]; + break; + case PREVIEW_MINOR: + ret = &fimc[1]; + break; + default: + panic("Unknow Minor Number \n"); + } + return ret; +} + + +static int camif_codec_start(camif_cfg_t *cfg) +{ + int ret = 0; + ret =camif_check_preview(cfg); + switch(ret) { + case 0: /* Play alone */ + DPRINTK("Start Alone \n"); + camif_4fsm_start(cfg); + cfg->gc->status |= C_WORKING; + break; + case -ERESTARTSYS: /* Busy , retry */ + //DPRINTK("Error \n"); + printk("Error \n"); + break; + case 1: + DPRINTK("need callback \n"); + ret = camif_callback_start(cfg); + if(ret < 0 ) { + printk(KERN_INFO "Busy RESTART \n"); + return ret; /* Busy, retry */ + } + break; + } + return ret; +} + + +ssize_t camif_write (struct file *f, const char *b, size_t c,loff_t *offset) +{ + camif_cfg_t *cfg; + + c = 0; /* return value */ + DPRINTK("\n"); + cfg = get_camif(MINOR(f->f_dentry->d_inode->i_rdev)); + switch (*b) { + case 'O': + if (cfg->dma_type & CAMIF_PREVIEW) { + if (cfg->gc->status & C_WORKING) { + camif_start_c_with_p(cfg,get_camif(CODEC_MINOR)); + } + else { + camif_4fsm_start(cfg); + } + } + else{ + c = camif_codec_start(cfg); + if(c < 0) c = 1; /* Error and neet to retry */ + } + + break; + case 'X': + camif_p_stop(cfg); + break; + default: + panic("CAMERA:camif_write: Unexpected Param\n"); + } + DPRINTK("end\n"); + + return c; +} + + +ssize_t camif_p_read(struct file *file, char *buf, size_t count, loff_t *pos) +{ + camif_cfg_t *cfg = NULL; + size_t end; + + cfg = get_camif(MINOR(file->f_dentry->d_inode->i_rdev)); + cfg->status = CAMIF_STARTED; + + if (wait_event_interruptible(cfg->waitq,cfg->status == CAMIF_INT_HAPPEN)) + return -ERESTARTSYS; + + cfg->status = CAMIF_STOPPED; + end = min_t(size_t, cfg->pp_totalsize /cfg->pp_num, count); + if (copy_to_user(buf, camif_g_frame(cfg), end)) + return -EFAULT; + + return end; +} + + +static ssize_t +camif_c_read(struct file *file, char *buf, size_t count, loff_t *pos) +{ + camif_cfg_t *cfg = NULL; + size_t end; + + /* cfg = file->private_data; */ + cfg = get_camif(MINOR(file->f_dentry->d_inode->i_rdev)); +#if 0 + if(file->f_flags & O_NONBLOCK) { + printk(KERN_ERR"Don't Support NON_BLOCK \n"); + } +#endif + + /* Change the below wait_event_interruptible func */ + if (wait_event_interruptible(cfg->waitq,cfg->status == CAMIF_INT_HAPPEN)) + return -ERESTARTSYS; + cfg->status = CAMIF_STOPPED; + end = min_t(size_t, cfg->pp_totalsize /cfg->pp_num, count); + if (copy_to_user(buf, camif_g_frame(cfg), end)) + return -EFAULT; + return end; +} + + +static void camif_c_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + camif_cfg_t *cfg = (camif_cfg_t *)dev_id; + DPRINTK("\n"); + camif_g_fifo_status(cfg); + camif_g_frame_num(cfg); + if(camif_enter_c_4fsm(cfg) == INSTANT_SKIP) return; + wake_up_interruptible(&cfg->waitq); +} + +static void camif_p_irq(int irq, void *dev_id, struct pt_regs * regs) +{ + camif_cfg_t *cfg = (camif_cfg_t *)dev_id; + DPRINTK("\n"); + camif_g_fifo_status(cfg); + camif_g_frame_num(cfg); + if(camif_enter_p_4fsm(cfg) == INSTANT_SKIP) return; + wake_up_interruptible(&cfg->waitq); +#if 0 + if( (cfg->perf.frames % 5) == 0) + DPRINTK("5\n"); +#endif +} + +static void camif_release_irq(camif_cfg_t *cfg) +{ + disable_irq(cfg->irq); + free_irq(cfg->irq, cfg); +} + +static int camif_irq_request(camif_cfg_t *cfg) +{ + int ret = 0; + + if (cfg->dma_type & CAMIF_CODEC) { + if ((ret = request_irq(cfg->irq, camif_c_irq, + SA_INTERRUPT,cfg->shortname, cfg))) { + printk("request_irq(CAM_C) failed.\n"); + } + } + if (cfg->dma_type & CAMIF_PREVIEW) { + if ((ret = request_irq(cfg->irq, camif_p_irq, + SA_INTERRUPT,cfg->shortname, cfg))) { + printk("request_irq(CAM_P) failed.\n"); + } + } + return 0; +} + +static void camif_init_sensor(camif_cfg_t *cfg) +{ + camif_gc_t *gc = cfg->gc; + if (!gc->sensor) + panic("CAMERA:I2C Client(Img Sensor)Not registered\n"); + if(!gc->init_sensor) { + camif_reset(gc->reset_type, gc->reset_udelay); + gc->sensor->driver->command(gc->sensor,SENSOR_INIT,NULL); + gc->init_sensor = 1; /*sensor init done */ + } + gc->sensor->driver->command(gc->sensor, USER_ADD, NULL); +} + +static int camif_open(struct inode *inode, struct file *file) +{ + int err; + camif_cfg_t * cfg = get_camif(MINOR(inode->i_rdev)); + + if(cfg->dma_type & CAMIF_PREVIEW) { + if(down_interruptible(&cfg->gc->lock)) + return -ERESTARTSYS; + if (cfg->dma_type & CAMIF_PREVIEW) { + cfg->gc->status &= ~PNOTWORKING; + } + up(&cfg->gc->lock); + } + err = video_exclusive_open(inode,file); + cfg->gc->user++; + cfg->status = CAMIF_STOPPED; + if (err < 0) return err; + if (file->f_flags & O_NONCAP ) { + printk("Don't Support Non-capturing open \n"); + return 0; + } + file->private_data = cfg; + camif_irq_request(cfg); + camif_init_sensor(cfg); + return 0; +} + +#if 0 +static void print_pregs(void) +{ + printk(" CISRCFMT 0x%08X \n", CISRCFMT); + printk(" CIWDOFST 0x%08X \n", CIWDOFST); + printk(" CIGCTRL 0x%08X \n", CIGCTRL); + printk(" CIPRTRGFMT 0x%08X \n", CIPRTRGFMT); + printk(" CIPRCTRL 0x%08X \n", CIPRCTRL); + printk(" CIPRSCPRERATIO 0x%08X \n", CIPRSCPRERATIO); + printk(" CIPRSCPREDST 0x%08X \n", CIPRSCPREDST); + printk(" CIPRSCCTRL 0x%08X \n", CIPRSCCTRL); + printk(" CIPRTAREA 0x%08X \n", CIPRTAREA); + printk(" CIPRSTATUS 0x%08X \n", CIPRSTATUS); + printk(" CIIMGCPT 0x%08X \n", CIIMGCPT); +} + +static void print_cregs(void) +{ + printk(" CISRCFMT 0x%08X \n", CISRCFMT); + printk(" CIWDOFST 0x%08X \n", CIWDOFST); + printk(" CIGCTRL 0x%08X \n", CIGCTRL); + printk(" CICOCTRL 0x%8X \n", CICOCTRL); + printk(" CICOSCPRERATIO 0x%08X \n", CICOSCPRERATIO); + printk(" CICOSCPREDST 0x%08X \n", CICOSCPREDST); + printk(" CICOSCCTRL 0x%08X \n", CICOSCCTRL); + printk(" CICOTAREA 0x%08X \n", CICOTAREA); + printk(" CICOSTATUS 0x%8X \n", CICOSTATUS); + printk(" CIIMGCPT 0x%08X \n", CIIMGCPT); +} +#endif + + +static int camif_release(struct inode *inode, struct file *file) +{ + camif_cfg_t * cfg = get_camif(MINOR(inode->i_rdev)); + + //DPRINTK(" cfg->status 0x%0X cfg->gc->status 0x%0X \n", cfg->status,cfg->gc->status ); + if (cfg->dma_type & CAMIF_PREVIEW) { + if(down_interruptible(&cfg->gc->lock)) + return -ERESTARTSYS; + cfg->gc->status &= ~PWANT2START; + cfg->gc->status |= PNOTWORKING; + up(&cfg->gc->lock); + } + else { + cfg->gc->status &= ~CWANT2START; /* No need semaphore */ + } + camif_dynamic_close(cfg); + camif_release_irq(cfg); + video_exclusive_release(inode,file); + camif_p_stop(cfg); + cfg->gc->sensor->driver->command(cfg->gc->sensor, USER_EXIT, NULL); + cfg->gc->user--; + cfg->status = CAMIF_STOPPED; + return 0; +} + +static void fimc_config(camif_cfg_t *cfg,u32 x, u32 y, int bpp) +{ + cfg->target_x = x; + cfg->target_y = y; + + switch (bpp) { + case 16: + cfg->fmt = CAMIF_RGB16; + break; + case 24: + cfg->fmt = CAMIF_RGB24; + break; + case 420: + cfg->fmt = CAMIF_IN_YCBCR422|CAMIF_OUT_YCBCR420; + break; + case 422: + cfg->fmt = CAMIF_IN_YCBCR422|CAMIF_OUT_YCBCR422; + break; + default: + panic("Wrong BPP \n"); + } +} + + +static int +camif_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + camif_cfg_t *cfg = file->private_data; + camif_param_t par; + + switch (cmd) { + case CMD_CAMERA_INIT: + if (copy_from_user(&par,(camif_param_t *)arg, + sizeof(camif_param_t))) + return -EFAULT; + fimc_config(cfg,par.dst_x, par.dst_y, par.bpp); + if (camif_dynamic_open(cfg)) { + printk(" Eror Happens \n"); + ret = -1; + } + + switch (par.flip) { + case 3 : + cfg->flip = CAMIF_FLIP_MIRROR; + break; + case 1 : + cfg->flip = CAMIF_FLIP_X; + break; + case 2 : + cfg->flip = CAMIF_FLIP_Y; + break; + case 0 : + default: + cfg->flip = CAMIF_FLIP; + } + break; + /* Todo + case CMD_SENSOR_BRIGHTNESS: + cfg->gc->sensor->driver->command(cfg->gc->sensor, SENSOR_BRIGHTNESS, NULL); + break; + */ + default: + ret = -EINVAL; + break; + } + + return ret; +} + + +#if 0 +static int camif_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ +// camif_cfg_t *cfg = file->private_data; + + + switch (cmd) { +/* case Some_other_action */ + default: + return video_usercopy(inode, file, cmd, arg, camif_do_ioctl); + } +} +#endif + +static struct file_operations camif_c_fops = +{ + .owner = THIS_MODULE, + .open = camif_open, + .release = camif_release, + .ioctl = camif_ioctl, + .read = camif_c_read, + .write = camif_write, +}; + +static struct file_operations camif_p_fops = +{ + .owner = THIS_MODULE, + .open = camif_open, + .release = camif_release, + .ioctl = camif_ioctl, +#ifdef Z_API + .read = z_read, + .write = z_write, +#else + .read = camif_p_read, + .write = camif_write, +#endif +}; + +static struct video_device codec_template = +{ + .name = "CODEC_IF", + .type = VID_TYPE_CAPTURE|VID_TYPE_CLIPPING|VID_TYPE_SCALES, + .hardware = VID_HARDWARE_SAMSUNG_FIMC20, + .fops = &camif_c_fops, +// .release = camif_release + .minor = -1, +}; + +static struct video_device preview_template = +{ + .name = "PREVIEW_IF", + .type = VID_TYPE_CAPTURE|VID_TYPE_CLIPPING|VID_TYPE_SCALES, + .hardware = VID_HARDWARE_SAMSUNG_FIMC20, + .fops = &camif_p_fops, + .minor = -1, +}; + +static int preview_init(camif_cfg_t *cfg) +{ + char name[16]="CAM_PREVIEW"; + + memset(cfg, 0, sizeof(camif_cfg_t)); + cfg->target_x = 640; + cfg->target_y = 480; + cfg->pp_num = 4; + cfg->dma_type = CAMIF_PREVIEW; + cfg->fmt = CAMIF_RGB16; + cfg->flip = CAMIF_FLIP_Y; + cfg->v = &preview_template; + init_MUTEX(&cfg->v->lock); + cfg->irq = IRQ_CAM_P; + + strcpy(cfg->shortname,name); + init_waitqueue_head(&cfg->waitq); + cfg->status = CAMIF_STOPPED; + return cfg->status; +} + +static int codec_init(camif_cfg_t *cfg) +{ + char name[16]="CAM_CODEC"; + + memset(cfg, 0, sizeof(camif_cfg_t)); + cfg->target_x = 176; + cfg->target_y = 144; + cfg->pp_num = 4; + cfg->dma_type = CAMIF_CODEC; + cfg->fmt = CAMIF_IN_YCBCR422|CAMIF_OUT_YCBCR420; + cfg->flip = CAMIF_FLIP_X; + cfg->v = &codec_template; + init_MUTEX(&cfg->v->lock); + cfg->irq = IRQ_CAM_C; + strcpy(cfg->shortname,name); + init_waitqueue_head(&cfg->waitq); + cfg->status = CAMIF_STOPPED; + return cfg->status; +} + +static void camif_init(void) +{ + camif_setup_sensor(); +} + + + +static void print_version(void) +{ + printk(KERN_INFO"FIMC built:"__DATE__ " "__TIME__"\n%s\n%s\n%s\n", + fimc_version, driver_version,fsm_version); +} + + +static int camif_m_in(void) +{ + int ret = 0; + camif_cfg_t * cfg; + + camif_init(); + cfg = get_camif(CODEC_MINOR); + codec_init(cfg); + + if (video_register_device(cfg->v,0,CODEC_MINOR)!=0) { + DPRINTK("Couldn't register codec driver.\n"); + return 0; + } + cfg = get_camif(PREVIEW_MINOR); + preview_init(cfg); + if (video_register_device(cfg->v,0,PREVIEW_MINOR)!=0) { + DPRINTK("Couldn't register preview driver.\n"); + return 0; + } + + print_version(); + return ret; +} + +static void unconfig_device(camif_cfg_t *cfg) +{ + video_unregister_device(cfg->v); + camif_hw_close(cfg); + //memset(cfg, 0, sizeof(camif_cfg_t)); +} + +static void camif_m_out(void) /* module out */ +{ + camif_cfg_t *cfg; + + cfg = get_camif(CODEC_MINOR); + unconfig_device(cfg); + cfg = get_camif(PREVIEW_MINOR); + unconfig_device(cfg); + return; +} + +void camif_register_decoder(struct i2c_client *ptr) +{ + camif_cfg_t *cfg; + + cfg =get_camif(CODEC_MINOR); + cfg->gc = (camif_gc_t *)(ptr->data); + + cfg =get_camif(PREVIEW_MINOR); + cfg->gc = (camif_gc_t *)(ptr->data); + + sema_init(&cfg->gc->lock,1); /* global lock for both Codec and Preview */ + cfg->gc->status |= PNOTWORKING; /* Default Value */ + camif_hw_open(cfg->gc); +} + +void camif_unregister_decoder(struct i2c_client *ptr) +{ + camif_gc_t *gc; + + gc = (camif_gc_t *)(ptr->data); + gc->init_sensor = 0; /* need to modify */ +} + +module_init(camif_m_in); +module_exit(camif_m_out); + +EXPORT_SYMBOL(camif_register_decoder); +EXPORT_SYMBOL(camif_unregister_decoder); + +MODULE_AUTHOR("SW.LEE "); +MODULE_DESCRIPTION("Video-Driver For Fimc2.0 MISC Drivers"); +MODULE_LICENSE("GPL"); + + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/arch/arm/mach-s3c2440/camera/videodev.c b/arch/arm/mach-s3c2440/camera/videodev.c new file mode 100644 index 0000000..0b3498f --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/videodev.c @@ -0,0 +1,342 @@ +/* + * Video capture interface for Linux Character Device Driver. + * based on + * Alan Cox, video4linux + * + * Author: SW.LEE + * 2004 (C) Samsung Electronics + * Modified for S3C2440/S3C24A0 Interface + * + * This file is released under the GPLv2 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#include "camif.h" +#include "videodev.h" +#include "miscdevice.h" + + +static DECLARE_MUTEX(videodev_lock); + +const char *fimc_version = "$Id: videodev.c,v 1.1.1.1 2004/04/27 03:52:50 swlee Exp $"; + +#define VIDEO_NAME "video4linux" + + +static inline unsigned iminor(struct inode *inode) +{ + return MINOR(inode->i_rdev); +} + +static inline unsigned imajor(struct inode *inode) +{ + return MAJOR(inode->i_rdev); +} + + +#define VIDEO_NUM_DEVICES 2 +static struct video_device *video_device[VIDEO_NUM_DEVICES]; + +static inline struct video_device * get_vd(int nr) +{ + if ( nr == CODEC_MINOR) + return video_device[0]; + else { + assert ( nr & PREVIEW_MINOR); + return video_device[1]; + } +} + +static inline void set_vd ( struct video_device * vd, int nr) +{ + if ( nr == CODEC_MINOR) + video_device[0] = vd; + else { + assert ( nr & PREVIEW_MINOR); + video_device[1] = vd; + } +} + +static inline int video_release(struct inode *inode, struct file *f) +{ + int minor = MINOR(inode->i_rdev); + struct video_device *vfd; + + vfd = get_vd(minor); +#if 1 /* needed until all drivers are fixed */ + if (!vfd->release) + return 0; +#endif + vfd->release(vfd); + return 0; +} + +struct video_device* video_devdata(struct file *file) +{ + return video_device[iminor(file->f_dentry->d_inode)]; +} + + +/* + * Open a video device. + */ +static int video_open(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + int err = 0; + struct video_device *vfl; + struct file_operations *old_fops; + + down(&videodev_lock); + + vfl = get_vd(minor); + + old_fops = file->f_op; + file->f_op = fops_get(vfl->fops); + if(file->f_op->open) + err = file->f_op->open(inode,file); + if (err) { + fops_put(file->f_op); + file->f_op = fops_get(old_fops); + } + fops_put(old_fops); + up(&videodev_lock); + return err; +} + +/* + * open/release helper functions -- handle exclusive opens + */ +extern int video_exclusive_open(struct inode *inode, struct file *file) +{ + struct video_device *vfl = get_vd(MINOR(inode->i_rdev)); + int retval = 0; + + down(&vfl->lock); + if (vfl->users) { + retval = -EBUSY; + } else { + vfl->users++; + } + up(&vfl->lock); + return retval; +} + +extern int video_exclusive_release(struct inode *inode, struct file *file) +{ + struct video_device *vfl = get_vd(MINOR(inode->i_rdev)); + vfl->users--; + return 0; +} + +int +video_usercopy(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)) +{ + char sbuf[128]; + void *mbuf = NULL; + void *parg = NULL; + int err = -EINVAL; + + // cmd = video_fix_command(cmd); + + /* Copy arguments into temp kernel buffer */ + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: + parg = (void *)arg; + break; + case _IOC_READ: + case _IOC_WRITE: + case (_IOC_WRITE | _IOC_READ): + if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { + parg = sbuf; + } else { + /* too big to allocate from stack */ + mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); + if (NULL == mbuf) + return -ENOMEM; + parg = mbuf; + } + + err = -EFAULT; + if (_IOC_DIR(cmd) & _IOC_WRITE) + if (copy_from_user(parg, (void *)arg, _IOC_SIZE(cmd))) + goto out; + break; + } + + /* call driver */ + err = func(inode, file, cmd, parg); + if (err == -ENOIOCTLCMD) + err = -EINVAL; + if (err < 0) + goto out; + + /* Copy results into user buffer */ + switch (_IOC_DIR(cmd)) + { + case _IOC_READ: + case (_IOC_WRITE | _IOC_READ): + if (copy_to_user((void *)arg, parg, _IOC_SIZE(cmd))) + err = -EFAULT; + break; + } + +out: + if (mbuf) + kfree(mbuf); + return err; +} + + +static struct file_operations video_fops= +{ + .owner = THIS_MODULE, + .llseek = no_llseek, + .open = video_open, + .release = video_release, +}; + +static struct miscdevice codec_dev = { + minor: CODEC_MINOR, + name : "codec", + fops : &video_fops +}; + +static struct miscdevice preview_dev = { + minor: PREVIEW_MINOR, + name : "preview", + fops : &video_fops +}; + + +/** + * video_register_device - register video4linux devices + * @vfd: video device structure we want to register + * @type: type of device to register + * @nr: minor number + * + * Zero is returned on success. + * type : ignored. + * nr : + * 0 Codec index + * 1 Preview index + */ +int video_register_device(struct video_device *vfd, int type, int nr) +{ + int ret=0; + + /* pick a minor number */ + down(&videodev_lock); + set_vd (vfd, nr); + vfd->minor=nr; + up(&videodev_lock); + + switch (vfd->minor) { + case CODEC_MINOR: + ret = misc_register(&codec_dev); + if (ret) { + printk(KERN_ERR + "can't misc_register : codec on minor=%d\n", CODEC_MINOR); + panic(" Give me misc codec \n"); + } + break; + case PREVIEW_MINOR: + ret = misc_register(&preview_dev); + if (ret) { + printk(KERN_ERR + "can't misc_register (preview) on minor=%d\n", PREVIEW_MINOR); + panic(" Give me misc codec \n"); + } + break; + } + +#if 0 /* needed until all drivers are fixed */ + if (!vfd->release) + printk(KERN_WARNING "videodev: \"%s\" has no release callback. " + "Please fix your driver for proper sysfs support, see " + "http://lwn.net/Articles/36850/\n", vfd->name); +#endif + return 0; +} + +/** + * video_unregister_device - unregister a video4linux device + * @vfd: the device to unregister + * + * This unregisters the passed device and deassigns the minor + * number. Future open calls will be met with errors. + */ + +void video_unregister_device(struct video_device *vfd) +{ + down(&videodev_lock); + + if(get_vd(vfd->minor)!=vfd) + panic("videodev: bad unregister"); + + if (vfd->minor== CODEC_MINOR) + misc_deregister(&codec_dev); + else + misc_deregister(&preview_dev); + set_vd (NULL, vfd->minor); + up(&videodev_lock); +} + + +/* + * Initialise video for linux + */ + +static int __init videodev_init(void) +{ +// printk(KERN_INFO "FIMC2.0 Built:"__DATE__" "__TIME__"\n%s\n",fimc_version); + return 0; +} + +static void __exit videodev_exit(void) +{ +} + +module_init(videodev_init) +module_exit(videodev_exit) + +EXPORT_SYMBOL(video_register_device); +EXPORT_SYMBOL(fimc_version); +EXPORT_SYMBOL(video_unregister_device); +EXPORT_SYMBOL(video_usercopy); +EXPORT_SYMBOL(video_exclusive_open); +EXPORT_SYMBOL(video_exclusive_release); + + +MODULE_AUTHOR("SW.LEE "); +MODULE_DESCRIPTION("VideoDev For FIMC2.0 MISC Drivers"); +MODULE_LICENSE("GPL"); + + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/arch/arm/mach-s3c2440/camera/videodev.h b/arch/arm/mach-s3c2440/camera/videodev.h new file mode 100644 index 0000000..f12db43 --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/videodev.h @@ -0,0 +1,110 @@ +#ifndef __LINUX_S3C_VIDEODEV_H +#define __LINUX_S3C_VIDEODEV_H + +#include +#include +#include "videodev2.h" + + +struct video_device +{ + /* device info */ + // struct device *dev; + char name[32]; + int type; /* v4l1 */ + int type2; /* v4l2 */ + int hardware; + int minor; + + /* device ops + callbacks */ + struct file_operations *fops; + void (*release)(struct video_device *vfd); + + +#if 1 /* to be removed in 2.7.x */ + /* obsolete -- fops->owner is used instead */ + struct module *owner; + /* dev->driver_data will be used instead some day. + * Use the video_{get|set}_drvdata() helper functions, + * so the switch over will be transparent for you. + * Or use {pci|usb}_{get|set}_drvdata() directly. */ + void *priv; +#endif + + /* for videodev.c intenal usage -- please don't touch */ + int users; /* video_exclusive_{open|close} ... */ + struct semaphore lock; /* ... helper function uses these */ + char devfs_name[64]; /* devfs */ + // struct class_device class_dev; /* sysfs */ +}; + +#define VIDEO_MAJOR 81 + +#define VFL_TYPE_GRABBER 0 + + +extern int video_register_device(struct video_device *, int type, int nr); +extern void video_unregister_device(struct video_device *); +extern struct video_device* video_devdata(struct file*); + + + +struct video_picture +{ + __u16 brightness; + __u16 hue; + __u16 colour; + __u16 contrast; + __u16 whiteness; /* Black and white only */ + __u16 depth; /* Capture depth */ + __u16 palette; /* Palette in use */ +#define VIDEO_PALETTE_GREY 1 /* Linear greyscale */ +#define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */ +#define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */ +#define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */ +#define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */ +#define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */ +#define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */ +#define VIDEO_PALETTE_YUYV 8 +#define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */ +#define VIDEO_PALETTE_YUV420 10 +#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */ +#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */ +#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */ +#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */ +#define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */ +#define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */ +#define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */ +#define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */ +}; + +extern int video_exclusive_open(struct inode *inode, struct file *file); +extern int video_exclusive_release(struct inode *inode, struct file *file); +extern int video_usercopy(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)); + + + + +#define VID_TYPE_CAPTURE 1 /* Can capture */ +#define VID_TYPE_CLIPPING 32 /* Can clip */ +#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ +#define VID_TYPE_SCALES 128 /* Scalable */ +#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ + + + +#define VID_HARDWARE_SAMSUNG_FIMC 255 + + + +#endif + + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/arch/arm/mach-s3c2440/camera/videodev2.h b/arch/arm/mach-s3c2440/camera/videodev2.h new file mode 100644 index 0000000..1bfc45a --- /dev/null +++ b/arch/arm/mach-s3c2440/camera/videodev2.h @@ -0,0 +1,938 @@ +#ifndef __LINUX_VIDEODEV2_H +#define __LINUX_VIDEODEV2_H +/* + * Video for Linux Two + * + * Header file for v4l or V4L2 drivers and applications, for + * Linux kernels 2.2.x or 2.4.x. + * + * See http://bytesex.org/v4l/ for API specs and other + * v4l2 documentation. + * + * Author: Bill Dirks + * Justin Schoeman + * et al. + */ +#ifdef __KERNEL__ +#include /* need struct timeval */ +#endif + +/* + * M I S C E L L A N E O U S + */ + +/* Four-character-code (FOURCC) */ +#define v4l2_fourcc(a,b,c,d)\ + (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) + +/* + * E N U M S + */ +enum v4l2_field { + V4L2_FIELD_ANY = 0, /* driver can choose from none, + top, bottom, interlaced + depending on whatever it thinks + is approximate ... */ + V4L2_FIELD_NONE = 1, /* this device has no fields ... */ + V4L2_FIELD_TOP = 2, /* top field only */ + V4L2_FIELD_BOTTOM = 3, /* bottom field only */ + V4L2_FIELD_INTERLACED = 4, /* both fields interlaced */ + V4L2_FIELD_SEQ_TB = 5, /* both fields sequential into one + buffer, top-bottom order */ + V4L2_FIELD_SEQ_BT = 6, /* same as above + bottom-top order */ + V4L2_FIELD_ALTERNATE = 7, /* both fields alternating into + separate buffers */ +}; +#define V4L2_FIELD_HAS_TOP(field) \ + ((field) == V4L2_FIELD_TOP ||\ + (field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) +#define V4L2_FIELD_HAS_BOTTOM(field) \ + ((field) == V4L2_FIELD_BOTTOM ||\ + (field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) +#define V4L2_FIELD_HAS_BOTH(field) \ + ((field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) + +enum v4l2_buf_type { + V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, + V4L2_BUF_TYPE_VIDEO_OUTPUT = 2, + V4L2_BUF_TYPE_VIDEO_OVERLAY = 3, + V4L2_BUF_TYPE_VBI_CAPTURE = 4, + V4L2_BUF_TYPE_VBI_OUTPUT = 5, + V4L2_BUF_TYPE_PRIVATE = 0x80, +}; + +enum v4l2_ctrl_type { + V4L2_CTRL_TYPE_INTEGER = 1, + V4L2_CTRL_TYPE_BOOLEAN = 2, + V4L2_CTRL_TYPE_MENU = 3, + V4L2_CTRL_TYPE_BUTTON = 4, +}; + +enum v4l2_tuner_type { + V4L2_TUNER_RADIO = 1, + V4L2_TUNER_ANALOG_TV = 2, +}; + +enum v4l2_memory { + V4L2_MEMORY_MMAP = 1, + V4L2_MEMORY_USERPTR = 2, + V4L2_MEMORY_OVERLAY = 3, +}; + +/* see also http://vektor.theorem.ca/graphics/ycbcr/ */ +enum v4l2_colorspace { + /* ITU-R 601 -- broadcast NTSC/PAL */ + V4L2_COLORSPACE_SMPTE170M = 1, + + /* 1125-Line (US) HDTV */ + V4L2_COLORSPACE_SMPTE240M = 2, + + /* HD and modern captures. */ + V4L2_COLORSPACE_REC709 = 3, + + /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */ + V4L2_COLORSPACE_BT878 = 4, + + /* These should be useful. Assume 601 extents. */ + V4L2_COLORSPACE_470_SYSTEM_M = 5, + V4L2_COLORSPACE_470_SYSTEM_BG = 6, + + /* I know there will be cameras that send this. So, this is + * unspecified chromaticities and full 0-255 on each of the + * Y'CbCr components + */ + V4L2_COLORSPACE_JPEG = 7, + + /* For RGB colourspaces, this is probably a good start. */ + V4L2_COLORSPACE_SRGB = 8, +}; + +enum v4l2_priority { + V4L2_PRIORITY_UNSET = 0, /* not initialized */ + V4L2_PRIORITY_BACKGROUND = 1, + V4L2_PRIORITY_INTERACTIVE = 2, + V4L2_PRIORITY_RECORD = 3, + V4L2_PRIORITY_DEFAULT = V4L2_PRIORITY_INTERACTIVE, +}; + +struct v4l2_rect { + __s32 left; + __s32 top; + __s32 width; + __s32 height; +}; + +struct v4l2_fract { + __u32 numerator; + __u32 denominator; +}; + +/* + * D R I V E R C A P A B I L I T I E S + */ +struct v4l2_capability +{ + __u8 driver[16]; /* i.e. "bttv" */ + __u8 card[32]; /* i.e. "Hauppauge WinTV" */ + __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ + __u32 version; /* should use KERNEL_VERSION() */ + __u32 capabilities; /* Device capabilities */ + __u32 reserved[4]; +}; + +/* Values for 'capabilities' field */ +#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */ +#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */ +#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */ +#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a VBI capture device */ +#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a VBI output device */ +#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ + +#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ +#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ +#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */ + +#define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */ +#define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ +#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */ + +/* + * V I D E O I M A G E F O R M A T + */ + +struct v4l2_pix_format +{ + __u32 width; + __u32 height; + __u32 pixelformat; + enum v4l2_field field; + __u32 bytesperline; /* for padding, zero if unused */ + __u32 sizeimage; + enum v4l2_colorspace colorspace; + __u32 priv; /* private data, depends on pixelformat */ +}; + +/* Pixel format FOURCC depth Description */ +#define V4L2_PIX_FMT_RGB332 v4l2_fourcc('R','G','B','1') /* 8 RGB-3-3-2 */ +#define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R','G','B','O') /* 16 RGB-5-5-5 */ +#define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R','G','B','P') /* 16 RGB-5-6-5 */ +#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R','G','B','Q') /* 16 RGB-5-5-5 BE */ +#define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R','G','B','R') /* 16 RGB-5-6-5 BE */ +#define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B','G','R','3') /* 24 BGR-8-8-8 */ +#define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R','G','B','3') /* 24 RGB-8-8-8 */ +#define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B','G','R','4') /* 32 BGR-8-8-8-8 */ +#define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R','G','B','4') /* 32 RGB-8-8-8-8 */ +#define V4L2_PIX_FMT_GREY v4l2_fourcc('G','R','E','Y') /* 8 Greyscale */ +#define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y','V','U','9') /* 9 YVU 4:1:0 */ +#define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */ +#define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y','U','Y','V') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_UYVY v4l2_fourcc('U','Y','V','Y') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4','2','2','P') /* 16 YVU422 planar */ +#define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4','1','1','P') /* 16 YVU411 planar */ +#define V4L2_PIX_FMT_Y41P v4l2_fourcc('Y','4','1','P') /* 12 YUV 4:1:1 */ + +/* two planes -- one Y, one Cr + Cb interleaved */ +#define V4L2_PIX_FMT_NV12 v4l2_fourcc('N','V','1','2') /* 12 Y/CbCr 4:2:0 */ +#define V4L2_PIX_FMT_NV21 v4l2_fourcc('N','V','2','1') /* 12 Y/CrCb 4:2:0 */ + +/* The following formats are not defined in the V4L2 specification */ +#define V4L2_PIX_FMT_YUV410 v4l2_fourcc('Y','U','V','9') /* 9 YUV 4:1:0 */ +#define V4L2_PIX_FMT_YUV420 v4l2_fourcc('Y','U','1','2') /* 12 YUV 4:2:0 */ +#define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y','Y','U','V') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_HI240 v4l2_fourcc('H','I','2','4') /* 8 8-bit color */ + +/* compressed formats */ +#define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M','J','P','G') /* Motion-JPEG */ +#define V4L2_PIX_FMT_JPEG v4l2_fourcc('J','P','E','G') /* JFIF JPEG */ +#define V4L2_PIX_FMT_DV v4l2_fourcc('d','v','s','d') /* 1394 */ +#define V4L2_PIX_FMT_MPEG v4l2_fourcc('M','P','E','G') /* MPEG */ + +/* Vendor-specific formats */ +#define V4L2_PIX_FMT_WNVA v4l2_fourcc('W','N','V','A') /* Winnov hw compress */ + +/* + * F O R M A T E N U M E R A T I O N + */ +struct v4l2_fmtdesc +{ + __u32 index; /* Format number */ + enum v4l2_buf_type type; /* buffer type */ + __u32 flags; + __u8 description[32]; /* Description string */ + __u32 pixelformat; /* Format fourcc */ + __u32 reserved[4]; +}; + +#define V4L2_FMT_FLAG_COMPRESSED 0x0001 + + +/* + * T I M E C O D E + */ +struct v4l2_timecode +{ + __u32 type; + __u32 flags; + __u8 frames; + __u8 seconds; + __u8 minutes; + __u8 hours; + __u8 userbits[4]; +}; + +/* Type */ +#define V4L2_TC_TYPE_24FPS 1 +#define V4L2_TC_TYPE_25FPS 2 +#define V4L2_TC_TYPE_30FPS 3 +#define V4L2_TC_TYPE_50FPS 4 +#define V4L2_TC_TYPE_60FPS 5 + +/* Flags */ +#define V4L2_TC_FLAG_DROPFRAME 0x0001 /* "drop-frame" mode */ +#define V4L2_TC_FLAG_COLORFRAME 0x0002 +#define V4L2_TC_USERBITS_field 0x000C +#define V4L2_TC_USERBITS_USERDEFINED 0x0000 +#define V4L2_TC_USERBITS_8BITCHARS 0x0008 +/* The above is based on SMPTE timecodes */ + + +/* + * C O M P R E S S I O N P A R A M E T E R S + */ +#if 0 +/* ### generic compression settings don't work, there is too much + * ### codec-specific stuff. Maybe reuse that for MPEG codec settings + * ### later ... */ +struct v4l2_compression +{ + __u32 quality; + __u32 keyframerate; + __u32 pframerate; + __u32 reserved[5]; + +/* what we'll need for MPEG, extracted from some postings on + the v4l list (Gert Vervoort, PlasmaJohn). + +system stream: + - type: elementary stream(ES), packatised elementary stream(s) (PES) + program stream(PS), transport stream(TS) + - system bitrate + - PS packet size (DVD: 2048 bytes, VCD: 2324 bytes) + - TS video PID + - TS audio PID + - TS PCR PID + - TS system information tables (PAT, PMT, CAT, NIT and SIT) + - (MPEG-1 systems stream vs. MPEG-2 program stream (TS not supported + by MPEG-1 systems) + +audio: + - type: MPEG (+Layer I,II,III), AC-3, LPCM + - bitrate + - sampling frequency (DVD: 48 Khz, VCD: 44.1 KHz, 32 kHz) + - Trick Modes? (ff, rew) + - Copyright + - Inverse Telecine + +video: + - picturesize (SIF, 1/2 D1, 2/3 D1, D1) and PAL/NTSC norm can be set + through excisting V4L2 controls + - noise reduction, parameters encoder specific? + - MPEG video version: MPEG-1, MPEG-2 + - GOP (Group Of Pictures) definition: + - N: number of frames per GOP + - M: distance between reference (I,P) frames + - open/closed GOP + - quantiser matrix: inter Q matrix (64 bytes) and intra Q matrix (64 bytes) + - quantiser scale: linear or logarithmic + - scanning: alternate or zigzag + - bitrate mode: CBR (constant bitrate) or VBR (variable bitrate). + - target video bitrate for CBR + - target video bitrate for VBR + - maximum video bitrate for VBR - min. quantiser value for VBR + - max. quantiser value for VBR + - adaptive quantisation value + - return the number of bytes per GOP or bitrate for bitrate monitoring + +*/ +}; +#endif + +struct v4l2_jpegcompression +{ + int quality; + + int APPn; /* Number of APP segment to be written, + * must be 0..15 */ + int APP_len; /* Length of data in JPEG APPn segment */ + char APP_data[60]; /* Data in the JPEG APPn segment. */ + + int COM_len; /* Length of data in JPEG COM segment */ + char COM_data[60]; /* Data in JPEG COM segment */ + + __u32 jpeg_markers; /* Which markers should go into the JPEG + * output. Unless you exactly know what + * you do, leave them untouched. + * Inluding less markers will make the + * resulting code smaller, but there will + * be fewer aplications which can read it. + * The presence of the APP and COM marker + * is influenced by APP_len and COM_len + * ONLY, not by this property! */ + +#define V4L2_JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ +#define V4L2_JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ +#define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ +#define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ +#define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will + * allways use APP0 */ +}; + + +/* + * M E M O R Y - M A P P I N G B U F F E R S + */ +struct v4l2_requestbuffers +{ + __u32 count; + enum v4l2_buf_type type; + enum v4l2_memory memory; + __u32 reserved[2]; +}; + +struct v4l2_buffer +{ + __u32 index; + enum v4l2_buf_type type; + __u32 bytesused; + __u32 flags; + enum v4l2_field field; + struct timeval timestamp; + struct v4l2_timecode timecode; + __u32 sequence; + + /* memory location */ + enum v4l2_memory memory; + union { + __u32 offset; + unsigned long userptr; + } m; + __u32 length; + + __u32 reserved[2]; +}; + +/* Flags for 'flags' field */ +#define V4L2_BUF_FLAG_MAPPED 0x0001 /* Buffer is mapped (flag) */ +#define V4L2_BUF_FLAG_QUEUED 0x0002 /* Buffer is queued for processing */ +#define V4L2_BUF_FLAG_DONE 0x0004 /* Buffer is ready */ +#define V4L2_BUF_FLAG_KEYFRAME 0x0008 /* Image is a keyframe (I-frame) */ +#define V4L2_BUF_FLAG_PFRAME 0x0010 /* Image is a P-frame */ +#define V4L2_BUF_FLAG_BFRAME 0x0020 /* Image is a B-frame */ +#define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */ + +/* + * O V E R L A Y P R E V I E W + */ +struct v4l2_framebuffer +{ + __u32 capability; + __u32 flags; +/* FIXME: in theory we should pass something like PCI device + memory + * region + offset instead of some physical address */ + void* base; + struct v4l2_pix_format fmt; +}; +/* Flags for the 'capability' field. Read only */ +#define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001 +#define V4L2_FBUF_CAP_CHROMAKEY 0x0002 +#define V4L2_FBUF_CAP_LIST_CLIPPING 0x0004 +#define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0008 +/* Flags for the 'flags' field. */ +#define V4L2_FBUF_FLAG_PRIMARY 0x0001 +#define V4L2_FBUF_FLAG_OVERLAY 0x0002 +#define V4L2_FBUF_FLAG_CHROMAKEY 0x0004 + +struct v4l2_clip +{ + struct v4l2_rect c; + struct v4l2_clip *next; +}; + +struct v4l2_window +{ + struct v4l2_rect w; + enum v4l2_field field; + __u32 chromakey; + struct v4l2_clip *clips; + __u32 clipcount; + void *bitmap; +}; + + +/* + * C A P T U R E P A R A M E T E R S + */ +struct v4l2_captureparm +{ + __u32 capability; /* Supported modes */ + __u32 capturemode; /* Current mode */ + struct v4l2_fract timeperframe; /* Time per frame in .1us units */ + __u32 extendedmode; /* Driver-specific extensions */ + __u32 readbuffers; /* # of buffers for read */ + __u32 reserved[4]; +}; +/* Flags for 'capability' and 'capturemode' fields */ +#define V4L2_MODE_HIGHQUALITY 0x0001 /* High quality imaging mode */ +#define V4L2_CAP_TIMEPERFRAME 0x1000 /* timeperframe field is supported */ + +struct v4l2_outputparm +{ + __u32 capability; /* Supported modes */ + __u32 outputmode; /* Current mode */ + struct v4l2_fract timeperframe; /* Time per frame in seconds */ + __u32 extendedmode; /* Driver-specific extensions */ + __u32 writebuffers; /* # of buffers for write */ + __u32 reserved[4]; +}; + +/* + * I N P U T I M A G E C R O P P I N G + */ + +struct v4l2_cropcap { + enum v4l2_buf_type type; + struct v4l2_rect bounds; + struct v4l2_rect defrect; + struct v4l2_fract pixelaspect; +}; + +struct v4l2_crop { + enum v4l2_buf_type type; + struct v4l2_rect c; +}; + +/* + * A N A L O G V I D E O S T A N D A R D + */ + +typedef __u64 v4l2_std_id; + +/* one bit for each */ +#define V4L2_STD_PAL_B ((v4l2_std_id)0x00000001) +#define V4L2_STD_PAL_B1 ((v4l2_std_id)0x00000002) +#define V4L2_STD_PAL_G ((v4l2_std_id)0x00000004) +#define V4L2_STD_PAL_H ((v4l2_std_id)0x00000008) +#define V4L2_STD_PAL_I ((v4l2_std_id)0x00000010) +#define V4L2_STD_PAL_D ((v4l2_std_id)0x00000020) +#define V4L2_STD_PAL_D1 ((v4l2_std_id)0x00000040) +#define V4L2_STD_PAL_K ((v4l2_std_id)0x00000080) + +#define V4L2_STD_PAL_M ((v4l2_std_id)0x00000100) +#define V4L2_STD_PAL_N ((v4l2_std_id)0x00000200) +#define V4L2_STD_PAL_Nc ((v4l2_std_id)0x00000400) +#define V4L2_STD_PAL_60 ((v4l2_std_id)0x00000800) + +#define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000) +#define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000) + +#define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000) +#define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000) +#define V4L2_STD_SECAM_G ((v4l2_std_id)0x00040000) +#define V4L2_STD_SECAM_H ((v4l2_std_id)0x00080000) +#define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000) +#define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000) +#define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000) + +/* ATSC/HDTV */ +#define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000) +#define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000) + +/* some common needed stuff */ +#define V4L2_STD_PAL_BG (V4L2_STD_PAL_B |\ + V4L2_STD_PAL_B1 |\ + V4L2_STD_PAL_G) +#define V4L2_STD_PAL_DK (V4L2_STD_PAL_D |\ + V4L2_STD_PAL_D1 |\ + V4L2_STD_PAL_K) +#define V4L2_STD_PAL (V4L2_STD_PAL_BG |\ + V4L2_STD_PAL_DK |\ + V4L2_STD_PAL_H |\ + V4L2_STD_PAL_I) +#define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\ + V4L2_STD_NTSC_M_JP) +#define V4L2_STD_SECAM (V4L2_STD_SECAM_B |\ + V4L2_STD_SECAM_D |\ + V4L2_STD_SECAM_G |\ + V4L2_STD_SECAM_H |\ + V4L2_STD_SECAM_K |\ + V4L2_STD_SECAM_K1 |\ + V4L2_STD_SECAM_L) + +#define V4L2_STD_525_60 (V4L2_STD_PAL_M |\ + V4L2_STD_PAL_60 |\ + V4L2_STD_NTSC) +#define V4L2_STD_625_50 (V4L2_STD_PAL |\ + V4L2_STD_PAL_N |\ + V4L2_STD_PAL_Nc |\ + V4L2_STD_SECAM) + +#define V4L2_STD_UNKNOWN 0 +#define V4L2_STD_ALL (V4L2_STD_525_60 |\ + V4L2_STD_625_50) + +struct v4l2_standard +{ + __u32 index; + v4l2_std_id id; + __u8 name[24]; + struct v4l2_fract frameperiod; /* Frames, not fields */ + __u32 framelines; + __u32 reserved[4]; +}; + + +/* + * V I D E O I N P U T S + */ +struct v4l2_input +{ + __u32 index; /* Which input */ + __u8 name[32]; /* Label */ + __u32 type; /* Type of input */ + __u32 audioset; /* Associated audios (bitfield) */ + __u32 tuner; /* Associated tuner */ + v4l2_std_id std; + __u32 status; + __u32 reserved[4]; +}; +/* Values for the 'type' field */ +#define V4L2_INPUT_TYPE_TUNER 1 +#define V4L2_INPUT_TYPE_CAMERA 2 + +/* field 'status' - general */ +#define V4L2_IN_ST_NO_POWER 0x00000001 /* Attached device is off */ +#define V4L2_IN_ST_NO_SIGNAL 0x00000002 +#define V4L2_IN_ST_NO_COLOR 0x00000004 + +/* field 'status' - analog */ +#define V4L2_IN_ST_NO_H_LOCK 0x00000100 /* No horizontal sync lock */ +#define V4L2_IN_ST_COLOR_KILL 0x00000200 /* Color killer is active */ + +/* field 'status' - digital */ +#define V4L2_IN_ST_NO_SYNC 0x00010000 /* No synchronization lock */ +#define V4L2_IN_ST_NO_EQU 0x00020000 /* No equalizer lock */ +#define V4L2_IN_ST_NO_CARRIER 0x00040000 /* Carrier recovery failed */ + +/* field 'status' - VCR and set-top box */ +#define V4L2_IN_ST_MACROVISION 0x01000000 /* Macrovision detected */ +#define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied */ +#define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */ + +/* + * V I D E O O U T P U T S + */ +struct v4l2_output +{ + __u32 index; /* Which output */ + __u8 name[32]; /* Label */ + __u32 type; /* Type of output */ + __u32 audioset; /* Associated audios (bitfield) */ + __u32 modulator; /* Associated modulator */ + v4l2_std_id std; + __u32 reserved[4]; +}; +/* Values for the 'type' field */ +#define V4L2_OUTPUT_TYPE_MODULATOR 1 +#define V4L2_OUTPUT_TYPE_ANALOG 2 +#define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3 + +/* + * C O N T R O L S + */ +struct v4l2_control +{ + __u32 id; + __s32 value; +}; + +/* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ +struct v4l2_queryctrl +{ + __u32 id; + enum v4l2_ctrl_type type; + __u8 name[32]; /* Whatever */ + __s32 minimum; /* Note signedness */ + __s32 maximum; + __s32 step; + __s32 default_value; + __u32 flags; + __u32 reserved[2]; +}; + +/* Used in the VIDIOC_QUERYMENU ioctl for querying menu items */ +struct v4l2_querymenu +{ + __u32 id; + __u32 index; + __u8 name[32]; /* Whatever */ + __u32 reserved; +}; + +/* Control flags */ +#define V4L2_CTRL_FLAG_DISABLED 0x0001 +#define V4L2_CTRL_FLAG_GRABBED 0x0002 + +/* Control IDs defined by V4L2 */ +#define V4L2_CID_BASE 0x00980900 +/* IDs reserved for driver specific controls */ +#define V4L2_CID_PRIVATE_BASE 0x08000000 + +#define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE+0) +#define V4L2_CID_CONTRAST (V4L2_CID_BASE+1) +#define V4L2_CID_SATURATION (V4L2_CID_BASE+2) +#define V4L2_CID_HUE (V4L2_CID_BASE+3) +#define V4L2_CID_AUDIO_VOLUME (V4L2_CID_BASE+5) +#define V4L2_CID_AUDIO_BALANCE (V4L2_CID_BASE+6) +#define V4L2_CID_AUDIO_BASS (V4L2_CID_BASE+7) +#define V4L2_CID_AUDIO_TREBLE (V4L2_CID_BASE+8) +#define V4L2_CID_AUDIO_MUTE (V4L2_CID_BASE+9) +#define V4L2_CID_AUDIO_LOUDNESS (V4L2_CID_BASE+10) +#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11) +#define V4L2_CID_AUTO_WHITE_BALANCE (V4L2_CID_BASE+12) +#define V4L2_CID_DO_WHITE_BALANCE (V4L2_CID_BASE+13) +#define V4L2_CID_RED_BALANCE (V4L2_CID_BASE+14) +#define V4L2_CID_BLUE_BALANCE (V4L2_CID_BASE+15) +#define V4L2_CID_GAMMA (V4L2_CID_BASE+16) +#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* ? Not sure */ +#define V4L2_CID_EXPOSURE (V4L2_CID_BASE+17) +#define V4L2_CID_AUTOGAIN (V4L2_CID_BASE+18) +#define V4L2_CID_GAIN (V4L2_CID_BASE+19) +#define V4L2_CID_HFLIP (V4L2_CID_BASE+20) +#define V4L2_CID_VFLIP (V4L2_CID_BASE+21) +#define V4L2_CID_HCENTER (V4L2_CID_BASE+22) +#define V4L2_CID_VCENTER (V4L2_CID_BASE+23) +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+24) /* last CID + 1 */ + +/* + * T U N I N G + */ +struct v4l2_tuner +{ + __u32 index; + __u8 name[32]; + enum v4l2_tuner_type type; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 rxsubchans; + __u32 audmode; + __s32 signal; + __s32 afc; + __u32 reserved[4]; +}; + +struct v4l2_modulator +{ + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 txsubchans; + __u32 reserved[4]; +}; + +/* Flags for the 'capability' field */ +#define V4L2_TUNER_CAP_LOW 0x0001 +#define V4L2_TUNER_CAP_NORM 0x0002 +#define V4L2_TUNER_CAP_STEREO 0x0010 +#define V4L2_TUNER_CAP_LANG2 0x0020 +#define V4L2_TUNER_CAP_SAP 0x0020 +#define V4L2_TUNER_CAP_LANG1 0x0040 + +/* Flags for the 'rxsubchans' field */ +#define V4L2_TUNER_SUB_MONO 0x0001 +#define V4L2_TUNER_SUB_STEREO 0x0002 +#define V4L2_TUNER_SUB_LANG2 0x0004 +#define V4L2_TUNER_SUB_SAP 0x0004 +#define V4L2_TUNER_SUB_LANG1 0x0008 + +/* Values for the 'audmode' field */ +#define V4L2_TUNER_MODE_MONO 0x0000 +#define V4L2_TUNER_MODE_STEREO 0x0001 +#define V4L2_TUNER_MODE_LANG2 0x0002 +#define V4L2_TUNER_MODE_SAP 0x0002 +#define V4L2_TUNER_MODE_LANG1 0x0003 + +struct v4l2_frequency +{ + __u32 tuner; + enum v4l2_tuner_type type; + __u32 frequency; + __u32 reserved[8]; +}; + +/* + * A U D I O + */ +struct v4l2_audio +{ + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 mode; + __u32 reserved[2]; +}; +/* Flags for the 'capability' field */ +#define V4L2_AUDCAP_STEREO 0x00001 +#define V4L2_AUDCAP_AVL 0x00002 + +/* Flags for the 'mode' field */ +#define V4L2_AUDMODE_AVL 0x00001 + +struct v4l2_audioout +{ + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 mode; + __u32 reserved[2]; +}; + +/* + * D A T A S E R V I C E S ( V B I ) + * + * Data services API by Michael Schimek + */ + +struct v4l2_vbi_format +{ + __u32 sampling_rate; /* in 1 Hz */ + __u32 offset; + __u32 samples_per_line; + __u32 sample_format; /* V4L2_PIX_FMT_* */ + __s32 start[2]; + __u32 count[2]; + __u32 flags; /* V4L2_VBI_* */ + __u32 reserved[2]; /* must be zero */ +}; + +/* VBI flags */ +#define V4L2_VBI_UNSYNC (1<< 0) +#define V4L2_VBI_INTERLACED (1<< 1) + + +/* + * A G G R E G A T E S T R U C T U R E S + */ + +/* Stream data format + */ +struct v4l2_format +{ + enum v4l2_buf_type type; + union + { + struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE + struct v4l2_window win; // V4L2_BUF_TYPE_VIDEO_OVERLAY + struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE + __u8 raw_data[200]; // user-defined + } fmt; +}; + + +/* Stream type-dependent parameters + */ +struct v4l2_streamparm +{ + enum v4l2_buf_type type; + union + { + struct v4l2_captureparm capture; + struct v4l2_outputparm output; + __u8 raw_data[200]; /* user-defined */ + } parm; +}; + + + +/* + * I O C T L C O D E S F O R V I D E O D E V I C E S + * + */ +#define VIDIOC_QUERYCAP _IOR ('V', 0, struct v4l2_capability) +#define VIDIOC_RESERVED _IO ('V', 1) +#define VIDIOC_ENUM_FMT _IOWR ('V', 2, struct v4l2_fmtdesc) +#define VIDIOC_G_FMT _IOWR ('V', 4, struct v4l2_format) +#define VIDIOC_S_FMT _IOWR ('V', 5, struct v4l2_format) +#if 0 +#define VIDIOC_G_COMP _IOR ('V', 6, struct v4l2_compression) +#define VIDIOC_S_COMP _IOW ('V', 7, struct v4l2_compression) +#endif +#define VIDIOC_REQBUFS _IOWR ('V', 8, struct v4l2_requestbuffers) +#define VIDIOC_QUERYBUF _IOWR ('V', 9, struct v4l2_buffer) +#define VIDIOC_G_FBUF _IOR ('V', 10, struct v4l2_framebuffer) +#define VIDIOC_S_FBUF _IOW ('V', 11, struct v4l2_framebuffer) +#define VIDIOC_OVERLAY _IOW ('V', 14, int) +#define VIDIOC_QBUF _IOWR ('V', 15, struct v4l2_buffer) +#define VIDIOC_DQBUF _IOWR ('V', 17, struct v4l2_buffer) +#define VIDIOC_STREAMON _IOW ('V', 18, int) +#define VIDIOC_STREAMOFF _IOW ('V', 19, int) +#define VIDIOC_G_PARM _IOWR ('V', 21, struct v4l2_streamparm) +#define VIDIOC_S_PARM _IOWR ('V', 22, struct v4l2_streamparm) +#define VIDIOC_G_STD _IOR ('V', 23, v4l2_std_id) +#define VIDIOC_S_STD _IOW ('V', 24, v4l2_std_id) +#define VIDIOC_ENUMSTD _IOWR ('V', 25, struct v4l2_standard) +#define VIDIOC_ENUMINPUT _IOWR ('V', 26, struct v4l2_input) +#define VIDIOC_G_CTRL _IOWR ('V', 27, struct v4l2_control) +#define VIDIOC_S_CTRL _IOWR ('V', 28, struct v4l2_control) +#define VIDIOC_G_TUNER _IOWR ('V', 29, struct v4l2_tuner) +#define VIDIOC_S_TUNER _IOW ('V', 30, struct v4l2_tuner) +#define VIDIOC_G_AUDIO _IOR ('V', 33, struct v4l2_audio) +#define VIDIOC_S_AUDIO _IOW ('V', 34, struct v4l2_audio) +#define VIDIOC_QUERYCTRL _IOWR ('V', 36, struct v4l2_queryctrl) +#define VIDIOC_QUERYMENU _IOWR ('V', 37, struct v4l2_querymenu) +#define VIDIOC_G_INPUT _IOR ('V', 38, int) +#define VIDIOC_S_INPUT _IOWR ('V', 39, int) +#define VIDIOC_G_OUTPUT _IOR ('V', 46, int) +#define VIDIOC_S_OUTPUT _IOWR ('V', 47, int) +#define VIDIOC_ENUMOUTPUT _IOWR ('V', 48, struct v4l2_output) +#define VIDIOC_G_AUDOUT _IOR ('V', 49, struct v4l2_audioout) +#define VIDIOC_S_AUDOUT _IOW ('V', 50, struct v4l2_audioout) +#define VIDIOC_G_MODULATOR _IOWR ('V', 54, struct v4l2_modulator) +#define VIDIOC_S_MODULATOR _IOW ('V', 55, struct v4l2_modulator) +#define VIDIOC_G_FREQUENCY _IOWR ('V', 56, struct v4l2_frequency) +#define VIDIOC_S_FREQUENCY _IOW ('V', 57, struct v4l2_frequency) +#define VIDIOC_CROPCAP _IOR ('V', 58, struct v4l2_cropcap) +#define VIDIOC_G_CROP _IOWR ('V', 59, struct v4l2_crop) +#define VIDIOC_S_CROP _IOW ('V', 60, struct v4l2_crop) +#define VIDIOC_G_JPEGCOMP _IOR ('V', 61, struct v4l2_jpegcompression) +#define VIDIOC_S_JPEGCOMP _IOW ('V', 62, struct v4l2_jpegcompression) +#define VIDIOC_QUERYSTD _IOR ('V', 63, v4l2_std_id) +#define VIDIOC_TRY_FMT _IOWR ('V', 64, struct v4l2_format) +#define VIDIOC_ENUMAUDIO _IOWR ('V', 65, struct v4l2_audio) +#define VIDIOC_ENUMAUDOUT _IOWR ('V', 66, struct v4l2_audioout) +#define VIDIOC_G_PRIORITY _IOR ('V', 67, enum v4l2_priority) +#define VIDIOC_S_PRIORITY _IOW ('V', 68, enum v4l2_priority) + +/* for compatibility, will go away some day */ +#define VIDIOC_OVERLAY_OLD _IOWR ('V', 14, int) +#define VIDIOC_S_PARM_OLD _IOW ('V', 22, struct v4l2_streamparm) +#define VIDIOC_S_CTRL_OLD _IOW ('V', 28, struct v4l2_control) +#define VIDIOC_G_AUDIO_OLD _IOWR ('V', 33, struct v4l2_audio) +#define VIDIOC_G_AUDOUT_OLD _IOWR ('V', 49, struct v4l2_audioout) + +#define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */ + + +#ifdef __KERNEL__ +/* + * + * V 4 L 2 D R I V E R H E L P E R A P I + * + * Some commonly needed functions for drivers (v4l2-common.o module) + */ +#include + +/* Video standard functions */ +extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs); +extern int v4l2_video_std_construct(struct v4l2_standard *vs, + int id, char *name); + +/* prority handling */ +struct v4l2_prio_state { + atomic_t prios[4]; +}; +int v4l2_prio_init(struct v4l2_prio_state *global); +int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, + enum v4l2_priority new); +int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local); +int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local); +enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global); +int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local); + +/* names for fancy debug output */ +extern char *v4l2_field_names[]; +extern char *v4l2_type_names[]; +extern char *v4l2_ioctl_names[]; + +/* Compatibility layer interface -- v4l1-compat module */ +typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg); +int v4l_compat_translate_ioctl(struct inode *inode, struct file *file, + int cmd, void *arg, v4l2_kioctl driver_ioctl); + +#endif /* __KERNEL__ */ +#endif /* __LINUX_VIDEODEV2_H */ + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ -- 1.5.6.5