蓝森林首页 | 返回主页 | 本站地图 | 站内搜索 | 联系信箱 |
 您目前的位置:首页 > 自由软件 > 技术交流 > 系统管理


    

蓝森林 http://www.lslnet.com 2006年8月21日 12:28

linux2.6的移植进度

注:该log文件将从2005-9-13号开始记录cefanty移植2.6.13内核到SMDK2410的步骤和进度

9-13:到今天为止已经完成的工作:(以下部分均编译通过)
1.yaffs2移植完成.发现我的开发板上的nandflash有坏块了.呜呜....
2.usb-host移植完成,能挂载各种u盘和移动硬盘了.只是启动的时候提示找不到有这样的
提示:hub 1-0:1.0: Cannot enable port 2. Maybe the USB cable is bad? 待解决!!!
3.usb-devices 部分代码移植完毕,测试未完成.嘻嘻....
4.cs8900A网卡部分移植完毕,mount nfs OK!
5.UDA1341音频部分的驱动部分的bug已经修正完毕 .用mplayer播放mp3 OK
6.frambuffer部分frambuffer驱动已经移植在SMDK2410上,但是测试没有通过.失败!!!

需解决的问题:
1.在我的开发板始终没有能在266MHZ上运行linux2.6,why??? (9-19 已解决)
2.usb device驱动的测试 (9-21 已解决)
3.frambuffer驱动的测试

9-19:
1.修正了vivi初始化CPU为266MHZ时,nandflash不能工作的bug.
s3c2410_nand_calc_rate函数计算有问题
2.修正了SD卡,不能热插拔的问题.(但是我测试的SD卡现在mount vfat失败了,
????是卡的问题??)

9-20:
1.取消了讨厌的nandflash有坏块的提示,在得到有效解决办法之前
还是不要看到它们.(真的很烦)
2.发现yaffs2支持的page为1024,而我们的64M的nandflash的page为512,
所以只能用yaffs.编译时候就不选上yaffs2了
3.修正了一些 SD 卡的bug,但是发现SD只能工作在总线速度为3MHZ.
否则mount 不成功.郁闷中.

需解决的问题:
1.SD卡的读写速度的问题 (9-23 已解决)
2.busybox1.0 mount nfs 失败的问题.(0.63版本的没有问题)

9-21:
1.修正usb host 数目的问题,可以在配置时选择。一般选择一个host,一个device.
(启动的时候不再提示usb host的错误了)
2.完成了usb gadget的功能.模拟成了u disk.测试基本通过.就是速度比较慢(SD卡的速度问题)

9-23:
1.修正了SD卡的热插拔功能的完善.(检测正确有效)
2.修正了SD卡高速运行的bug.(现在基本运行在16MHZ 呵呵)
3.修正SD卡的兼容性问题. 兼容性更好(起码我手头上的T flash卡和mini SD没有问题了).

............待续

Re: linux2.6的移植进度

老大,你真厉害,能不能给我一份全部的。如果不行的话,能不能给我UDA1341的驱动,急啊。
arrow_zhw@21cn.com

Re: linux2.6的移植进度

能分享一下你的经验吗?

email:zhangzq71@hotmail.com

Re: linux2.6的移植进度

我现在在移植usb gadget 设备驱动到s3c2410硬件平台。kernel2.6.11.1
insmod s3c2410_udc.ko
insmod g_file_storage.ko file=/dev/mtdblock/3 removable=1
现在模块都插进去了,但是host端一点反应都没有。盘附都没有。

用bus hound在host监测。
我不是很懂bus hound上的监测信息代表什么意思,请问能给我分析一下吗
看到:

Device Address Length Phase Data Description Delta Cmd.Phase.Ofs(rep) Date Time Driver

------ ------------------- -------- ----- ----- ---------------- ----- ------------------ ---------- ------------ ------------

10 24 IN 00 00 .. 2.0sc 1.1.0(197) 2005-11-15 10:47:09.286 unknown

00 00 .. 1.1.2

00 00 .. 1.1.4

00 00 .. 1.1.6

10 IRP 06 00 7us 1.2.0 2005-11-15 10:47:09.286

90 01 1.2.2

00 00 1.2.4

00 00 1.2.6

10 STAK 03 00 READ 4us 1.3.0 2005-11-15 10:47:09.286

00 00 1.3.2

f0 00 1.3.4

00 00 1.3.6

10 24 IN 00 00 .. 18sc 198.1.0 2005-11-15 10:47:27.429 unknown

00 00 .. 198.1.2

01 00 .. 198.1.4

00 00 .. 198.1.6

10 IRP 06 00 10us 198.2.0 2005-11-15 10:47:27.429

90 01 198.2.2

00 00 198.2.4

00 00 198.2.6

10 STAK 03 00 READ 4us 198.3.0 2005-11-15 10:47:27.429

00 00 198.3.2

f0 00 198.3.4

00 00 198.3.6

10 24 IN 00 00 .. 266ms 199.1.0 2005-11-15 10:47:27.695 unknown

00 00 .. 199.1.2

02 00 .. 199.1.4

00 00 .. 199.1.6

10 IRP 06 00 8us 199.2.0 2005-11-15 10:47:27.695

90 01 199.2.2

00 00 199.2.4

00 00 199.2.6

10 STAK 03 00 READ 3us 199.3.0 2005-11-15 10:47:27.695

00 00 199.3.2

f0 00 199.3.4

00 00 199.3.6

10 24 IN 00 00 .. 3.8sc 200.1.0(142) 2005-11-15 10:47:31.565 unknown

00 00 .. 200.1.2

00 00 .. 200.1.4

00 00 .. 200.1.6

10 IRP 06 00 8us 200.2.0 2005-11-15 10:47:31.565

90 01 200.2.2

00 00 200.2.4

00 00 200.2.6

10 STAK 03 00 READ 4us 200.3.0 2005-11-15 10:47:31.565

00 00 200.3.2

f0 00 200.3.4

00 00 200.3.6

10 24 IN 00 00 .. 1.7mn 342.1.0 2005-11-15 10:49:17.248 unknown

00 00 .. 342.1.2

01 00 .. 342.1.4

00 00 .. 342.1.6

10 IRP 06 00 6us 342.2.0 2005-11-15 10:49:17.248

90 01 342.2.2

00 00 342.2.4

00 00 342.2.6

10 STAK 03 00 READ 3us 342.3.0 2005-11-15 10:49:17.248

00 00 342.3.2

f0 00 342.3.4

00 00 342.3.6

10 24 IN 00 00 .. 88ms 343.1.0(2) 2005-11-15 10:49:17.336 unknown

00 00 .. 343.1.2

00 00 .. 343.1.4

00 00 .. 343.1.6

10 IRP 06 00 5us 343.2.0 2005-11-15 10:49:17.336

90 01 343.2.2

00 00 343.2.4

00 00 343.2.6

10 STAK 03 00 READ 4us 343.3.0 2005-11-15 10:49:17.336

00 00 343.3.2

f0 00 343.3.4

