1.引言
  液晶显示器(LCD)具有显示信息丰富、功耗低、体积小、重量轻、超薄等许多其他显示器无法比拟的优点,近几年来被广泛用于单片机控制的智能仪器、仪表和低功耗电子产品中。LCD可分为段位式LCD、字符式LCD和点阵式LCD。其中,段位式LCD和字符式LCD只能用于字符和数字的简单显示,不能满足图形曲线和汉字显示的要求;而点阵式LCD不仅可以显示字符、数字,还可以显示各种图形、曲线及汉字,并且可以实现屏幕上下左右滚动、动画、分区开窗口、反转、闪烁等功能,用途十分广泛。本文介绍点阵式液晶显示器HS12232-1、HS12232-9与单片机的接口及编程的方法,同时给出两种显示器常用的字符显示和汉字显示程序。

2.不带汉字库的HS12232-1下的汉字显示
  2.1 显示原理
  利用PC上的16×16点阵汉字库,提取后将点阵文件存入ROM,直接利用PC中汉字内码作为单片机系统的编码(不再形成新的汉字编码)。

  2.2 硬件组成
  首先要采用点阵图形液晶显示器。(例如一行为240点,总列数为128点,可以容纳16×16点阵的汉字15个[因为240/16=15],128列可以显示8行[因为128/16=8]),广州市千喜科技开发有限公司的HS12232-1内置SED1520驱动控制器的点阵为122×32点,每行7个半汉字,共2行。如果要扩展存储器,全部国标16×16点阵汉字、8×16点阵的ASCII码点阵数据及汉字语句编码数据要使用1片512KB的存储器来存储,多出部分可以留作数据存储器。本文只探讨液晶显示器与单片机的接口部分,扩展存储器部分略。下面给出HS-12232-1与单片机8031的一种接口,如图1所示(VDD=+5V)。

  2.3 汉字显示原理
  国家标准信息交换用汉字字符集GB 2312-80共收录了汉字、图形符号等共7445个,其中汉字6763个,按照汉字使用的频度分为两级,其中一级汉字3755个,二级汉字3008个。汉字、图形符号根据其位置将其分为94个“区”,每个区包含94个汉字字符,每个汉字字符又称为“位”。其中“区”的序号由01区至94区,“位”的序号也由01位至94位。若以横向表示“位”号,纵向表示“区” 号,则“区”和“位”构成一个二维坐标。给定一个“区”值和“位”值就可以确定一个惟一的汉字或图形符号。即4位阿拉伯数字就可以惟一地确定一个汉字或符号。如“北”字的区位码是“1717”,而京字的区位码是“3009”。前两位是“区”号,后两位是“位”号。其中1至15区是各种图形符号、制表符和一些主要国家的语言字母,16区至87区是汉字,其中16区至55区是一级汉字,56至87区是二级汉字。

  UCDOS软件中的文件HZK16和文件ASC16分别为16×16的国际汉字点阵文件和8×16的ASCII码点阵文件,HZK16中按汉字区位码从小到大依次存放国标区位码表中的所有汉字,每个汉字占用32字节,每个区为94个汉字。而asc16文件中按ascii码从小到大依次存有8×16的ASCII码点阵,每个ASCII码占用16字节。

  PC的文本文件中,汉字是用机内码的形式存储的,每个汉字占2字节,其中第一个字节为机内码的区码,汉字机内码的区码范围是从0A1H(十六进制)开始,对应区位码中区码的第一区;而机内码的第二个字节为机内码的位码,范围也是从0A1H(十六进制)开始,对应某区中的第一个位码。就是说将汉字机内码减去0A0AH就得到该汉字的区位码。例如汉字“北”的机内码是十六进制的“B1B1”,其中前两位“B1”表示机内码的区码,后两位“B1”表示机内码的位码。所以“北”的区位码为0B1B1H-0A0A0H=1111H,将区码和位码分别转换为十进制,得汉字“北”的区位码为“1717”。即“北”的点阵位于第17区的第17个字的位置,在文件HZK16中的位置为第32×[(17-1)×94+(17-1)]=48640D以后的32个字节为“北”的显示点阵。用RF-1800编程器读入二进制文件hzk16j.bin后利用其编辑功能中的缓冲区编辑查找到BE00 H (48640D是十进制,将其转变为十六进制后得BE00 H)开始的32个字节:04 80 04 80 04 88 04 98 04 A0 7C C0 04 80 04 80 04 80 04 80 04 80 04 80 1C 82 E4 82 44 7E 00 00(以上全为下十六进制),将其写在16×16点阵方格纸上,即得图2。由此可以理解其相互逻辑关系。

  在单片机系统中,连续取32个字节送到LCD的相应位置,就能正确显示汉字后的图形符号。从HS-12232-1使用的SED1520的控制原理得知,字模送显示前要旋转90°,例如“逢”的区位码是3778,在HZK16中的位置为第32*[(37-1)*94+(78-1)]=110752D以后的32个字节:04 44 FF FE 05 40 41 F8 33 10 14 E0 01 18 F6 46 1B F8 10 40 13 F8 10 40 17 FC 10 40 28 46 47 FC , 旋转90°后上16个字节:82 8A 92 B2 02 A7 92 5E 2A AF 2A 5A 4A 83 82 00,下16个字节;00 80 40 3F 04 90 95 95 95 FF 95 95 95 D0 40 00。

  2.4 ASCII码的显示原理
  ASCII码的显示与汉字的显示基本原理相同,在ASC16文件中不存在机内码的问题,其显示点阵直接按ASCII码从小到大依次排列,不过每个ASCII码在文本文件中只占1个字节并且小于80 H, 每个ASCII码为8×16点阵,即在ASCII16文件中,每个ASCII码的点阵也只占16个字节。

3.带汉字库的HS12232-9下的汉字显示
  广州市千喜科技开发有限公司阵的HS12232-9内置ST7920A驱动控制器,点阵为122×32点,每行7个半汉字,共2行。内部字型ROM 包括8192个16×16点阵的中文字型和126个16×8点阵的字母符号字型,另外还提供一个64×256点的绘图区域(GDRAM)及240点的ICON RAM,可以和文字画面混合显示。内含的CGRAM有4组可编程的1616点阵的造字功能。与单片机的接口有8位并行、4位并行、2/3线串行。它采用低功率电源消耗,电压范围2.7~5.5V,功能齐全,汉字、点阵图形、ASCII码、曲线同屏显示;上下左右移动当前显示屏幕、清屏、光标显示、闪烁、睡眠、唤醒、关闭显示功能齐备,适合许多场合应用。上面使用了并行方式,现在研究串行方式。

  3.1 串行时序与硬件接口电路
  HS12232-9与单片机的串行接口时序如图3所示,即24个时钟脉冲传送一个字节。单片机首先发送数据传输起始位5个“1”,HS12232-9收到连续的5个“1”,内部传输被重置,同时串行传输被同步,紧接着RW位用于决定数据的传输方向(读还是写),RS用来选择是内部数据寄存器还是指令寄存器,第8位固定为“0”。收到起始位、RW、RS、“0”组成的第一个字节后,一个字节的数据或指令被分成两个字节来串行传送或接收。数据或指令的高4位被放在第二个字节串行数据的高4位,低4位补4个“0”,数据或指令的低4位被放在第三个字节串行数据的高4位,低4位补4个“0”,这样完成一个字节或数据的传送。HS12232-9内部没有发送/接收缓冲区,传送节奏要注意,否则要丢指令或数据。

  PIC16C5X单片机与HS12232-9接口电路如图4所示,只占用RA0、RA1两根I/O口,或者用16f877的RD6、RD7两根I/O口,RS(CS)引脚是片选,只有一片时固定接高电平使片选始终有效,SID引脚作数据线,SCLK引脚作时钟线。单片机通过SID数据线在SCLK同步时钟线配合下完成数据(指令)传输的任务。接口电路十分简单。

4.结束语
  利用自带字库的中文液晶图形点阵模块串口接口方式的优势比并口明显,节省I/O了口,不占用ROM,接口电路简单,解决了显示汉字
字符数量有限的瓶颈问题和小体积非总线结构单片机的汉字显示问题。笔者相信今后其使用率将逐步提高,对照本文的串并口两种方式,希望对广大同行在使用液晶图形点阵模块时有所启发和帮助。

  在具体介绍gba编程之前,我想先感谢一个人,他就是 水银 兄。在我学习的过程中水银兄给了我很多有用的宝贵资料,在此我向他表示感谢。

  GBA是新一代的32位手掌机,强大的机能吸引了无数玩家和编程爱好者。现在用于开发的编译器有两种,一种是完全免费的GCC,和收费的ARM SDT,目前我在使用的是gcc,虽然网上也有D过来的arm sdt但我是无福享用的,23MB的大家伙啊,当初下载gcc这个12MB的东东时我就已经吐血了,可怜我的小猫啊。

  好了,废话少说,进入正题。GBA使用的是卡带也就是只读rom为存储载体虽然容量可以很大,但问题也不少。也就是说我们不可能动态的分配使用卡上的内存了尽管它可以有128MB。当然gba也为我们提供了ram,至于容量嘛……,看下面的资料知道了。

单词含义:
1. GBA – 'Game Boy Advance' ^_^
2. BG(Backgroud) – '背景'
3. Sprite – '精灵'
4. Tile – '地图图块'
5. RAM(Random Access Memory) – '随机访问存储器'

接口地址 :

  外部 RAM: 地址: 0×02000000 大小: 256Kb 作用: 存放程序及数据
  内部 RAM: 地址: 0×03000000 大小: 32Kb? 作用: 我想是高速内存,和cache作用一样吧
  IO RAM: 地址: 0×04000000 大小: 1Kb 作用: 控制图像,声音,DMA等内存映射IO
  Palette – '调色板'
  地址: 0×05000000 大小: 0×400 bytes 作用: 存放调色板数据
  VRAM(Video RAM) – '视频内存'
  地址: 0×06000000 大小: 0×20000 bytes 作用: 位图模式下存放帧缓冲数据,图块模式下存放图块数据及图块地图数据
  OAM(Object Attribute Memory) – '精灵对象属性内存'
  地址: 0×07000000 大小: 0×400 bytes 作用: 用于控制精灵

