[PATCH 4/4] mx31_3ds: Add support for the camera device on the personality board
Uwe Kleine-König
u.kleine-koenig at pengutronix.de
Tue Mar 8 14:59:46 EST 2011
Hello Alberto,
On Sun, Mar 06, 2011 at 04:41:41PM +0100, Alberto Panizzo wrote:
> Signed-off-by: Alberto Panizzo <alberto at amarulasolutions.com>
> ---
> arch/arm/mach-mx3/mach-mx31_3ds.c | 157 +++++++++++++++++++++++++++++++++++++
> 1 files changed, 157 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c
> index de250cb..9ea2c2c 100644
> --- a/arch/arm/mach-mx3/mach-mx31_3ds.c
> +++ b/arch/arm/mach-mx3/mach-mx31_3ds.c
> @@ -25,6 +25,9 @@
> #include <linux/regulator/machine.h>
> #include <linux/usb/otg.h>
> #include <linux/usb/ulpi.h>
> +#include <linux/memblock.h>
> +
> +#include <media/soc_camera.h>
>
> #include <mach/hardware.h>
> #include <asm/mach-types.h>
> @@ -39,6 +42,7 @@
> #include <mach/mmc.h>
> #include <mach/ipu.h>
> #include <mach/mx3fb.h>
> +#include <mach/mx3_camera.h>
>
> #include "devices-imx31.h"
> #include "devices.h"
> @@ -141,6 +145,98 @@ static int mx31_3ds_pins[] = {
> MX31_PIN_HSYNC__HSYNC,
> MX31_PIN_FPSHIFT__FPSHIFT,
> MX31_PIN_CONTRAST__CONTRAST,
> + /* CSI */
> + 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,
> + MX31_PIN_CSI_D12__CSI_D12,
> + MX31_PIN_CSI_D13__CSI_D13,
> + 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_D5__GPIO3_5, /* CMOS PWDN */
> + IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_GPIO), /* CMOS reset */
> +};
> +
> +/*
> + * Camera support
> + */
> +static phys_addr_t mx3_camera_base __initdata;
> +#define MX3_CAMERA_BUF_SIZE SZ_8M
> +
> +static int __init mx31_3ds_camera_alloc_dma(void)
> +{
> + int dma;
> +
> + if (!mx3_camera_base)
> + return -ENOMEM;
> +
> + dma = dma_declare_coherent_memory(&mx3_camera.dev,
> + mx3_camera_base, mx3_camera_base,
> + MX3_CAMERA_BUF_SIZE,
> + DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
This conflicts with the series I sent end of last week. Sascha didn't
comment yet.
> +
> + if (!(dma & DMA_MEMORY_MAP))
> + return -ENOMEM;
> +
> + return 0;
> +}
> +
> +static int mx31_3ds_camera_power(struct device *dev, int on)
> +{
> + /* enable or disable the camera */
> + pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE");
> + gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), on ? 0 : 1);
> +
> + if (!on)
> + goto out;
> +
> + /* If enabled, give a reset impulse */
> + gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_RI_DTE1), 0);
> + msleep(20);
> + gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_RI_DTE1), 1);
> + msleep(100);
> +
> +out:
> + return 0;
> +}
> +
> +static struct i2c_board_info mx31_3ds_i2c_camera = {
> + I2C_BOARD_INFO("ov2640", 0x30),
> +};
> +
> +static struct regulator_bulk_data mx31_3ds_camera_regs[] = {
> + { .supply = "cmos_vcore" },
> + { .supply = "cmos_2v8" },
> +};
> +
> +static struct soc_camera_link iclink_ov2640 = {
> + .bus_id = 0,
> + .board_info = &mx31_3ds_i2c_camera,
> + .i2c_adapter_id = 0,
> + .power = mx31_3ds_camera_power,
> + .regulators = mx31_3ds_camera_regs,
> + .num_regulators = ARRAY_SIZE(mx31_3ds_camera_regs),
> +};
> +
> +static struct platform_device mx31_3ds_ov2640 = {
> + .name = "soc-camera-pdrv",
> + .id = 0,
> + .dev = {
> + .platform_data = &iclink_ov2640,
> + },
> +};
for a few extra points you could dynamically allocate this device.
> +
> +struct mx3_camera_pdata mx31_3ds_camera_pdata = {
> + .dma_dev = &mx3_ipu.dev,
> + .flags = MX3_CAMERA_DATAWIDTH_10,
> + .mclk_10khz = 2600,
> };
>
> /*
> @@ -320,6 +416,7 @@ static struct regulator_init_data vmmc2_init = {
>
> static struct regulator_consumer_supply vmmc1_consumers[] = {
> REGULATOR_SUPPLY("lcd_2v8", NULL),
> + REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"),
> };
>
> static struct regulator_init_data vmmc1_init = {
> @@ -350,6 +447,22 @@ static struct regulator_init_data vgen_init = {
> .consumer_supplies = vgen_consumers,
> };
>
> +static struct regulator_consumer_supply vvib_consumers[] = {
> + REGULATOR_SUPPLY("cmos_vcore", "soc-camera-pdrv.0"),
> +};
> +
> +static struct regulator_init_data vvib_init = {
> + .constraints = {
> + .min_uV = 1300000,
> + .max_uV = 1300000,
> + .apply_uV = 1,
> + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
> + REGULATOR_CHANGE_STATUS,
> + },
> + .num_consumer_supplies = ARRAY_SIZE(vvib_consumers),
> + .consumer_supplies = vvib_consumers,
> +};
> +
> static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = {
> {
> .id = MC13783_REG_PWGT1SPI, /* Power Gate for ARM core. */
> @@ -373,6 +486,9 @@ static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = {
> }, {
> .id = MC13783_REG_VGEN, /* Power LCD */
> .init_data = &vgen_init,
> + }, {
> + .id = MC13783_REG_VVIB, /* Power CMOS */
> + .init_data = &vvib_init,
> },
> };
>
> @@ -565,8 +681,14 @@ static const struct imxi2c_platform_data mx31_3ds_i2c0_data __initconst = {
> .bitrate = 100000,
> };
>
> +static struct platform_device *devices[] __initdata = {
> + &mx31_3ds_ov2640,
> +};
> +
> static void __init mx31_3ds_init(void)
> {
> + int ret;
> +
> mxc_iomux_setup_multiple_pins(mx31_3ds_pins, ARRAY_SIZE(mx31_3ds_pins),
> "mx31_3ds");
>
> @@ -577,6 +699,8 @@ static void __init mx31_3ds_init(void)
> spi_register_board_info(mx31_3ds_spi_devs,
> ARRAY_SIZE(mx31_3ds_spi_devs));
>
> + platform_add_devices(devices, ARRAY_SIZE(devices));
> +
> imx31_add_imx_keypad(&mx31_3ds_keymap_data);
>
> mx31_3ds_usbotg_init();
> @@ -604,6 +728,29 @@ static void __init mx31_3ds_init(void)
> imx31_add_spi_imx0(&spi0_pdata);
> mxc_register_device(&mx3_ipu, &mx3_ipu_data);
> mxc_register_device(&mx3_fb, &mx3fb_pdata);
> +
> + /* CSI */
> + /* Camera power: default - off */
> + ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_CSI_D5),
> + "camera-power");
> + if (!ret) {
> + gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), 1);
> + } else {
> + pr_err("Failed to request the camera-power gpio");
> + iclink_ov2640.power = NULL;
> + }
> +
> + ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_RI_DTE1),
> + "camera-reset");
> + if (!ret)
> + gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_RI_DTE1), 1);
> + else
> + pr_err("Failed to request the camera-reset gpio");
> +
> + if (!mx31_3ds_camera_alloc_dma())
> + mxc_register_device(&mx3_camera, &mx31_3ds_camera_pdata);
> + else
> + pr_err("Failed to allocate dma memory for camera");
Do you really want to continue registering the camera if the
gpio_request above failed?
> }
>
> static void __init mx31_3ds_timer_init(void)
> @@ -615,6 +762,15 @@ static struct sys_timer mx31_3ds_timer = {
> .init = mx31_3ds_timer_init,
> };
>
> +static void __init mx31_3ds_reserve(void)
> +{
> + /* reserve MX3_CAMERA_BUF_SIZE bytes for mx3-camera */
> + mx3_camera_base = memblock_alloc(MX3_CAMERA_BUF_SIZE,
> + MX3_CAMERA_BUF_SIZE);
> + memblock_free(mx3_camera_base, MX3_CAMERA_BUF_SIZE);
> + memblock_remove(mx3_camera_base, MX3_CAMERA_BUF_SIZE);
> +}
> +
> MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
> /* Maintainer: Freescale Semiconductor, Inc. */
> .boot_params = MX3x_PHYS_OFFSET + 0x100,
> @@ -623,4 +779,5 @@ MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
> .init_irq = mx31_init_irq,
> .timer = &mx31_3ds_timer,
> .init_machine = mx31_3ds_init,
> + .reserve = mx31_3ds_reserve,
> MACHINE_END
Russell wants a different ordering here, see
http://article.gmane.org/gmane.linux.ports.arm.omap/50721/match=russell+init_early+reserve+map_io
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
More information about the linux-arm-kernel
mailing list