00 00 343.3.6

10 24 IN 00 00 .. 149ms 345.1.0 2005-11-15 10:49:17.486 unknown

00 00 .. 345.1.2

02 00 .. 345.1.4

00 00 .. 345.1.6

10 IRP 06 00 11us 345.2.0 2005-11-15 10:49:17.486

90 01 345.2.2

00 00 345.2.4

00 00 345.2.6

10 STAK 03 00 READ 5us 345.3.0 2005-11-15 10:49:17.486

00 00 345.3.2

f0 00 345.3.4

00 00 345.3.6

10 24 IN 00 00 .. 521ms 346.1.0(85) 2005-11-15 10:49:18.007 unknown

00 00 .. 346.1.2

00 00 .. 346.1.4

00 00 .. 346.1.6

10 IRP 06 00 8us 346.2.0 2005-11-15 10:49:18.007

90 01 346.2.2

00 00 346.2.4

00 00 346.2.6

10 STAK 03 00 READ 4us 346.3.0 2005-11-15 10:49:18.007

00 00 346.3.2

f0 00 346.3.4

00 00 346.3.6

3 CMD 28 00 READ 4.2sc 431.1.0 2005-11-15 10:49:22.264 classpnp

00 1e 431.1.2

3c 27 431.1.4

00 00 431.1.6

10 24 IN 00 00 .. 1.6ms 432.1.0(23) 2005-11-15 10:49:22.265 unknown

00 00 .. 432.1.2

00 00 .. 432.1.4

00 00 .. 432.1.6

10 IRP 06 00 4us 432.2.0 2005-11-15 10:49:22.265

90 01 432.2.2

00 00 432.2.4

00 00 432.2.6

10 STAK 03 00 READ 4us 432.3.0 2005-11-15 10:49:22.265

00 00 432.3.2

f0 00 432.3.4

00 00 432.3.6

3 CMD 2a 08 WRITE 258ms 455.1.0 2005-11-15 10:49:22.524 classpnp

00 5f 455.1.2

0d e7 455.1.4

00 00 455.1.6

3 CMD 2a 00 WRITE 82us 456.1.0 2005-11-15 10:49:22.524 classpnp

00 4c 456.1.2

dd 7f 456.1.4

00 00 456.1.6

10 24 IN 00 00 .. 16ms 457.1.0 2005-11-15 10:49:22.541 unknown

00 00 .. 457.1.2

00 00 .. 457.1.4

00 00 .. 457.1.6

10 IRP 06 00 6us 457.2.0 2005-11-15 10:49:22.541

90 01 457.2.2

00 00 457.2.4

00 00 457.2.6



Re: linux2.6的移植进度

9-26:
1.修正了S3C2410_uda1341 不能录音的bug(返回的数据长度总是零).
2.修正了MTD 字符型设备的devfs的问题.
3.开启Yaffs的ECC 和page verified功能
4.增加了i2c总线的电池监控芯片的驱动

10-25:
1.framebuffer工作,看到可爱的小企鹅啦.
2.修正RTC的问题,并用程序校准RTC的时钟

11-9:
1.完成S3C2410的ADC驱动
2.修正S3c2410 Watchdog的功能.

11-12 :
1.开始把linux-2.6.13 向 linux-2.6.14上 转移

11-17 :
1. 给linux-2.6.14 打 linux-2.6.14.2 补丁
2. 修改 usb gadget 和 mmc/SD 代码 ,模拟的U盘在windows下读取和存储文件速率在600kb/s左右. mplayer 播放各种媒体文件流畅



Re: linux2.6的移植进度

看到现在,还不知道你为什么要发这个帖子,难道是想把linuxforum当博客?或者是想让大家在台下看看你有多酷?

Re: linux2.6的移植进度

看到 chengzhu 的帖子,突然意识到这个问题了,比如UDA1341的驱动,好像2.6标准内核里面一直没有,你没有发布patch吗?

如果你做的东西发了patch,然后在这里通知大家,那我们欢迎,如果你只是说你做了什么,但是你做的东西根本不release,那请你不要发这样的帖子了,请到博客网站去写好了。

谢谢!


Re: linux2.6的移植进度

我同意你说的。这种德性的人网上多的很!!! 或者只会充水,或者只会盗用他人成果。

Re: linux2.6的移植进度

看到这位老兄说的,让我想起作usb gadget的那段经历。起码我做好了还发布给了不下10位给我发email的筒子。后来因为没有时间回复一些用了我的驱动的筒子的问题。我暂停了发布驱动源码。
我可不比起您老兄,好像你的usb gadget驱动是要花5000大元才卖的。
虽然我的工作只是开发智能手机的。只是个人爱好弄上了liunux。因为公布源码的事情上,发生了让我很不开心的事情。缘故不想再多说了.所以我不在贸然的发布patch,或者源码。我之所以写这些东西。是告诉需要的筒子。如果在深圳需要这方面的东西。也许和我聊聊。可以交的朋友。我会发布给这些人,当然不是所有的人。如果是个人兴趣爱好,用于学习研究交流用,我不会要money的.


Re: linux2.6的移植进度

谢谢版主的发言。我知道错了,以后我尽量少发这类灌水的帖子了。
至于uda1341的驱动.如果版主需要,我可以发给版主,你再决定是否需要发布到论坛上。
起码我不想再给自己找一些麻烦了

Re: linux2.6的移植进度

至于你,唉.........
不说了.

Re: linux2.6的移植进度

呵呵,隐私被人抖出来了
5000块你会买吗?好象是没有人会买,我的用意很简单,开发人员能做的事情不要想着去买。碰到什么问题,别人能帮忙的话肯定会帮忙。但是确实有些兄弟在问问题之前根本就没有仔细的看源码,做基本的分析。

Re: linux2.6的移植进度

如果你现在心情好,麻烦你给我发一份gadget driver。最近搞这个很郁闷的,声明,我只是学习用。本人目前还是学生。想做这方面的毕业论文。
zhangfy811@163.com

Re: linux2.6的移植进度

发给我一份吧,我一个朋友在找这个。
linux_arm_kernel#yahoo.com
# = @

不过我推荐你发布到标准内核,内核里面有你的代码应该值得骄傲;-)


Re: linux2.6的移植进度

老兄,给我这个初学者也发一份吧,正在学嵌入式呢,希望你的成果能帮上后来者的忙,谢谢啦.
我的邮箱: anoba@163.com


Re: linux2.6的移植进度

介绍一下移植sd卡驱动的经验啊,我现在在http://svn.opentom.org/cgi-bin/viewcvs.cgi/trunk/linux-2.6/drivers/mmc/?rev=88&root=opentom
上找到了关于s3c2410 mmc/sd卡控制器驱动的代码,移植过来后,插上sd卡,还是不行,后来发现与此相关的代码
例如:include/linux/mmc/下,和/driver/mmc/下的许多代码都和2.6.11.1下的不同,是不是都要改过来才能驱动呢!

又或是有其它的办法,望给个建议

Re: linux2.6的移植进度

