aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHaavard Skinnemoen <hskinnemoen@atmel.com>2007-03-21 13:08:49 -0400
committerHaavard Skinnemoen <hskinnemoen@atmel.com>2007-05-15 08:13:27 -0400
commitd0a2b7af27f6d01a443f3af8252fa0b955bf1913 (patch)
tree2240f60b5e4f5cd4abec83812048962b4b959b88 /arch
parent78c129b949bdee21dd996ac5f5cfc655cd5bd42e (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')
-rw-r--r--arch/avr32/boards/atstk1000/atstk1000.h15
-rw-r--r--arch/avr32/boards/atstk1000/atstk1002.c10
-rw-r--r--arch/avr32/boards/atstk1000/setup.c45
-rw-r--r--arch/avr32/mach-at32ap/at32ap7000.c77
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
13extern 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
33static struct eth_addr __initdata hw_addr[2]; 36static struct eth_addr __initdata hw_addr[2];
34
35static struct eth_platform_data __initdata eth_data[2]; 37static struct eth_platform_data __initdata eth_data[2];
36static struct lcdc_platform_data atstk1000_fb0_data;
37 38
38static struct spi_board_info spi0_board_info[] __initdata = { 39static 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, &eth_data[0])); 149 set_hw_addr(at32_add_device_eth(0, &eth_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. */
20struct tag *bootloader_tags __initdata; 24struct tag *bootloader_tags __initdata;
25
26static 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
42static 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
54struct 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 * -------------------------------------------------------------------- */
884static struct lcdc_platform_data lcdc0_data; 887static struct atmel_lcdfb_info atmel_lcdfb0_data;
885static struct resource lcdc0_resource[] = { 888static 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};
893DEFINE_DEV_DATA(lcdc, 0); 902DEFINE_DEV_DATA(atmel_lcdfb, 0);
894DEV_CLK(hclk, lcdc0, hsb, 7); 903DEV_CLK(hck1, atmel_lcdfb0, hsb, 7);
895static struct clk lcdc0_pixclk = { 904static 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
905struct platform_device *__init 914struct platform_device *__init
906at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data) 915at32_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
996err_invalid_id:
997 kfree(modedb);
998err_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