6. ROM(Read Only Memory) – '只读存储器'
地址: 0×08000000 大小: 看你的游戏卡的大小罗 作用: 存放所有的程序和数据
7. ARM – 32bit 指令系统 (RISC,精简指令集)
8. Thumb – 16bit 指令系统 (具体区别详见 http://gbadev.org/files/armthumb-romram.txt)
9. DMA(Direct Memory Access) – 直接内存访问
10.DISPCNT(Display Controller) – 显示控制(内存地址)

  当初看水银兄写的gba教程时一直不明白明明是256色模式,可指向VRAM的指针却是short型的。后来才知道,gba访问VRAM时一次必须读写2个字节,即16bit。我晕~~!所以我只好严格要求自己的blit函数。虽然也找到一个可以写8bit的putpixel函数代码,但速度太慢了不适合用在显示大量图片的地方。

  需要注意的地方大概都说完了,我们可以进入代码部分了。

  虽然是专用游戏机,但显示模式也需要设定才行。

#define REG_DISPCNT *(u16*)0×04000000// 显示寄存器地址
#define VRAM 0×06000000 // 图像缓冲区地址
#define M5_VRAM 0x0600A000 // M5缓冲区地址
#define BACKBUFFER 0×010// 双缓冲/背缓冲地址
#define PALETTE 0×5000000// 调色板地址
#define MODE_3 0×03 // 240*160 15位/单缓冲区
#define MODE_4 0×04 // 240*160 8位/双缓冲区
#define MODE_5 0×05 // 160*128 15位/双缓冲区
#define BG2_ENABLE 0×0400 // BG_2
#define SetMode(Mode) REG_DISPCNT=(Mode) // 设置显示模式的宏定义

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;

typedef struct BITMAP
{
int x,y,w,h;
u16 MskCol;
float bitx,bity;
u8 flag;
u16 *dat;
}BITMAP;

BITMAP screen;

u16 *palette_mem = (u16 *)PALETTE;

void grp_init()
{
SetMode(MODE_4|BG2_ENABLE);
screen.w=240;
screen.h=160;
screen.dat=(u16 *)VRAM;
}

这样我们就进入了240*160*256的模式了, SetMode中的BG2_ENABLE这个参数不能少否则将没有任何显示。为了能够正常的显示图象还需要设置调色板。

void set_palette(unsigned short *palette)
{
int loop;
for(loop=0;loop<256;loop++)
{
palette_mem[loop] = palette[loop];
}
}

调色板数据可以从bmp2gba转换bmp图象后的.h中得到,需要注意的是bmp2gba不能够正确的转换过大的图象,大概是240*160以上的图片转换后都有问题,所以我自己写了一个pic2gba,可以转换256色的pcx,bmp(未压缩,转换前还需要进行一下旋转处理),gif格式的程序,但我不知道bmp2gba是如何转换调色板数据的,所以这部分数据是不正确的。

pic2gba使用方法:pic2gba in-file out-file。

水银兄的教程中是直接使用图象数据的,这对以后写game可不是一个好的方法,所以我才定义了BITMAP结构既然要显示图象就需要将图象数据装入BITMAP:

BITMAP load_bitmap(int width,int height,const unsigned char *dat)
{
BITMAP bitmap;
bitmap.dat=(u16*)dat;
bitmap.x=bitmap.y =0;
bitmap.w=width;
bitmap.h=height;
bitmap.MskCol=*bitmap.dat;
bitmap.flag=TRUE;
return bitmap;
}

然后再blit:

void blit(BITMAP dst,BITMAP src,int x1,int y1,int x,int y,int w,int h)
{
register int i=0,j;
register u16 *_bak1,*_bak2;
_bak1=dst.dat;
_bak2=src.dat;
_bak1+=x1+y1*(dst.w>>1);
_bak2+=x+y*(src.w>>1);

while(i<h)
{
memcpy(_bak1,_bak2,w);
_bak1+=120;
_bak2+=src.w>>1;
i++;
}
}

这个是最快的方法了。哦,对了还有更快的方法:直接使用DMA,可惜我这没资料。

如果是要显示汉字,除了水银兄的方法外(比较适合游戏中使用)也可以把整个汉字库都放到rom中去,用这个rhzk程序来转换数据。(需要UCDOS的HZK16,ASC16两个字库。)因为这里要写点,速度要求也比较低可以使用这个函数:

inline void putpixel(BITMAP bmp,int x,int y,u8 col)
{
u16 *tc;
tc=bmp.dat+(y)*(bmp.w>>1)+(x>>1);
if(x&1)*tc=((*tc&255)+(col<<8));
else
*tc=(*tc&65280)+col;
}

下面的是显示汉字的主体部分了,

struct ChinaHzk{
short len;
const u8 *CHzkBuf,*AHzkBuf;
char Loadhzk,HZK;
ChinaHzk();
}ChinaHzk;

ChinaHzk::ChinaHzk()
{
CHzkBuf=_CHzkBuf;
AHzkBuf=_AHzkBuf;//这两个指针在rhzk程序转换后的.h中定义
}

void hzput(int x,int y,int col,BITMAP bitmap1)
{
u8 dot;
register int i,j,k,mask;
if(ChinaHzk.HZK)
{
for(i=0;i<=15;i++)
{
for(j=0;j<=1;j++)
{
dot=*ChinaHzk.CHzkBuf++;
mask=0×80;
for(k=0;k<=7;k++)
{
if(dot&mask)
putpixel(bitmap1,x+j*8+k,y+i,col);
mask>>=1;
}
}
}
}
else
for(i=0;i<=15;i++)
{
dot=*ChinaHzk.AHzkBuf++;
mask=0×80;
for(k=0;k<=7;k++)
{
if(dot&mask)
putpixel(bitmap1,x+k,y+i,col);
mask>>=1;
}
}

ChinaHzk.HZK=1;
}

//显示字符
void textout(BITMAP bitmap1,char *Str,int x,int y,unsigned char col)
{
register unsigned long offset1;<
br /> int oldx;
const u8 *_bakCHzkBuf,*_bakAHzkBuf;

_bakCHzkBuf=ChinaHzk.CHzkBuf;
_bakAHzkBuf=ChinaHzk.AHzkBuf;
oldx=x;
while(*Str)
{
if(*Str=='\n') {y+=17;x=oldx;*Str++;continue;}
if(*Str==' ') {x+=8;*Str++;continue;}

if(!(*Str&0×80))
{
offset1=*Str<<4;
ChinaHzk.HZK=0;
ChinaHzk.AHzkBuf+=offset1;
hzput(x,y,col,bitmap1);
if(x+8+ChinaHzk.len<bitmap1.w)
{
x+=(8+ChinaHzk.len);
}
else
{
y+=17;x=oldx;
}
Str++;
ChinaHzk.HZK=1;
ChinaHzk.AHzkBuf=_bakAHzkBuf;
continue;
}

offset1=(unsigned int)((((*Str+95)<<6)+((*Str+95)<<5))-((*Str+95)<<1)+(*(Str+1)+95))<<5;
ChinaHzk.CHzkBuf+=(unsigned int)(offset1-778240);
hzput(x,y,col,bitmap1);
if(x+16+ChinaHzk.len<bitmap1.w)
{
x+=(16+ChinaHzk.len);
}
else
{
y+=17;x=oldx;
}
Str+=2;
ChinaHzk.CHzkBuf=_bakCHzkBuf;
}
}

//显示字符
void OutText(BITMAP bitmap,int x,int y,char *str,…)
{
va_list ptr;char *strr;
strr=(char*)malloc(strlen(str)+2);
va_start(ptr,str);
vsprintf(strr,str,ptr);
va_end(ptr);
textout(bitmap,strr,x,y,_COLOR);
free(strr);
}

你可以直接使用textout来显示也可以用OutText显示 变量-》字符 这样的信息,例:

OutText(screen,100,100,"X=%d,Y=%d",x,y);

有了这些基本函数,我想你已经可以写出一些东西来了,更多的资料请下载我写的函数库 GBA.ZIP
也许你看了这些会觉得有些眼熟,是的,如果你以前曾用过我写的游戏开发库Beauty的话,会发现基本上代码没有改变,而我当初也的确是有着样的想法, 即使在不同的平台上,不同的系统但使用一套相似的开发库进行开发可以为以后的移植工作省下很大力气。我在进行gba程序编写时就一直在使用Beauty库做测试相比之下要比用gba模拟器方便的多。

如果您是中国移动的手机用户,键入“0000”,发送短信至186201,数秒钟内将自动回复一条短信列表,显示您的手机上究竟订制了哪些短信服务,究竟是哪些短信服务商明着、暗着每月扣除您的手机费;键入“00000”,即可退订所有短信服务。这是3月14日,中国移动出台提示透明消费措施的内容之一。
移动:发0000到186201查询,发00000到186201退订所有短信服务
联通:手机拨打10109696(人工服务)

第一个男朋友很帅
可惜不高

第二个男朋友很帅很高
可惜没钱
 
第三个男朋友很帅很高有钱
可惜学历低
 
第四个男朋友很帅很高博士学位很有钱
可惜岁数太大了
 
第五个男朋友很帅很高博士学位很有钱年龄适当
可惜父母都是偏瘫
 
第六个男朋友很帅很高博士学位很有钱年龄适当家境优良
可惜爱你爱的不够深
 
第七个南朋友很帅很高博士学位很有钱年龄适当家境优良非常爱我
可惜已经结婚了
 
第八个男朋友很帅很高博士学位很有钱年龄适当家境优良非常爱我未婚
可惜他有八个女朋友
 
第九个男朋友很帅很高博士学位很有钱年龄适当家境优良非常爱我未婚只有我一个女朋友
可惜他堵赌博

第十个男朋友很帅很高博士学位很有钱年龄适当家境优良非常爱我未婚只有我一个女朋友人品优秀
可惜他有心脏病加高血压

Abstract
1 LCD Module\Driver\Controller
2 Linux Frame Buffer Driver
2.1 Why Frame Buffer?
2.2 What is Frame Buffer Devices?
2.3 How to Write Frame Buffer Device Drivers?
3 Analysis of Linux Frame Buffer Driver Source Codes
3.1 fb.h
3.2 fbmem.c
4 Skeleton of LCD controller rivers
4.1 Allocate a system memory as video memory
4.2 Implement the fb_ops functions
Reference

Abstract
This material discusses how to write a Linux frame buffer LCD device driver.

1 LCD Module\Driver\Controller

Besides the datasheet of LCD devices, there are two quite good books (.pdf format) on LCD technology. Both of them are written in Chinese. One is “液晶显示技术”, and the other is “液晶显示器件”. The two books give almost all needed LCD knowledge, including introductions to hardware implementation of LCD devices and low level software programming used to operate LCD devices. This helps LCD circuits design and low level LCD programming.

2 Linux Frame Buffer Driver

2.1 Why Frame Buffer?
If GUIs (Graphic User Interface) such as MiniGUI, MicroWindows are used, LCD device drivers must be implemented as Linux frame buffer device drivers in addition to those low level operations which only deal with commands provided by LCD controllers.

2.2 What is Frame Buffer Devices?
The frame buffer device provides an abstraction for the graphics hardware. It represents the frame buffer of some video hardware and allows application software to access the graphics hardware through a well-defined interface, so the software doesn't need to know anything about the low-level (hardware register) stuff.
The device is accessed through special device nodes, usually located in the /dev directory, i.e. /dev/fb*.
More description about frame buffer device can be found in two txt files: linux /Documentation /fb /framebuffer.txt and linux /Documentation /fb /interal.txt

2.3 How to Write Frame Buffer Device Drivers?
There are few instructive materials about writing frame buffer device drivers. You may find “Linux Frame buffer Driver Writing HOWTO” at this web page http: //linux-fbdev.sourceforge.net /HOWTO /index.html, but the HOWTO is somewhat curt and not enough. So having a look into Linux source codes is necessary. The next section is an analysis of the related source codes.

3 Analysis of Linux Frame Buffer Driver Source Codes

Linux implements Frame Buffer Drivers mainly based on the groundwork of these two files:
1) linux/include/linux/fb.h
2) linux/drivers/video/fbmem.c
It’s time to have a close look at them.

