diff options
author | mirko <mirko@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-12-12 00:02:36 +0000 |
---|---|---|
committer | mirko <mirko@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-12-12 00:02:36 +0000 |
commit | cc3146824acbf585f487a803b4a2eadf36b9b47d (patch) | |
tree | efab142ef89b35ce42e8a79e028eff15be362af8 /target/linux/s3c24xx/patches/0145-introduce-samsung-camera-unit-driver.patch.patch | |
parent | 22b3854919b7cb44d725eb7a7efd018ad9aec25c (diff) |
add support for target 3c24xx (more known as Openmoko GTA02 "Freerunner") and merge it with the openmoko-target and the work Michael Buesch <mb> did
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@13609 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/s3c24xx/patches/0145-introduce-samsung-camera-unit-driver.patch.patch')
-rwxr-xr-x | target/linux/s3c24xx/patches/0145-introduce-samsung-camera-unit-driver.patch.patch | 5883 |
1 files changed, 5883 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches/0145-introduce-samsung-camera-unit-driver.patch.patch b/target/linux/s3c24xx/patches/0145-introduce-samsung-camera-unit-driver.patch.patch new file mode 100755 index 0000000000..8db75f0f6d --- /dev/null +++ b/target/linux/s3c24xx/patches/0145-introduce-samsung-camera-unit-driver.patch.patch @@ -0,0 +1,5883 @@ +From 573919b9c0d6752c42b2b130fde41d6b80a843b7 Mon Sep 17 00:00:00 2001 +From: SW.LEE <hitchcar@samsung.com> +Date: Fri, 25 Jul 2008 23:06:10 +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 | 8 +- + 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(+), 8 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 3e9e9f1..e042965 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 +@@ -93,4 +96,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 4932232..e9c6334 100644 +--- a/arch/arm/mach-s3c2440/Makefile ++++ b/arch/arm/mach-s3c2440/Makefile +@@ -1,10 +1,4 @@ +-# arch/arm/mach-s3c2440/Makefile +-# +-# Copyright 2007 Simtec Electronics +-# +-# Licensed under GPLv2 +- +-obj-y := ++obj-y += camera/ + obj-m := + obj-n := + obj- := +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 <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 __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 <hitchcar@samsung.com> ++ * ++ * 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 <linux/config.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/sched.h> ++#include <linux/irq.h> ++#include <linux/tqueue.h> ++#include <linux/locks.h> ++#include <linux/completion.h> ++#include <linux/delay.h> ++#include <linux/slab.h> ++#include <linux/vmalloc.h> ++#include <linux/miscdevice.h> ++#include <linux/wait.h> ++#include <linux/miscdevice.h> ++#include <asm/io.h> ++#include <asm/semaphore.h> ++#include <asm/hardware.h> ++#include <asm/uaccess.h> ++ ++#ifdef CONFIG_ARCH_S3C24A0A ++#include <asm/arch/S3C24A0.h> ++#include <asm/arch/clocks.h> ++#else ++#include <asm/arch/S3C2440.h> ++#include <asm/arch/clocks.h> ++#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 <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_H_ ++#define __FIMC20_CAMIF_H_ ++ ++#ifdef __KERNEL__ ++ ++#include "bits.h" ++#include "videodev.h" ++#include <asm/types.h> ++#include <linux/i2c.h> ++ ++#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 <hitchcar@sec.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. ++*/ ++ ++#include <linux/version.h> ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/errno.h> ++#include <linux/fs.h> ++#include <linux/kernel.h> ++#include <linux/major.h> ++#include <linux/slab.h> ++#include <linux/poll.h> ++#include <linux/signal.h> ++#include <linux/ioport.h> ++#include <linux/sched.h> ++#include <linux/types.h> ++#include <linux/interrupt.h> ++#include <linux/kmod.h> ++#include <linux/vmalloc.h> ++#include <linux/init.h> ++#include <linux/pagemap.h> ++#include <asm/io.h> ++#include <asm/irq.h> ++#include <asm/semaphore.h> ++#include <linux/miscdevice.h> ++ ++//#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 <hitchcar@samsung.com> ++ * ++ * 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 <linux/config.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/i2c.h> ++#include <linux/slab.h> ++#include <linux/string.h> ++#include <linux/init.h> ++#include <linux/delay.h> ++ ++ ++#ifdef CONFIG_ARCH_S3C24A0A ++#else ++#include <asm/arch/S3C2440.h> ++#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 <hitchcar@sec.samsung.com>"); ++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 <hitchcar@samsung.com> ++ * ++ * 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 <linux/version.h> ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/errno.h> ++#include <linux/fs.h> ++#include <linux/kernel.h> ++#include <linux/major.h> ++#include <linux/slab.h> ++#include <linux/poll.h> ++#include <linux/signal.h> ++#include <linux/ioport.h> ++#include <linux/sched.h> ++#include <linux/types.h> ++#include <linux/interrupt.h> ++#include <linux/kmod.h> ++#include <linux/vmalloc.h> ++#include <linux/init.h> ++#include <asm/io.h> ++#include <asm/page.h> ++#include <asm/irq.h> ++#include <asm/semaphore.h> ++#include <linux/miscdevice.h> ++ ++//#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 <hitchcar@sec.samsung.com> ++ 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 <hitchcar@samsung.com> ++ * ++ * 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 <hitchcar@sec.samsung.com> ++ * 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 <hitchcar@sec.samsung.com> ++ * 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 <hitchcar@sec.samsung.com> ++ * ++ * 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 <hitchcar@sec.samsung.com> ++ * 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 <hitchcar@sec.samsung.com> ++ * ++ * 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 <linux/config.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/sched.h> ++#include <linux/irq.h> ++#include <linux/tqueue.h> ++#include <linux/locks.h> ++#include <linux/completion.h> ++#include <linux/delay.h> ++#include <linux/slab.h> ++#include <linux/vmalloc.h> ++#include <linux/miscdevice.h> ++#include <linux/wait.h> ++ ++#include <asm/io.h> ++#include <asm/semaphore.h> ++#include <asm/hardware.h> ++#include <asm/uaccess.h> ++ ++#include <asm/arch/cpu_s3c2440.h> ++#include <asm/arch/S3C2440.h> ++ ++#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 <hitchcar@sec.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. ++*/ ++ ++#include <linux/version.h> ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/errno.h> ++#include <linux/fs.h> ++#include <linux/kernel.h> ++#include <linux/major.h> ++#include <linux/slab.h> ++#include <linux/poll.h> ++#include <linux/signal.h> ++#include <linux/ioport.h> ++#include <linux/sched.h> ++#include <linux/types.h> ++#include <linux/interrupt.h> ++#include <linux/kmod.h> ++#include <linux/vmalloc.h> ++#include <linux/init.h> ++#include <asm/io.h> ++#include <asm/page.h> ++#include <asm/irq.h> ++#include <asm/semaphore.h> ++#include <linux/miscdevice.h> ++ ++//#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 <hitchcar@sec.samsung.com>"); ++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, <alan@redhat.com> video4linux ++ * ++ * Author: SW.LEE <hitchcar@samsung.com> ++ * 2004 (C) Samsung Electronics ++ * Modified for S3C2440/S3C24A0 Interface ++ * ++ * This file is released under the GPLv2 ++ */ ++ ++ ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/sched.h> ++#include <linux/smp_lock.h> ++#include <linux/mm.h> ++#include <linux/string.h> ++#include <linux/errno.h> ++#include <linux/init.h> ++#include <linux/kmod.h> ++#include <linux/slab.h> ++#include <linux/devfs_fs_kernel.h> ++#include <linux/miscdevice.h> ++#include <asm/uaccess.h> ++#include <asm/system.h> ++#include <asm/semaphore.h> ++ ++ ++ ++#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 <hitchcar@sec.samsung.com>"); ++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 <linux/types.h> ++#include <linux/version.h> ++#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 <bdirks@pacbell.net> ++ * Justin Schoeman ++ * et al. ++ */ ++#ifdef __KERNEL__ ++#include <linux/time.h> /* 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 <linux/fs.h> ++ ++/* 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.3 + |