From: Guennadi Liakhovetski <lg@xxxxxxx> The driver has been tested on a pcm037 test-board from Phycore. The driver uses a coherent memory buffer, because although i.MX31 supports video to scatter-gather lists, it can only pack an integer number of rows in an sg-buffer, which makes it useless with fixed size sg-elements, and videobuf-dma-sg.c uses fixed page-sized buffers. Signed-off-by: Guennadi Liakhovetski <lg@xxxxxxx> --- This one will have to be updated for new-style pin-configuration macros, etc. Just for the ease of testing here. arch/arm/mach-mx3/devices.c | 56 +++++++++++++++++++++++++++ arch/arm/mach-mx3/pcm037.c | 46 ++++++++++++++++++++++ arch/arm/plat-mxc/include/mach/mx3_camera.h | 2 + 3 files changed, 104 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index 1138a61..e03b127 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c @@ -28,6 +28,7 @@ #include <mach/iomux-mx3.h> #include <mach/ipu.h> #include <mach/mx3fb.h> +#include <mach/mx3_camera.h> static struct resource uart0[] = { { @@ -229,6 +230,61 @@ int __init mx3_register_fb(const char *name, const struct fb_videomode *modes, return platform_device_register(&mx3_fb); } +struct mx3_camera_pdata camera_pdata = { + .dma_dev = &mx3_ipu.dev, +}; + +static struct resource camera_resources[] = { + { + .start = IPU_CTRL_BASE_ADDR + 0x60, + .end = IPU_CTRL_BASE_ADDR + 0x87, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device mx3_camera = { + .name = "mx3-camera", + .id = 0, + .num_resources = ARRAY_SIZE(camera_resources), + .resource = camera_resources, + .dev = { + .platform_data = &camera_pdata, + .coherent_dma_mask = DMA_32BIT_MASK, + }, +}; + +int __init mx3_register_camera(size_t buf_size, unsigned long flags, + unsigned long mclk_freq_10khz) +{ + dma_addr_t dma_handle; + void *buf; + + if (!ipu_registered) { + int ret = platform_device_register(&mx3_ipu); + if (ret < 0) + return ret; + ipu_registered = true; + } + + buf = dma_alloc_coherent(NULL, buf_size, &dma_handle, + GFP_KERNEL); + if (!buf) { + pr_err("%s: cannot allocate camera buffer-memory\n", __func__); + return -ENOMEM; + } + + memset(buf, 0, buf_size); + + dma_declare_coherent_memory(&mx3_camera.dev, + dma_handle, dma_handle, buf_size, + DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE); + + camera_pdata.flags = flags; + camera_pdata.mclk_10khz = mclk_freq_10khz; + + return platform_device_register(&mx3_camera); +} + /* Resource definition for the I2C1 */ static struct resource mxci2c1_resources[] = { [0] = { diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c index 12e4d68..4678407 100644 --- a/arch/arm/mach-mx3/pcm037.c +++ b/arch/arm/mach-mx3/pcm037.c @@ -42,6 +42,7 @@ #include <mach/iomux-mx3.h> #include <mach/board-pcm037.h> #include <mach/mx3fb.h> +#include <mach/mx3_camera.h> #include "devices.h" @@ -132,6 +133,12 @@ static struct i2c_board_info __initdata pcm037_i2c_devices[] = { }, }; +/* + * Try to reserve buffer space enough for 8 buffers 320x240@1 for + * streaming plus 2 buffers 2048x1536@1 for still image < 10MB + */ +#define PCM037_CAMERA_MEM_SIZE (4 * 1024 * 1024) + static struct platform_device *devices[] __initdata = { &pcm037_flash, &pcm037_eth, @@ -163,6 +170,8 @@ static const struct fb_videomode fb_modedb[] = { */ static void __init mxc_board_init(void) { + int ret; + platform_add_devices(devices, ARRAY_SIZE(devices)); mxc_iomux_mode(MX31_PIN_CTS1__CTS1); @@ -218,6 +227,43 @@ static void __init mxc_board_init(void) mxc_iomux_mode(IOMUX_MODE(MX31_PIN_D3_CLS, IOMUX_CONFIG_FUNC)); mx3_register_fb(fb_modedb[0].name, fb_modedb, ARRAY_SIZE(fb_modedb)); + + /* CSI */ + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_D6, IOMUX_CONFIG_FUNC)); + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_D7, IOMUX_CONFIG_FUNC)); + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_D8, IOMUX_CONFIG_FUNC)); + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_D9, IOMUX_CONFIG_FUNC)); + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_D10, IOMUX_CONFIG_FUNC)); + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_D11, IOMUX_CONFIG_FUNC)); + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_D12, IOMUX_CONFIG_FUNC)); + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_D13, IOMUX_CONFIG_FUNC)); + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_D14, IOMUX_CONFIG_FUNC)); + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_D15, IOMUX_CONFIG_FUNC)); + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_HSYNC, IOMUX_CONFIG_FUNC)); + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_MCLK, IOMUX_CONFIG_FUNC)); + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_PIXCLK, IOMUX_CONFIG_FUNC)); + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_VSYNC, IOMUX_CONFIG_FUNC)); + + /* ATA power off, disable ATA Buffer, enable CSI buffer */ + ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_CSI_D4), "CSI D4"); + if (!ret) { + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_D4, IOMUX_CONFIG_GPIO)); + gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CSI_D4), 0); + } else + printk(KERN_WARNING "Could not get GPIO %u\n", + IOMUX_TO_GPIO(MX31_PIN_CSI_D4)); + + ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), "CSI D5"); + if (!ret) { + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_GPIO)); + gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), 1); + } else + printk(KERN_WARNING "Could not get GPIO %u\n", + IOMUX_TO_GPIO(MX31_PIN_CSI_D5)); + + mx3_register_camera(PCM037_CAMERA_MEM_SIZE, + MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10, + 2000); } /* diff --git a/arch/arm/plat-mxc/include/mach/mx3_camera.h b/arch/arm/plat-mxc/include/mach/mx3_camera.h index 36d7ff2..eddbdc0 100644 --- a/arch/arm/plat-mxc/include/mach/mx3_camera.h +++ b/arch/arm/plat-mxc/include/mach/mx3_camera.h @@ -49,4 +49,6 @@ struct mx3_camera_pdata { struct device *dma_dev; }; +extern int mx3_register_camera(size_t, unsigned long, unsigned long); + #endif -- 1.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html