大虾的能力值得肯定!
我最近在搞2.6下s3c2410的lcd驱动,2.6.14.7里默认的不好用,还请指点
正在试最新版本: 2.6.15.4
如果能把 您调试好用的 2.6 下的lcd驱动源码给一份,将不胜感激
sunshiyou_hit@126.com



Re: linux2.6的移植进度

另:这里我已经移植好了dm9000的驱动,在2.6(s3c2410)下,有需要者可以直接下载
本人现在正在2.6内核下摸爬滚打,愿结交有志之士共同进步!
qq : 520049739

Re: linux2.6的移植进度

内核 2.6.14.7
s3c2410fb.c 启动代码(init---probe)
int __init s3c2410fb_probe(struct device *dev)
{
struct s3c2410fb_info *info;
struct fb_info *fbinfo;
struct platform_device *pdev = to_platform_device(dev);
struct s3c2410fb_hw *mregs;
int ret;
int irq;
int i;

mach_info = dev->platform_data;
if (mach_info == NULL) {
dev_err(dev,"no platform data for lcd, cannot attach\n");
return -EINVAL;
}
。。。。。。。

内核启动提示信息:

。。。。。。。。。。。。。。
Initializing Cryptographic API
s3c2410-lcd s3c2410-lcd: no platform data for lcd, cannot attach
s3c2410-lcd: probe of s3c2410-lcd failed with error -22
Real Time Clock Driver v1.12
。。。。。。。。。。。
不知这个问题该怎样解决,请指教。

Re: linux2.6的移植进度

以下是framebuffer驱动的patch.请自己研究.遇到问题,在提问!

diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/mach-s3c2410/devs.c
@@ -29,7 +29,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
-
+#include <asm/arch/fb.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -105,6 +105,15 @@ struct platform_device s3c_device_lcd =

EXPORT_SYMBOL(s3c_device_lcd);

+static struct s3c2410fb_mach_info s3c2410fb_info;
+
+void __init set_s3c2410fb_info(struct s3c2410fb_mach_info *hard_s3c2410fb_info)
+{
+ memcpy(&s3c2410fb_info,hard_s3c2410fb_info,sizeof(struct s3c2410fb_mach_info));
+ s3c_device_lcd.dev.platform_data = &s3c2410fb_info;
+}
+EXPORT_SYMBOL(set_s3c2410fb_info);
+
/* NAND Controller */

static struct resource s3c_nand_resource[] = {
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -47,7 +47,9 @@
//#include <asm/debug-ll.h>
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>

+#include <asm/arch/fb.h>
#include <asm/arch/udc.h>
#include <asm/arch/ts.h>

@@ -118,6 +120,48 @@ static struct s3c2410_ts_mach_info h1940
.oversampling_shift = 2,
};

+/**
+ * Set lcd on or off
+ **/
+static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = {
+ .fixed_syncs= 1,
+ .regs={
+ .lcdcon1= S3C2410_LCDCON1_TFT16BPP | \
+ S3C2410_LCDCON1_TFT | \
+ S3C2410_LCDCON1_CLKVAL(0x0C),
+
+ .lcdcon2= S3C2410_LCDCON2_VBPD(7) | \
+ S3C2410_LCDCON2_LINEVAL(319) | \
+ S3C2410_LCDCON2_VFPD(6) | \
+ S3C2410_LCDCON2_VSPW(0),
+
+ .lcdcon3= S3C2410_LCDCON3_HBPD(19) | \
+ S3C2410_LCDCON3_HOZVAL(239) | \
+ S3C2410_LCDCON3_HFPD(7),
+
+ .lcdcon4= S3C2410_LCDCON4_MVAL(0) | \
+ S3C2410_LCDCON4_HSPW(3),
+
+ .lcdcon5= S3C2410_LCDCON5_FRM565 | \
+ S3C2410_LCDCON5_INVVLINE | \
+ S3C2410_LCDCON5_HWSWP,
+ },
+ .lpcsel= 0x02,
+ .gpccon= 0xaa940659,
+ .gpccon_mask= 0xffffffff,
+ .gpcup= 0x0000ffff,
+ .gpcup_mask= 0xffffffff,
+ .gpdcon= 0xaa84aaa0,
+ .gpdcon_mask= 0xffffffff,
+ .gpdup= 0x0000faff,
+ .gpdup_mask= 0xffffffff,
+
+ .width= 240,
+ .height= 320,
+ .xres= {240,240,240},
+ .yres= {320,320,320},
+ .bpp= {16,16,16},
+};

static struct platform_device *h1940_devices[] __initdata = {
&s3c_device_usb,
@@ -154,6 +198,7 @@ void __init h1940_init(void)
set_s3c2410udc_info(&h1940_udc_cfg);
/* Set pad to usb device and usbsuspend to 'normal' */
__raw_writel(__raw_readl(S3C2410_MISCCR)&~0x3008,S3C2410_MISCCR);
+ set_s3c2410fb_info(&h1940_lcdcfg);
}

MACHINE_START(H1940, "IPAQ-H1940")
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1484,6 +1484,30 @@ config FB_S1D13XXX
working with S1D13806). Product specs at
<http://www.erd.epson.com/vdc/html/legacy_13xxx.htm>

+config FB_S3C2410
+ tristate "S3C2410 LCD framebuffer support"
+ depends on FB && ARCH_S3C2410
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ ---help---
+ Frame buffer driver for the built-in LCD controller in the Samsung
+ S3C2410 processor.
+
+ This driver is also available as a module ( = code which can be
+ inserted and removed from the running kernel whenever you want). The
+ module will be called s3c2410fb. If you want to compile it as a module,
+ say M here and read <file:Documentation/modules.txt>.
+
+ If unsure, say N.
+config FB_S3C2410_DEBUG
+ bool "S3C2410 lcd debug messages"
+ depends on FB_S3C2410
+ help
+ Turn on debugging messages. Note that you can set/unset at run time
+ through sysfs
+
config FB_VIRTUAL
tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -92,6 +92,7 @@ obj-$(CONFIG_FB_MAXINE) += maxinefb.o
obj-$(CONFIG_FB_TX3912) += tx3912fb.o
obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
obj-$(CONFIG_FB_IMX) += imxfb.o
+obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o

