Monday, October 10, 2011

Framebuffer Video Card Technology


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 and is mmaped to userspace for direct access. This model is, of course, simplified for the purpose of making programming 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 understand how exactly the video card itself works.

2.1 Monitor

First, lets describe one of the biggest but often overlooked components: the monitor. Today, there exist 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 goes for the top to bottom approach, but at a much slower 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". Some systems encode this information. For example, 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 frequencies (aka refresh rate), as they determine how often per second a whole image is drawn. A monitor knows nothing about depth, clocks, and 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   data datadatadatadatadatadatadatadatadatadata data  
time12 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), 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 before 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 1 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 640x480 standard VESA mode, this is 640 pixels.
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 640x480 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 648x486 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 visible area of the monitor (which is useless), or interfere with the retrace, what 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 tunable monitors that allow stretching 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.

For more info follow this link:
http://www.linux-fbdev.org/HOWTO/index.html

No comments: