diff options
author | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-03-21 13:08:49 -0400 |
---|---|---|
committer | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-05-15 08:13:27 -0400 |
commit | d0a2b7af27f6d01a443f3af8252fa0b955bf1913 (patch) | |
tree | 2240f60b5e4f5cd4abec83812048962b4b959b88 /arch/avr32 | |
parent | 78c129b949bdee21dd996ac5f5cfc655cd5bd42e (diff) |
[AVR32] Implement platform hooks for atmel_lcdfb driver
This modifies and extends the existing lcdc platform code to support
the new atmel_lcdfb driver. The ATSTK1000 board code is set up to use
the on-board Samsung LTV350QV LCD panel.
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Diffstat (limited to 'arch/avr32')
-rw-r--r-- | arch/avr32/boards/atstk1000/atstk1000.h | 15 | ||||
-rw-r--r-- | arch/avr32/boards/atstk1000/atstk1002.c | 10 | ||||
-rw-r--r-- | arch/avr32/boards/atstk1000/setup.c | 45 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap7000.c | 77 |
4 files changed, 124 insertions, 23 deletions
diff --git a/arch/avr32/boards/atstk1000/atstk1000.h b/arch/avr32/boards/atstk1000/atstk1000.h new file mode 100644 index 000000000000..9a49ed036b72 --- /dev/null +++ b/arch/avr32/boards/atstk1000/atstk1000.h | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * ATSTK1000 setup code: Daughterboard interface | ||
3 | * | ||
4 | * Copyright (C) 2007 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #ifndef __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H | ||
11 | #define __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H | ||
12 | |||
13 | extern struct atmel_lcdfb_info atstk1000_lcdc_data; | ||
14 | |||
15 | #endif /* __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H */ | ||
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index abe6ca203fa7..fe1dbe2e28f4 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/spi/spi.h> | 17 | #include <linux/spi/spi.h> |
18 | 18 | ||
19 | #include <video/atmel_lcdc.h> | ||
20 | |||
19 | #include <asm/io.h> | 21 | #include <asm/io.h> |
20 | #include <asm/setup.h> | 22 | #include <asm/setup.h> |
21 | #include <asm/arch/at32ap7000.h> | 23 | #include <asm/arch/at32ap7000.h> |
@@ -23,6 +25,7 @@ | |||
23 | #include <asm/arch/init.h> | 25 | #include <asm/arch/init.h> |
24 | #include <asm/arch/portmux.h> | 26 | #include <asm/arch/portmux.h> |
25 | 27 | ||
28 | #include "atstk1000.h" | ||
26 | 29 | ||
27 | #define SW2_DEFAULT /* MMCI and UART_A available */ | 30 | #define SW2_DEFAULT /* MMCI and UART_A available */ |
28 | 31 | ||
@@ -31,9 +34,7 @@ struct eth_addr { | |||
31 | }; | 34 | }; |
32 | 35 | ||
33 | static struct eth_addr __initdata hw_addr[2]; | 36 | static struct eth_addr __initdata hw_addr[2]; |
34 | |||
35 | static struct eth_platform_data __initdata eth_data[2]; | 37 | static struct eth_platform_data __initdata eth_data[2]; |
36 | static struct lcdc_platform_data atstk1000_fb0_data; | ||
37 | 38 | ||
38 | static struct spi_board_info spi0_board_info[] __initdata = { | 39 | static struct spi_board_info spi0_board_info[] __initdata = { |
39 | { | 40 | { |
@@ -148,9 +149,8 @@ static int __init atstk1002_init(void) | |||
148 | set_hw_addr(at32_add_device_eth(0, ð_data[0])); | 149 | set_hw_addr(at32_add_device_eth(0, ð_data[0])); |
149 | 150 | ||
150 | at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); | 151 | at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); |
151 | atstk1000_fb0_data.fbmem_start = fbmem_start; | 152 | at32_add_device_lcdc(0, &atstk1000_lcdc_data, |
152 | atstk1000_fb0_data.fbmem_size = fbmem_size; | 153 | fbmem_start, fbmem_size); |
153 | at32_add_device_lcdc(0, &atstk1000_fb0_data); | ||
154 | 154 | ||
155 | return 0; | 155 | return 0; |
156 | } | 156 | } |
diff --git a/arch/avr32/boards/atstk1000/setup.c b/arch/avr32/boards/atstk1000/setup.c index 2bc4b88d7edb..c9af409ada9a 100644 --- a/arch/avr32/boards/atstk1000/setup.c +++ b/arch/avr32/boards/atstk1000/setup.c | |||
@@ -8,13 +8,56 @@ | |||
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | #include <linux/bootmem.h> | 10 | #include <linux/bootmem.h> |
11 | #include <linux/fb.h> | ||
11 | #include <linux/init.h> | 12 | #include <linux/init.h> |
12 | #include <linux/types.h> | 13 | #include <linux/types.h> |
13 | #include <linux/linkage.h> | 14 | #include <linux/linkage.h> |
14 | 15 | ||
15 | #include <asm/setup.h> | 16 | #include <video/atmel_lcdc.h> |
16 | 17 | ||
18 | #include <asm/setup.h> | ||
17 | #include <asm/arch/board.h> | 19 | #include <asm/arch/board.h> |
18 | 20 | ||
21 | #include "atstk1000.h" | ||
22 | |||
19 | /* Initialized by bootloader-specific startup code. */ | 23 | /* Initialized by bootloader-specific startup code. */ |
20 | struct tag *bootloader_tags __initdata; | 24 | struct tag *bootloader_tags __initdata; |
25 | |||
26 | static struct fb_videomode __initdata ltv350qv_modes[] = { | ||
27 | { | ||
28 | .name = "320x240 @ 75", | ||
29 | .refresh = 75, | ||
30 | .xres = 320, .yres = 240, | ||
31 | .pixclock = KHZ2PICOS(6891), | ||
32 | |||
33 | .left_margin = 17, .right_margin = 33, | ||
34 | .upper_margin = 10, .lower_margin = 10, | ||
35 | .hsync_len = 16, .vsync_len = 1, | ||
36 | |||
37 | .sync = 0, | ||
38 | .vmode = FB_VMODE_NONINTERLACED, | ||
39 | }, | ||
40 | }; | ||
41 | |||
42 | static struct fb_monspecs __initdata atstk1000_default_monspecs = { | ||
43 | .manufacturer = "SNG", | ||
44 | .monitor = "LTV350QV", | ||
45 | .modedb = ltv350qv_modes, | ||
46 | .modedb_len = ARRAY_SIZE(ltv350qv_modes), | ||
47 | .hfmin = 14820, | ||
48 | .hfmax = 22230, | ||
49 | .vfmin = 60, | ||
50 | .vfmax = 90, | ||
51 | .dclkmax = 30000000, | ||
52 | }; | ||
53 | |||
54 | struct atmel_lcdfb_info __initdata atstk1000_lcdc_data = { | ||
55 | .default_bpp = 24, | ||
56 | .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, | ||
57 | .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT | ||
58 | | ATMEL_LCDC_INVCLK | ||
59 | | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE | ||
60 | | ATMEL_LCDC_MEMOR_BIG), | ||
61 | .default_monspecs = &atstk1000_default_monspecs, | ||
62 | .guard_time = 2, | ||
63 | }; | ||
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index 56db45b99a0f..1d2bf347a1d6 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c | |||
@@ -6,6 +6,7 @@ | |||
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | #include <linux/clk.h> | 8 | #include <linux/clk.h> |
9 | #include <linux/fb.h> | ||
9 | #include <linux/init.h> | 10 | #include <linux/init.h> |
10 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
11 | #include <linux/spi/spi.h> | 12 | #include <linux/spi/spi.h> |
@@ -17,6 +18,8 @@ | |||
17 | #include <asm/arch/portmux.h> | 18 | #include <asm/arch/portmux.h> |
18 | #include <asm/arch/sm.h> | 19 | #include <asm/arch/sm.h> |
19 | 20 | ||
21 | #include <video/atmel_lcdc.h> | ||
22 | |||
20 | #include "clock.h" | 23 | #include "clock.h" |
21 | #include "hmatrix.h" | 24 | #include "hmatrix.h" |
22 | #include "pio.h" | 25 | #include "pio.h" |
@@ -881,20 +884,26 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n) | |||
881 | /* -------------------------------------------------------------------- | 884 | /* -------------------------------------------------------------------- |
882 | * LCDC | 885 | * LCDC |
883 | * -------------------------------------------------------------------- */ | 886 | * -------------------------------------------------------------------- */ |
884 | static struct lcdc_platform_data lcdc0_data; | 887 | static struct atmel_lcdfb_info atmel_lcdfb0_data; |
885 | static struct resource lcdc0_resource[] = { | 888 | static struct resource atmel_lcdfb0_resource[] = { |
886 | { | 889 | { |
887 | .start = 0xff000000, | 890 | .start = 0xff000000, |
888 | .end = 0xff000fff, | 891 | .end = 0xff000fff, |
889 | .flags = IORESOURCE_MEM, | 892 | .flags = IORESOURCE_MEM, |
890 | }, | 893 | }, |
891 | IRQ(1), | 894 | IRQ(1), |
895 | { | ||
896 | /* Placeholder for pre-allocated fb memory */ | ||
897 | .start = 0x00000000, | ||
898 | .end = 0x00000000, | ||
899 | .flags = 0, | ||
900 | }, | ||
892 | }; | 901 | }; |
893 | DEFINE_DEV_DATA(lcdc, 0); | 902 | DEFINE_DEV_DATA(atmel_lcdfb, 0); |
894 | DEV_CLK(hclk, lcdc0, hsb, 7); | 903 | DEV_CLK(hck1, atmel_lcdfb0, hsb, 7); |
895 | static struct clk lcdc0_pixclk = { | 904 | static struct clk atmel_lcdfb0_pixclk = { |
896 | .name = "pixclk", | 905 | .name = "lcdc_clk", |
897 | .dev = &lcdc0_device.dev, | 906 | .dev = &atmel_lcdfb0_device.dev, |
898 | .mode = genclk_mode, | 907 | .mode = genclk_mode, |
899 | .get_rate = genclk_get_rate, | 908 | .get_rate = genclk_get_rate, |
900 | .set_rate = genclk_set_rate, | 909 | .set_rate = genclk_set_rate, |
@@ -903,13 +912,34 @@ static struct clk lcdc0_pixclk = { | |||
903 | }; | 912 | }; |
904 | 913 | ||
905 | struct platform_device *__init | 914 | struct platform_device *__init |
906 | at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data) | 915 | at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, |
916 | unsigned long fbmem_start, unsigned long fbmem_len) | ||
907 | { | 917 | { |
908 | struct platform_device *pdev; | 918 | struct platform_device *pdev; |
919 | struct atmel_lcdfb_info *info; | ||
920 | struct fb_monspecs *monspecs; | ||
921 | struct fb_videomode *modedb; | ||
922 | unsigned int modedb_size; | ||
923 | |||
924 | /* | ||
925 | * Do a deep copy of the fb data, monspecs and modedb. Make | ||
926 | * sure all allocations are done before setting up the | ||
927 | * portmux. | ||
928 | */ | ||
929 | monspecs = kmemdup(data->default_monspecs, | ||
930 | sizeof(struct fb_monspecs), GFP_KERNEL); | ||
931 | if (!monspecs) | ||
932 | return NULL; | ||
933 | |||
934 | modedb_size = sizeof(struct fb_videomode) * monspecs->modedb_len; | ||
935 | modedb = kmemdup(monspecs->modedb, modedb_size, GFP_KERNEL); | ||
936 | if (!modedb) | ||
937 | goto err_dup_modedb; | ||
938 | monspecs->modedb = modedb; | ||
909 | 939 | ||
910 | switch (id) { | 940 | switch (id) { |
911 | case 0: | 941 | case 0: |
912 | pdev = &lcdc0_device; | 942 | pdev = &atmel_lcdfb0_device; |
913 | select_peripheral(PC(19), PERIPH_A, 0); /* CC */ | 943 | select_peripheral(PC(19), PERIPH_A, 0); /* CC */ |
914 | select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */ | 944 | select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */ |
915 | select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */ | 945 | select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */ |
@@ -942,19 +972,32 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data) | |||
942 | select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */ | 972 | select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */ |
943 | select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */ | 973 | select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */ |
944 | 974 | ||
945 | clk_set_parent(&lcdc0_pixclk, &pll0); | 975 | clk_set_parent(&atmel_lcdfb0_pixclk, &pll0); |
946 | clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0)); | 976 | clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0)); |
947 | break; | 977 | break; |
948 | 978 | ||
949 | default: | 979 | default: |
950 | return NULL; | 980 | goto err_invalid_id; |
951 | } | 981 | } |
952 | 982 | ||
953 | memcpy(pdev->dev.platform_data, data, | 983 | if (fbmem_len) { |
954 | sizeof(struct lcdc_platform_data)); | 984 | pdev->resource[2].start = fbmem_start; |
985 | pdev->resource[2].end = fbmem_start + fbmem_len - 1; | ||
986 | pdev->resource[2].flags = IORESOURCE_MEM; | ||
987 | } | ||
988 | |||
989 | info = pdev->dev.platform_data; | ||
990 | memcpy(info, data, sizeof(struct atmel_lcdfb_info)); | ||
991 | info->default_monspecs = monspecs; | ||
955 | 992 | ||
956 | platform_device_register(pdev); | 993 | platform_device_register(pdev); |
957 | return pdev; | 994 | return pdev; |
995 | |||
996 | err_invalid_id: | ||
997 | kfree(modedb); | ||
998 | err_dup_modedb: | ||
999 | kfree(monspecs); | ||
1000 | return NULL; | ||
958 | } | 1001 | } |
959 | 1002 | ||
960 | /* -------------------------------------------------------------------- | 1003 | /* -------------------------------------------------------------------- |
@@ -1037,8 +1080,8 @@ struct clk *at32_clock_list[] = { | |||
1037 | &macb1_pclk, | 1080 | &macb1_pclk, |
1038 | &atmel_spi0_spi_clk, | 1081 | &atmel_spi0_spi_clk, |
1039 | &atmel_spi1_spi_clk, | 1082 | &atmel_spi1_spi_clk, |
1040 | &lcdc0_hclk, | 1083 | &atmel_lcdfb0_hck1, |
1041 | &lcdc0_pixclk, | 1084 | &atmel_lcdfb0_pixclk, |
1042 | &gclk0, | 1085 | &gclk0, |
1043 | &gclk1, | 1086 | &gclk1, |
1044 | &gclk2, | 1087 | &gclk2, |
@@ -1077,7 +1120,7 @@ void __init at32_clock_init(void) | |||
1077 | genclk_init_parent(&gclk2); | 1120 | genclk_init_parent(&gclk2); |
1078 | genclk_init_parent(&gclk3); | 1121 | genclk_init_parent(&gclk3); |
1079 | genclk_init_parent(&gclk4); | 1122 | genclk_init_parent(&gclk4); |
1080 | genclk_init_parent(&lcdc0_pixclk); | 1123 | genclk_init_parent(&atmel_lcdfb0_pixclk); |
1081 | 1124 | ||
1082 | /* | 1125 | /* |
1083 | * Turn on all clocks that have at least one user already, and | 1126 | * Turn on all clocks that have at least one user already, and |