diff options
author | Alberto Panizzo <alberto@amarulasolutions.com> | 2011-03-07 05:47:37 -0500 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2011-03-08 07:24:22 -0500 |
commit | 164f7b5237cca2701dd2943928ec8d078877a28d (patch) | |
tree | 7f0330eef457ec7d2c90f6182f3214029a5d37aa /arch/arm/mach-mx3 | |
parent | e42010e0e129cc31a83ce9d8d1c7e1d50ba155f3 (diff) |
mach-mx31_3ds: Add support for the camera device on the personality board
Signed-off-by: Alberto Panizzo <alberto@amarulasolutions.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/mach-mx3')
-rw-r--r-- | arch/arm/mach-mx3/mach-mx31_3ds.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c index d760a06c9e3c..544d3e414f58 100644 --- a/arch/arm/mach-mx3/mach-mx31_3ds.c +++ b/arch/arm/mach-mx3/mach-mx31_3ds.c | |||
@@ -25,6 +25,9 @@ | |||
25 | #include <linux/regulator/machine.h> | 25 | #include <linux/regulator/machine.h> |
26 | #include <linux/usb/otg.h> | 26 | #include <linux/usb/otg.h> |
27 | #include <linux/usb/ulpi.h> | 27 | #include <linux/usb/ulpi.h> |
28 | #include <linux/memblock.h> | ||
29 | |||
30 | #include <media/soc_camera.h> | ||
28 | 31 | ||
29 | #include <mach/hardware.h> | 32 | #include <mach/hardware.h> |
30 | #include <asm/mach-types.h> | 33 | #include <asm/mach-types.h> |
@@ -39,6 +42,7 @@ | |||
39 | #include <mach/mmc.h> | 42 | #include <mach/mmc.h> |
40 | #include <mach/ipu.h> | 43 | #include <mach/ipu.h> |
41 | #include <mach/mx3fb.h> | 44 | #include <mach/mx3fb.h> |
45 | #include <mach/mx3_camera.h> | ||
42 | 46 | ||
43 | #include "devices-imx31.h" | 47 | #include "devices-imx31.h" |
44 | #include "devices.h" | 48 | #include "devices.h" |
@@ -141,6 +145,106 @@ static int mx31_3ds_pins[] = { | |||
141 | MX31_PIN_HSYNC__HSYNC, | 145 | MX31_PIN_HSYNC__HSYNC, |
142 | MX31_PIN_FPSHIFT__FPSHIFT, | 146 | MX31_PIN_FPSHIFT__FPSHIFT, |
143 | MX31_PIN_CONTRAST__CONTRAST, | 147 | MX31_PIN_CONTRAST__CONTRAST, |
148 | /* CSI */ | ||
149 | MX31_PIN_CSI_D6__CSI_D6, | ||
150 | MX31_PIN_CSI_D7__CSI_D7, | ||
151 | MX31_PIN_CSI_D8__CSI_D8, | ||
152 | MX31_PIN_CSI_D9__CSI_D9, | ||
153 | MX31_PIN_CSI_D10__CSI_D10, | ||
154 | MX31_PIN_CSI_D11__CSI_D11, | ||
155 | MX31_PIN_CSI_D12__CSI_D12, | ||
156 | MX31_PIN_CSI_D13__CSI_D13, | ||
157 | MX31_PIN_CSI_D14__CSI_D14, | ||
158 | MX31_PIN_CSI_D15__CSI_D15, | ||
159 | MX31_PIN_CSI_HSYNC__CSI_HSYNC, | ||
160 | MX31_PIN_CSI_MCLK__CSI_MCLK, | ||
161 | MX31_PIN_CSI_PIXCLK__CSI_PIXCLK, | ||
162 | MX31_PIN_CSI_VSYNC__CSI_VSYNC, | ||
163 | MX31_PIN_CSI_D5__GPIO3_5, /* CMOS PWDN */ | ||
164 | IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_GPIO), /* CMOS reset */ | ||
165 | }; | ||
166 | |||
167 | /* | ||
168 | * Camera support | ||
169 | */ | ||
170 | static phys_addr_t mx3_camera_base __initdata; | ||
171 | #define MX31_3DS_CAMERA_BUF_SIZE SZ_8M | ||
172 | |||
173 | #define MX31_3DS_GPIO_CAMERA_PW IOMUX_TO_GPIO(MX31_PIN_CSI_D5) | ||
174 | #define MX31_3DS_GPIO_CAMERA_RST IOMUX_TO_GPIO(MX31_PIN_RI_DTE1) | ||
175 | |||
176 | static struct gpio mx31_3ds_camera_gpios[] = { | ||
177 | { MX31_3DS_GPIO_CAMERA_PW, GPIOF_OUT_INIT_HIGH, "camera-power" }, | ||
178 | { MX31_3DS_GPIO_CAMERA_RST, GPIOF_OUT_INIT_HIGH, "camera-reset" }, | ||
179 | }; | ||
180 | |||
181 | static int __init mx31_3ds_camera_alloc_dma(void) | ||
182 | { | ||
183 | int dma; | ||
184 | |||
185 | if (!mx3_camera_base) | ||
186 | return -ENOMEM; | ||
187 | |||
188 | dma = dma_declare_coherent_memory(&mx3_camera.dev, | ||
189 | mx3_camera_base, mx3_camera_base, | ||
190 | MX31_3DS_CAMERA_BUF_SIZE, | ||
191 | DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE); | ||
192 | |||
193 | if (!(dma & DMA_MEMORY_MAP)) | ||
194 | return -ENOMEM; | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static int mx31_3ds_camera_power(struct device *dev, int on) | ||
200 | { | ||
201 | /* enable or disable the camera */ | ||
202 | pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE"); | ||
203 | gpio_set_value(MX31_3DS_GPIO_CAMERA_PW, on ? 0 : 1); | ||
204 | |||
205 | if (!on) | ||
206 | goto out; | ||
207 | |||
208 | /* If enabled, give a reset impulse */ | ||
209 | gpio_set_value(MX31_3DS_GPIO_CAMERA_RST, 0); | ||
210 | msleep(20); | ||
211 | gpio_set_value(MX31_3DS_GPIO_CAMERA_RST, 1); | ||
212 | msleep(100); | ||
213 | |||
214 | out: | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static struct i2c_board_info mx31_3ds_i2c_camera = { | ||
219 | I2C_BOARD_INFO("ov2640", 0x30), | ||
220 | }; | ||
221 | |||
222 | static struct regulator_bulk_data mx31_3ds_camera_regs[] = { | ||
223 | { .supply = "cmos_vcore" }, | ||
224 | { .supply = "cmos_2v8" }, | ||
225 | }; | ||
226 | |||
227 | static struct soc_camera_link iclink_ov2640 = { | ||
228 | .bus_id = 0, | ||
229 | .board_info = &mx31_3ds_i2c_camera, | ||
230 | .i2c_adapter_id = 0, | ||
231 | .power = mx31_3ds_camera_power, | ||
232 | .regulators = mx31_3ds_camera_regs, | ||
233 | .num_regulators = ARRAY_SIZE(mx31_3ds_camera_regs), | ||
234 | }; | ||
235 | |||
236 | static struct platform_device mx31_3ds_ov2640 = { | ||
237 | .name = "soc-camera-pdrv", | ||
238 | .id = 0, | ||
239 | .dev = { | ||
240 | .platform_data = &iclink_ov2640, | ||
241 | }, | ||
242 | }; | ||
243 | |||
244 | struct mx3_camera_pdata mx31_3ds_camera_pdata = { | ||
245 | .dma_dev = &mx3_ipu.dev, | ||
246 | .flags = MX3_CAMERA_DATAWIDTH_10, | ||
247 | .mclk_10khz = 2600, | ||
144 | }; | 248 | }; |
145 | 249 | ||
146 | /* | 250 | /* |
@@ -307,6 +411,7 @@ static struct regulator_init_data vmmc2_init = { | |||
307 | 411 | ||
308 | static struct regulator_consumer_supply vmmc1_consumers[] = { | 412 | static struct regulator_consumer_supply vmmc1_consumers[] = { |
309 | REGULATOR_SUPPLY("lcd_2v8", NULL), | 413 | REGULATOR_SUPPLY("lcd_2v8", NULL), |
414 | REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"), | ||
310 | }; | 415 | }; |
311 | 416 | ||
312 | static struct regulator_init_data vmmc1_init = { | 417 | static struct regulator_init_data vmmc1_init = { |
@@ -337,6 +442,22 @@ static struct regulator_init_data vgen_init = { | |||
337 | .consumer_supplies = vgen_consumers, | 442 | .consumer_supplies = vgen_consumers, |
338 | }; | 443 | }; |
339 | 444 | ||
445 | static struct regulator_consumer_supply vvib_consumers[] = { | ||
446 | REGULATOR_SUPPLY("cmos_vcore", "soc-camera-pdrv.0"), | ||
447 | }; | ||
448 | |||
449 | static struct regulator_init_data vvib_init = { | ||
450 | .constraints = { | ||
451 | .min_uV = 1300000, | ||
452 | .max_uV = 1300000, | ||
453 | .apply_uV = 1, | ||
454 | .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | | ||
455 | REGULATOR_CHANGE_STATUS, | ||
456 | }, | ||
457 | .num_consumer_supplies = ARRAY_SIZE(vvib_consumers), | ||
458 | .consumer_supplies = vvib_consumers, | ||
459 | }; | ||
460 | |||
340 | static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = { | 461 | static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = { |
341 | { | 462 | { |
342 | .id = MC13783_REG_PWGT1SPI, /* Power Gate for ARM core. */ | 463 | .id = MC13783_REG_PWGT1SPI, /* Power Gate for ARM core. */ |
@@ -360,6 +481,9 @@ static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = { | |||
360 | }, { | 481 | }, { |
361 | .id = MC13783_REG_VGEN, /* Power LCD */ | 482 | .id = MC13783_REG_VGEN, /* Power LCD */ |
362 | .init_data = &vgen_init, | 483 | .init_data = &vgen_init, |
484 | }, { | ||
485 | .id = MC13783_REG_VVIB, /* Power CMOS */ | ||
486 | .init_data = &vvib_init, | ||
363 | }, | 487 | }, |
364 | }; | 488 | }; |
365 | 489 | ||
@@ -552,8 +676,14 @@ static const struct imxi2c_platform_data mx31_3ds_i2c0_data __initconst = { | |||
552 | .bitrate = 100000, | 676 | .bitrate = 100000, |
553 | }; | 677 | }; |
554 | 678 | ||
679 | static struct platform_device *devices[] __initdata = { | ||
680 | &mx31_3ds_ov2640, | ||
681 | }; | ||
682 | |||
555 | static void __init mx31_3ds_init(void) | 683 | static void __init mx31_3ds_init(void) |
556 | { | 684 | { |
685 | int ret; | ||
686 | |||
557 | mxc_iomux_setup_multiple_pins(mx31_3ds_pins, ARRAY_SIZE(mx31_3ds_pins), | 687 | mxc_iomux_setup_multiple_pins(mx31_3ds_pins, ARRAY_SIZE(mx31_3ds_pins), |
558 | "mx31_3ds"); | 688 | "mx31_3ds"); |
559 | 689 | ||
@@ -564,6 +694,8 @@ static void __init mx31_3ds_init(void) | |||
564 | spi_register_board_info(mx31_3ds_spi_devs, | 694 | spi_register_board_info(mx31_3ds_spi_devs, |
565 | ARRAY_SIZE(mx31_3ds_spi_devs)); | 695 | ARRAY_SIZE(mx31_3ds_spi_devs)); |
566 | 696 | ||
697 | platform_add_devices(devices, ARRAY_SIZE(devices)); | ||
698 | |||
567 | imx31_add_imx_keypad(&mx31_3ds_keymap_data); | 699 | imx31_add_imx_keypad(&mx31_3ds_keymap_data); |
568 | 700 | ||
569 | mx31_3ds_usbotg_init(); | 701 | mx31_3ds_usbotg_init(); |
@@ -591,6 +723,20 @@ static void __init mx31_3ds_init(void) | |||
591 | imx31_add_spi_imx0(&spi0_pdata); | 723 | imx31_add_spi_imx0(&spi0_pdata); |
592 | mxc_register_device(&mx3_ipu, &mx3_ipu_data); | 724 | mxc_register_device(&mx3_ipu, &mx3_ipu_data); |
593 | mxc_register_device(&mx3_fb, &mx3fb_pdata); | 725 | mxc_register_device(&mx3_fb, &mx3fb_pdata); |
726 | |||
727 | /* CSI */ | ||
728 | /* Camera power: default - off */ | ||
729 | ret = gpio_request_array(mx31_3ds_camera_gpios, | ||
730 | ARRAY_SIZE(mx31_3ds_camera_gpios)); | ||
731 | if (ret) { | ||
732 | pr_err("Failed to request camera gpios"); | ||
733 | iclink_ov2640.power = NULL; | ||
734 | } | ||
735 | |||
736 | if (!mx31_3ds_camera_alloc_dma()) | ||
737 | mxc_register_device(&mx3_camera, &mx31_3ds_camera_pdata); | ||
738 | else | ||
739 | pr_err("Failed to allocate dma memory for camera"); | ||
594 | } | 740 | } |
595 | 741 | ||
596 | static void __init mx31_3ds_timer_init(void) | 742 | static void __init mx31_3ds_timer_init(void) |
@@ -602,6 +748,15 @@ static struct sys_timer mx31_3ds_timer = { | |||
602 | .init = mx31_3ds_timer_init, | 748 | .init = mx31_3ds_timer_init, |
603 | }; | 749 | }; |
604 | 750 | ||
751 | static void __init mx31_3ds_reserve(void) | ||
752 | { | ||
753 | /* reserve MX31_3DS_CAMERA_BUF_SIZE bytes for mx3-camera */ | ||
754 | mx3_camera_base = memblock_alloc(MX31_3DS_CAMERA_BUF_SIZE, | ||
755 | MX31_3DS_CAMERA_BUF_SIZE); | ||
756 | memblock_free(mx3_camera_base, MX31_3DS_CAMERA_BUF_SIZE); | ||
757 | memblock_remove(mx3_camera_base, MX31_3DS_CAMERA_BUF_SIZE); | ||
758 | } | ||
759 | |||
605 | MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)") | 760 | MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)") |
606 | /* Maintainer: Freescale Semiconductor, Inc. */ | 761 | /* Maintainer: Freescale Semiconductor, Inc. */ |
607 | .boot_params = MX3x_PHYS_OFFSET + 0x100, | 762 | .boot_params = MX3x_PHYS_OFFSET + 0x100, |
@@ -610,4 +765,5 @@ MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)") | |||
610 | .init_irq = mx31_init_irq, | 765 | .init_irq = mx31_init_irq, |
611 | .timer = &mx31_3ds_timer, | 766 | .timer = &mx31_3ds_timer, |
612 | .init_machine = mx31_3ds_init, | 767 | .init_machine = mx31_3ds_init, |
768 | .reserve = mx31_3ds_reserve, | ||
613 | MACHINE_END | 769 | MACHINE_END |