From abfa3df36c01a32b081fb448750181af76eb9d55 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Sat, 11 Jun 2011 14:46:43 -0300 Subject: [media] marvell-cam: Separate out the Marvell camera core There will eventually be multiple users of the core camera controller, so separate it from the bus/platform/i2c stuff. I've tried to do the minimal set of changes to get the driver functioning in this configuration; I did clean up a bunch of old checkpatch gripes in the process. This driver works like the old one did on OLPC XO 1 systems. Cc: Daniel Drake Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/marvell-ccic/mcam-core.h | 311 +++++++++++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100644 drivers/media/video/marvell-ccic/mcam-core.h (limited to 'drivers/media/video/marvell-ccic/mcam-core.h') diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h new file mode 100644 index 00000000000..0b55b8e6bb7 --- /dev/null +++ b/drivers/media/video/marvell-ccic/mcam-core.h @@ -0,0 +1,311 @@ +/* + * Marvell camera core structures. + * + * Copyright 2011 Jonathan Corbet corbet@lwn.net + */ + +/* + * Tracking of streaming I/O buffers. + * FIXME doesn't belong in this file + */ +struct mcam_sio_buffer { + struct list_head list; + struct v4l2_buffer v4lbuf; + char *buffer; /* Where it lives in kernel space */ + int mapcount; + struct mcam_camera *cam; +}; + +enum mcam_state { + S_NOTREADY, /* Not yet initialized */ + S_IDLE, /* Just hanging around */ + S_FLAKED, /* Some sort of problem */ + S_SINGLEREAD, /* In read() */ + S_SPECREAD, /* Speculative read (for future read()) */ + S_STREAMING /* Streaming data */ +}; +#define MAX_DMA_BUFS 3 + +/* + * A description of one of our devices. + * Locking: controlled by s_mutex. Certain fields, however, require + * the dev_lock spinlock; they are marked as such by comments. + * dev_lock is also required for access to device registers. + */ +struct mcam_camera { + /* + * These fields should be set by the platform code prior to + * calling mcam_register(). + */ + struct i2c_adapter i2c_adapter; + unsigned char __iomem *regs; + spinlock_t dev_lock; + struct device *dev; /* For messages, dma alloc */ + unsigned int chip_id; + + /* + * Callbacks from the core to the platform code. + */ + void (*plat_power_up) (struct mcam_camera *cam); + void (*plat_power_down) (struct mcam_camera *cam); + + /* + * Everything below here is private to the mcam core and + * should not be touched by the platform code. + */ + struct v4l2_device v4l2_dev; + enum mcam_state state; + unsigned long flags; /* Buffer status, mainly (dev_lock) */ + int users; /* How many open FDs */ + struct file *owner; /* Who has data access (v4l2) */ + + /* + * Subsystem structures. + */ + struct video_device vdev; + struct v4l2_subdev *sensor; + unsigned short sensor_addr; + + struct list_head dev_list; /* link to other devices */ + + /* DMA buffers */ + unsigned int nbufs; /* How many are alloc'd */ + int next_buf; /* Next to consume (dev_lock) */ + unsigned int dma_buf_size; /* allocated size */ + void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */ + dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */ + unsigned int specframes; /* Unconsumed spec frames (dev_lock) */ + unsigned int sequence; /* Frame sequence number */ + unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual buffers */ + + /* Streaming buffers */ + unsigned int n_sbufs; /* How many we have */ + struct mcam_sio_buffer *sb_bufs; /* The array of housekeeping structs */ + struct list_head sb_avail; /* Available for data (we own) (dev_lock) */ + struct list_head sb_full; /* With data (user space owns) (dev_lock) */ + struct tasklet_struct s_tasklet; + + /* Current operating parameters */ + u32 sensor_type; /* Currently ov7670 only */ + struct v4l2_pix_format pix_format; + enum v4l2_mbus_pixelcode mbus_code; + + /* Locks */ + struct mutex s_mutex; /* Access to this structure */ + + /* Misc */ + wait_queue_head_t iowait; /* Waiting on frame data */ +}; + + +/* + * Register I/O functions. These are here because the platform code + * may legitimately need to mess with the register space. + */ +/* + * Device register I/O + */ +static inline void mcam_reg_write(struct mcam_camera *cam, unsigned int reg, + unsigned int val) +{ + iowrite32(val, cam->regs + reg); +} + +static inline unsigned int mcam_reg_read(struct mcam_camera *cam, + unsigned int reg) +{ + return ioread32(cam->regs + reg); +} + + +static inline void mcam_reg_write_mask(struct mcam_camera *cam, unsigned int reg, + unsigned int val, unsigned int mask) +{ + unsigned int v = mcam_reg_read(cam, reg); + + v = (v & ~mask) | (val & mask); + mcam_reg_write(cam, reg, v); +} + +static inline void mcam_reg_clear_bit(struct mcam_camera *cam, + unsigned int reg, unsigned int val) +{ + mcam_reg_write_mask(cam, reg, 0, val); +} + +static inline void mcam_reg_set_bit(struct mcam_camera *cam, + unsigned int reg, unsigned int val) +{ + mcam_reg_write_mask(cam, reg, val, val); +} + +/* + * Functions for use by platform code. + */ +int mccic_register(struct mcam_camera *cam); +int mccic_irq(struct mcam_camera *cam, unsigned int irqs); +void mccic_shutdown(struct mcam_camera *cam); +#ifdef CONFIG_PM +void mccic_suspend(struct mcam_camera *cam); +int mccic_resume(struct mcam_camera *cam); +#endif + +/* + * Register definitions for the m88alp01 camera interface. Offsets in bytes + * as given in the spec. + */ +#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_GL_FCR 0x3038 /* GPIO functional control register */ +#define GFCR_GPIO_ON 0x08 /* Camera GPIO enabled */ +#define REG_GL_GPIOR 0x315c /* GPIO register */ +#define GGPIO_OUT 0x80000 /* GPIO output */ +#define GGPIO_VAL 0x00008 /* Output pin value */ + +#define REG_LEN (REG_GL_IMASK + 4) + + +/* + * Useful stuff that probably belongs somewhere global. + */ +#define VGA_WIDTH 640 +#define VGA_HEIGHT 480 -- cgit v1.2.2 From 2164b5af1dd42ebb7b5aa6bbcf9d9c3c067db246 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Sat, 11 Jun 2011 14:46:44 -0300 Subject: [media] marvell-cam: Pass sensor parameters from the platform Depending on the controller, the ov7670 sensor may be told to work with a different clock speed or to use the SMBUS protocol. Remove the wired-in code and pass that information from the platform layer. The Cafe driver now just assumes it's running on an OLPC XO 1; I do not believe it has ever run anywhere else. Cc: Daniel Drake Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/marvell-ccic/mcam-core.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/video/marvell-ccic/mcam-core.h') diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h index 0b55b8e6bb7..21485e7ec8f 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.h +++ b/drivers/media/video/marvell-ccic/mcam-core.h @@ -42,6 +42,8 @@ struct mcam_camera { spinlock_t dev_lock; struct device *dev; /* For messages, dma alloc */ unsigned int chip_id; + short int clock_speed; /* Sensor clock speed, default 30 */ + short int use_smbus; /* SMBUS or straight I2c? */ /* * Callbacks from the core to the platform code. -- cgit v1.2.2 From f8ff6a96cd6e9f7dc8b606f302129f99bcb82674 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Sat, 11 Jun 2011 14:46:46 -0300 Subject: [media] marvell-cam: Move Cafe-specific register definitions to cafe-driver.c Nobody else ever needs to see these, so let's hide them. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/marvell-ccic/mcam-core.h | 56 +--------------------------- 1 file changed, 1 insertion(+), 55 deletions(-) (limited to 'drivers/media/video/marvell-ccic/mcam-core.h') diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h index 21485e7ec8f..e8a7de05100 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.h +++ b/drivers/media/video/marvell-ccic/mcam-core.h @@ -249,63 +249,9 @@ int mccic_resume(struct mcam_camera *cam); #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 */ - - +/* This appears to be a Cafe-only register */ #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_GL_FCR 0x3038 /* GPIO functional control register */ -#define GFCR_GPIO_ON 0x08 /* Camera GPIO enabled */ -#define REG_GL_GPIOR 0x315c /* GPIO register */ -#define GGPIO_OUT 0x80000 /* GPIO output */ -#define GGPIO_VAL 0x00008 /* Output pin value */ - -#define REG_LEN (REG_GL_IMASK + 4) - - /* * Useful stuff that probably belongs somewhere global. */ -- cgit v1.2.2 From 595a93a47a3b7dc1be84160fbd73b1406074f411 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Sat, 11 Jun 2011 14:46:48 -0300 Subject: [media] marvell-cam: Allocate the i2c adapter in the platform driver The upcoming mmp-camera driver will need an i2c_adapter structure allocated externally, so change the core adapter to a pointer and require the platform code to fill it in. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/marvell-ccic/mcam-core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video/marvell-ccic/mcam-core.h') diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h index e8a7de05100..5effa820341 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.h +++ b/drivers/media/video/marvell-ccic/mcam-core.h @@ -37,7 +37,7 @@ struct mcam_camera { * These fields should be set by the platform code prior to * calling mcam_register(). */ - struct i2c_adapter i2c_adapter; + struct i2c_adapter *i2c_adapter; unsigned char __iomem *regs; spinlock_t dev_lock; struct device *dev; /* For messages, dma alloc */ -- cgit v1.2.2 From b5210fd2c737dd178ff0401a0050dc62148fed60 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Mon, 20 Jun 2011 16:14:36 -0300 Subject: [media] marvell-cam: convert to videobuf2 This is a basic, naive conversion to the videobuf2 infrastructure, removing a lot of code in the process. For now, we're using vmalloc, which is suboptimal, but it does match what the cafe driver did before. In the cafe case, it may have to stay that way just because memory is too tight to do direct streaming; mmp-camera will be able to do better. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/marvell-ccic/mcam-core.h | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers/media/video/marvell-ccic/mcam-core.h') diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h index 5effa820341..f40450cf72a 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.h +++ b/drivers/media/video/marvell-ccic/mcam-core.h @@ -3,6 +3,13 @@ * * Copyright 2011 Jonathan Corbet corbet@lwn.net */ +#ifndef _MCAM_CORE_H +#define _MCAM_CORE_H + +#include +#include +#include +#include /* * Tracking of streaming I/O buffers. @@ -20,8 +27,6 @@ enum mcam_state { S_NOTREADY, /* Not yet initialized */ S_IDLE, /* Just hanging around */ S_FLAKED, /* Some sort of problem */ - S_SINGLEREAD, /* In read() */ - S_SPECREAD, /* Speculative read (for future read()) */ S_STREAMING /* Streaming data */ }; #define MAX_DMA_BUFS 3 @@ -70,21 +75,19 @@ struct mcam_camera { struct list_head dev_list; /* link to other devices */ + /* Videobuf2 stuff */ + struct vb2_queue vb_queue; + struct list_head buffers; /* Available frames */ + /* DMA buffers */ unsigned int nbufs; /* How many are alloc'd */ int next_buf; /* Next to consume (dev_lock) */ unsigned int dma_buf_size; /* allocated size */ void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */ dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */ - unsigned int specframes; /* Unconsumed spec frames (dev_lock) */ unsigned int sequence; /* Frame sequence number */ - unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual buffers */ + unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */ - /* Streaming buffers */ - unsigned int n_sbufs; /* How many we have */ - struct mcam_sio_buffer *sb_bufs; /* The array of housekeeping structs */ - struct list_head sb_avail; /* Available for data (we own) (dev_lock) */ - struct list_head sb_full; /* With data (user space owns) (dev_lock) */ struct tasklet_struct s_tasklet; /* Current operating parameters */ @@ -94,9 +97,6 @@ struct mcam_camera { /* Locks */ struct mutex s_mutex; /* Access to this structure */ - - /* Misc */ - wait_queue_head_t iowait; /* Waiting on frame data */ }; @@ -257,3 +257,5 @@ int mccic_resume(struct mcam_camera *cam); */ #define VGA_WIDTH 640 #define VGA_HEIGHT 480 + +#endif /* _MCAM_CORE_H */ -- cgit v1.2.2 From a9b36e850782db853b9da050be9ed2050de51ad4 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Mon, 20 Jun 2011 16:14:40 -0300 Subject: [media] marvell-cam: implement contiguous DMA operation The core driver can now operate in either vmalloc or dma-contig modes; obviously the latter is preferable when it is supported. Default is currently vmalloc on all platforms; load the module with buffer_mode=1 for contiguous DMA mode. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/marvell-ccic/mcam-core.h | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers/media/video/marvell-ccic/mcam-core.h') diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h index f40450cf72a..2e667a05620 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.h +++ b/drivers/media/video/marvell-ccic/mcam-core.h @@ -27,10 +27,20 @@ enum mcam_state { S_NOTREADY, /* Not yet initialized */ S_IDLE, /* Just hanging around */ S_FLAKED, /* Some sort of problem */ - S_STREAMING /* Streaming data */ + S_STREAMING, /* Streaming data */ + S_BUFWAIT /* streaming requested but no buffers yet */ }; #define MAX_DMA_BUFS 3 +/* + * Different platforms work best with different buffer modes, so we + * let the platform pick. + */ +enum mcam_buffer_mode { + B_vmalloc = 0, + B_DMA_contig +}; + /* * A description of one of our devices. * Locking: controlled by s_mutex. Certain fields, however, require @@ -49,7 +59,7 @@ struct mcam_camera { unsigned int chip_id; short int clock_speed; /* Sensor clock speed, default 30 */ short int use_smbus; /* SMBUS or straight I2c? */ - + enum mcam_buffer_mode buffer_mode; /* * Callbacks from the core to the platform code. */ @@ -79,7 +89,7 @@ struct mcam_camera { struct vb2_queue vb_queue; struct list_head buffers; /* Available frames */ - /* DMA buffers */ + /* DMA buffers - vmalloc mode */ unsigned int nbufs; /* How many are alloc'd */ int next_buf; /* Next to consume (dev_lock) */ unsigned int dma_buf_size; /* allocated size */ @@ -88,6 +98,11 @@ struct mcam_camera { unsigned int sequence; /* Frame sequence number */ unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */ + /* DMA buffers - contiguous DMA mode */ + struct mcam_vb_buffer *vb_bufs[MAX_DMA_BUFS]; + struct vb2_alloc_ctx *vb_alloc_ctx; + unsigned short last_delivered; + struct tasklet_struct s_tasklet; /* Current operating parameters */ -- cgit v1.2.2 From cbc4f3a277ce52c217457ce08f433d8e9ad4925f Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Thu, 30 Jun 2011 17:05:27 -0300 Subject: [media] marvell-cam: Working s/g DMA The core Marvell camera driver can now do scatter/gather DMA on controllers which support that functionality. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/marvell-ccic/mcam-core.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/media/video/marvell-ccic/mcam-core.h') diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h index 2e667a05620..55fd07823ae 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.h +++ b/drivers/media/video/marvell-ccic/mcam-core.h @@ -38,7 +38,8 @@ enum mcam_state { */ enum mcam_buffer_mode { B_vmalloc = 0, - B_DMA_contig + B_DMA_contig, + B_DMA_sg }; /* @@ -250,8 +251,11 @@ int mccic_resume(struct mcam_camera *cam); #define C0_SIF_HVSYNC 0x00000000 /* Use H/VSYNC */ #define CO_SOF_NOSYNC 0x40000000 /* Use inband active signaling */ - +/* Bits below C1_444ALPHA are not present in Cafe */ #define REG_CTRL1 0x40 /* Control 1 */ +#define C1_CLKGATE 0x00000001 /* Sensor clock gate */ +#define C1_DESC_ENA 0x00000100 /* DMA descriptor enable */ +#define C1_DESC_3WORD 0x00000200 /* Three-word descriptors used */ #define C1_444ALPHA 0x00f00000 /* Alpha field in RGB444 */ #define C1_ALPHA_SHFT 20 #define C1_DMAB32 0x00000000 /* 32-byte DMA burst */ @@ -267,6 +271,14 @@ int mccic_resume(struct mcam_camera *cam); /* This appears to be a Cafe-only register */ #define REG_UBAR 0xc4 /* Upper base address register */ +/* Armada 610 DMA descriptor registers */ +#define REG_DMA_DESC_Y 0x200 +#define REG_DMA_DESC_U 0x204 +#define REG_DMA_DESC_V 0x208 +#define REG_DESC_LEN_Y 0x20c /* Lengths are in bytes */ +#define REG_DESC_LEN_U 0x210 +#define REG_DESC_LEN_V 0x214 + /* * Useful stuff that probably belongs somewhere global. */ -- cgit v1.2.2 From 983587c82189ac6c83fcd7a8914021f49098e473 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 8 Jul 2011 17:50:45 -0300 Subject: [media] marvell-cam: delete struct mcam_sio_buffer This structure got passed over in the videobuf2 conversion; it has no reason to exist now. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/marvell-ccic/mcam-core.h | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/media/video/marvell-ccic/mcam-core.h') diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h index 55fd07823ae..9a39e08b752 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.h +++ b/drivers/media/video/marvell-ccic/mcam-core.h @@ -11,17 +11,6 @@ #include #include -/* - * Tracking of streaming I/O buffers. - * FIXME doesn't belong in this file - */ -struct mcam_sio_buffer { - struct list_head list; - struct v4l2_buffer v4lbuf; - char *buffer; /* Where it lives in kernel space */ - int mapcount; - struct mcam_camera *cam; -}; enum mcam_state { S_NOTREADY, /* Not yet initialized */ -- cgit v1.2.2 From 7498469f619e1ba380fc90042a2b1736c7c6942c Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 8 Jul 2011 17:50:49 -0300 Subject: [media] marvell-cam: Allow selection of supported buffer modes The Marvell camera core can support all three videobuf2 buffer modes, which is slick, but it also requires that all three modes be built and present, even though only one is likely to be used. This patch allows the supported modes to be selected at configuration time, reducing the footprint of the driver. Prior to this patch, the MMP camera driver looked like this: mmp_camera 19092 0 videobuf2_core 15542 1 mmp_camera videobuf2_dma_sg 3173 1 mmp_camera videobuf2_dma_contig 2188 1 mmp_camera videobuf2_vmalloc 1718 1 mmp_camera videobuf2_memops 2100 3 videobuf2_dma_sg,videobuf2_dma_contig,videobuf2_vmalloc Afterward, instead, with scatter/gather only configured: mmp_camera 16021 0 videobuf2_core 15542 1 mmp_camera videobuf2_dma_sg 3173 1 mmp_camera videobuf2_memops 2100 1 videobuf2_dma_sg The total goes from 43,813 bytes to 36,836. The emphasis has been on simplicity and minimal #ifdef use rather than on squeezing out every possible byte of code. For configuration, the driver simply looks at which videobuf2 modes have been configured in and supports them all; it's simplistic but should be good enough. The cafe driver is set to support vmalloc and dma-contig; mmp supports only dma-sg, since that's the only mode that really makes sense to use. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/marvell-ccic/mcam-core.h | 59 +++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 5 deletions(-) (limited to 'drivers/media/video/marvell-ccic/mcam-core.h') diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h index 9a39e08b752..aa552553723 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.h +++ b/drivers/media/video/marvell-ccic/mcam-core.h @@ -11,6 +11,27 @@ #include #include +/* + * Create our own symbols for the supported buffer modes, but, for now, + * base them entirely on which videobuf2 options have been selected. + */ +#if defined(CONFIG_VIDEOBUF2_VMALLOC) || defined(CONFIG_VIDEOBUF2_VMALLOC_MODULE) +#define MCAM_MODE_VMALLOC 1 +#endif + +#if defined(CONFIG_VIDEOBUF2_DMA_CONTIG) || defined(CONFIG_VIDEOBUF2_DMA_CONTIG_MODULE) +#define MCAM_MODE_DMA_CONTIG 1 +#endif + +#if defined(CONFIG_VIDEOBUF2_DMA_SG) || defined(CONFIG_VIDEOBUF2_DMA_SG_MODULE) +#define MCAM_MODE_DMA_SG 1 +#endif + +#if !defined(MCAM_MODE_VMALLOC) && !defined(MCAM_MODE_DMA_CONTIG) && \ + !defined(MCAM_MODE_DMA_SG) +#error One of the videobuf buffer modes must be selected in the config +#endif + enum mcam_state { S_NOTREADY, /* Not yet initialized */ @@ -27,10 +48,32 @@ enum mcam_state { */ enum mcam_buffer_mode { B_vmalloc = 0, - B_DMA_contig, - B_DMA_sg + B_DMA_contig = 1, + B_DMA_sg = 2 }; +/* + * Is a given buffer mode supported by the current kernel configuration? + */ +static inline int mcam_buffer_mode_supported(enum mcam_buffer_mode mode) +{ + switch (mode) { +#ifdef MCAM_MODE_VMALLOC + case B_vmalloc: +#endif +#ifdef MCAM_MODE_DMA_CONTIG + case B_DMA_contig: +#endif +#ifdef MCAM_MODE_DMA_SG + case B_DMA_sg: +#endif + return 1; + default: + return 0; + } +} + + /* * A description of one of our devices. * Locking: controlled by s_mutex. Certain fields, however, require @@ -79,21 +122,27 @@ struct mcam_camera { struct vb2_queue vb_queue; struct list_head buffers; /* Available frames */ - /* DMA buffers - vmalloc mode */ unsigned int nbufs; /* How many are alloc'd */ int next_buf; /* Next to consume (dev_lock) */ + + /* DMA buffers - vmalloc mode */ +#ifdef MCAM_MODE_VMALLOC unsigned int dma_buf_size; /* allocated size */ void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */ dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */ + struct tasklet_struct s_tasklet; +#endif unsigned int sequence; /* Frame sequence number */ unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */ - /* DMA buffers - contiguous DMA mode */ + /* DMA buffers - DMA modes */ struct mcam_vb_buffer *vb_bufs[MAX_DMA_BUFS]; struct vb2_alloc_ctx *vb_alloc_ctx; unsigned short last_delivered; - struct tasklet_struct s_tasklet; + /* Mode-specific ops, set at open time */ + void (*dma_setup)(struct mcam_camera *cam); + void (*frame_complete)(struct mcam_camera *cam, int frame); /* Current operating parameters */ u32 sensor_type; /* Currently ov7670 only */ -- cgit v1.2.2 From 9f26392a6afbb8ecf9d19037f137162142c8f04b Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 8 Jul 2011 17:50:50 -0300 Subject: [media] marvell-cam: clean up a couple of unused cam structure fields Delete a couple of leftover fields whose time has passed. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/marvell-ccic/mcam-core.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/media/video/marvell-ccic/mcam-core.h') diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h index aa552553723..917200e6325 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.h +++ b/drivers/media/video/marvell-ccic/mcam-core.h @@ -116,8 +116,6 @@ struct mcam_camera { struct v4l2_subdev *sensor; unsigned short sensor_addr; - struct list_head dev_list; /* link to other devices */ - /* Videobuf2 stuff */ struct vb2_queue vb_queue; struct list_head buffers; /* Available frames */ @@ -138,7 +136,6 @@ struct mcam_camera { /* DMA buffers - DMA modes */ struct mcam_vb_buffer *vb_bufs[MAX_DMA_BUFS]; struct vb2_alloc_ctx *vb_alloc_ctx; - unsigned short last_delivered; /* Mode-specific ops, set at open time */ void (*dma_setup)(struct mcam_camera *cam); -- cgit v1.2.2