# Platform or fallback drivers go here
obj-$(CONFIG_FB_VESA) += vesafb.o
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
new file mode 100644
--- /dev/null
+++ b/drivers/video/s3c2410fb.c
@@ -0,0 +1,902 @@
+/*
+ * linux/drivers/video/s3c2410fb.c
+ * Copyright (c) Arnaud Patard, Ben Dooks
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * S3C2410 LCD Controller Frame Buffer Driver
+ * based on skeletonfb.c, sa1100fb.c and others
+ *
+ * ChangeLog
+ * 2005-04-07: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - u32 state -> pm_message_t state
+ * - S3C2410_{VA,SZ}_LCD -> S3C24XX
+ *
+ * 2005-03-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Removed the ioctl
+ * - use readl/writel instead of __raw_writel/__raw_readl
+ *
+ * 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Added the possibility to set on or off the
+ * debugging mesaages
+ * - Replaced 0 and 1 by on or off when reading the
+ * /sys files
+ *
+ * 2005-03-23: Ben Dooks <ben-linux@fluff.org>
+ * - added non 16bpp modes
+ * - updated platform information for range of x/y/bpp
+ * - add code to ensure palette is written correctly
+ * - add pixel clock divisor control
+ *
+ * 2004-11-11: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Removed the use of currcon as it no more exist
+ * - Added LCD power sysfs interface
+ *
+ * 2004-11-03: Ben Dooks <ben-linux@fluff.org>
+ * - minor cleanups
+ * - add suspend/resume support
+ * - s3c2410fb_setcolreg() not valid in >8bpp modes
+ * - removed last CONFIG_FB_S3C2410_FIXED
+ * - ensure lcd controller stopped before cleanup
+ * - added sysfs interface for backlight power
+ * - added mask for gpio configuration
+ * - ensured IRQs disabled during GPIO configuration
+ * - disable TPAL before enabling video
+ *
+ * 2004-09-20: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Suppress command line options
+ *
+ * 2004-09-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - code cleanup
+ *
+ * 2004-09-07: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Renamed from h1940fb.c to s3c2410fb.c
+ * - Add support for different devices
+ * - Backlight support
+ *
+ * 2004-09-05: Herbert P鰐zl <herbert@13thfloor.at>
+ * - added clock (de-)allocation code
+ * - added fixem fbmem option
+ *
+ * 2004-07-27: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - code cleanup
+ * - added a forgotten return in h1940fb_init
+ *
+ * 2004-07-19: Herbert P鰐zl <herbert@13thfloor.at>
+ * - code cleanup and extended debugging
+ *
+ * 2004-07-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - First version
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/wait.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/div64.h>
+
+#include <asm/mach/map.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/fb.h>
+#include <asm/hardware/clock.h>
+
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+#include "s3c2410fb.h"
+
+
+static struct s3c2410fb_info info;
+static struct s3c2410fb_mach_info *mach_info;
+
+/* Debugging stuff */
+#ifdef CONFIG_FB_S3C2410_DEBUG
+static int debug = 1;
+#else
+static int debug = 0;
+#endif
+
+#define dprintk(msg...) if (debug) { printk(KERN_DEBUG "s3c2410fb: " msg); }
+
+/* useful functions */
+
+static inline struct s3c2410fb_info *fb_to_s3cfb(struct fb_info *info)
+{
+ return container_of(info, struct s3c2410fb_info, fb);
+}
+
+/* s3c2410fb_set_lcdaddr
+ *
+ * initialise lcd controller address pointers
+*/
+
+static void s3c2410fb_set_lcdaddr(struct s3c2410fb_info *fbi)
+{
+ struct fb_var_screeninfo *var = &fbi->fb.var;
+ unsigned long saddr1, saddr2, saddr3;
+
+ saddr1 = fbi->fb.fix.smem_start >> 1;
+ saddr2 = fbi->fb.fix.smem_start;
+ saddr2 += (var->xres * var->yres * var->bits_per_pixel)/8;
+ saddr2>>= 1;
+
+ saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH(var->xres);
+
+ dprintk("LCDSADDR1 = 0x%08lx\n", saddr1);
+ dprintk("LCDSADDR2 = 0x%08lx\n", saddr2);
+ dprintk("LCDSADDR3 = 0x%08lx\n", saddr3);
+
+ writel(saddr1, S3C2410_LCDSADDR1);
+ writel(saddr2, S3C2410_LCDSADDR2);
+ writel(saddr3, S3C2410_LCDSADDR3);
+}
+
+/* s3c2410fb_calc_pixclk()
+ *
+ * calculate divisor for clk->pixclk
+*/
+
+static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi,
+ unsigned long pixclk)
+{
+ unsigned long clk = clk_get_rate(fbi->clk);
+ unsigned long long div;
+
+ /* pixclk is in picoseoncds, our clock is in Hz
+ *
+ * Hz -> picoseconds is / 10^-12
+ */
+
+ div = (unsigned long long)clk * pixclk;
+ do_div(div,1000000UL);
+ do_div(div,1000000UL);
+
+ dprintk("pixclk %ld, divisor is %ld\n", pixclk, (long)div);
+ return div;
+}
+
+/*
+ * s3c2410fb_check_var():
+ * Get the video params out of 'var'. If a value doesn't fit, round it up,
+ * if it's too big, return -EINVAL.
+ *
+ */
+static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct s3c2410fb_info *fbi = fb_to_s3cfb(info);
+
+ dprintk("check_var(var=%p, info=%p)\n", var, info);
+
+ /* validate x/y resolution */
+
+ if (var->yres > fbi->mach_info->yres.max)
+ var->yres = fbi->mach_info->yres.max;
+ else if (var->yres < fbi->mach_info->yres.min)
+ var->yres = fbi->mach_info->yres.min;
+
+ if (var->xres > fbi->mach_info->xres.max)
+ var->yres = fbi->mach_info->xres.max;
+ else if (var->xres < fbi->mach_info->xres.min)
+ var->xres = fbi->mach_info->xres.min;
+
+ /* validate bpp */
+
+ if (var->bits_per_pixel > fbi->mach_info->bpp.max)
+ var->bits_per_pixel = fbi->mach_info->bpp.max;
+ else if (var->bits_per_pixel < fbi->mach_info->bpp.min)
+ var->bits_per_pixel = fbi->mach_info->bpp.min;
+
+ /* set r/g/b positions */
+
+ if (var->bits_per_pixel == 16) {
+ var->red.offset = 11;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 6;
+ var->blue.length = 5;
+ var->transp.length = 0;
+ } else {
+ var->red.length = 8;
+ var->red.offset = 0;
+ var->green.length = 0;
+ var->green.offset = 8;
+ var->blue.length = 8;
+ var->blue.offset = 0;
+ var->transp.length = 0;
+ }
+
+ return 0;
+}
+
+/* s3c2410fb_activate_var
+ *
+ * activate (set) the controller from the given framebuffer
+ * information
+*/
+
+static int s3c2410fb_activate_var(struct s3c2410fb_info *fbi,
+ struct fb_var_screeninfo *var)
+{
+ fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK;
+
+ dprintk("%s: var->xres = %d\n", __FUNCTION__, var->xres);
+ dprintk("%s: var->yres = %d\n", __FUNCTION__, var->yres);
+ dprintk("%s: var->bpp = %d\n", __FUNCTION__, var->bits_per_pixel);
+
+ switch (var->bits_per_pixel) {
+ case 1:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
+ break;
+ case 2:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
+ break;
+ case 4:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
+ break;
+ case 8:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
+ break;
+ case 16:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
+ break;
+
+ default:
+ /* invalid pixel depth */
+ dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel);
+ }
+
+ /* check to see if we need to update sync/borders */
+
+ if (!fbi->mach_info->fixed_syncs) {
+ dprintk("setting vert: up=%d, low=%d, sync=%d\n",
+ var->upper_margin, var->lower_margin,
+ var->vsync_len);
+
+ dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
+ var->left_margin, var->right_margin,
+ var->hsync_len);
+
+ fbi->regs.lcdcon2 =
+ S3C2410_LCDCON2_VBPD(var->upper_margin - 1) |
+ S3C2410_LCDCON2_VFPD(var->lower_margin - 1) |
+ S3C2410_LCDCON2_VSPW(var->vsync_len - 1);
+
+ fbi->regs.lcdcon3 =
+ S3C2410_LCDCON3_HBPD(var->right_margin - 1) |
+ S3C2410_LCDCON3_HFPD(var->left_margin - 1);
+
+ fbi->regs.lcdcon4 &= ~S3C2410_LCDCON4_HSPW(0xff);
+ fbi->regs.lcdcon4 |= S3C2410_LCDCON4_HSPW(var->hsync_len - 1);
+ }
+
+ /* update X/Y info */
+
+ fbi->regs.lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff);
+ fbi->regs.lcdcon2 |= S3C2410_LCDCON2_LINEVAL(var->yres - 1);
+
+ fbi->regs.lcdcon3 &= ~S3C2410_LCDCON3_HOZVAL(0x7ff);
+ fbi->regs.lcdcon3 |= S3C2410_LCDCON3_HOZVAL(var->xres - 1);
+
+ if (var->pixclock > 0) {
+ int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock);
+
+ clkdiv = (clkdiv / 2) -1;
+ if (clkdiv < 0)
+ clkdiv = 0;
+
+ fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_CLKVAL(0x3ff);
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv);
+ }
+
+ /* write new registers */
+
+ dprintk("new register set:\n");
+ dprintk("lcdcon[1] = 0x%08lx\n", fbi->regs.lcdcon1);
+ dprintk("lcdcon[2] = 0x%08lx\n", fbi->regs.lcdcon2);
+ dprintk("lcdcon[3] = 0x%08lx\n", fbi->regs.lcdcon3);
+ dprintk("lcdcon[4] = 0x%08lx\n", fbi->regs.lcdcon4);
+ dprintk("lcdcon[5] = 0x%08lx\n", fbi->regs.lcdcon5);
+
+ writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);
+ writel(fbi->regs.lcdcon2, S3C2410_LCDCON2);
+ writel(fbi->regs.lcdcon3, S3C2410_LCDCON3);
+ writel(fbi->regs.lcdcon4, S3C2410_LCDCON4);
+ writel(fbi->regs.lcdcon5, S3C2410_LCDCON5);
+
+ /* set lcd address pointers */
+ s3c2410fb_set_lcdaddr(fbi);
+
+ writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
+}
+
+
+/*
+ * s3c2410fb_set_par - Optional function. Alters the hardware state.
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ */
+static int s3c2410fb_set_par(struct fb_info *info)
+{
+ struct s3c2410fb_info *fbi = (struct s3c2410fb_info *)info;
+ struct fb_var_screeninfo *var = &info->var;
+
+ if (var->bits_per_pixel == 16)
+ fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+ else
+ fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+ fbi->fb.fix.line_length = (var->width*var->bits_per_pixel)/8;
+
+ /* activate this new configuration */
+
+ s3c2410fb_activate_var(fbi, var);
+ return 0;
+}
+
+static void schedule_palette_update(struct s3c2410fb_info *fbi,
+ unsigned int regno, unsigned int val)
+{
+ unsigned long flags;
+ unsigned long irqen;
+
+ local_irq_save(flags);
+
+ fbi->palette_buffer[regno] = val;
+
+ if (!fbi->palette_ready) {
+ fbi->palette_ready = 1;
+
+ /* enable IRQ */
+ irqen = readl(S3C2410_LCDINTMSK);
+ irqen &= ~S3C2410_LCDINT_FRSYNC;
+ writel(irqen, S3C2410_LCDINTMSK);
+ }
+
+ local_irq_restore(flags);
+}
+
+/* from pxafb.c */
+static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
+{
+ chan &= 0xffff;
+ chan >>= 16 - bf->length;
+ return chan << bf->offset;
+}
+
+static int s3c2410fb_setcolreg(unsigned regno,
+ unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *info)
+{
+ struct s3c2410fb_info *fbi = (struct s3c2410fb_info *)info;
+ unsigned int val;
+
+ /* dprintk("setcol: regno=%d, rgb=%d,%d,%d\n", regno, red, green, blue); */
+
+ switch (fbi->fb.fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ /* true-colour, use pseuo-palette */
+
+ if (regno < 16) {
+ u32 *pal = fbi->fb.pseudo_palette;
+
+ val = chan_to_field(red, &fbi->fb.var.red);
+ val |= chan_to_field(green, &fbi->fb.var.green);
+ val |= chan_to_field(blue, &fbi->fb.var.blue);
+
+ pal[regno] = val;
+ }
+
+ case FB_VISUAL_STATIC_PSEUDOCOLOR:
+ case FB_VISUAL_PSEUDOCOLOR:
+ if (regno < 256) {
+ /* currently assume RGB 5-6-5 mode */
+
+ val = ((red >> 0) & 0xf800);
+ val |= ((green >> 5) & 0x07e0);
+ val |= ((blue >> 11) & 0x001f);
+
+ writel(val, S3C2410_TFTPAL(regno));
+ schedule_palette_update(fbi, regno, val);
+ }
+
+ break;
+
+ default:
+ return 1; /* unknown type */
+ }
+
+ return 0;
+}
+
+
+/**
+ * s3c2410fb_pan_display
+ * @var: frame buffer variable screen structure
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ * Pan (or wrap, depending on the `vmode' field) the display using the
+ * `xoffset' and `yoffset' fields of the `var' structure.
+ * If the values don't fit, return -EINVAL.
+ *
+ * Returns negative errno on error, or zero on success.
+ */
+static int s3c2410fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ dprintk("pan_display(var=%p, info=%p)\n", var, info);
+
+ dprintk("pan_display: xoffset=%d\n", var->xoffset);
+ dprintk("pan_display: yoffset=%d\n", var->yoffset);
+
+ return 0;
+}
+
+/**
+ * s3c2410fb_blank
+ * @blank_mode: the blank mode we want.
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ * Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ * blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ * video mode which doesn't support it. Implements VESA suspend
+ * and powerdown modes on hardware that supports disabling hsync/vsync:
+ * blank_mode == 2: suspend vsync
+ * blank_mode == 3: suspend hsync
+ * blank_mode == 4: powerdown
+ *
+ * Returns negative errno on error, or zero on success.
+ *
+ */
+static int s3c2410fb_blank(int blank_mode, struct fb_info *info)
+{
+ dprintk("blank(mode=%d, info=%p)\n", blank_mode, info);
+
+ if (mach_info == NULL)
+ return -EINVAL;
+
+ if (blank_mode == FB_BLANK_UNBLANK)
+ writel(0x0, S3C2410_TPAL);
+ else {
+ dprintk("setting TPAL to output 0x000000\n");
+ writel(S3C2410_TPAL_EN, S3C2410_TPAL);
+ }
+
+ return 0;
+}
+
+static int s3c2410fb_debug_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", debug ? "on" : "off");
+}
+static int s3c2410fb_debug_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ if (mach_info == NULL)
+ return -EINVAL;
+
+ if (len < 1)
+ return -EINVAL;
+
+ if (strnicmp(buf, "on", 2) == 0 ||
+ strnicmp(buf, "1", 1) == 0) {
+ debug = 1;
+ printk(KERN_DEBUG "s3c2410fb: Debug On");
+ } else if (strnicmp(buf, "off", 3) == 0 ||
+ strnicmp(buf, "0", 1) == 0) {
+ debug = 0;
+ printk(KERN_DEBUG "s3c2410fb: Debug Off");
+ } else {
+ return -EINVAL;
+ }
+
+ return len;
+}
+
+
+static DEVICE_ATTR(debug, 0666,
+ s3c2410fb_debug_show,
+ s3c2410fb_debug_store);
+
+static struct fb_ops s3c2410fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = s3c2410fb_check_var,
+ .fb_set_par = s3c2410fb_set_par,
+ .fb_blank = s3c2410fb_blank,
+ .fb_pan_display = s3c2410fb_pan_display,
+ .fb_setcolreg = s3c2410fb_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor,
+};
+
+
+/* Fake monspecs to fill in fbinfo structure */
+/* Don't know if the values are important */
+static struct fb_monspecs monspecs __initdata = {
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 50,
+ .vfmax = 65,
+};
+
+/*
+ * s3c2410fb_map_video_memory():
+ * Allocates the DRAM memory for the frame buffer. This buffer is
+ * remapped into a non-cached, non-buffered, memory region to
+ * allow palette and pixel writes to occur without flushing the
+ * cache. Once this area is remapped, all virtual memory
+ * access to the video memory should occur at the new region.
+ */
+static int __init s3c2410fb_map_video_memory(struct s3c2410fb_info *fbi)
+{
+ dprintk("map_video_memory(fbi=%p)\n", fbi);
+
+ fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
+ fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
+ &fbi->map_dma, GFP_KERNEL);
+
+ fbi->map_size = fbi->fb.fix.smem_len;
+
+ if (fbi->map_cpu) {
+ /* prevent initial garbage on screen */
+ dprintk("map_video_memory: clear %p:%08x\n",
+ fbi->map_cpu, fbi->map_size);
+ memset(fbi->map_cpu, 0xf0, fbi->map_size);
+
+ fbi->screen_dma = fbi->map_dma;
+ fbi->fb.screen_base = fbi->map_cpu;
+ fbi->fb.fix.smem_start = fbi->screen_dma;
+
+ dprintk("map_video_memory: dma=%08x cpu=%p size=%08x\n",
+ fbi->map_dma, fbi->map_cpu, fbi->fb.fix.smem_len);
+ }
+
+ return fbi->map_cpu ? 0 : -ENOMEM;
+}
+
+static inline void modify_gpio(void __iomem *reg,
+ unsigned long set, unsigned long mask)
+{
+ unsigned long tmp;
+
+ tmp = readl(reg) & ~mask;
+ writel(tmp | set, reg);
+}
+
+
+/*
+ * s3c2410fb_init_registers - Initialise all LCD-related registers
+ */
+
+int s3c2410fb_init_registers(struct s3c2410fb_info *fbi)
+{
+ unsigned long flags;
+
+ /* Initialise LCD with values from haret */
+
+ local_irq_save(flags);
+
+ /* modify the gpio(s) with interrupts set (bjd) */
+
+ modify_gpio(S3C2410_GPCUP, mach_info->gpcup, mach_info->gpcup_mask);
+ modify_gpio(S3C2410_GPCCON, mach_info->gpccon, mach_info->gpccon_mask);
+ modify_gpio(S3C2410_GPDUP, mach_info->gpdup, mach_info->gpdup_mask);
+ modify_gpio(S3C2410_GPDCON, mach_info->gpdcon, mach_info->gpdcon_mask);
+
+ local_irq_restore(flags);
+
+ writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
+ writel(fbi->regs.lcdcon2, S3C2410_LCDCON2);
+ writel(fbi->regs.lcdcon3, S3C2410_LCDCON3);
+ writel(fbi->regs.lcdcon4, S3C2410_LCDCON4);
+ writel(fbi->regs.lcdcon5, S3C2410_LCDCON5);
+
+ s3c2410fb_set_lcdaddr(fbi);
+
+ dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel);
+ writel(mach_info->lpcsel, S3C2410_LPCSEL);
+
+ dprintk("replacing TPAL %08x\n", readl(S3C2410_TPAL));
+
+ /* ensure temporary palette disabled */
+ writel(0x00, S3C2410_TPAL);
+
+ /* Enable video by setting the ENVID bit to 1 */
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID;
+ writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
+ return 0;
+}
+
+static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi)
+{
+ unsigned int i;
+ unsigned long ent;
+
+ fbi->palette_ready = 0;
+
+ for (i = 0; i < 256; i++) {
+ if ((ent = fbi->palette_buffer[i]) == PALETTE_BUFF_CLEAR)
+ continue;
+
+ writel(ent, S3C2410_TFTPAL(i));
+
+ /* it seems the only way to know exactly
+ * if the palette wrote ok, is to check
+ * to see if the value verifies ok
+ */
+
+ if (readw(S3C2410_TFTPAL(i)) == ent)
+ fbi->palette_buffer[i] = PALETTE_BUFF_CLEAR;
+ else
+ fbi->palette_ready = 1; /* retry */
+ }
+}
+
+static irqreturn_t s3c2410fb_irq(int irq, void *dev_id, struct pt_regs *r)
+{
+ struct s3c2410fb_info *fbi = dev_id;
+ unsigned long lcdirq = readl(S3C2410_LCDINTPND);
+
+ if (lcdirq & S3C2410_LCDINT_FRSYNC) {
+ if (fbi->palette_ready)
+ s3c2410fb_write_palette(fbi);
+
+ writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDINTPND);
+ writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDSRCPND);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static char driver_name[]="s3c2410fb";
+
+int __init s3c2410fb_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct s3c2410fb_hw *mregs;
+ int ret;
+ int irq;
+ int i;
+
+ mach_info = dev->platform_data;
+ if (mach_info == NULL) {
+ dev_err(dev,"no platform data for lcd, cannot attach\n");
+ return -EINVAL;
+ }
+
+ mregs = &mach_info->regs;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "no irq for device\n");
+ return -ENOENT;
+ }
+
+ s3c2410fb_init_registers(&info);
+
+ dprintk("devinit\n");
+
+ strcpy(info.fb.fix.id, driver_name);
+
+ memcpy(&info.regs, &mach_info->regs, sizeof(info.regs));
+
+ info.mach_info = dev->platform_data;
+
+ info.fb.fix.type = FB_TYPE_PACKED_PIXELS;
+ info.fb.fix.type_aux = 0;
+ info.fb.fix.xpanstep = 0;
+ info.fb.fix.ypanstep = 0;
+ info.fb.fix.ywrapstep = 0;
+ info.fb.fix.accel = FB_ACCEL_NONE;
+
+ info.fb.var.nonstd = 0;
+ info.fb.var.activate = FB_ACTIVATE_NOW;
+ info.fb.var.height = mach_info->height;
+ info.fb.var.width = mach_info->width;
+ info.fb.var.accel_flags = 0;
+ info.fb.var.vmode = FB_VMODE_NONINTERLACED;
+
+ info.fb.fbops = &s3c2410fb_ops;
+ info.fb.flags = FBINFO_FLAG_DEFAULT;
+ info.fb.monspecs = monspecs;
+ info.fb.pseudo_palette = &info.pseudo_pal;
+
+ info.fb.var.xres = mach_info->xres.defval;
+ info.fb.var.xres_virtual = mach_info->xres.defval;
+ info.fb.var.yres = mach_info->yres.defval;
+ info.fb.var.yres_virtual = mach_info->yres.defval;
+ info.fb.var.bits_per_pixel = mach_info->bpp.defval;
+
+ info.fb.var.upper_margin = S3C2410_LCDCON2_GET_VBPD(mregs->lcdcon2) +1;
+ info.fb.var.lower_margin = S3C2410_LCDCON2_GET_VFPD(mregs->lcdcon2) +1;
+ info.fb.var.vsync_len = S3C2410_LCDCON2_GET_VSPW(mregs->lcdcon2) + 1;
+
+ info.fb.var.left_margin = S3C2410_LCDCON3_GET_HFPD(mregs->lcdcon3) + 1;
+ info.fb.var.right_margin = S3C2410_LCDCON3_GET_HBPD(mregs->lcdcon3) + 1;
+ info.fb.var.hsync_len = S3C2410_LCDCON4_GET_HSPW(mregs->lcdcon4) + 1;
+
+ info.fb.var.red.offset = 11;
+ info.fb.var.green.offset = 5;
+ info.fb.var.blue.offset = 0;
+ info.fb.var.transp.offset = 0;
+ info.fb.var.red.length = 5;
+ info.fb.var.green.length = 6;
+ info.fb.var.blue.length = 5;
+ info.fb.var.transp.length = 0;
+ info.fb.fix.smem_len = mach_info->xres.max *
+ mach_info->yres.max *
+ mach_info->bpp.max / 8;
+
+ for (i = 0; i < 256; i++)
+ info.palette_buffer[i] = PALETTE_BUFF_CLEAR;
+
+ if (!request_mem_region((unsigned long)S3C24XX_VA_LCD, SZ_1M, "s3c2410-lcd"))
+ return -EBUSY;
+
+ dprintk("got LCD region\n");
+
+ ret = request_irq(irq, s3c2410fb_irq, SA_INTERRUPT, pdev->name, &info);
+ if (ret) {
+ dev_err(dev, "cannot get irq %d - err %d\n", irq, ret);
+ return -EBUSY;
+ }
+
+ info.clk = clk_get(NULL, "lcd");
+ if (!info.clk || IS_ERR(info.clk)) {
+ printk(KERN_ERR "failed to get lcd clock source\n");
+ return -ENOENT;
+ }
+
+ clk_use(info.clk);
+ clk_enable(info.clk);
+ dprintk("got and enabled clock\n");
+
+ msleep(1);
+
+
+ /* Initialize video memory */
+ ret = s3c2410fb_map_video_memory(&info);
+ if (ret) {
+ printk( KERN_ERR "Failed to allocate video RAM: %d\n", ret);
+ ret = -ENOMEM;
+ goto failed;
+ }
+ dprintk("got video memory\n");
+
+ ret = s3c2410fb_init_registers(&info);
+
+ ret = s3c2410fb_check_var(&info.fb.var, &info.fb);
+
+ ret = register_framebuffer(&info.fb);
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to register framebuffer device: %d\n", ret);
+ goto failed;
+ }
+
+ /* create device files */
+ device_create_file(dev, &dev_attr_debug);
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n",
+ info.fb.node, info.fb.fix.id);
+
+ return 0;
+failed:
+ release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD);
+ return ret;
+}
+
+/* s3c2410fb_stop_lcd
+ *
+ * shutdown the lcd controller
+*/
+
+static void s3c2410fb_stop_lcd(void)
+{
+ unsigned long flags;
+ unsigned long tmp;
+
+ local_irq_save(flags);
+
+ tmp = readl(S3C2410_LCDCON1);
+ writel(tmp & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);
+
+ local_irq_restore(flags);
+}
+
+/*
+ * Cleanup
+ */
+static void __exit s3c2410fb_cleanup(void)
+{
+ s3c2410fb_stop_lcd();
+ msleep(1);
+
+ if (info.clk) {
+ clk_disable(info.clk);
+ clk_unuse(info.clk);
+ clk_put(info.clk);
+ info.clk = NULL;
+ }
+
+ unregister_framebuffer(&info.fb);
+ release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD);
+}
+
+#ifdef CONFIG_PM
+
+/* suspend and resume support for the lcd controller */
+
+static int s3c2410fb_suspend(struct device *dev, pm_message_t state, u32 level)
+{
+ if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN) {
+ s3c2410fb_stop_lcd();
+
+ /* sleep before disabling the clock, we need to ensure
+ * the LCD DMA engine is not going to get back on the bus
+ * before the clock goes off again (bjd) */
+
+ msleep(1);
+ clk_disable(info.clk);
+ }
+
+ return 0;
+}
+
+static int s3c2410fb_resume(struct device *dev, u32 level)
+{
+ if (level == RESUME_ENABLE) {
+ clk_enable(info.clk);
+ msleep(1);
+
+ s3c2410fb_init_registers(&info);
+
+ }
+
+ return 0;
+}
+
+#else
+#define s3c2410fb_suspend NULL
+#define s3c2410fb_resume NULL
+#endif
+
+static struct device_driver s3c2410fb_driver = {
+ .name = "s3c2410-lcd",
+ .bus = &platform_bus_type,
+ .probe = s3c2410fb_probe,
+ .suspend = s3c2410fb_suspend,
+ .resume = s3c2410fb_resume,
+};
+
+int __devinit s3c2410fb_init(void)
+{
+ return driver_register(&s3c2410fb_driver);
+}
+
+module_init(s3c2410fb_init);
+module_exit(s3c2410fb_cleanup);
+
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, Ben Dooks <ben-linux@fluff.org>");
+MODULE_DESCRIPTION("Framebuffer driver for the s3c2410");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h
new file mode 100644
--- /dev/null
+++ b/drivers/video/s3c2410fb.h
@@ -0,0 +1,56 @@
+/*
+ * linux/drivers/s3c2410fb.h
+ * Copyright (c) Arnaud Patard
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * S3C2410 LCD Controller Frame Buffer Driver
+ * based on skeletonfb.c, sa1100fb.h
+ *
+ * ChangeLog
+ *
+ * 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Moved dprintk to s3c2410fb.c
+ *
+ * 2004-09-07: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Renamed from h1940fb.h to s3c2410fb.h
+ * - Chenged h1940 to s3c2410
+ *
+ * 2004-07-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - First version
+ */
+
+#ifndef __S3C2410FB_H
+#define __S3C2410FB_H
+
+struct s3c2410fb_info {
+ struct fb_info fb;
+ struct device *dev;
+ struct clk *clk;
+
+ struct s3c2410fb_mach_info *mach_info;
+
+ /* raw memory addresses */
+ dma_addr_t map_dma; /* physical */
+ u_char * map_cpu; /* virtual */
+ u_int map_size;
+
+ struct s3c2410fb_hw regs;
+
+ /* addresses of pieces placed in raw buffer */
+ u_char * screen_cpu; /* virtual address of buffer */
+ dma_addr_t screen_dma; /* physical address of buffer */
+ unsigned int palette_ready;
+
+ /* keep these registers in case we need to re-write palette */
+ u32 palette_buffer[256];
+ u32 pseudo_pal[16];
+};
+
+#define PALETTE_BUFF_CLEAR (0x80000000) /* entry is clear/invalid */
+
+int s3c2410fb_init(void);
+
+#endif
diff --git a/include/asm-arm/arch-s3c2410/fb.h b/include/asm-arm/arch-s3c2410/fb.h
new file mode 100644
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/fb.h
@@ -0,0 +1,69 @@
+/* linux/include/asm/arch-s3c2410/fb.h
+ *
+ * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * Inspired by pxafb.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *
+ * Changelog:
+ * 07-Sep-2004 RTP Created file
+ * 03-Nov-2004 BJD Updated and minor cleanups
+ * 03-Aug-2005 RTP Renamed to fb.h
+*/
+
+#ifndef __ASM_ARM_FB_H
+#define __ASM_ARM_FB_H
+
+#include <asm/arch/regs-lcd.h>
+
+struct s3c2410fb_val {
+ unsigned int defval;
+ unsigned int min;
+ unsigned int max;
+};
+
+struct s3c2410fb_hw {
+ unsigned long lcdcon1;
+ unsigned long lcdcon2;
+ unsigned long lcdcon3;
+ unsigned long lcdcon4;
+ unsigned long lcdcon5;
+};
+
+struct s3c2410fb_mach_info {
+ unsigned char fixed_syncs; /* do not update sync/border */
+
+ /* Screen size */
+ int width;
+ int height;
+
+ /* Screen info */
+ struct s3c2410fb_val xres;
+ struct s3c2410fb_val yres;
+ struct s3c2410fb_val bpp;
+
+ /* lcd configuration registers */
+ struct s3c2410fb_hw regs;
+
+ /* GPIOs */
+
+ unsigned long gpcup;
+ unsigned long gpcup_mask;
+ unsigned long gpccon;
+ unsigned long gpccon_mask;
+ unsigned long gpdup;
+ unsigned long gpdup_mask;
+ unsigned long gpdcon;
+ unsigned long gpdcon_mask;
+
+ /* lpc3600 control register */
+ unsigned long lpcsel;
+};
+
+void __init set_s3c2410fb_info(struct s3c2410fb_mach_info *hard_s3c2410fb_info);
+
+#endif /* __ASM_ARM_FB_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-lcd.h b/include/asm-arm/arch-s3c2410/regs-lcd.h
--- a/include/asm-arm/arch-s3c2410/regs-lcd.h
+++ b/include/asm-arm/arch-s3c2410/regs-lcd.h
@@ -51,21 +51,32 @@

