aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/geode/display_gx.c
diff options
context:
space:
mode:
authorDavid Vrabel <dvrabel@arcom.com>2006-03-27 04:17:23 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-27 11:44:55 -0500
commitfc4effc7a98d0d320e478d1d42bc4a8a64380150 (patch)
tree2291ae0b2eca05c45399f6f161714f3083269f1d /drivers/video/geode/display_gx.c
parent7a07cd786dbd0111b9dd977e114438220cb4eee5 (diff)
[PATCH] fbdev: framebuffer driver for Geode GX
A framebuffer driver for the display controller in AMD Geode GX processors (Geode GX533, Geode GX500 etc.). Tested at 640x480, 800x600, 1024x768 and 1280x1024 at 8, 16, and 24 bpp with both CRT and TFT. No accelerated features currently implemented and compression remains disabled. This driver requires that the BIOS (or the SoftVG/Firmbase code in the BIOS) has created an appropriate virtual PCI header. Signed-off-by: David Vrabel <dvrabel@arcom.com> Signed-off-by: Antonino Daplas <adaplas@pol.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/video/geode/display_gx.c')
-rw-r--r--drivers/video/geode/display_gx.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c
new file mode 100644
index 000000000000..825c3405f5c2
--- /dev/null
+++ b/drivers/video/geode/display_gx.c
@@ -0,0 +1,156 @@
1/*
2 * Geode GX display controller.
3 *
4 * Copyright (C) 2005 Arcom Control Systems Ltd.
5 *
6 * Portions from AMD's original 2.4 driver:
7 * Copyright (C) 2004 Advanced Micro Devices, Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by * the
11 * Free Software Foundation; either version 2 of the License, or * (at your
12 * option) any later version.
13 */
14#include <linux/spinlock.h>
15#include <linux/fb.h>
16#include <linux/delay.h>
17#include <asm/io.h>
18#include <asm/div64.h>
19#include <asm/delay.h>
20
21#include "geodefb.h"
22#include "display_gx.h"
23
24int gx_frame_buffer_size(void)
25{
26 /* Assuming 16 MiB. */
27 return 16*1024*1024;
28}
29
30int gx_line_delta(int xres, int bpp)
31{
32 /* Must be a multiple of 8 bytes. */
33 return (xres * (bpp >> 3) + 7) & ~0x7;
34}
35
36static void gx_set_mode(struct fb_info *info)
37{
38 struct geodefb_par *par = info->par;
39 u32 gcfg, dcfg;
40 int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
41 int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
42
43 /* Unlock the display controller registers. */
44 readl(par->dc_regs + DC_UNLOCK);
45 writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
46
47 gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
48 dcfg = readl(par->dc_regs + DC_DISPLAY_CFG);
49
50 /* Disable the timing generator. */
51 dcfg &= ~(DC_DCFG_TGEN);
52 writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
53
54 /* Wait for pending memory requests before disabling the FIFO load. */
55 udelay(100);
56
57 /* Disable FIFO load and compression. */
58 gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
59 writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
60
61 /* Setup DCLK and its divisor. */
62 par->vid_ops->set_dclk(info);
63
64 /*
65 * Setup new mode.
66 */
67
68 /* Clear all unused feature bits. */
69 gcfg &= DC_GCFG_YUVM | DC_GCFG_VDSE;
70 dcfg = 0;
71
72 /* Set FIFO priority (default 6/5) and enable. */
73 /* FIXME: increase fifo priority for 1280x1024 and higher modes? */
74 gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE;
75
76 /* Framebuffer start offset. */
77 writel(0, par->dc_regs + DC_FB_ST_OFFSET);
78
79 /* Line delta and line buffer length. */
80 writel(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH);
81 writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
82 par->dc_regs + DC_LINE_SIZE);
83
84 /* Enable graphics and video data and unmask address lines. */
85 dcfg |= DC_DCFG_GDEN | DC_DCFG_VDEN | DC_DCFG_A20M | DC_DCFG_A18M;
86
87 /* Set pixel format. */
88 switch (info->var.bits_per_pixel) {
89 case 8:
90 dcfg |= DC_DCFG_DISP_MODE_8BPP;
91 break;
92 case 16:
93 dcfg |= DC_DCFG_DISP_MODE_16BPP;
94 dcfg |= DC_DCFG_16BPP_MODE_565;
95 break;
96 case 32:
97 dcfg |= DC_DCFG_DISP_MODE_24BPP;
98 dcfg |= DC_DCFG_PALB;
99 break;
100 }
101
102 /* Enable timing generator. */
103 dcfg |= DC_DCFG_TGEN;
104
105 /* Horizontal and vertical timings. */
106 hactive = info->var.xres;
107 hblankstart = hactive;
108 hsyncstart = hblankstart + info->var.right_margin;
109 hsyncend = hsyncstart + info->var.hsync_len;
110 hblankend = hsyncend + info->var.left_margin;
111 htotal = hblankend;
112
113 vactive = info->var.yres;
114 vblankstart = vactive;
115 vsyncstart = vblankstart + info->var.lower_margin;
116 vsyncend = vsyncstart + info->var.vsync_len;
117 vblankend = vsyncend + info->var.upper_margin;
118 vtotal = vblankend;
119
120 writel((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING);
121 writel((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING);
122 writel((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING);
123
124 writel((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING);
125 writel((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING);
126 writel((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING);
127
128 /* Write final register values. */
129 writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
130 writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
131
132 par->vid_ops->configure_display(info);
133
134 /* Relock display controller registers */
135 writel(0, par->dc_regs + DC_UNLOCK);
136}
137
138static void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno,
139 unsigned red, unsigned green, unsigned blue)
140{
141 struct geodefb_par *par = info->par;
142 int val;
143
144 /* Hardware palette is in RGB 8-8-8 format. */
145 val = (red << 8) & 0xff0000;
146 val |= (green) & 0x00ff00;
147 val |= (blue >> 8) & 0x0000ff;
148
149 writel(regno, par->dc_regs + DC_PAL_ADDRESS);
150 writel(val, par->dc_regs + DC_PAL_DATA);
151}
152
153struct geode_dc_ops gx_dc_ops = {
154 .set_mode = gx_set_mode,
155 .set_palette_reg = gx_set_hw_palette_reg,
156};