3.1 fb.h
Almost all important structures are defined in this file. First let me describe what each means and how they are used one by one.

1) fb_var_screeninfo
It is used to describe the features of a video card you normally can set. With fb_var_screeninfo, you can define such things as depth and the resolution you want.

struct fb_var_screeninfo {
__u32 xres; /* visible resolution */
__u32 yres;
__u32 xres_virtual; /* virtual resolution */
__u32 yres_virtual;
__u32 xoffset; /* offset from virtual to visible */
__u32 yoffset; /* resolution */

__u32 bits_per_pixel; /* guess what */
__u32 grayscale; /* != 0 Graylevels instead of colors */

struct fb_bitfield red; /* bitfield in fb mem if true color, */
struct fb_bitfield green; /* else only length is significant */
struct fb_bitfield blue;
struct fb_bitfield transp; /* transparency */

__u32 nonstd; /* != 0 Non standard pixel format */

__u32 activate; /* see FB_ACTIVATE_* */

__u32 height; /* height of picture in mm */
__u32 width; /* width of picture in mm */

__u32 accel_flags; /* acceleration flags (hints) */

/* Timing: All values in pixclocks, except pixclock (of course) */
__u32 pixclock; /* pixel clock in ps (pico seconds) */
__u32 left_margin; /* time from sync to picture */
__u32 right_margin; /* time from picture to sync */
__u32 upper_margin; /* time from sync to picture */
__u32 lower_margin;
__u32 hsync_len; /* length of horizontal sync */
__u32 vsync_len; /* length of vertical sync */
__u32 sync; /* see FB_SYNC_* */
__u32 vmode; /* see FB_VMODE_* */
__u32 reserved[6]; /* Reserved for future compatibility */
};

2) fb_fix_screeninfon
It defines the properties of a card that are created when you set a mode and can't be changed otherwise. A good example is the start address of the framebuffer memory. This can depend on what mode is set. Now while using that mode, you don't want to have the memory position change on you. In this case, the video hardware tells you the memory location and you have no say about it.

struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */
unsigned long smem_start; /* Start of frame buffer mem */
/* (physical address) */
__u32 smem_len; /* Length of frame buffer mem */
__u32 type; /* see FB_TYPE_* */
__u32 type_aux; /* Interleave for interleaved Planes */
__u32 visual; /* see FB_VISUAL_* */
__u16 xpanstep; /* zero if no hardware panning */
__u16 ypanstep; /* zero if no hardware panning */
__u16 ywrapstep; /* zero if no hardware ywrap */
__u32 line_length; /* length of a line in bytes */
unsigned long mmio_start; /* Start of Memory Mapped I/O */
/* (physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O */
__u32 accel; /* Type of acceleration available */
__u16 reserved[3]; /* Reserved for future compatibility */
};

3) fb_cmap
Device independent colormap information. You can get and set the colormap using the FBIOGETCMAP and FBIOPUTCMAP ioctls.

struct fb_cmap {
__u32 start; /* First entry */
__u32 len; /* Number of entries */
__u16 *red; /* Red values */
__u16 *green;
__u16 *blue;
__u16 *transp; /* transparency, can be NULL */
};

4) fb_info
It defines the current state of the video card. fb_info is only visible from the kernel. Inside of fb_info, there exist a fb_ops which is a collection of needed functions to make driver work.

struct fb_info {
char modename[40]; /* default video mode */
kdev_t node;
int flags;
int open; /* Has this been open already ? */
#define FBINFO_FLAG_MODULE 1 /* Low-level driver is a module */
struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */
struct fb_monspecs monspecs; /* Current Monitor specs */
struct fb_cmap cmap; /* Current cmap */
struct fb_ops *fbops;
char *screen_base; /* Virtual address */
struct display *disp; /* initial display variable */
struct vc_data *display_fg; /* Console visible on this display */
char fontname[40]; /* default font name */
devfs_handle_t devfs_handle; /* Devfs handle for new name */
devfs_handle_t devfs_lhandle; /* Devfs handle for compat. symlink */
int (*changevar)(int); /* tell console var has changed */
int (*switch_con)(int, struct fb_info*);
/* tell fb to switch consoles */
int (*updatevar)(int, struct fb_info*);
/* tell fb to update the vars */
void (*blank)(int, struct fb_info*); /* tell fb to (un)blank the screen */
/* arg = 0: unblank */
/* arg > 0: VESA level (arg-1) */
void *pseudo_palette; /* Fake palette of 16 colors and
the cursor's color for non
palette mode */
/* From here on everything is device dependent */
void *par;
};

5) struct fb_ops <
br />User application program can use ioctl() system call to operate low LCD hardware. Methods defined in fb_ops structure are used to support these operations.

struct fb_ops {
/* open/release and usage marking */
struct module *owner;
int (*fb_open)(struct fb_info *info, int user);
int (*fb_release)(struct fb_info *info, int user);
/* get non settable parameters */
int (*fb_get_fix)(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
/* get settable parameters */
int (*fb_get_var)(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
/* set settable parameters */
int (*fb_set_var)(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
/* get colormap */
int (*fb_get_cmap)(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info);
/* set colormap */
int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info);
/* pan display (optional) */
int (*fb_pan_display)(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
/* perform fb specific ioctl (optional) */
int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg, int con, struct fb_info *info);
/* perform fb specific mmap */
int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma);
/* switch to/from raster image mode */
int (*fb_rasterimg)(struct fb_info *info, int start);
};

6) structure map
struct fb_info_gen | struct fb_info | fb_var_screeninfo
| | fb_fix_screeninfo
| | fb_cmap
| | modename[40]
| | fb_ops —|—>ops on var
| | … | fb_open
| | | fb_release
| | | fb_ioctl
| | | fb_mmap
| struct fbgen_hwswitch -|-> detect
| | encode_fix
| | encode_var
| | decode_fix
| | decode_var
| | get_var
| | set_var
| | getcolreg
| | setcolreg
| | pan_display
| | blank
| | set_disp

[编排有点困难,第一行的第一条竖线和下面的第一列竖线对齐,第一行的第二条竖线和下面的第二列竖线对齐就可以了]
struct fbgen_hwswitch is an abstraction of hardware operations. It is not necessary, but sometimes useful.

3.2 fbmem.c
fbmem.c is at the middle place of frame buffer driver architecture. It provides system calls to support upper user application programs. It also provides an interface to low level drivers for specific hardware. Those low level frame buffer drivers can register themselves into the kernel by this interface. fbmem.c implements the common codes used by all drivers, thus avoids repeated work.

1) Global Varibles

struct fb_info *registered_fb[FB_MAX];
int num_registered_fb;
The two are used to record on-using instance of fb_info structure. fb_info represents the current state of video card. All fb_info structures are globally placed in an array. When a frame buffer registers itself to kernel, a new fb_info is added to this array and num_registered_fb increases 1.

static struct {
const char *name;
int (*init)(void);
int (*setup)(void);
} fb_drivers[] __initdata= { ….};
If frame buffer driver is static linked into kernel, a new entry must be added to this table. If use insmod/rmmod, don’t care this.

static struct file_operations fb_ops ={
owner: THIS_MODULE,
read: fb_read,
write: fb_write,
ioctl: fb_ioctl,
mmap: fb_mmap,
open: fb_open,
release: fb_release
};
This is the interface to user application programs. fbmem.c implements these functions here.

