diff options
author | Josh Wu <josh.wu@atmel.com> | 2011-10-22 03:17:40 -0400 |
---|---|---|
committer | Nicolas Ferre <nicolas.ferre@atmel.com> | 2012-02-03 07:45:17 -0500 |
commit | 343754f50694e84b158b97b2f726dd6a66dbe765 (patch) | |
tree | cc387e109b240a32a050c7125afa81fc87a236c4 /arch/arm | |
parent | 45bb9e6fb2b8ac674ad3f4c4446018e9e57dfe8b (diff) |
ARM: at91: add Atmel ISI and ov2640 support on sam9m10g45 board
This patch adds:
- ov2640 sensor in at91sam9m10g45ek board
- support to use PCK as ISI_MCK. PCK's parent is managed at
SoC level, e.g. at91sam9g45_devices.c
Signed-off-by: Josh Wu <josh.wu@atmel.com>
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-at91/at91sam9g45_devices.c | 94 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-sam9m10g45ek.c | 80 |
2 files changed, 172 insertions, 2 deletions
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 96e2adcd5a8..bd4e68cd3e2 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/dma-mapping.h> | 15 | #include <linux/dma-mapping.h> |
16 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
17 | #include <linux/clk.h> | ||
17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
18 | #include <linux/i2c-gpio.h> | 19 | #include <linux/i2c-gpio.h> |
19 | #include <linux/atmel-mci.h> | 20 | #include <linux/atmel-mci.h> |
@@ -28,7 +29,10 @@ | |||
28 | #include <mach/at_hdmac.h> | 29 | #include <mach/at_hdmac.h> |
29 | #include <mach/atmel-mci.h> | 30 | #include <mach/atmel-mci.h> |
30 | 31 | ||
32 | #include <media/atmel-isi.h> | ||
33 | |||
31 | #include "generic.h" | 34 | #include "generic.h" |
35 | #include "clock.h" | ||
32 | 36 | ||
33 | 37 | ||
34 | /* -------------------------------------------------------------------- | 38 | /* -------------------------------------------------------------------- |
@@ -870,6 +874,96 @@ void __init at91_add_device_ac97(struct ac97c_platform_data *data) | |||
870 | void __init at91_add_device_ac97(struct ac97c_platform_data *data) {} | 874 | void __init at91_add_device_ac97(struct ac97c_platform_data *data) {} |
871 | #endif | 875 | #endif |
872 | 876 | ||
877 | /* -------------------------------------------------------------------- | ||
878 | * Image Sensor Interface | ||
879 | * -------------------------------------------------------------------- */ | ||
880 | #if defined(CONFIG_VIDEO_ATMEL_ISI) || defined(CONFIG_VIDEO_ATMEL_ISI_MODULE) | ||
881 | static u64 isi_dmamask = DMA_BIT_MASK(32); | ||
882 | static struct isi_platform_data isi_data; | ||
883 | |||
884 | struct resource isi_resources[] = { | ||
885 | [0] = { | ||
886 | .start = AT91SAM9G45_BASE_ISI, | ||
887 | .end = AT91SAM9G45_BASE_ISI + SZ_16K - 1, | ||
888 | .flags = IORESOURCE_MEM, | ||
889 | }, | ||
890 | [1] = { | ||
891 | .start = AT91SAM9G45_ID_ISI, | ||
892 | .end = AT91SAM9G45_ID_ISI, | ||
893 | .flags = IORESOURCE_IRQ, | ||
894 | }, | ||
895 | }; | ||
896 | |||
897 | static struct platform_device at91sam9g45_isi_device = { | ||
898 | .name = "atmel_isi", | ||
899 | .id = 0, | ||
900 | .dev = { | ||
901 | .dma_mask = &isi_dmamask, | ||
902 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
903 | .platform_data = &isi_data, | ||
904 | }, | ||
905 | .resource = isi_resources, | ||
906 | .num_resources = ARRAY_SIZE(isi_resources), | ||
907 | }; | ||
908 | |||
909 | static struct clk_lookup isi_mck_lookups[] = { | ||
910 | CLKDEV_CON_DEV_ID("isi_mck", "atmel_isi.0", NULL), | ||
911 | }; | ||
912 | |||
913 | void __init at91_add_device_isi(struct isi_platform_data *data, | ||
914 | bool use_pck_as_mck) | ||
915 | { | ||
916 | struct clk *pck; | ||
917 | struct clk *parent; | ||
918 | |||
919 | if (!data) | ||
920 | return; | ||
921 | isi_data = *data; | ||
922 | |||
923 | at91_set_A_periph(AT91_PIN_PB20, 0); /* ISI_D0 */ | ||
924 | at91_set_A_periph(AT91_PIN_PB21, 0); /* ISI_D1 */ | ||
925 | at91_set_A_periph(AT91_PIN_PB22, 0); /* ISI_D2 */ | ||
926 | at91_set_A_periph(AT91_PIN_PB23, 0); /* ISI_D3 */ | ||
927 | at91_set_A_periph(AT91_PIN_PB24, 0); /* ISI_D4 */ | ||
928 | at91_set_A_periph(AT91_PIN_PB25, 0); /* ISI_D5 */ | ||
929 | at91_set_A_periph(AT91_PIN_PB26, 0); /* ISI_D6 */ | ||
930 | at91_set_A_periph(AT91_PIN_PB27, 0); /* ISI_D7 */ | ||
931 | at91_set_A_periph(AT91_PIN_PB28, 0); /* ISI_PCK */ | ||
932 | at91_set_A_periph(AT91_PIN_PB30, 0); /* ISI_HSYNC */ | ||
933 | at91_set_A_periph(AT91_PIN_PB29, 0); /* ISI_VSYNC */ | ||
934 | at91_set_B_periph(AT91_PIN_PB8, 0); /* ISI_PD8 */ | ||
935 | at91_set_B_periph(AT91_PIN_PB9, 0); /* ISI_PD9 */ | ||
936 | at91_set_B_periph(AT91_PIN_PB10, 0); /* ISI_PD10 */ | ||
937 | at91_set_B_periph(AT91_PIN_PB11, 0); /* ISI_PD11 */ | ||
938 | |||
939 | platform_device_register(&at91sam9g45_isi_device); | ||
940 | |||
941 | if (use_pck_as_mck) { | ||
942 | at91_set_B_periph(AT91_PIN_PB31, 0); /* ISI_MCK (PCK1) */ | ||
943 | |||
944 | pck = clk_get(NULL, "pck1"); | ||
945 | parent = clk_get(NULL, "plla"); | ||
946 | |||
947 | BUG_ON(IS_ERR(pck) || IS_ERR(parent)); | ||
948 | |||
949 | if (clk_set_parent(pck, parent)) { | ||
950 | pr_err("Failed to set PCK's parent\n"); | ||
951 | } else { | ||
952 | /* Register PCK as ISI_MCK */ | ||
953 | isi_mck_lookups[0].clk = pck; | ||
954 | clkdev_add_table(isi_mck_lookups, | ||
955 | ARRAY_SIZE(isi_mck_lookups)); | ||
956 | } | ||
957 | |||
958 | clk_put(pck); | ||
959 | clk_put(parent); | ||
960 | } | ||
961 | } | ||
962 | #else | ||
963 | void __init at91_add_device_isi(struct isi_platform_data *data, | ||
964 | bool use_pck_as_mck) {} | ||
965 | #endif | ||
966 | |||
873 | 967 | ||
874 | /* -------------------------------------------------------------------- | 968 | /* -------------------------------------------------------------------- |
875 | * LCD Controller | 969 | * LCD Controller |
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c index ea0d1b9c2b7..57497e2b887 100644 --- a/arch/arm/mach-at91/board-sam9m10g45ek.c +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c | |||
@@ -24,11 +24,13 @@ | |||
24 | #include <linux/gpio_keys.h> | 24 | #include <linux/gpio_keys.h> |
25 | #include <linux/input.h> | 25 | #include <linux/input.h> |
26 | #include <linux/leds.h> | 26 | #include <linux/leds.h> |
27 | #include <linux/clk.h> | ||
28 | #include <linux/atmel-mci.h> | 27 | #include <linux/atmel-mci.h> |
28 | #include <linux/delay.h> | ||
29 | 29 | ||
30 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
31 | #include <video/atmel_lcdc.h> | 31 | #include <video/atmel_lcdc.h> |
32 | #include <media/soc_camera.h> | ||
33 | #include <media/atmel-isi.h> | ||
32 | 34 | ||
33 | #include <asm/setup.h> | 35 | #include <asm/setup.h> |
34 | #include <asm/mach-types.h> | 36 | #include <asm/mach-types.h> |
@@ -185,6 +187,71 @@ static void __init ek_add_device_nand(void) | |||
185 | 187 | ||
186 | 188 | ||
187 | /* | 189 | /* |
190 | * ISI | ||
191 | */ | ||
192 | static struct isi_platform_data __initdata isi_data = { | ||
193 | .frate = ISI_CFG1_FRATE_CAPTURE_ALL, | ||
194 | /* to use codec and preview path simultaneously */ | ||
195 | .full_mode = 1, | ||
196 | .data_width_flags = ISI_DATAWIDTH_8 | ISI_DATAWIDTH_10, | ||
197 | /* ISI_MCK is provided by programmable clock or external clock */ | ||
198 | .mck_hz = 25000000, | ||
199 | }; | ||
200 | |||
201 | |||
202 | /* | ||
203 | * soc-camera OV2640 | ||
204 | */ | ||
205 | #if defined(CONFIG_SOC_CAMERA_OV2640) || \ | ||
206 | defined(CONFIG_SOC_CAMERA_OV2640_MODULE) | ||
207 | static unsigned long isi_camera_query_bus_param(struct soc_camera_link *link) | ||
208 | { | ||
209 | /* ISI board for ek using default 8-bits connection */ | ||
210 | return SOCAM_DATAWIDTH_8; | ||
211 | } | ||
212 | |||
213 | static int i2c_camera_power(struct device *dev, int on) | ||
214 | { | ||
215 | /* enable or disable the camera */ | ||
216 | pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE"); | ||
217 | at91_set_gpio_output(AT91_PIN_PD13, !on); | ||
218 | |||
219 | if (!on) | ||
220 | goto out; | ||
221 | |||
222 | /* If enabled, give a reset impulse */ | ||
223 | at91_set_gpio_output(AT91_PIN_PD12, 0); | ||
224 | msleep(20); | ||
225 | at91_set_gpio_output(AT91_PIN_PD12, 1); | ||
226 | msleep(100); | ||
227 | |||
228 | out: | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static struct i2c_board_info i2c_camera = { | ||
233 | I2C_BOARD_INFO("ov2640", 0x30), | ||
234 | }; | ||
235 | |||
236 | static struct soc_camera_link iclink_ov2640 = { | ||
237 | .bus_id = 0, | ||
238 | .board_info = &i2c_camera, | ||
239 | .i2c_adapter_id = 0, | ||
240 | .power = i2c_camera_power, | ||
241 | .query_bus_param = isi_camera_query_bus_param, | ||
242 | }; | ||
243 | |||
244 | static struct platform_device isi_ov2640 = { | ||
245 | .name = "soc-camera-pdrv", | ||
246 | .id = 0, | ||
247 | .dev = { | ||
248 | .platform_data = &iclink_ov2640, | ||
249 | }, | ||
250 | }; | ||
251 | #endif | ||
252 | |||
253 | |||
254 | /* | ||
188 | * LCD Controller | 255 | * LCD Controller |
189 | */ | 256 | */ |
190 | #if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE) | 257 | #if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE) |
@@ -377,7 +444,12 @@ static struct gpio_led ek_pwm_led[] = { | |||
377 | #endif | 444 | #endif |
378 | }; | 445 | }; |
379 | 446 | ||
380 | 447 | static struct platform_device *devices[] __initdata = { | |
448 | #if defined(CONFIG_SOC_CAMERA_OV2640) || \ | ||
449 | defined(CONFIG_SOC_CAMERA_OV2640_MODULE) | ||
450 | &isi_ov2640, | ||
451 | #endif | ||
452 | }; | ||
381 | 453 | ||
382 | static void __init ek_board_init(void) | 454 | static void __init ek_board_init(void) |
383 | { | 455 | { |
@@ -399,6 +471,8 @@ static void __init ek_board_init(void) | |||
399 | ek_add_device_nand(); | 471 | ek_add_device_nand(); |
400 | /* I2C */ | 472 | /* I2C */ |
401 | at91_add_device_i2c(0, NULL, 0); | 473 | at91_add_device_i2c(0, NULL, 0); |
474 | /* ISI, using programmable clock as ISI_MCK */ | ||
475 | at91_add_device_isi(&isi_data, true); | ||
402 | /* LCD Controller */ | 476 | /* LCD Controller */ |
403 | at91_add_device_lcdc(&ek_lcdc_data); | 477 | at91_add_device_lcdc(&ek_lcdc_data); |
404 | /* Touch Screen */ | 478 | /* Touch Screen */ |
@@ -410,6 +484,8 @@ static void __init ek_board_init(void) | |||
410 | /* LEDs */ | 484 | /* LEDs */ |
411 | at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); | 485 | at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); |
412 | at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led)); | 486 | at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led)); |
487 | /* Other platform devices */ | ||
488 | platform_add_devices(devices, ARRAY_SIZE(devices)); | ||
413 | } | 489 | } |
414 | 490 | ||
415 | MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK") | 491 | MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK") |