-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
V4L/DVB (4797): Marvell 88ALP01 "cafe" driver
A driver for the Marvell M88ALP01 "CAFE" CMOS integrated camera controller. This driver has been renamed "cafe_ccic" since my previous patch set. Signed-off-by: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
- Loading branch information
Jonathan Corbet
authored and
Mauro Carvalho Chehab
committed
Dec 10, 2006
1 parent
9c4dfad
commit d905b38
Showing
6 changed files
with
2,463 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
"cafe_ccic" is a driver for the Marvell 88ALP01 "cafe" CMOS camera | ||
controller. This is the controller found in first-generation OLPC systems, | ||
and this driver was written with support from the OLPC project. | ||
|
||
Current status: the core driver works. It can generate data in YUV422, | ||
RGB565, and RGB444 formats. (Anybody looking at the code will see RGB32 as | ||
well, but that is a debugging aid which will be removed shortly). VGA and | ||
QVGA modes work; CIF is there but the colors remain funky. Only the OV7670 | ||
sensor is known to work with this controller at this time. | ||
|
||
To try it out: either of these commands will work: | ||
|
||
mplayer tv:// -tv driver=v4l2:width=640:height=480 -nosound | ||
mplayer tv:// -tv driver=v4l2:width=640:height=480:outfmt=bgr16 -nosound | ||
|
||
The "xawtv" utility also works; gqcam does not, for unknown reasons. | ||
|
||
There are a few load-time options, most of which can be changed after | ||
loading via sysfs as well: | ||
|
||
- alloc_bufs_at_load: Normally, the driver will not allocate any DMA | ||
buffers until the time comes to transfer data. If this option is set, | ||
then worst-case-sized buffers will be allocated at module load time. | ||
This option nails down the memory for the life of the module, but | ||
perhaps decreases the chances of an allocation failure later on. | ||
|
||
- dma_buf_size: The size of DMA buffers to allocate. Note that this | ||
option is only consulted for load-time allocation; when buffers are | ||
allocated at run time, they will be sized appropriately for the current | ||
camera settings. | ||
|
||
- n_dma_bufs: The controller can cycle through either two or three DMA | ||
buffers. Normally, the driver tries to use three buffers; on faster | ||
systems, however, it will work well with only two. | ||
|
||
- min_buffers: The minimum number of streaming I/O buffers that the driver | ||
will consent to work with. Default is one, but, on slower systems, | ||
better behavior with mplayer can be achieved by setting to a higher | ||
value (like six). | ||
|
||
- max_buffers: The maximum number of streaming I/O buffers; default is | ||
ten. That number was carefully picked out of a hat and should not be | ||
assumed to actually mean much of anything. | ||
|
||
- flip: If this boolean parameter is set, the sensor will be instructed to | ||
invert the video image. Whether it makes sense is determined by how | ||
your particular camera is mounted. | ||
|
||
Work is ongoing with this driver, stay tuned. | ||
|
||
jon | ||
|
||
Jonathan Corbet | ||
corbet@lwn.net |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
/* | ||
* Register definitions for the m88alp01 camera interface. Offsets in bytes | ||
* as given in the spec. | ||
* | ||
* Copyright 2006 One Laptop Per Child Association, Inc. | ||
* | ||
* Written by Jonathan Corbet, corbet@lwn.net. | ||
* | ||
* This file may be distributed under the terms of the GNU General | ||
* Public License, version 2. | ||
*/ | ||
#define REG_Y0BAR 0x00 | ||
#define REG_Y1BAR 0x04 | ||
#define REG_Y2BAR 0x08 | ||
/* ... */ | ||
|
||
#define REG_IMGPITCH 0x24 /* Image pitch register */ | ||
#define IMGP_YP_SHFT 2 /* Y pitch params */ | ||
#define IMGP_YP_MASK 0x00003ffc /* Y pitch field */ | ||
#define IMGP_UVP_SHFT 18 /* UV pitch (planar) */ | ||
#define IMGP_UVP_MASK 0x3ffc0000 | ||
#define REG_IRQSTATRAW 0x28 /* RAW IRQ Status */ | ||
#define IRQ_EOF0 0x00000001 /* End of frame 0 */ | ||
#define IRQ_EOF1 0x00000002 /* End of frame 1 */ | ||
#define IRQ_EOF2 0x00000004 /* End of frame 2 */ | ||
#define IRQ_SOF0 0x00000008 /* Start of frame 0 */ | ||
#define IRQ_SOF1 0x00000010 /* Start of frame 1 */ | ||
#define IRQ_SOF2 0x00000020 /* Start of frame 2 */ | ||
#define IRQ_OVERFLOW 0x00000040 /* FIFO overflow */ | ||
#define IRQ_TWSIW 0x00010000 /* TWSI (smbus) write */ | ||
#define IRQ_TWSIR 0x00020000 /* TWSI read */ | ||
#define IRQ_TWSIE 0x00040000 /* TWSI error */ | ||
#define TWSIIRQS (IRQ_TWSIW|IRQ_TWSIR|IRQ_TWSIE) | ||
#define FRAMEIRQS (IRQ_EOF0|IRQ_EOF1|IRQ_EOF2|IRQ_SOF0|IRQ_SOF1|IRQ_SOF2) | ||
#define ALLIRQS (TWSIIRQS|FRAMEIRQS|IRQ_OVERFLOW) | ||
#define REG_IRQMASK 0x2c /* IRQ mask - same bits as IRQSTAT */ | ||
#define REG_IRQSTAT 0x30 /* IRQ status / clear */ | ||
|
||
#define REG_IMGSIZE 0x34 /* Image size */ | ||
#define IMGSZ_V_MASK 0x1fff0000 | ||
#define IMGSZ_V_SHIFT 16 | ||
#define IMGSZ_H_MASK 0x00003fff | ||
#define REG_IMGOFFSET 0x38 /* IMage offset */ | ||
|
||
#define REG_CTRL0 0x3c /* Control 0 */ | ||
#define C0_ENABLE 0x00000001 /* Makes the whole thing go */ | ||
|
||
/* Mask for all the format bits */ | ||
#define C0_DF_MASK 0x00fffffc /* Bits 2-23 */ | ||
|
||
/* RGB ordering */ | ||
#define C0_RGB4_RGBX 0x00000000 | ||
#define C0_RGB4_XRGB 0x00000004 | ||
#define C0_RGB4_BGRX 0x00000008 | ||
#define C0_RGB4_XBGR 0x0000000c | ||
#define C0_RGB5_RGGB 0x00000000 | ||
#define C0_RGB5_GRBG 0x00000004 | ||
#define C0_RGB5_GBRG 0x00000008 | ||
#define C0_RGB5_BGGR 0x0000000c | ||
|
||
/* Spec has two fields for DIN and DOUT, but they must match, so | ||
combine them here. */ | ||
#define C0_DF_YUV 0x00000000 /* Data is YUV */ | ||
#define C0_DF_RGB 0x000000a0 /* ... RGB */ | ||
#define C0_DF_BAYER 0x00000140 /* ... Bayer */ | ||
/* 8-8-8 must be missing from the below - ask */ | ||
#define C0_RGBF_565 0x00000000 | ||
#define C0_RGBF_444 0x00000800 | ||
#define C0_RGB_BGR 0x00001000 /* Blue comes first */ | ||
#define C0_YUV_PLANAR 0x00000000 /* YUV 422 planar format */ | ||
#define C0_YUV_PACKED 0x00008000 /* YUV 422 packed */ | ||
#define C0_YUV_420PL 0x0000a000 /* YUV 420 planar */ | ||
/* Think that 420 packed must be 111 - ask */ | ||
#define C0_YUVE_YUYV 0x00000000 /* Y1CbY0Cr */ | ||
#define C0_YUVE_YVYU 0x00010000 /* Y1CrY0Cb */ | ||
#define C0_YUVE_VYUY 0x00020000 /* CrY1CbY0 */ | ||
#define C0_YUVE_UYVY 0x00030000 /* CbY1CrY0 */ | ||
#define C0_YUVE_XYUV 0x00000000 /* 420: .YUV */ | ||
#define C0_YUVE_XYVU 0x00010000 /* 420: .YVU */ | ||
#define C0_YUVE_XUVY 0x00020000 /* 420: .UVY */ | ||
#define C0_YUVE_XVUY 0x00030000 /* 420: .VUY */ | ||
/* Bayer bits 18,19 if needed */ | ||
#define C0_HPOL_LOW 0x01000000 /* HSYNC polarity active low */ | ||
#define C0_VPOL_LOW 0x02000000 /* VSYNC polarity active low */ | ||
#define C0_VCLK_LOW 0x04000000 /* VCLK on falling edge */ | ||
#define C0_DOWNSCALE 0x08000000 /* Enable downscaler */ | ||
#define C0_SIFM_MASK 0xc0000000 /* SIF mode bits */ | ||
#define C0_SIF_HVSYNC 0x00000000 /* Use H/VSYNC */ | ||
#define CO_SOF_NOSYNC 0x40000000 /* Use inband active signaling */ | ||
|
||
|
||
#define REG_CTRL1 0x40 /* Control 1 */ | ||
#define C1_444ALPHA 0x00f00000 /* Alpha field in RGB444 */ | ||
#define C1_ALPHA_SHFT 20 | ||
#define C1_DMAB32 0x00000000 /* 32-byte DMA burst */ | ||
#define C1_DMAB16 0x02000000 /* 16-byte DMA burst */ | ||
#define C1_DMAB64 0x04000000 /* 64-byte DMA burst */ | ||
#define C1_DMAB_MASK 0x06000000 | ||
#define C1_TWOBUFS 0x08000000 /* Use only two DMA buffers */ | ||
#define C1_PWRDWN 0x10000000 /* Power down */ | ||
|
||
#define REG_CLKCTRL 0x88 /* Clock control */ | ||
#define CLK_DIV_MASK 0x0000ffff /* Upper bits RW "reserved" */ | ||
|
||
#define REG_GPR 0xb4 /* General purpose register. This | ||
controls inputs to the power and reset | ||
pins on the OV7670 used with OLPC; | ||
other deployments could differ. */ | ||
#define GPR_C1EN 0x00000020 /* Pad 1 (power down) enable */ | ||
#define GPR_C0EN 0x00000010 /* Pad 0 (reset) enable */ | ||
#define GPR_C1 0x00000002 /* Control 1 value */ | ||
/* | ||
* Control 0 is wired to reset on OLPC machines. For ov7x sensors, | ||
* it is active low, for 0v6x, instead, it's active high. What | ||
* fun. | ||
*/ | ||
#define GPR_C0 0x00000001 /* Control 0 value */ | ||
|
||
#define REG_TWSIC0 0xb8 /* TWSI (smbus) control 0 */ | ||
#define TWSIC0_EN 0x00000001 /* TWSI enable */ | ||
#define TWSIC0_MODE 0x00000002 /* 1 = 16-bit, 0 = 8-bit */ | ||
#define TWSIC0_SID 0x000003fc /* Slave ID */ | ||
#define TWSIC0_SID_SHIFT 2 | ||
#define TWSIC0_CLKDIV 0x0007fc00 /* Clock divider */ | ||
#define TWSIC0_MASKACK 0x00400000 /* Mask ack from sensor */ | ||
#define TWSIC0_OVMAGIC 0x00800000 /* Make it work on OV sensors */ | ||
|
||
#define REG_TWSIC1 0xbc /* TWSI control 1 */ | ||
#define TWSIC1_DATA 0x0000ffff /* Data to/from camchip */ | ||
#define TWSIC1_ADDR 0x00ff0000 /* Address (register) */ | ||
#define TWSIC1_ADDR_SHIFT 16 | ||
#define TWSIC1_READ 0x01000000 /* Set for read op */ | ||
#define TWSIC1_WSTAT 0x02000000 /* Write status */ | ||
#define TWSIC1_RVALID 0x04000000 /* Read data valid */ | ||
#define TWSIC1_ERROR 0x08000000 /* Something screwed up */ | ||
|
||
|
||
#define REG_UBAR 0xc4 /* Upper base address register */ | ||
|
||
/* | ||
* Here's the weird global control registers which are said to live | ||
* way up here. | ||
*/ | ||
#define REG_GL_CSR 0x3004 /* Control/status register */ | ||
#define GCSR_SRS 0x00000001 /* SW Reset set */ | ||
#define GCSR_SRC 0x00000002 /* SW Reset clear */ | ||
#define GCSR_MRS 0x00000004 /* Master reset set */ | ||
#define GCSR_MRC 0x00000008 /* HW Reset clear */ | ||
#define GCSR_CCIC_EN 0x00004000 /* CCIC Clock enable */ | ||
#define REG_GL_IMASK 0x300c /* Interrupt mask register */ | ||
#define GIMSK_CCIC_EN 0x00000004 /* CCIC Interrupt enable */ | ||
|
||
#define REG_LEN REG_GL_IMASK + 4 | ||
|
||
|
||
/* | ||
* Useful stuff that probably belongs somewhere global. | ||
*/ | ||
#define VGA_WIDTH 640 | ||
#define VGA_HEIGHT 480 |
Oops, something went wrong.