2) register_framebuffer(struct fb_info *fb_info)
unregister_framebuffer(struct fb_info *fb_info)
This is the interface to low level frame buffer device driver. The drivers use this pair of functions to register or unregister themselves.
Almost all the work those low level drivers needed to do is to fill in an fb_info structure and then to (un)register it.

4 Skeleton of LCD controller rivers
LCD drivers operate LCD device hardwares, while fbmem.c records and administrates these drivers. There is a skeleton frame buffer driver in linux /drivers /fb /skeleton.c. It shows how to implement a frame buffer driver with very few codes. Because it is too simple, it does nothing but filling an fb_info and then (un)registering it.
In order to implement a usable LCD controller driver, something else must be added into it. But what should be added? As we all know, device drivers abstract hardware and provide system call interface to user programs. So we can implements the low level hardware operations according to the need of the system call interface, namely the file_operations structure which is discussed in section 3.2.

4.1 Allocate a system memory as video memory
After a careful lookup in fbmem.c, we know that open() and release() method of file_operations structure do not need low level support, while read(), write() and mmap() need a common support function fb_get_fix(). So fb_get_fix() must be provided by driver writers.
Additionally the writer should allocate a system memory as video memory, for most LCD controllers have no their own video memory. The allocated memory start address and length are later placed in smem_start and smem_len fields of fb_fix_screeninfo structure. The allocated memory should be physically consecutive.

4.2 Implement the fb_ops functions
The only method of file_operations still not discussed is ioctl(). User application programs use ioctl() system call to operate LCD hardware. Methods defined in fb_ops structure(section 3.1) are used to support these operations. NOTE: fb_ops structure is NOT file_operations structure. fb_ops is for abstraction of low level operations, while file_operations is for upper level system call interface
Again we’d better first decide which methods should be implemented. ioctl() system call is implemented in fbmem.c, so we turn to it and quickly we can find out such relationship between ioctl() commands and fb_ops’s methods:
FBIOGET_VSCREENINFO fb_get_var
FBIOPUT_VSCREENINFO fb_set_var
FBIOGET_FSCREENINFO fb_get_fix
FBIOPUTCMAP fb_set_cmap
FBIOGETCMAP fb_get_cmap
FBIOPAN_DISPLAY fb_pan_display
Now we know that if we implement these fb_XXX_XXX functions, then user application writers can use FBIOXXXX micros to operate LCD hardwares. But how can we implement them?
It is fine to have a reference to linux/drivers/video/fbgen.c or other drivers under the linux/drivers/video directory.
Among these functions, fb_set_var() is the most important. It is used to set video mode and more. The following is the common steps performed by a fb_set_var() function:
1) Check if mode setting is necessary
2) Set the mode
3) Set colormap
4) Reconfigure the registers of LCD controller according former settings
The fourth step shows where low level operations are placed. Curious men may have such a question: how image data of user application are put onto the screen. Driver writer allocates a system memory as video memory, and later he sets the start address and length of the memory to LCD controller’s registers(often in fb_set_var() function). The content of the memory will be sent to screen automatically by LCD controller(for details, see specific LCD controller). On the other hand, the allocated system memory is mapped to user space by mmap(). Thereby, when a user sends data to the mapped memory, the data will be shown on LCD screen.

James Simmons, jsimmons@edgeglobal.com
v1.00, 9 October 1999

This document describes how to support a framebuffer video card for Linux.
It lists the supported video hardware, describes how to program the kernel
drivers, and answers frequently asked questions. The goal is to bring
current framebuffer driver writers as well as new ones up to speed on the
new developments accuring in the graphics system for linux.

______________________________________________________________________

Table of Contents

1. Introduction

1.1 Acknowledgments
1.2 Revision History
1.3 New versions of this document
1.4 Feedback
1.5 Distribution Policy

2. Framebuffer Video Card Technology

2.1 Monitor
2.2 Video Card

3. Setting a video mode

3.1 Fixed Frequency Monitors
3.2 Multi Frequency Monitors
3.3 Receipe for multisync monitors
3.4 Receipe for Monosync
3.5 Clocks
3.5.1 DCLK
3.5.2 MCLK
3.5.3 PLL
3.6 CRTC registers   
3.7 Colors

4. Framebuffer internal API

4.1 Data Structures
4.2 Driver layout

5. Answers To Frequently Asked Questions

5.1 Does fbdev support accels?

6. References

______________________________________________________________________

1. Introduction

This is the Linux Framebuffer driver HOWTO. It is intended as a quick
reference covering everything you need to know to write a framebuffer
video driver under Linux. Frequently asked questions about video mode
setting under Linux are answered, and references are given to some other
sources of information on a variety of topics related to computer
graphics. Also read this document not once, not twice but three times if
you are not familiar with video hardware.

The scope is limited to the aspects of writing a mode setting video card
framebuffer driver pertaining to Linux. See the other documents listed in
the References section for more general information on how to setup
framebuffer cards and setting up the XFB_Dev X server.

1.1. Acknowledgments

Much of this information came from the new framebuffer internal API being
developed by me for the upcoming next series of kernels. Originally this
was based on a patch by Fabrice Bellard. I learned of this patch and
was impressed by it. Later I took over development and improved it even
more. Much thanks goes to Fabrice for getting the ball rolling. This API is
a natural extension of the original API developed by Martin Schaller and
now maintained by Geert Uytterhoeven (geert@linux-m68k.org). Thanks
to you and the many others who developed the Linux framebuffer system,
drivers and utilities. A great amount of thanks goes to Andreas Beck of
the GGI project for helping me write this document and teaching me about
mode setting. Thanks also goes out to those who have supported my work.

Thanks to the SGML Tools package, this HOWTO is available in several
formats, all generated from a common source file.

1.2. Revision History

Version 1.0
first version; posted to fbdev mailing list only

1.3. New versions of this document

New versions of this document will be periodically posted to the
comp.os.linux.answers newsgroup. They will also be uploaded to various
anonymous ftp sites that archive such information including
<ftp://metalabs.unc.edu/pub/Linux/docs/HOWTO/>.

Hypertext versions of this and other Linux HOWTOs are available on
many World-Wide-Web sites, including <http://metalab.unc.edu/LDP/>.
Most Linux CD-ROM distributions include the HOWTOs, often under the
/usr/doc directory, and you can also buy printed copies from several
vendors. Sometimes the HOWTOs available from CD-ROM vendors, ftp
sites, and printed format are out of date. If the date on this HOWTO
is more than six months in the past, then a newer copy is probably
available on the Internet.

Most translations of this and other Linux HOWTOs can also be found at
<http://sunsite.unc.edu/pub/Linux/docs/HOWTO/translations/> and
<ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/translations/>.

If you make a translation of this document into another language, let
me know and I'll include a reference to it here. As of yet there are no
translations.

1.4. Feedback

I rely on you, the reader, to make this HOWTO useful. If you have any
suggestions, corrections, or comments, please send them to me,
jsimmons@edgeglobal.com, and I will try to incorporate them in the next
revision.

I am also willing to answer general questions on video cards and fbcon
under Linux, as best I can. Before doing so, please read all of the
information in this HOWTO, and send me detailed information about the
problem. Please do not ask me about using framebuffer cards under
operating systems other than Linux.

If you publish this document on a CD-ROM or in hardcopy form, a
complimentary copy would be appreciated. Mail me for my postal
address. Also consider making a donation to the Linux Documentation
Project to help support free documentation for Linux. Contact the
Linux HOWTO coordinator, Tim Bynum <mailto:linux-howto@sunsite.unc.edu>,
for more information.

1.5. Distribution Policy

Copyright (c) 1999 by James Simmons. This document may be
distributed under the terms set forth in the LDP license at
<http://sunsite.unc.edu/LDP/COPYRIGHT.html>.

2. Framebuffer Card Technology

This section gives a very cursory overview of graphics cards that have
accessible framebuffer technology, in order to help you understand the
concepts used later in the document. If you are considering writing a
driver for a video card please contact the manufacturer for documentation
on the card. Also please consider reading some books on video hardware in
order to learn more.

The way framebuffer devices behave under linux is something very similar
to /dev/mem. /dev/fb is in fact viewed as a memory device except in this case
the memory is video ram. Fbdev mmaps this memory to userspace for direct
access. This model is of course simplified for purpose of making programing
the frame buffer much easier as well as making it device and platform
independent. Since we are interested in building a driver we need to
userstand how exactly the video card itself works.

2.1 Monitor

First lets discribe one of the biggest but often overlooked components,
the monitor. Today there are many types of monitors. Flat screen to LED
and so on. For all the many types the basic principle behind the monitor is
the same. Basically a monitor builds an image sequentially from the data it
gets on its input lines. To achieve this a beam scans over the screen in a
kind of "zig-zag" pattern that covers the whole visible part of the screen
once per frame. It happens so fast the eye can't see this happening. Well we
hope. So which way does this beam go? All monitors have chosen to always
go left to right with a quick jump back to the far left when we hit the
right boundary of the monitor. Same for the top to bottom approach but at a
much slowe
r pace since most of our time is used to move left to right for
every single line. Obviously, the displayed data needs to be synchronized
with the current position of the beam to be able to build a steady picture.
This is what those HSYNC and VSYNC you see in your monitor manual are for.
These two lines that say "hey move the beam to the left now" and "move the
ray to the top now". Now some systems encode this information for example in
the green channel, which is called sync on green, but that doesn't change
the principle. All a monitor knows about a mode is what it gets that's
contained in the frequencies with which those signals return. These
frequencies are called the horizontal and vertical frequency (aka refresh
rate), as it determines how often per second a whole image is drawn. So a
monitor knows nothing about depth, clocks, borders. If two modes have the
same frequencies they will be the same to the monitor. This is why different
centering data for e.g. 640x480x16 and 640x480x32 are not stored in the
monitor. The monitor can't distinguish between those modes. Between two
HSYNC we get the RGB signals.

HSYNC __/~~~\______________________________________________/~~~\___
RGB ___________datadatadatadatadatadatadatadatadatad_____________
time 1 2 3 4 5

