diff options
Diffstat (limited to 'arch/avr32/mach-at32ap/at32ap7000.c')
| -rw-r--r-- | arch/avr32/mach-at32ap/at32ap7000.c | 77 |
1 files changed, 60 insertions, 17 deletions
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 |
