[PATCH 5/6] mx31moboard: camera support
From: Valentin Longchamp <hidden>
Date: 2009-10-28 14:36:19
Hi Guennadi, Thanks for your input about the patch. I haven't had time to answer you before. Guennadi Liakhovetski wrote:
Hi Val below are some comments to the patch, I'll also reply to your /dev/video* question in a separate mail.
I answered you in a separate email too.
On Thu, 15 Oct 2009, Valentin Longchamp wrote:quoted
We have two mt9t031 cameras that have a muxed bus on the robot. We can control which one we are using with gpio outputs. This currently is not optimal Signed-off-by: Valentin Longchamp <redacted> --- arch/arm/mach-mx3/mx31moboard-marxbot.c | 78 ++++++++++++++++++++++++++++++- arch/arm/mach-mx3/mx31moboard.c | 37 ++++++++++++++- 2 files changed, 113 insertions(+), 2 deletions(-)diff --git a/arch/arm/mach-mx3/mx31moboard-marxbot.c b/arch/arm/mach-mx3/mx31moboard-marxbot.c index 49d47ab..303cbdb 100644 --- a/arch/arm/mach-mx3/mx31moboard-marxbot.c +++ b/arch/arm/mach-mx3/mx31moboard-marxbot.c@@ -16,9 +16,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/delay.h> #include <linux/gpio.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/types.h>@@ -28,6 +30,8 @@ #include <mach/iomux-mx3.h> #include <mach/mmc.h> +#include <media/soc_camera.h> + #include "devices.h" static unsigned int marxbot_pins[] = {@@ -37,7 +41,6 @@ static unsigned int marxbot_pins[] = { MX31_PIN_PC_CD2_B__SD2_CLK, MX31_PIN_PC_CD1_B__SD2_CMD, MX31_PIN_ATA_DIOR__GPIO3_28, MX31_PIN_ATA_DIOW__GPIO3_29, /* CSI */ - MX31_PIN_CSI_D4__CSI_D4, MX31_PIN_CSI_D5__CSI_D5, MX31_PIN_CSI_D6__CSI_D6, MX31_PIN_CSI_D7__CSI_D7, MX31_PIN_CSI_D8__CSI_D8, MX31_PIN_CSI_D9__CSI_D9, MX31_PIN_CSI_D10__CSI_D10, MX31_PIN_CSI_D11__CSI_D11,@@ -45,6 +48,7 @@ static unsigned int marxbot_pins[] = { MX31_PIN_CSI_D14__CSI_D14, MX31_PIN_CSI_D15__CSI_D15, MX31_PIN_CSI_HSYNC__CSI_HSYNC, MX31_PIN_CSI_MCLK__CSI_MCLK, MX31_PIN_CSI_PIXCLK__CSI_PIXCLK, MX31_PIN_CSI_VSYNC__CSI_VSYNC, + MX31_PIN_CSI_D4__GPIO3_4, MX31_PIN_CSI_D5__GPIO3_5, MX31_PIN_GPIO3_0__GPIO3_0, MX31_PIN_GPIO3_1__GPIO3_1, MX31_PIN_TXD2__GPIO1_28, /* dsPIC resets */@@ -122,6 +126,78 @@ static void dspics_resets_init(void) } } +#define TURRETCAM_POWER IOMUX_TO_GPIO(MX31_PIN_GPIO3_1) +#define BASECAM_POWER IOMUX_TO_GPIO(MX31_PIN_CSI_D5) +#define TURRETCAM_RST_B IOMUX_TO_GPIO(MX31_PIN_GPIO3_0) +#define BASECAM_RST_B IOMUX_TO_GPIO(MX31_PIN_CSI_D4) +#define CAM_CHOICE IOMUX_TO_GPIO(MX31_PIN_TXD2) + +static int marxbot_cam_power(struct device *dev, int on) +{ + gpio_set_value(BASECAM_POWER, !on); + return 0; +} + +static int marxbot_cam_reset(struct device *dev) +{ + gpio_set_value(BASECAM_RST_B, 0); + udelay(100); + gpio_set_value(BASECAM_RST_B, 1); + return 0; +} + +static struct i2c_board_info marxbot_i2c_devices[] = { + { + I2C_BOARD_INFO("mt9t031", 0x5d), + }, +}; + +static struct soc_camera_link iclink = { + .bus_id = 0, /* Must match with the camera ID */ + .power = marxbot_cam_power, + .reset = marxbot_cam_reset, + .board_info = &marxbot_i2c_devices[0], + .i2c_adapter_id = 0, + .module_name = "mt9t031", +}; + +static struct platform_device marxbot_camera = { + .name = "soc-camera-pdrv", + .id = 0, + .dev = { + .platform_data = &iclink, + }, +}; + +static int __init marxbot_cam_init(void) +{ + int ret = gpio_request(CAM_CHOICE, "cam-choice"); + if (ret) + return ret; + gpio_direction_output(CAM_CHOICE, 1); + gpio_export(CAM_CHOICE, false);Why are exporting this and two more gpios below? Does this allow you to switch cameras from the user-space? Even if so, I wouldn't push this upstream, as you won't need this in the future, when you add proper support for the second camera into the kernel.
Yeah, the purpose of this is to allow to switch camera from userspace. But you are maybe right, I should not push the export to upstream but keep it in a local patch while waiting for a solution to switch in the kernel. The other gpios below would not be exported anyomore but used by the second _client_ video platform_device (and should disappear in the next version of the patch).
quoted
+ ret = gpio_request(BASECAM_RST_B, "basecam-reset"); + if (ret) + return ret; + gpio_direction_output(BASECAM_RST_B, 1); + ret = gpio_request(BASECAM_POWER, "basecam-standby"); + if (ret) + return ret; + gpio_direction_output(BASECAM_POWER, 0); + + /*temporary part: we must use the mux better*/Please, add spaces around text in comment.quoted
+ gpio_request(TURRETCAM_RST_B, "turretcam-reset"); + gpio_direction_output(TURRETCAM_RST_B, 1); + gpio_export(TURRETCAM_RST_B, false); + + gpio_request(TURRETCAM_POWER, "turretcam-standby"); + gpio_direction_output(TURRETCAM_POWER, 0); + gpio_export(TURRETCAM_POWER, false); + + return platform_device_register(&marxbot_camera); +} + + /* * system init for baseboard usage. Will be called by mx31moboard init. */diff --git a/arch/arm/mach-mx3/mx31moboard.c b/arch/arm/mach-mx3/mx31moboard.c index 706a993..605c0fa 100644 --- a/arch/arm/mach-mx3/mx31moboard.c +++ b/arch/arm/mach-mx3/mx31moboard.c@@ -40,7 +40,7 @@ #include <mach/ipu.h> #include <mach/i2c.h> #include <mach/mmc.h> -#include <mach/mx31.h> +#include <mach/mx3_camera.h>Need #include <linux/dma-mapping.h> for DMA_MEMORY_MAP and DMA_MEMORY_EXCLUSIVE macros, etc.
correct. It must have been melted in another patch, I have to revise the patch stack.
quoted
#include "devices.h"@@ -287,6 +287,39 @@ static struct platform_device *devices[] __initdata = { &mx31moboard_leds_device, }; +static struct mx3_camera_pdata camera_pdata = { + .dma_dev = &mx3_ipu.dev, + .flags = MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10, + .mclk_10khz = 4800, +}; + +#define CAMERA_BUF_SIZE (4*1024*1024) + +static int __init mx31moboard_cam_alloc_dma(const size_t buf_size) +{ + dma_addr_t dma_handle; + void *buf; + int dma; + + if (buf_size < 2 * 1024 * 1024) + return -EINVAL; + + 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 = dma_declare_coherent_memory(&mx3_camera.dev, + dma_handle, dma_handle, buf_size, + DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE); + + /* The way we call dma_declare_coherent_memory only a malloc can fail */ + return dma & DMA_MEMORY_MAP ? 0 : -ENOMEM; +} + static int mx31moboard_baseboard; core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444);@@ -312,6 +345,8 @@ static void __init mxc_board_init(void) mxc_register_device(&mxcsdhc_device0, &sdhc1_pdata); mxc_register_device(&mx3_ipu, &mx3_ipu_data); + if (!mx31moboard_cam_alloc_dma(CAMERA_BUF_SIZE)) + mxc_register_device(&mx3_camera, &camera_pdata); usb_xcvr_reset();--
Thanks Val -- Valentin Longchamp, PhD Student, EPFL-STI-LSRO1 valentin.longchamp at epfl.ch, Phone: +41216937827 http://people.epfl.ch/valentin.longchamp MEA3485, Station 9, CH-1015 Lausanne