At 1, the HSYNC pulse gets raised. The beam will now quickly move to the
left. During that time, the rgb lines should be black (ray off), as
otherwise it would leave a noticeable trace while moving, which would look
ugly.

At 2, the HSYNC pulse ends. This point isn't of much interest, as you cannot
tell if the ray is already at the left edge. The only thing important
about point 2 is, that the time between point 1 and 2 must be sufficiently
high for the monitor to detect the HSYNC signal. Usually the HSYNC pulse can
be made very small.

At some point after 1, the ray will start flying to the right again. When
point 3 comes, it will actually start to display data. Point 3 can thus be
adjusted to change the left border location. If you wait longer until you
start sending data, the left border will move to the right.

When you have sent all data you reach point 4. As a HSYNC pulse should then
be sent, to start a new line, we set the RGB lines to black again.
At point 5 we have completed a cycle and start the next line.

2.2 Video card

Next we look at the video card point of view. The video card could send out
a steady stream of data to the monitor except for one thing. The monitor
needs time for retracing so the video card will be put into some "delay"
at specific times. To be precise between point 4 and point on the NEXT line)
on the previous diagram. For the video card the "natural" coordinate system
starts at point 3, when it starts emitting data. This point usually causes
some confusion with modeline-calculation:

HSYNC __/~~~\______________________________________________/~~~\___
RGB ___________datadatadatadatadatadatadatadatadatad_____________
time 1 2 3 4 5 6
grc SS SE 0 W SS SE

From the graphics card point of view (grc) a line starts at "0". From that
point onward, it will output the data in its video ram. There is a counter
that will limit the number of pixels that are put on one line. This is what
we call the width of the mode. On a 640×480 standard VESA mode, this is 640
pixels.

Now we will usually want a small right border to allow the monitor to
prepare for the following SYNC pulse we will generate. The aforementioned
counter will run on (but data output from video RAM will be suppressed)
until we reach the point SS (SyncStart). On a 640×480 standard VGA mode,
this happens at 664 pixels. That is, we left a border of 24 pixels.

Now we raise the HSYNC to tell the monitor to go left. This signal remains
asserted until we reach the point SE (SyncEnd). (760 pixels on VGA -
i.e. 96 pixels of sync pulse. This is pretty long, but VGA monitors weren't
very quick.)

We will also want some left border, so we wait until we reach the next "0"
point before starting to generate a signal again. On standard VGA this
happens at 800 pixels (40 pixels left border). At that point, we reset the
counter to 0 and start over. This point is usually called the "total"
for this reason.

Now let us look at how we can change the picture's appearance by changing
values in such a modeline.

Moving SE should not cause any difference at all, except if you make the
sync pulse too small for the monitor to recognize.

Moving SS and SE together will move the location of the sync pulse within
the picture. Let us assume we move them both to the "left", i.e. we
decrease their startpoints. What happens is, that we decrease the distance
W-SS (which determines the right border) and increase 0-SE (the left
border). As a result, the picture moves to the right.

Now what happens, if you change W ? You get extra pixels at the right
border. As usually borders are pretty large for standard VGA modes,
you can usually display something like 648×486 without a problem on a
standard VGA monitor. You will not be able to see the difference.

Of course there are limits to this: If you go too far, you will produce
pixels beyond the visiable area of the monitor which is useless, or
interfere with the retrace; that gives ugly stripes from the retracing
CRT ray.

Now let's shed some light on a few remaining terms:

Blankstart BS and blankend BE. Between SE and 0, you can put a BE point on
many graphics cards. At that point, the RGB lines are no longer clamped to
black (to avoid interfering with the retrace), but can be programmed to a
border color. The same goes for BS, which can be placed between W and SS.
Usually one doesn't use that feature nowadays, as we have tuneable monitors
that allow to stretch the mode to the physical limits of the monitor.

On old monitors, one used large borders to ensure the data was always
visible. There the border color made some sense as kind of eye candy.

Pixelclock. That is the rate at which pixels are output to the RGB lines.
It is usually the basic unit for all timing values in a graphics card.

3. Actually calculating a mode

If you look at the fbdev driver you think yikes. Yes it's complex but not as
much as you think. A side note about standard modes. It's a common
misconception that graphics cards cannot do anything but the VGA/VESA
induced "standard" modes like 640×480, 800×600, 1024×768, 1280×960, …
With most cards, about any resolution can be programmed, though many
accelerators have been optimized for the abovementioned modes, so that it
is usually NOT wise to use other widths, as one might need to turn OFF
accelerator support. So if you write a driver, don't cling to these modes.
If the card can handle it, allow any mode.

Here the type of monitor has a big impact on what kind of modes we can have.
There are two basic types of monitors, fixed frequency (they usually can do
multiple vertical frequencies, though, which are much less critical, as they
are much lower) and multifrequency.

3.1 Fixed freq
uency monitors

The monitor manual says the horizontal frequency (hfreq) is 31.5 kHz.

And we want to display a given mode, say 640×480.

We can now already determine the absolute minimum dotclock we need, as

dotclock = horiz_total * hfreq

and

horiz_total = width + right_border + sync + left_border > width

The minimum dotclock computes to 20.16 MHz. We will probably need
something around 20% "slack" for borders and sync, so let's say we need
about a 24MHz clock. Now we look at the next higher clock our card can
handle, which is 25.175 MHz, as we assume we have a VGA compatible card.

Now we can compute the horizontal total:

horiz_total = dotclock / hfreq = 799.2

We can only program this as multiples of 8, so we round to 800.
Now we still need to determine the length and placement of the sync pulse,
which will give all remaining parameters.

There is no clean mathematical requirement for those. Technically, the sync
must be long enough to be detected, and placed in a way that the mode is
centered. The centering issue is not very pressing anymore, as digitally
controlled monitors are common, which allow to control that externally.
Generally you should place the sync pulse early (i.e. keep right_border
small), as this will usually not cause artifacts that would arise from
turning on the output again too early, when the sync pulse is placed too
late.

So if we as a "rule-of-thumb" use a half of the blanking period for the sync
and divide the rest as 1/3 right-border, 2/3 left border, we get a modeline
of

"640×480" 25.175 640 664 744 800 ??? ??? ??? ???

While this is not perfectly the same as a standard VGA timing, it should run
as well on VGA monitors. The sync is a bit shorter, but that shouldn't be a
real problem.

Now for the vertical timing. At 480 lines, a VGA monitor uses 60Hz.

hfreq = vfreq * vert_total

which yields vert_total=525. The vertical timings usually use much less
overhead than the horizontal ones, as here we count whole _lines_, which
means much longer delays than just pixels. 10% overhead suffice here, and
we again split the borders 1/3 : 2/3, with only a few lines (say 2) for
the sync pulse, as this is already much longer than a HSYNC and thus easily
detectable.

"640×480" 25.175 640 664 744 800 480 495 497 525

let us compare that to an XF86 Modeline that claims to be standard VGA:

Modeline "640×480" 25.175 640 664 760 800 480 491 493 525

Not much difference – right ? They should both work well, just a little
shifted against each other vertically.

3.2 multiscan monitor

Here we will consider a theorical monitor that can do hfreq 31-95kHz and
vfreq 50-130Hz. Now let's look at a 640×480 mode. Our heuristics say,
that we will need about 768×528 (20% and 10% more) for borders and sync.
We as well want maximum refresh rate, so let's look what limits the mode:

hfreq = vfreq * vtotal = 130 * 528 = 68.6 kHz

Oh – we cannot use the full hfreq of our monitor … well no problem. What
counts is the vfreq, as it determines how much flicker we see.

O.K. – what pixelclock will we need ?

pixclock = hfreq * htotal.

The calculation yields 52.7MHz.

Now we look what the card can do. Say we have a fixed set of clocks. We look
what clocks we have close by. Assume the card can do 50 and 60 MHz.

Now we have the choice: We can either use a lower clock, thus scaling down
the refresh rate a bit (by 5% … so what …): This is what one usually
does.

Or we can use a higher clock, but this would exceed the monitor
specifications. That can be countered by adding more border, but this is
usually not done, as it is a waste of space on the screen
However keep it in mind as a trick for displaying 320×200, when you do not
have doubling features. It will display in a tiny window in the middle of
the screen, but it will display.

O.K. – what will our calculation yield ?

"640×480" 50 640 664 728 768 480 496 498 528 # 65kHz 123Hz

I just mentioned doubling features. This is how VGA does 320×200. It
displays each pixel twice in both directions. Thus it effectively is a
640×400 mode. If this would not be done, you would need a pixelclock of
12.59MHz and you would still have the problem of needing a 140Hz refresh, if
hsync should stay at 31.5kHz.

A horizontal doubling feature allows to use the 25.175MHz clock intended
for 640, and a line doubling feature keeps the vsync the same as 400 lines.
Actually the line-doubler is programmable, so you can as well use modes as
sick as 640×50.

O.K. – another example. Same monitor, 1280×1024.

Now we need about 1536×1126 total (same rule of thumb).
That yields 130Hz*1126lines = 146 kHz. We would exceed the hfreq with that,
so now the hfreq is the limit and we can only reach a refresh rate of about
(95kHz/1126) 84 Hz anymore.

The required clock is now 146MHz. That would yield:

"1280×1024" 146 1280 1320 1448 1536 1024 1058 1060 1126 # 95kHz 84Hz

Now the clock might be programmable, but keep in mind, that there may be
limits to the clock. DO NOT OVERCLOCK a graphics card. This will result in
the RAMDAC producing blurry images (as it cannot cope with the high speed),
and more importantly, the RAMDAC will OVERHEAT and might be destroyed.

Another issue is memory bandwidth. The video memory can only give a certain
amount of data per time unit. This often limits the maximum clock at modes
with high color depth (i.e. much data per pixel). In the case of my card it
limits the clock to 130MHz at 16 bit depth, what would produce:

"1280×1024" 130 1280 1320 1448 1536 1024 1058 1060 1126 # 85kHz 75Hz