#define S3C2410_LCDCON1_ENVID (1)

+#define S3C2410_LCDCON1_MODEMASK 0x1E
+
#define S3C2410_LCDCON2_VBPD(x) ((x) << 24)
#define S3C2410_LCDCON2_LINEVAL(x) ((x) << 14)
#define S3C2410_LCDCON2_VFPD(x) ((x) << 6)
#define S3C2410_LCDCON2_VSPW(x) ((x) << 0)

+#define S3C2410_LCDCON2_GET_VBPD(x) ( ((x) >> 24) & 0xFF)
+#define S3C2410_LCDCON2_GET_VFPD(x) ( ((x) >> 6) & 0xFF)
+#define S3C2410_LCDCON2_GET_VSPW(x) ( ((x) >> 0) & 0x3F)
+
#define S3C2410_LCDCON3_HBPD(x) ((x) << 19)
#define S3C2410_LCDCON3_WDLY(x) ((x) << 19)
#define S3C2410_LCDCON3_HOZVAL(x) ((x) << 8)
#define S3C2410_LCDCON3_HFPD(x) ((x) << 0)
#define S3C2410_LCDCON3_LINEBLANK(x)((x) << 0)

+#define S3C2410_LCDCON3_GET_HBPD(x) ( ((x) >> 19) & 0x7F)
+#define S3C2410_LCDCON3_GET_HFPD(x) ( ((x) >> 0) & 0xFF)
+
#define S3C2410_LCDCON4_MVAL(x) ((x) << 8)
#define S3C2410_LCDCON4_HSPW(x) ((x) << 0)
#define S3C2410_LCDCON4_WLH(x) ((x) << 0)