which is pretty much, what my monitor shows now, if I ask it.

3.3 Recipe for multisync monitors

a) Determine the totals by calculating htotal = width*1.2 and
vtotal = height*1.1 .
b) Check what limits the refresh by calculating vfreq2 = hfreqmax/vtotal.
If that exceeds vfreqmax, the limit is on the vfreq side, and we use
vfre = vfreqmax and hfreq = vfreqmax*vtotal. If it doesn't, the mode is
limited by hfreq and we have to use vfreq = vfreq2.
Note, that if this is smaller than vfreqmin, the mode cannot be displayed.
In the vfreq-limited case, you might exceed hfreqmin, which can be
countered by using linedoubling facilities, if available. You can also
add extra blank lines (increase vtotal) as a last-resort alternative.
c) Now that you have hfreq and vfreq, calculate the pixel clock using
pixclock=hfreq*htotal. Use the next lower pixel clock. If you are below
the lowest clock, you might want to try horizontal doubling features or
you will have to pad the mode by increasing htotal.
d) Again check the monitor limits. You might be violating lower bounds now
… In that case you might need to resort to choosing a higher clock
and padding as well.
e) You now have pixclock, width, height, htotal and vtotal. Calculate the
sync start positions: hss=width+(htotal-width)/2/3 ;
vss=height+(vtotal-height)/3; Make sure to properly align them as
required by the video card hardware hss usually has to be a
multiple of
8.
f) SyncEnd is calculated similarly: hse=hss+(htotal-width)/2 and vse=vss+2.

3.4 Receipe for Monosync:
a) Calculate the number of lines. As hfreq and vfreq are given, vtotal is
fixed: vtotal=hfreq/vfreq. If there are multiple vfreqs allowed, choose
them according to your desired vtotal (i.e. one that gives the lowest
vtotal above what you really need).
b) Calculate the pixelclock. pixclock=hfreq*htotal. htotal starts at the
same estimate (width*1.2) we used above.
c) Adjust the pixelclock to hardware-limits. Adjust _UP_. Now recalculate
the htotal=pixclock/hfreq.
d) Go to 3.3. e)

A important final word. Most video card documentations gives you the exact
equations needed to set a mode. Here we give approached values. Use the
exact values given in the documents.

3.5 Clocks

Clocks on a video card ensure that different parts of the video hardware
happen at the correct time and in the correct order. For those not familiar
with computer clocks they work by generating a pulse at regular intervals
like what is shown below. You will something similar in your video
documentation.
___ ___ -  
| | | | V The period (T) represents the time between two
___| |___| |___ _ "ticks" of thee clock, and the frequency of the
clock is how many clock ticks happen per second.
| T |

The height of the pulse (V) is the difference in the voltage. This means
for T/2 units of time the voltage is at V1 then for the next T/2 it goes
to another voltage. Normally you don't have to worry about the amplitude
(height) of the pulse except for some cards that allow you to set the
height for powersaving mode. Normally you just want to change the frequency.
The hardware uses a clock for every part of the hardware except the bus
clock which is apart of the motherboard. No need to worry about that one.
Their exist many types of clocks. For video cards you can come across two
types of clocks. The first type you might come across are fixed clock
generators which are used in older video cards. The second type of clock
used in modern vidoe cards are called PLL (Phase Lock Loop).

In the documentation you might see terms about edge triggered devices. The
different types of edge triggers can be:

3.5.1 PLL
  
A PLL is composed of a multipler and a divider. They multiple a reference
frequency by a integer mulitplier, and then divide it by a integer divider.
Of course a PLL has a low

3.5.2 DCLK

3.5.3 MCLK

3.6 CRTC registers   

3.7 Colors

There is an endless number of colors but colors have a special property.
If you take two colors and mix them together you get a different color.
There are many models to represent colors but fbdev is based on what is
known as the RGB color model. Out of all the colors there are three colors
in this model which when mixed in different amounts can produce any color.
These colors are known as primary colors. There is a physical limit
to mixing colors. If you mix red, green, and blue in equal amounts
you get gray. Now if you make each color component equally brighter the final
color will become white. Now there is a point where making each component
brighter and brighter you will still end up with white. You can increase the
intensity of a color component by any amount from some inital value up to
this physical limit. This is where the image depth comes in. As you know on
most cards you can have an image depth from one bit to 32 bits. Image depth
is independent of the mapping from the pixel to the color components. It
also is independent of the memory layout to pixel mapping. Note some cards
have a complex mapping from the pixel values to the color components (red,
blue, green) as well as video memory to pixel mapping. If this is the case
you will have to consult your documentation on your video card to see what
the mapping exactly is. Here are the mappings defined from top to bottom in
fbdev starting with the value of the color components.

{red,blue,green}
|
FB_VISUAL_MONO01
FB_VISUAL_MONO10
FB_VISUAL_TRUECOLOR
FB_VISUAL_PSEUDOCOLOR
FB_VISUAL_DIRECTCOLOR
FB_VISUAL_STATIC_PSEUDOCOLOR
|
pixel value
FB_TYPE_PACKED_PIXELS
FB_TYPE_PLANES
FB_TYPE_INTERLEAVED_PLANES
FB_TYPE_TEXT
FB_TYPE_VGA_PLANES
|
value in video memory

The way fbdev tells what this video memory to pixel mapping is, is with
the type field in fb_fix_screeninfo. Here I'm going to describe the
FB_TYPE_PACKED_PIXELS layout since it is the most common. Here there is
a direct mapping from video memory to pixel value. If you place a 5 in video
memory then the pixel value at that position will be 5. This is important
when you have memory mapped the video memory to userland. Next we consider
the mapping from a pixel value to the colors. This is represented in the
fbdev API by the visual field in fb_fix_screeninfo. As you can see from the
above diagram this mapping is independent from the mapping from video memory
to pixel value. This means a FB_TYPE_PLANES could have FB_VISUAL_MONO01 just
like FB_TYPE_PACKED_PIXELS can. To understand visuals we have to go back to
the first types of video hardware. In the begining there was just monochrome
monitors. Here we could only display 2 colors. The foreground and background
color. Traditionally these colors are black and white but if you are old
enough you would remember the old green monitors. In fbdev API we define two
types of monochrome modes. The difference between the two is that the
foreground and background colors are swapped. Then computers began to
support color. The only problem was they could only display a small number of
colors at one time. What if you wanted to have an application display a
certain set of colors. Well the way that was developed to get around this
was the idea of a color map. A color map translated a pixel value to the
colors needed. If your application needs a specific set of colors it would
switch the color maps and you would get the needed colors. Of course this
also switches the other colors in the applications. That was the trade off.
This became what was known as pseudocolor mode. In fbdev API there are two
types of pseudocolor mappings. A static one and a dynamic one.
FB_VISUAL_STATIC_PSEUDOCOLOR defines a video card that has a non programmable
color map. What colors you get are what you are stuck with. The other type
of color map can be changed. Video cards in time started to support more
colors but this required having a larger color map. Also video memory prices
started to drop and video cards begain to sell with more of it. To properly
support 256 color intensity levels for each color component you would
need a
color map of 16 million colors. So new mappings were developed in which
specific fields of a pixel were directly proportional to the intensity of a
color component. Two types of mappings were developed. One was truecolor
and the other directcolor. In truecolor you cannot change the mappings from
the pixel value to color intensities. Setting a value of 64 to the red
component of the pixel will result in a red intensity of 64. How bright of a
red this is depends on the image depth. For directcolor you can control this.
You could make a pixel value in the red field of 64 equal 128 for the
intensity. Also some cards support an alpha value which is used in higher
graphics which for fbdev is of little importance than it should always be
set to the highest value it can have. For most cards alpha shows up for 15
bit modes where each color compenent can have up to 32 intensity levels (2^5)
and one bit represents the alpha component. It also shows up for 32 bit
modes where each component red, blue, green, and alpha are given 256
intensity levels (2^8). 24 bit mode is like 32 bit mode except it lacks the
alpha component. A important note is that some cards only support 24 bit
mode on certain architectures.

4. Framebuffer internal API

Now that we understand the basic ideas behind video card technology and mode
setting we can now look at how the framebuffer devices abstract them. Also
we will see that fbdev actually handles most of the mode setting issues for
you to make life much easier. In the older API the console code was heavily
linked to the framebuffer devices. The newer API has now moved nearly all
console handling code into fbcon itself. Now fbcon is a true wrapper around
the video card's abilities. This allowed for massive code reduction and
easier driver developement. A good example of a framebuffer driver is vfb.
The vfb driver is not a true framebuffer driver. All it does is map a chunk
of memory to userspace. It's used for demonstration purposes and testing.

4.1 Data Structures

The framebuffer drivers depend heavily on four data structures. These
structures are declared in fb.h. They are fb_var_screeninfo,
fb_fix_screeninfo, fb_monospecs, and fb_info. The first three can be made
available to and from userland. First let me describe what each means and
how they are used. Fb_var_screeninfo is used to describe the features of
a video card you normally can set. It's with fb_var_screeninfo you can define
such things as depth and the resolution you want. The next structure is
fb_fix_screeninfo. This defines the properties of a card that are created
when you set a mode and can't be changed otherwise. A good example is the
start of the framebuffer memory. This can depend on what mode is set. Now
while using that mode you don't want to have the memory position change on
you. In this case the video hardware tells you the memory location and you
have no say about it. The third structure is fb_monospecs. In the old API
the importance of fb_monospecs was very little. This allowed for forbidden
things such as setting a mode of 800×600 on a fixed-frequency monitor. With
the new API fb_monospecs prevents such things and if used correctly can
prevent a monitor from being cooked. The final data structure is fb_info.
This defines the current state of the video card. Fb_info is only visible
from the kernel. Inside of fb_info there is a fb_ops which is a collection
of needed functions to make fbdev and fbcon work.

4.2 Driver layout

Here I discribe a clean way to code your drivers. A good example of the
basic layout is in vfb.c. In the example driver we first present our data
structures in the begining of the file. Note there is no fb_monospecs since
this is handled by code in fbmon.c. This can be done since monitors are
independent in behavior from video cards. First we define our three basic
data structures. For all the data structures I defined them static and
declare the default values. The reason I do this is that it's less memory
intensive than allocating a piece of memory and filling in the default
values. Note for drivers that support multihead on the same card
the fb_info should be dynamically allocated for each card present. For
fb_var_screeninfo and fb_fix_screeninfo they still are declared static
since all the cards can be set to the same mode.

4.3 Initialization and boot time parameter handling

There are two functions that handle the video card at boot time.

int xxfb_init(void);
int xxfb_setup(char*);

In the example driver as with most drivers these functions are placed at
the end of the driver. Both are very card specific. In order to link
your driver directly into the kernel both of these functions you must add
the above definition with extern in front to fbmem.c. Then add these
functions to the following in fbmem.c

static struct {
const char *name;
int (*init)(void);
int (*setup)(char*);
} fb_drivers[] __initdata = {
#ifdef CONFIG_FB_YOURCARD
{ "driver_name", xxxfb_init, xxxfb_setup },
#endif

Setup is used to pass card specific options from the boot prompt of your
favorite boot loader. A good example is boot:video=matrox:vesa:443. The
basic setup function is

int __init xxxfb_setup(char *options)
{
char *this_opt;

if (!options || !*options)
return 0;

for (this_opt = strtok(options, ","); this_opt;
this_opt = strtok(NULL, ","))
if (!strcmp(this_opt, "my_option")) {
/* Do your stuff. Usually set some static flags that
the driver later uses */
} else if (!strncmp(this_opt, "Other_option:", 5))
strcpy(some_flag_driver_uese, this_opt+5);
} else ….
}

The xxxfb_init function sets the inital state of the video card. This
function has to consider bus and platform handling since today most cards
can exist on many platforms. For bus types we have to deal with there are
PCI, ISA, zorro. Also some platforms offer firmware that returns information
about the video card. In these cases we often don't need to deal with the
bus unless we need more control over the card. Let's look at Open Firmware
that's available on PowerPCs. If you are going to use Open Firmware to
initalize your card you need to add the following to offb.c.

#ifdef CONFIG_FB_YOUR_CARD
extern void xxxfb_of_init(struct device_node *dp);
#endif /* CONFIG_FB_YOUR_CARD */

Then in the function offb_init_driver you add something similar to the
following.

#ifdef CONFIG_FB_YOUR_CARD
if (!strncmp(dp->name,"Open Firmware number of your card ",size_of_name)) {
xxxfb_of_init(dp);
return 1;
}
#endif /* CONFIG_FB_YOUR_CARD */

If Open Firmware doesn't detect your card then Open Firmware sets up a
generic video mode for you. Now in your driver you really need two
initalization functions.

The next major part of the driver is declaring the functions of fb_ops
declared in fb_info for the driver.

The first two functions xxfb_open and xxfb_release can be called from both
fbcon and fbdev.
In fact that's the use of the user flag. If user equals zero
then fbcon wants to access this device else it's an explicit open of the
framebuffer device. This way you can handle the framebuffer device for the
console in a special way for a particular video card. For most drivers this
function just does a MOD_INC_USE_COUNT or MOD_DEC_USE_COUNT.

These are the functions at the heart of mode setting. There are a
few cards that don't support mode changing. For these we have this function
return a -EINVAL to let the user know he/she can't set the mode. Actually
set_var does more than just set modes. It can check them as well. In
fb_var_screeninfo there is a flag called activate. This flag can take on
the the following values. FB_ACTIVATE_NOW,FB_ACTIVATE_NXTOPEN, and
FB_ACTIVATE_TEST. FB_ACTIVATE_TEST tells us if the hardware can handle what
the user requested. FB_ACTIVATE_NXTOPEN sets the values wanted on the next
explicit open of fbdev. The final one FB_ACTIVATE_NOW checks the mode to see
if it can be done and then sets the mode. You MUST check the mode before all
things. Note this function is very card specific but I attempt to give you
the most general layout.. The basic layout then for xxxfb_set_var is

static int vfb_set_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
int line_length;

/* Basic setup test. Here we look at what the user passed in that he/she
wants. For example to test the fb_var_screeninfo field vmode like is
done in vfb.c. Here we see if the user has FB_VMODE_YWARP. Also we
should look to see if the user tried to pass in invalid values like 17
bpp (bits per pixel) */

/* Remember the above discussion on how monitors see a mode. They don't
care about bit depth. So you can divide the checking into two parts.
One is to see if the user changed a mode from say 640×480 at 8 bpp to
640×480 at 32 bpp. Remember the var in fb_info represents the current
video mode. Before we actually change any resolutions we have to make
sure the card has enough memory for the new mode. Discovering how much
memory a video card has varies from card to card. Also finding out how
much memory we have is done in xxxfb_init since this never changes
unless you add more memory to your card which requires a reboot of the
machine anyway. You might have to do other tests depending on the make of
your card. Note the par filed in fb_info. This is used to store card
specific data. This data can effect set_var. Also it is present to
allow other possible drivers that could affect the framebuffer device
such as a special driver for an accel engine or memory mapping the z
buffer on a card */

/* Summary. First look at any var fields to see if they are valid. Next
test hardware with these fields without setting the hardware. An
example of one is find what the line_lenght would be for the new
mode. Then test the following */

if ((line_length * var->yres_virtual) > info->fix.smem_len)
return -ENOMEM;

if (info->var.xres != var->xres || info->var.yres != var->yres ||
info->var.xres_virtual != var->xres_virtual ||
info->var.yres_vitual != var->yres_virtual) {
/* Resolution changed !!! */

/* Next you must check to see if the monitor can handle this mode.
Don't want to fry your monitor or mess up the display really
badly */
if (fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal,
      const struct fb_info *fb_info))
/* Can't handle these timings. */
return -EINVAL;

/* Timings are okay. Next we see if we really want to change
this mode */
if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
/* Now let's program the clocks on this card. Here the code is
very card specific. Remember to change any fields for fix in
info that might be effected by the changing of the resolution.
*/

info->fix.line_length = line_length;

/* Now that we have dealt with the possible changing resolutions
let's handle a possible change of bit depth. */
if (info->var.bits_per_pixel != var->bits_per_pixel) {
if ((err = fb_alloc_cmap(&info->cmap, 0, 0)))
return err;
}
}

/* We have shown that the monitor and video card can handle this mode or
have actually set the mode. Next the fb_bitfield structure in
fb_var_screeninfo is filled in. Even if you don't set the mode you get
a feel of the mode before you really set it. These are typical values
but may be different for your card. For truecolor modes all the fields
matter. For pseudocolor modes only the length matters. Thus all the
lengths should be the same (=bpp). */

switch (var->bits_per_pixel) {
case 1:
case 8:
/* Pseudocolor mode example */
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 0;
var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 16: /* RGB 565 */
var->red.offset = 0;
var->red.length = 5;
var->green.offset = 5;
var->green.length = 6;
var->blue.offset = 11;
var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 24: /* RGB 888 */
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 8;
var->green.length = 8;
var->blue.offset = 16;
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 32: /* RGBA 8888 */
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 8;
var->green.length = 8;
var->blue.offset = 16;
var->blue.length = 8;
var->transp.offset = 24;
var->transp.length = 8;
break;
}
/* Yeah. We are done !!! */
}

The function xxxfb_setcolreg is used to set a single color register for a
video card. To use this properly you must understand colors which is
discribed above. This routine sets a color map entry. The regno passed into
the routine represents the color map index which is equal to the color that's
composed of the amount of red, green, blue, and even alpha that are also
passed into the function. For psuedocolor modes this col
or map index (regno)
represents the pixel value. So if you place a pixel value of regno in video
memory you get the color that's made of the red, green, blue that you passed
into xxxfb_setcolreg. Now for truecolor and directcolor mode it's a little
different. In this case we simulate a psuedo color map. The reason for this
is the console system always has a color map which has 16 entries. In fb_info
there is the pseudo_palette which gives a mapping from a non color map
mode to a color map based system. The pseudo_palette always has 17 entries.
The first 16 for the console colors and the last one for the cursor. So if
we wanted to display the 4 entry in the color map of the console we would
placed the value of info->psuedo_palette[4] directly into the video memory.
This is of course taken care of by fbcon. You just need to code the
"formula" that does this translation. A example follows for 32 bit mode.

red >>= 8;
green >>= 8;
blue >>= 8;
info->pseudo_palette[regno] =
(red << info->var.red.offset) |
(green << info->var.green.offset) |
(blue << info->var.blue.offset);

Here we first scale down the color components. Each color passed to
set_colreg are 16 bits in size. For 32 bit mode each color is 8 bits in size.
Then we or the colors together after we offseted them. The offset is used
because the pixel layout in 32 bits could be RBGA, ARGBA etc. In setcol_reg
of vfb.c is the standard way to deal with packed pixel format of various
image depths. Regno is the index to get this particular color.

That does it for required functions besides the set of needed accel
functions which has not been discussed yet. If the video card doesn't
support the function then we just place a NULL in fb_ops. The next fuction
in fb_ops is xxxfb_blank. This function provides support for hardware
blanking. For xxxfb_blank the first parameter represents the blanking modes
available. They are VESA_NO_BLANKING, VESA_VSYNC_SUSPEND, VESA_HSYNC_SUSPEND,
and VESA_POWERDOWN. VESA_NO_BLANKING powers up the display again.
VESA_POWERDOWN turns off the display. This is great power saving feature on
a laptop.

The next optional function is xxxfb_pan_display. This function enables
panning. Panning is often used for scrolling.

The ioctl function gives you the power to take advantage of special features
other cards don't have. If your card is nothing special then just give this
fb_ops function a NULL pointer. The sky is the limit for defining your ioctl
calls.