+#define S3C2410_LCDCON4_GET_HSPW(x) ( ((x) >> 0) & 0xFF)
+
#define S3C2410_LCDCON5_BPP24BL (1<<12)
#define S3C2410_LCDCON5_FRM565 (1<<11)
#define S3C2410_LCDCON5_INVVCLK (1<<10)
@@ -100,10 +111,16 @@
#define S3C2410_DITHMODE S3C2410_LCDREG(0x4C)
#define S3C2410_TPAL S3C2410_LCDREG(0x50)

+#define S3C2410_TPAL_EN (1<<24)
+
/* interrupt info */
#define S3C2410_LCDINTPND S3C2410_LCDREG(0x54)
#define S3C2410_LCDSRCPND S3C2410_LCDREG(0x58)
#define S3C2410_LCDINTMSK S3C2410_LCDREG(0x5C)
+#define S3C2410_LCDINT_FIWSEL (1<<2)
+#define S3C2410_LCDINT_FRSYNC (1<<1)
+#define S3C2410_LCDINT_FICNT (1<<0)
+
#define S3C2410_LPCSEL S3C2410_LCDREG(0x60)

#define S3C2410_TFTPAL(x) S3C2410_LCDREG((0x400 + (x)*4))




Re: linux2.6的移植进度

首先对 大虾的 无私奉献精神 表示 万分感谢,
小弟这里有礼了!
试验之。。。。。



Copyright © 1999-2000 LSLNET.COM. All rights reserved. 蓝森林网站 版权所有。 E-mail : webmaster@lslnet.com