There is a default memory map function for fbdev but sometimes it just
doesn't have the power you truly need. A good example of this is video
cards that work in sparc workstations. Those need their own mmap functions because
sparcs handle memory differently from other platforms. This is
true even for sparcs with PCI buses.

Now here is the next class of functions which are optional. The
xxxfb_accel_init and xxfb_accel_done. xxxfb_accel_init really depends on
the card. It is intended to initialize the engine or set the accel engine into
a state which you can use the acceleration engine. It also ensures that the
framebuffer is not accessed at the same time as the accel engine. This
can lock a system. Uusally there is a bit to test to see if an accel
engine is idle or the card generates an interrupt. For cards that used the
old fb_rasterimg this function replaces it. Some cards have a separate state
for 3D and 2D. This function insures that the card goes into a 2D state,
just in case a previous application set the accel engine into a 3D state
or made the accel engine very unhappy. The next function that encomposses
this set is xxxfb_accel_done. This function sets the video card in a state
such that you can write to the framebuffer again. You should provide both
functions if your driver uses even one hardware accelerated function. The
reason is to ensure that the framebuffer is not accessed at the same
time as the framebuffer.

Finally the third class of fb_op functions. Like the first they are required.
If your card does not support any of these accelerated functions there are
default functions for packed pixel framebuffer formats. They are
cfba_fillrect, cfba_copyarea, cfba_imgblit. If you supports some but not
all of the accels available you can still use some of these software emulated
accels. Each software emulated accel is stored in a seperate file. Now let's
describe each accel function. Before we discuss these functions we need to
note not to draw in areas past the video boundries. If it does you need to
adjust the width and height of the ares to avoid this problem. The first
function just fills in a rectangle starting at x1 and y1 of some width and
height with a pixel value of packed pixel format. If the video memory mapping
is not a direct mapping from the pixel value (not FB_TYPE_PACKED_PIXEL) you
will have to do some translating. There are two ways to fill in the
rectangle, FBA_ROP_COPY and FBA_ROP_XOR. FBA_ROP_XOR exclusive ors the pixel
value with the current pixel value. This allows things like quickly erasing
a rectangular area. The other function just directly copies the data. The
next function is xxxfb_copyarea. It just copies one area of the framebuffer
at source x and source y of some width and height to some destination x and
y. The final function is xxxfb_imageblt. This function copies an image from
system memory to video memory. You can get really fancy here but this is
fbdev which has the purpose of mode setting only. All the image blit
function does is draw bitmaps, images made of a foregound and background
color, and a color image of the same color depth as the framebuffer. The
second part is used to draw the little penguins. The drawing of bitmaps is
used to draw our fonts. That does it for the functions. Now you should be
set for writing your driver.

A new channel named "Niao Yu" contains some excellent articles from Economist.com. The sentences in the topic "Pretty Sentences" are all picked from the Economist.com as well.
Share with you.

As Paul Otellini prepares to take charge at Intel next week, is the giant chipmaker heading in the right direction?

http://www.felixwoo.com/wp-content/uploads/attachments/200505/13_201931_intel.jpg

WHEN it was confirmed last November that Intel’s new boss would be Paul Otellini, the firm’s chief operating officer and heir apparent for several years, nobody was surprised. The firm’s succession-planning is famed for being as clean and efficient as the factories where it makes its chips, and Craig Barrett, the retiring chief executive, who steps down on May 18th, has long seen Mr Otellini as his right-hand man. But Mr Otellini is Intel’s right-hand man in another sense, too. For he is the architect of the firm’s new strategy—a change of direction that Mr Otellini calls a “right-hand turn”. The world’s largest chipmaker now faces three big challenges—but Mr Otellini believes his plan can address all of them at once. Is he right?

The first challenge is technical. For years, Intel has consistently improved the performance of its chips by making them run at higher and higher clock speeds (measured in MHz or GHz). But it has now hit a wall. As chips get faster, they consume more power and generate more heat. It also becomes harder to keep all the parts of a chip marching in step.

Intel, along with its rivals, is embracing a new approach to chip design, in which performance is improved not through higher clock speeds, but by adding further processing “cores” to its existing chips. A “dual-core” chip can, at least in theory, deliver twice the number-crunching performance of a single-core chip, but at the same clock speed. In practice, the software on the chip must be rewritten to exploit multiple cores, but such software is becoming increasingly common.

The second challenge is that the personal computer (PC) market has matured. Intel still makes most of its money selling the processor chips at the heart of PCs. Mr Otellini’s predecessors, who ran the firm when the PC was in the ascendant, could rely on an expanding market to provide double-digit growth for Intel. Mr Otellini cannot, and must find new sources of growth, in the PC market and beyond it.

The third challenge is the growing competitiveness of Intel’s main rival, Advanced Micro Devices (AMD). In recent months Intel has suffered a string of embarrassments, some self-inflicted (such as the cancellation or delay of several new products), but others at the hands of AMD. Notably, AMD devised a clever way to enable chips to handle data in both 32-bit and 64-bit chunks, which improves their performance. Having spent years developing an entirely new 64-bit chip, Itanium, Intel was loth to undermine its prospects by adding 64-bit support to its 32-bit Pentium and Xeon chips. But last year it did just that, to remain competitive with AMD. As a result, Itanium is probably doomed.

Mr Otellini’s response to all of these challenges is the “right-hand turn”. First, Intel must change how it designs chips. As well as switching to a dual-core (and then multi-core) approach, the firm is starting to integrate other functions, such as security and networking features, on to its chips.

That points the way to the second part of Mr Otellini’s plan: “platformisation”. Rather than just selling processing chips to PC-makers, Intel intends to offer them entire “platforms”—bundles consisting of a processor, its ancillary chips and networking components, and the software needed to tie them all together. By doing this, Intel hopes to sell more components, thereby taking a larger cut of the selling price of each PC. It also hopes to boost demand by devising specific platforms for several promising new markets, such as home entertainment, mobile devices and health care.

This strategy, it hopes, will also enable Intel to outflank its rivals, which specialise in particular kinds of chips, such as processors (as in the case of AMD) or networking (Broadcom). PC-makers, goes the theory, would rather buy a single integrated package from Intel than assemble components from several other suppliers.

A man with a plan

This all sounds good in theory. But will it work in practice? When asked, Intel executives invariably cite the success of Centrino, the firm’s laptop platform, which combines a processor with a Wi-Fi networking chip, software and other supporting components. Centrino, launched in 2003, is the model for how Intel intends to sell chips in future. Rather than ask for “Intel inside”, laptop buyers can now demand “Centrino inside”. This encourages PC-makers to buy the entire platform.

Intel is now working on two similar platforms for home and office desktop machines, nicknamed “Desktrino”, due to be launched later this year. In January Mr Otellini reorganised Intel into platform-specific divisions, including digital home (for consumer PCs), corporate (business PCs and servers), mobility (laptops and mobile devices) and health care, which Intel regards as a promising new market.

Will it work? Consider Centrino. When it was launched, several laptop-makers initially turned their noses up at Intel’s Wi-Fi chip, and decided to buy only Intel’s laptop processor chip, which they combined with Wi-Fi chips bought from other vendors. Only when Intel’s Wi-Fi chip came up to scratch did laptop-makers opt for the whole Centrino package. “It took a while for the Centrino model to work,” says Dean McCarron of Mercury Research, a market-research firm. The platform model will only succeed, he says, if all the components are competitive in their own right.

While Intel has a good chance of getting the platform model to work in desktop PCs, breaking into new markets may prove much harder. Intel has yet to make any headway in the mobile-phone market; indeed, merging its laptop and mobile businesses into a single “mobility” division means that continuing losses in communications chips are helpfully obscured by the bumper profits from Centrino. Its prowess in processors is unquestioned, but Intel is still to prove itself when it comes to radio chips. It must do so if it is to realise its high hopes for new markets such as smartphones and wireless broadband (Intel is the main cheerleader for WiMax, a new wireless broadband technology). “They don’t have a significant technological advantage over the incumbents in the cell-phone business,” says Kevin Krewell of Microprocessor Report, an industry journal. “Until they come up with something truly unique, they’re just going to be a me-too player.”

There are other worries too. Dell, the world’s top PC-maker and one of Intel’s closest allies, has hitherto chosen not to use AMD’s chips. But Kevin Rollins, Dell’s chief executive, admitted in February that his firm came close to changing its mind last year, following product delays and other problems at Intel. Dell is careful never to rule out abandoning its Intel-only policy. If Dell ever changes its mind, Intel’s market share in PC processors, which has exceeded 80% for years, could come under threat. Intel rewards Dell and other PC-makers with generous discounts, in the form of marketing subsidies, to keep them loyal. Dirk Meyer, the number two at AMD, says that Intel has a “stranglehold” over PC-makers. He points out that Japanese antitrust regulators recently ruled that Intel’s business practices in that country, which are similar to those used elsewhere, were unfair. Mr Krewell, however, says that Intel had worse practices in the past, and has cleaned up its act.

As Mr Otellini takes the helm, Intel is already starting to move in the direction he has charted. The origins of the new strategy can be traced back to a speech he made in late 2001. Since then he has been gently steering the firm
into its right-hand turn. He is the first boss of Intel to have a business and marketing rather than a technical background (though, as a 31-year veteran at the firm, he is hardly a technological novice). As Intel faces the challenges not just of designing chips in new ways, but of selling them in new ways too, Mr Otellini would seem to be the right man for the job. He has mapped out where he wants to take the company: now he must get it there.

http://www.felixwoo.com/wp-content/uploads/attachments/old/200549235919686.gif
Gmail就是Google提供的邮箱,目前空间有2G多,并且每天都在按照他的"∞+1"理论递增。注册Gmail邮箱只能采用邀请的方式,我现在有100多个邀请,需要的朋友在回复中留下您的邮箱,我会尽快给你发出邀请。

京ICP备05053527号
经过44次查询历时7.853秒终于生成了此页面
Powered by WordPress & Designed by Felix © 2008