diff options
Diffstat (limited to 'drivers/video/geode')
-rw-r--r-- | drivers/video/geode/Kconfig | 20 | ||||
-rw-r--r-- | drivers/video/geode/Makefile | 2 | ||||
-rw-r--r-- | drivers/video/geode/display_gx.c | 125 | ||||
-rw-r--r-- | drivers/video/geode/display_gx.h | 101 | ||||
-rw-r--r-- | drivers/video/geode/gxfb.h | 358 | ||||
-rw-r--r-- | drivers/video/geode/gxfb_core.c | 160 | ||||
-rw-r--r-- | drivers/video/geode/lxfb.h | 527 | ||||
-rw-r--r-- | drivers/video/geode/lxfb_core.c | 118 | ||||
-rw-r--r-- | drivers/video/geode/lxfb_ops.c | 699 | ||||
-rw-r--r-- | drivers/video/geode/suspend_gx.c | 267 | ||||
-rw-r--r-- | drivers/video/geode/video_gx.c | 162 | ||||
-rw-r--r-- | drivers/video/geode/video_gx.h | 72 |
12 files changed, 1879 insertions, 732 deletions
diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig index 7608429b3943..c5d8ba4b9fc3 100644 --- a/drivers/video/geode/Kconfig +++ b/drivers/video/geode/Kconfig | |||
@@ -38,26 +38,6 @@ config FB_GEODE_GX | |||
38 | 38 | ||
39 | If unsure, say N. | 39 | If unsure, say N. |
40 | 40 | ||
41 | config FB_GEODE_GX_SET_FBSIZE | ||
42 | bool "Manually specify the Geode GX framebuffer size" | ||
43 | depends on FB_GEODE_GX | ||
44 | default n | ||
45 | ---help--- | ||
46 | If you want to manually specify the size of your GX framebuffer, | ||
47 | say Y here, otherwise say N to dynamically probe it. | ||
48 | |||
49 | Say N unless you know what you are doing. | ||
50 | |||
51 | config FB_GEODE_GX_FBSIZE | ||
52 | hex "Size of the GX framebuffer, in bytes" | ||
53 | depends on FB_GEODE_GX_SET_FBSIZE | ||
54 | default "0x1600000" | ||
55 | ---help--- | ||
56 | Specify the size of the GX framebuffer. Normally, you will | ||
57 | want this to be MB aligned. Common values are 0x80000 (8MB) | ||
58 | and 0x1600000 (16MB). Don't change this unless you know what | ||
59 | you are doing | ||
60 | |||
61 | config FB_GEODE_GX1 | 41 | config FB_GEODE_GX1 |
62 | tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)" | 42 | tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)" |
63 | depends on FB && FB_GEODE && EXPERIMENTAL | 43 | depends on FB && FB_GEODE && EXPERIMENTAL |
diff --git a/drivers/video/geode/Makefile b/drivers/video/geode/Makefile index 957304b45fba..5c98da126883 100644 --- a/drivers/video/geode/Makefile +++ b/drivers/video/geode/Makefile | |||
@@ -5,5 +5,5 @@ obj-$(CONFIG_FB_GEODE_GX) += gxfb.o | |||
5 | obj-$(CONFIG_FB_GEODE_LX) += lxfb.o | 5 | obj-$(CONFIG_FB_GEODE_LX) += lxfb.o |
6 | 6 | ||
7 | gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o | 7 | gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o |
8 | gxfb-objs := gxfb_core.o display_gx.o video_gx.o | 8 | gxfb-objs := gxfb_core.o display_gx.o video_gx.o suspend_gx.o |
9 | lxfb-objs := lxfb_core.o lxfb_ops.o | 9 | lxfb-objs := lxfb_core.o lxfb_ops.o |
diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c index 0f16e4bffc6c..e759895bf3d3 100644 --- a/drivers/video/geode/display_gx.c +++ b/drivers/video/geode/display_gx.c | |||
@@ -17,31 +17,40 @@ | |||
17 | #include <asm/io.h> | 17 | #include <asm/io.h> |
18 | #include <asm/div64.h> | 18 | #include <asm/div64.h> |
19 | #include <asm/delay.h> | 19 | #include <asm/delay.h> |
20 | #include <asm/geode.h> | ||
20 | 21 | ||
21 | #include "geodefb.h" | 22 | #include "gxfb.h" |
22 | #include "display_gx.h" | ||
23 | 23 | ||
24 | #ifdef CONFIG_FB_GEODE_GX_SET_FBSIZE | ||
25 | unsigned int gx_frame_buffer_size(void) | ||
26 | { | ||
27 | return CONFIG_FB_GEODE_GX_FBSIZE; | ||
28 | } | ||
29 | #else | ||
30 | unsigned int gx_frame_buffer_size(void) | 24 | unsigned int gx_frame_buffer_size(void) |
31 | { | 25 | { |
32 | unsigned int val; | 26 | unsigned int val; |
33 | 27 | ||
34 | /* FB size is reported by a virtual register */ | 28 | if (!geode_has_vsa2()) { |
29 | uint32_t hi, lo; | ||
30 | |||
31 | /* The number of pages is (PMAX - PMIN)+1 */ | ||
32 | rdmsr(MSR_GLIU_P2D_RO0, lo, hi); | ||
33 | |||
34 | /* PMAX */ | ||
35 | val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20); | ||
36 | /* PMIN */ | ||
37 | val -= (lo & 0x000fffff); | ||
38 | val += 1; | ||
39 | |||
40 | /* The page size is 4k */ | ||
41 | return (val << 12); | ||
42 | } | ||
43 | |||
44 | /* FB size can be obtained from the VSA II */ | ||
35 | /* Virtual register class = 0x02 */ | 45 | /* Virtual register class = 0x02 */ |
36 | /* VG_MEM_SIZE(512Kb units) = 0x00 */ | 46 | /* VG_MEM_SIZE(512Kb units) = 0x00 */ |
37 | 47 | ||
38 | outw(0xFC53, 0xAC1C); | 48 | outw(VSA_VR_UNLOCK, VSA_VRC_INDEX); |
39 | outw(0x0200, 0xAC1C); | 49 | outw(VSA_VR_MEM_SIZE, VSA_VRC_INDEX); |
40 | 50 | ||
41 | val = (unsigned int)(inw(0xAC1E)) & 0xFFl; | 51 | val = (unsigned int)(inw(VSA_VRC_DATA)) & 0xFFl; |
42 | return (val << 19); | 52 | return (val << 19); |
43 | } | 53 | } |
44 | #endif | ||
45 | 54 | ||
46 | int gx_line_delta(int xres, int bpp) | 55 | int gx_line_delta(int xres, int bpp) |
47 | { | 56 | { |
@@ -49,75 +58,76 @@ int gx_line_delta(int xres, int bpp) | |||
49 | return (xres * (bpp >> 3) + 7) & ~0x7; | 58 | return (xres * (bpp >> 3) + 7) & ~0x7; |
50 | } | 59 | } |
51 | 60 | ||
52 | static void gx_set_mode(struct fb_info *info) | 61 | void gx_set_mode(struct fb_info *info) |
53 | { | 62 | { |
54 | struct geodefb_par *par = info->par; | 63 | struct gxfb_par *par = info->par; |
55 | u32 gcfg, dcfg; | 64 | u32 gcfg, dcfg; |
56 | int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal; | 65 | int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal; |
57 | int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal; | 66 | int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal; |
58 | 67 | ||
59 | /* Unlock the display controller registers. */ | 68 | /* Unlock the display controller registers. */ |
60 | readl(par->dc_regs + DC_UNLOCK); | 69 | write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); |
61 | writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK); | ||
62 | 70 | ||
63 | gcfg = readl(par->dc_regs + DC_GENERAL_CFG); | 71 | gcfg = read_dc(par, DC_GENERAL_CFG); |
64 | dcfg = readl(par->dc_regs + DC_DISPLAY_CFG); | 72 | dcfg = read_dc(par, DC_DISPLAY_CFG); |
65 | 73 | ||
66 | /* Disable the timing generator. */ | 74 | /* Disable the timing generator. */ |
67 | dcfg &= ~(DC_DCFG_TGEN); | 75 | dcfg &= ~DC_DISPLAY_CFG_TGEN; |
68 | writel(dcfg, par->dc_regs + DC_DISPLAY_CFG); | 76 | write_dc(par, DC_DISPLAY_CFG, dcfg); |
69 | 77 | ||
70 | /* Wait for pending memory requests before disabling the FIFO load. */ | 78 | /* Wait for pending memory requests before disabling the FIFO load. */ |
71 | udelay(100); | 79 | udelay(100); |
72 | 80 | ||
73 | /* Disable FIFO load and compression. */ | 81 | /* Disable FIFO load and compression. */ |
74 | gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE); | 82 | gcfg &= ~(DC_GENERAL_CFG_DFLE | DC_GENERAL_CFG_CMPE | |
75 | writel(gcfg, par->dc_regs + DC_GENERAL_CFG); | 83 | DC_GENERAL_CFG_DECE); |
84 | write_dc(par, DC_GENERAL_CFG, gcfg); | ||
76 | 85 | ||
77 | /* Setup DCLK and its divisor. */ | 86 | /* Setup DCLK and its divisor. */ |
78 | par->vid_ops->set_dclk(info); | 87 | gx_set_dclk_frequency(info); |
79 | 88 | ||
80 | /* | 89 | /* |
81 | * Setup new mode. | 90 | * Setup new mode. |
82 | */ | 91 | */ |
83 | 92 | ||
84 | /* Clear all unused feature bits. */ | 93 | /* Clear all unused feature bits. */ |
85 | gcfg &= DC_GCFG_YUVM | DC_GCFG_VDSE; | 94 | gcfg &= DC_GENERAL_CFG_YUVM | DC_GENERAL_CFG_VDSE; |
86 | dcfg = 0; | 95 | dcfg = 0; |
87 | 96 | ||
88 | /* Set FIFO priority (default 6/5) and enable. */ | 97 | /* Set FIFO priority (default 6/5) and enable. */ |
89 | /* FIXME: increase fifo priority for 1280x1024 and higher modes? */ | 98 | /* FIXME: increase fifo priority for 1280x1024 and higher modes? */ |
90 | gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE; | 99 | gcfg |= (6 << DC_GENERAL_CFG_DFHPEL_SHIFT) | |
100 | (5 << DC_GENERAL_CFG_DFHPSL_SHIFT) | DC_GENERAL_CFG_DFLE; | ||
91 | 101 | ||
92 | /* Framebuffer start offset. */ | 102 | /* Framebuffer start offset. */ |
93 | writel(0, par->dc_regs + DC_FB_ST_OFFSET); | 103 | write_dc(par, DC_FB_ST_OFFSET, 0); |
94 | 104 | ||
95 | /* Line delta and line buffer length. */ | 105 | /* Line delta and line buffer length. */ |
96 | writel(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH); | 106 | write_dc(par, DC_GFX_PITCH, info->fix.line_length >> 3); |
97 | writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2, | 107 | write_dc(par, DC_LINE_SIZE, |
98 | par->dc_regs + DC_LINE_SIZE); | 108 | ((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2); |
99 | 109 | ||
100 | 110 | ||
101 | /* Enable graphics and video data and unmask address lines. */ | 111 | /* Enable graphics and video data and unmask address lines. */ |
102 | dcfg |= DC_DCFG_GDEN | DC_DCFG_VDEN | DC_DCFG_A20M | DC_DCFG_A18M; | 112 | dcfg |= DC_DISPLAY_CFG_GDEN | DC_DISPLAY_CFG_VDEN | |
113 | DC_DISPLAY_CFG_A20M | DC_DISPLAY_CFG_A18M; | ||
103 | 114 | ||
104 | /* Set pixel format. */ | 115 | /* Set pixel format. */ |
105 | switch (info->var.bits_per_pixel) { | 116 | switch (info->var.bits_per_pixel) { |
106 | case 8: | 117 | case 8: |
107 | dcfg |= DC_DCFG_DISP_MODE_8BPP; | 118 | dcfg |= DC_DISPLAY_CFG_DISP_MODE_8BPP; |
108 | break; | 119 | break; |
109 | case 16: | 120 | case 16: |
110 | dcfg |= DC_DCFG_DISP_MODE_16BPP; | 121 | dcfg |= DC_DISPLAY_CFG_DISP_MODE_16BPP; |
111 | dcfg |= DC_DCFG_16BPP_MODE_565; | ||
112 | break; | 122 | break; |
113 | case 32: | 123 | case 32: |
114 | dcfg |= DC_DCFG_DISP_MODE_24BPP; | 124 | dcfg |= DC_DISPLAY_CFG_DISP_MODE_24BPP; |
115 | dcfg |= DC_DCFG_PALB; | 125 | dcfg |= DC_DISPLAY_CFG_PALB; |
116 | break; | 126 | break; |
117 | } | 127 | } |
118 | 128 | ||
119 | /* Enable timing generator. */ | 129 | /* Enable timing generator. */ |
120 | dcfg |= DC_DCFG_TGEN; | 130 | dcfg |= DC_DISPLAY_CFG_TGEN; |
121 | 131 | ||
122 | /* Horizontal and vertical timings. */ | 132 | /* Horizontal and vertical timings. */ |
123 | hactive = info->var.xres; | 133 | hactive = info->var.xres; |
@@ -134,28 +144,34 @@ static void gx_set_mode(struct fb_info *info) | |||
134 | vblankend = vsyncend + info->var.upper_margin; | 144 | vblankend = vsyncend + info->var.upper_margin; |
135 | vtotal = vblankend; | 145 | vtotal = vblankend; |
136 | 146 | ||
137 | writel((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING); | 147 | write_dc(par, DC_H_ACTIVE_TIMING, (hactive - 1) | |
138 | writel((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING); | 148 | ((htotal - 1) << 16)); |
139 | writel((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING); | 149 | write_dc(par, DC_H_BLANK_TIMING, (hblankstart - 1) | |
150 | ((hblankend - 1) << 16)); | ||
151 | write_dc(par, DC_H_SYNC_TIMING, (hsyncstart - 1) | | ||
152 | ((hsyncend - 1) << 16)); | ||
140 | 153 | ||
141 | writel((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING); | 154 | write_dc(par, DC_V_ACTIVE_TIMING, (vactive - 1) | |
142 | writel((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING); | 155 | ((vtotal - 1) << 16)); |
143 | writel((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING); | 156 | write_dc(par, DC_V_BLANK_TIMING, (vblankstart - 1) | |
157 | ((vblankend - 1) << 16)); | ||
158 | write_dc(par, DC_V_SYNC_TIMING, (vsyncstart - 1) | | ||
159 | ((vsyncend - 1) << 16)); | ||
144 | 160 | ||
145 | /* Write final register values. */ | 161 | /* Write final register values. */ |
146 | writel(dcfg, par->dc_regs + DC_DISPLAY_CFG); | 162 | write_dc(par, DC_DISPLAY_CFG, dcfg); |
147 | writel(gcfg, par->dc_regs + DC_GENERAL_CFG); | 163 | write_dc(par, DC_GENERAL_CFG, gcfg); |
148 | 164 | ||
149 | par->vid_ops->configure_display(info); | 165 | gx_configure_display(info); |
150 | 166 | ||
151 | /* Relock display controller registers */ | 167 | /* Relock display controller registers */ |
152 | writel(0, par->dc_regs + DC_UNLOCK); | 168 | write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK); |
153 | } | 169 | } |
154 | 170 | ||
155 | static void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno, | 171 | void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno, |
156 | unsigned red, unsigned green, unsigned blue) | 172 | unsigned red, unsigned green, unsigned blue) |
157 | { | 173 | { |
158 | struct geodefb_par *par = info->par; | 174 | struct gxfb_par *par = info->par; |
159 | int val; | 175 | int val; |
160 | 176 | ||
161 | /* Hardware palette is in RGB 8-8-8 format. */ | 177 | /* Hardware palette is in RGB 8-8-8 format. */ |
@@ -163,11 +179,6 @@ static void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno, | |||
163 | val |= (green) & 0x00ff00; | 179 | val |= (green) & 0x00ff00; |
164 | val |= (blue >> 8) & 0x0000ff; | 180 | val |= (blue >> 8) & 0x0000ff; |
165 | 181 | ||
166 | writel(regno, par->dc_regs + DC_PAL_ADDRESS); | 182 | write_dc(par, DC_PAL_ADDRESS, regno); |
167 | writel(val, par->dc_regs + DC_PAL_DATA); | 183 | write_dc(par, DC_PAL_DATA, val); |
168 | } | 184 | } |
169 | |||
170 | struct geode_dc_ops gx_dc_ops = { | ||
171 | .set_mode = gx_set_mode, | ||
172 | .set_palette_reg = gx_set_hw_palette_reg, | ||
173 | }; | ||
diff --git a/drivers/video/geode/display_gx.h b/drivers/video/geode/display_gx.h deleted file mode 100644 index 0af33f329e88..000000000000 --- a/drivers/video/geode/display_gx.h +++ /dev/null | |||
@@ -1,101 +0,0 @@ | |||
1 | /* | ||
2 | * Geode GX display controller | ||
3 | * | ||
4 | * Copyright (C) 2006 Arcom Control Systems Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | #ifndef __DISPLAY_GX_H__ | ||
12 | #define __DISPLAY_GX_H__ | ||
13 | |||
14 | unsigned int gx_frame_buffer_size(void); | ||
15 | int gx_line_delta(int xres, int bpp); | ||
16 | |||
17 | extern struct geode_dc_ops gx_dc_ops; | ||
18 | |||
19 | /* MSR that tells us if a TFT or CRT is attached */ | ||
20 | #define GLD_MSR_CONFIG 0xC0002001 | ||
21 | #define GLD_MSR_CONFIG_DM_FP 0x40 | ||
22 | |||
23 | /* Display controller registers */ | ||
24 | |||
25 | #define DC_UNLOCK 0x00 | ||
26 | # define DC_UNLOCK_CODE 0x00004758 | ||
27 | |||
28 | #define DC_GENERAL_CFG 0x04 | ||
29 | # define DC_GCFG_DFLE 0x00000001 | ||
30 | # define DC_GCFG_CURE 0x00000002 | ||
31 | # define DC_GCFG_ICNE 0x00000004 | ||
32 | # define DC_GCFG_VIDE 0x00000008 | ||
33 | # define DC_GCFG_CMPE 0x00000020 | ||
34 | # define DC_GCFG_DECE 0x00000040 | ||
35 | # define DC_GCFG_VGAE 0x00000080 | ||
36 | # define DC_GCFG_DFHPSL_MASK 0x00000F00 | ||
37 | # define DC_GCFG_DFHPSL_POS 8 | ||
38 | # define DC_GCFG_DFHPEL_MASK 0x0000F000 | ||
39 | # define DC_GCFG_DFHPEL_POS 12 | ||
40 | # define DC_GCFG_STFM 0x00010000 | ||
41 | # define DC_GCFG_FDTY 0x00020000 | ||
42 | # define DC_GCFG_VGAFT 0x00040000 | ||
43 | # define DC_GCFG_VDSE 0x00080000 | ||
44 | # define DC_GCFG_YUVM 0x00100000 | ||
45 | # define DC_GCFG_VFSL 0x00800000 | ||
46 | # define DC_GCFG_SIGE 0x01000000 | ||
47 | # define DC_GCFG_SGRE 0x02000000 | ||
48 | # define DC_GCFG_SGFR 0x04000000 | ||
49 | # define DC_GCFG_CRC_MODE 0x08000000 | ||
50 | # define DC_GCFG_DIAG 0x10000000 | ||
51 | # define DC_GCFG_CFRW 0x20000000 | ||
52 | |||
53 | #define DC_DISPLAY_CFG 0x08 | ||
54 | # define DC_DCFG_TGEN 0x00000001 | ||
55 | # define DC_DCFG_GDEN 0x00000008 | ||
56 | # define DC_DCFG_VDEN 0x00000010 | ||
57 | # define DC_DCFG_TRUP 0x00000040 | ||
58 | # define DC_DCFG_DISP_MODE_MASK 0x00000300 | ||
59 | # define DC_DCFG_DISP_MODE_8BPP 0x00000000 | ||
60 | # define DC_DCFG_DISP_MODE_16BPP 0x00000100 | ||
61 | # define DC_DCFG_DISP_MODE_24BPP 0x00000200 | ||
62 | # define DC_DCFG_16BPP_MODE_MASK 0x00000c00 | ||
63 | # define DC_DCFG_16BPP_MODE_565 0x00000000 | ||
64 | # define DC_DCFG_16BPP_MODE_555 0x00000100 | ||
65 | # define DC_DCFG_16BPP_MODE_444 0x00000200 | ||
66 | # define DC_DCFG_DCEN 0x00080000 | ||
67 | # define DC_DCFG_PALB 0x02000000 | ||
68 | # define DC_DCFG_FRLK 0x04000000 | ||
69 | # define DC_DCFG_VISL 0x08000000 | ||
70 | # define DC_DCFG_FRSL 0x20000000 | ||
71 | # define DC_DCFG_A18M 0x40000000 | ||
72 | # define DC_DCFG_A20M 0x80000000 | ||
73 | |||
74 | #define DC_FB_ST_OFFSET 0x10 | ||
75 | |||
76 | #define DC_LINE_SIZE 0x30 | ||
77 | # define DC_LINE_SIZE_FB_LINE_SIZE_MASK 0x000007ff | ||
78 | # define DC_LINE_SIZE_FB_LINE_SIZE_POS 0 | ||
79 | # define DC_LINE_SIZE_CB_LINE_SIZE_MASK 0x007f0000 | ||
80 | # define DC_LINE_SIZE_CB_LINE_SIZE_POS 16 | ||
81 | # define DC_LINE_SIZE_VID_LINE_SIZE_MASK 0xff000000 | ||
82 | # define DC_LINE_SIZE_VID_LINE_SIZE_POS 24 | ||
83 | |||
84 | #define DC_GFX_PITCH 0x34 | ||
85 | # define DC_GFX_PITCH_FB_PITCH_MASK 0x0000ffff | ||
86 | # define DC_GFX_PITCH_FB_PITCH_POS 0 | ||
87 | # define DC_GFX_PITCH_CB_PITCH_MASK 0xffff0000 | ||
88 | # define DC_GFX_PITCH_CB_PITCH_POS 16 | ||
89 | |||
90 | #define DC_H_ACTIVE_TIMING 0x40 | ||
91 | #define DC_H_BLANK_TIMING 0x44 | ||
92 | #define DC_H_SYNC_TIMING 0x48 | ||
93 | #define DC_V_ACTIVE_TIMING 0x50 | ||
94 | #define DC_V_BLANK_TIMING 0x54 | ||
95 | #define DC_V_SYNC_TIMING 0x58 | ||
96 | |||
97 | #define DC_PAL_ADDRESS 0x70 | ||
98 | #define DC_PAL_DATA 0x74 | ||
99 | |||
100 | #define DC_GLIU0_MEM_OFFSET 0x84 | ||
101 | #endif /* !__DISPLAY_GX1_H__ */ | ||
diff --git a/drivers/video/geode/gxfb.h b/drivers/video/geode/gxfb.h new file mode 100644 index 000000000000..16a96f8fd8c5 --- /dev/null +++ b/drivers/video/geode/gxfb.h | |||
@@ -0,0 +1,358 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Andres Salomon <dilinger@debian.org> | ||
3 | * | ||
4 | * Geode GX2 header information | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | #ifndef _GXFB_H_ | ||
12 | #define _GXFB_H_ | ||
13 | |||
14 | #include <linux/io.h> | ||
15 | |||
16 | #define GP_REG_COUNT (0x50 / 4) | ||
17 | #define DC_REG_COUNT (0x90 / 4) | ||
18 | #define VP_REG_COUNT (0x138 / 8) | ||
19 | #define FP_REG_COUNT (0x68 / 8) | ||
20 | |||
21 | #define DC_PAL_COUNT 0x104 | ||
22 | |||
23 | struct gxfb_par { | ||
24 | int enable_crt; | ||
25 | void __iomem *dc_regs; | ||
26 | void __iomem *vid_regs; | ||
27 | void __iomem *gp_regs; | ||
28 | #ifdef CONFIG_PM | ||
29 | int powered_down; | ||
30 | |||
31 | /* register state, for power management functionality */ | ||
32 | struct { | ||
33 | uint64_t padsel; | ||
34 | uint64_t dotpll; | ||
35 | } msr; | ||
36 | |||
37 | uint32_t gp[GP_REG_COUNT]; | ||
38 | uint32_t dc[DC_REG_COUNT]; | ||
39 | uint64_t vp[VP_REG_COUNT]; | ||
40 | uint64_t fp[FP_REG_COUNT]; | ||
41 | |||
42 | uint32_t pal[DC_PAL_COUNT]; | ||
43 | #endif | ||
44 | }; | ||
45 | |||
46 | unsigned int gx_frame_buffer_size(void); | ||
47 | int gx_line_delta(int xres, int bpp); | ||
48 | void gx_set_mode(struct fb_info *info); | ||
49 | void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno, | ||
50 | unsigned red, unsigned green, unsigned blue); | ||
51 | |||
52 | void gx_set_dclk_frequency(struct fb_info *info); | ||
53 | void gx_configure_display(struct fb_info *info); | ||
54 | int gx_blank_display(struct fb_info *info, int blank_mode); | ||
55 | |||
56 | #ifdef CONFIG_PM | ||
57 | int gx_powerdown(struct fb_info *info); | ||
58 | int gx_powerup(struct fb_info *info); | ||
59 | #endif | ||
60 | |||
61 | |||
62 | /* Graphics Processor registers (table 6-23 from the data book) */ | ||
63 | enum gp_registers { | ||
64 | GP_DST_OFFSET = 0, | ||
65 | GP_SRC_OFFSET, | ||
66 | GP_STRIDE, | ||
67 | GP_WID_HEIGHT, | ||
68 | |||
69 | GP_SRC_COLOR_FG, | ||
70 | GP_SRC_COLOR_BG, | ||
71 | GP_PAT_COLOR_0, | ||
72 | GP_PAT_COLOR_1, | ||
73 | |||
74 | GP_PAT_COLOR_2, | ||
75 | GP_PAT_COLOR_3, | ||
76 | GP_PAT_COLOR_4, | ||
77 | GP_PAT_COLOR_5, | ||
78 | |||
79 | GP_PAT_DATA_0, | ||
80 | GP_PAT_DATA_1, | ||
81 | GP_RASTER_MODE, | ||
82 | GP_VECTOR_MODE, | ||
83 | |||
84 | GP_BLT_MODE, | ||
85 | GP_BLT_STATUS, | ||
86 | GP_HST_SRC, | ||
87 | GP_BASE_OFFSET, /* 0x4c */ | ||
88 | }; | ||
89 | |||
90 | #define GP_BLT_STATUS_BLT_PENDING (1 << 2) | ||
91 | #define GP_BLT_STATUS_BLT_BUSY (1 << 0) | ||
92 | |||
93 | |||
94 | /* Display Controller registers (table 6-38 from the data book) */ | ||
95 | enum dc_registers { | ||
96 | DC_UNLOCK = 0, | ||
97 | DC_GENERAL_CFG, | ||
98 | DC_DISPLAY_CFG, | ||
99 | DC_RSVD_0, | ||
100 | |||
101 | DC_FB_ST_OFFSET, | ||
102 | DC_CB_ST_OFFSET, | ||
103 | DC_CURS_ST_OFFSET, | ||
104 | DC_ICON_ST_OFFSET, | ||
105 | |||
106 | DC_VID_Y_ST_OFFSET, | ||
107 | DC_VID_U_ST_OFFSET, | ||
108 | DC_VID_V_ST_OFFSET, | ||
109 | DC_RSVD_1, | ||
110 | |||
111 | DC_LINE_SIZE, | ||
112 | DC_GFX_PITCH, | ||
113 | DC_VID_YUV_PITCH, | ||
114 | DC_RSVD_2, | ||
115 | |||
116 | DC_H_ACTIVE_TIMING, | ||
117 | DC_H_BLANK_TIMING, | ||
118 | DC_H_SYNC_TIMING, | ||
119 | DC_RSVD_3, | ||
120 | |||
121 | DC_V_ACTIVE_TIMING, | ||
122 | DC_V_BLANK_TIMING, | ||
123 | DC_V_SYNC_TIMING, | ||
124 | DC_RSVD_4, | ||
125 | |||
126 | DC_CURSOR_X, | ||
127 | DC_CURSOR_Y, | ||
128 | DC_ICON_X, | ||
129 | DC_LINE_CNT, | ||
130 | |||
131 | DC_PAL_ADDRESS, | ||
132 | DC_PAL_DATA, | ||
133 | DC_DFIFO_DIAG, | ||
134 | DC_CFIFO_DIAG, | ||
135 | |||
136 | DC_VID_DS_DELTA, | ||
137 | DC_GLIU0_MEM_OFFSET, | ||
138 | DC_RSVD_5, | ||
139 | DC_DV_ACC, /* 0x8c */ | ||
140 | }; | ||
141 | |||
142 | #define DC_UNLOCK_LOCK 0x00000000 | ||
143 | #define DC_UNLOCK_UNLOCK 0x00004758 /* magic value */ | ||
144 | |||
145 | #define DC_GENERAL_CFG_YUVM (1 << 20) | ||
146 | #define DC_GENERAL_CFG_VDSE (1 << 19) | ||
147 | #define DC_GENERAL_CFG_DFHPEL_SHIFT 12 | ||
148 | #define DC_GENERAL_CFG_DFHPSL_SHIFT 8 | ||
149 | #define DC_GENERAL_CFG_DECE (1 << 6) | ||
150 | #define DC_GENERAL_CFG_CMPE (1 << 5) | ||
151 | #define DC_GENERAL_CFG_VIDE (1 << 3) | ||
152 | #define DC_GENERAL_CFG_ICNE (1 << 2) | ||
153 | #define DC_GENERAL_CFG_CURE (1 << 1) | ||
154 | #define DC_GENERAL_CFG_DFLE (1 << 0) | ||
155 | |||
156 | #define DC_DISPLAY_CFG_A20M (1 << 31) | ||
157 | #define DC_DISPLAY_CFG_A18M (1 << 30) | ||
158 | #define DC_DISPLAY_CFG_PALB (1 << 25) | ||
159 | #define DC_DISPLAY_CFG_DISP_MODE_24BPP (1 << 9) | ||
160 | #define DC_DISPLAY_CFG_DISP_MODE_16BPP (1 << 8) | ||
161 | #define DC_DISPLAY_CFG_DISP_MODE_8BPP (0) | ||
162 | #define DC_DISPLAY_CFG_VDEN (1 << 4) | ||
163 | #define DC_DISPLAY_CFG_GDEN (1 << 3) | ||
164 | #define DC_DISPLAY_CFG_TGEN (1 << 0) | ||
165 | |||
166 | |||
167 | /* | ||
168 | * Video Processor registers (table 6-54). | ||
169 | * There is space for 64 bit values, but we never use more than the | ||
170 | * lower 32 bits. The actual register save/restore code only bothers | ||
171 | * to restore those 32 bits. | ||
172 | */ | ||
173 | enum vp_registers { | ||
174 | VP_VCFG = 0, | ||
175 | VP_DCFG, | ||
176 | |||
177 | VP_VX, | ||
178 | VP_VY, | ||
179 | |||
180 | VP_VS, | ||
181 | VP_VCK, | ||
182 | |||
183 | VP_VCM, | ||
184 | VP_GAR, | ||
185 | |||
186 | VP_GDR, | ||
187 | VP_RSVD_0, | ||
188 | |||
189 | VP_MISC, | ||
190 | VP_CCS, | ||
191 | |||
192 | VP_RSVD_1, | ||
193 | VP_RSVD_2, | ||
194 | |||
195 | VP_RSVD_3, | ||
196 | VP_VDC, | ||
197 | |||
198 | VP_VCO, | ||
199 | VP_CRC, | ||
200 | |||
201 | VP_CRC32, | ||
202 | VP_VDE, | ||
203 | |||
204 | VP_CCK, | ||
205 | VP_CCM, | ||
206 | |||
207 | VP_CC1, | ||
208 | VP_CC2, | ||
209 | |||
210 | VP_A1X, | ||
211 | VP_A1Y, | ||
212 | |||
213 | VP_A1C, | ||
214 | VP_A1T, | ||
215 | |||
216 | VP_A2X, | ||
217 | VP_A2Y, | ||
218 | |||
219 | VP_A2C, | ||
220 | VP_A2T, | ||
221 | |||
222 | VP_A3X, | ||
223 | VP_A3Y, | ||
224 | |||
225 | VP_A3C, | ||
226 | VP_A3T, | ||
227 | |||
228 | VP_VRR, | ||
229 | VP_AWT, | ||
230 | |||
231 | VP_VTM, /* 0x130 */ | ||
232 | }; | ||
233 | |||
234 | #define VP_VCFG_VID_EN (1 << 0) | ||
235 | |||
236 | #define VP_DCFG_DAC_VREF (1 << 26) | ||
237 | #define VP_DCFG_GV_GAM (1 << 21) | ||
238 | #define VP_DCFG_VG_CK (1 << 20) | ||
239 | #define VP_DCFG_CRT_SYNC_SKW_DEFAULT (1 << 16) | ||
240 | #define VP_DCFG_CRT_SYNC_SKW ((1 << 14) | (1 << 15) | (1 << 16)) | ||
241 | #define VP_DCFG_CRT_VSYNC_POL (1 << 9) | ||
242 | #define VP_DCFG_CRT_HSYNC_POL (1 << 8) | ||
243 | #define VP_DCFG_FP_DATA_EN (1 << 7) /* undocumented */ | ||
244 | #define VP_DCFG_FP_PWR_EN (1 << 6) /* undocumented */ | ||
245 | #define VP_DCFG_DAC_BL_EN (1 << 3) | ||
246 | #define VP_DCFG_VSYNC_EN (1 << 2) | ||
247 | #define VP_DCFG_HSYNC_EN (1 << 1) | ||
248 | #define VP_DCFG_CRT_EN (1 << 0) | ||
249 | |||
250 | #define VP_MISC_GAM_EN (1 << 0) | ||
251 | #define VP_MISC_DACPWRDN (1 << 10) | ||
252 | #define VP_MISC_APWRDN (1 << 11) | ||
253 | |||
254 | |||
255 | /* | ||
256 | * Flat Panel registers (table 6-55). | ||
257 | * Also 64 bit registers; see above note about 32-bit handling. | ||
258 | */ | ||
259 | |||
260 | /* we're actually in the VP register space, starting at address 0x400 */ | ||
261 | #define VP_FP_START 0x400 | ||
262 | |||
263 | enum fp_registers { | ||
264 | FP_PT1 = 0, | ||
265 | FP_PT2, | ||
266 | |||
267 | FP_PM, | ||
268 | FP_DFC, | ||
269 | |||
270 | FP_BLFSR, | ||
271 | FP_RLFSR, | ||
272 | |||
273 | FP_FMI, | ||
274 | FP_FMD, | ||
275 | |||
276 | FP_RSVD_0, | ||
277 | FP_DCA, | ||
278 | |||
279 | FP_DMD, | ||
280 | FP_CRC, | ||
281 | |||
282 | FP_FBB, /* 0x460 */ | ||
283 | }; | ||
284 | |||
285 | #define FP_PT1_VSIZE_SHIFT 16 /* undocumented? */ | ||
286 | #define FP_PT1_VSIZE_MASK 0x7FF0000 /* undocumented? */ | ||
287 | |||
288 | #define FP_PT2_HSP (1 << 22) | ||
289 | #define FP_PT2_VSP (1 << 23) | ||
290 | |||
291 | #define FP_PM_P (1 << 24) /* panel power on */ | ||
292 | #define FP_PM_PANEL_PWR_UP (1 << 3) /* r/o */ | ||
293 | #define FP_PM_PANEL_PWR_DOWN (1 << 2) /* r/o */ | ||
294 | #define FP_PM_PANEL_OFF (1 << 1) /* r/o */ | ||
295 | #define FP_PM_PANEL_ON (1 << 0) /* r/o */ | ||
296 | |||
297 | #define FP_DFC_NFI ((1 << 4) | (1 << 5) | (1 << 6)) | ||
298 | |||
299 | |||
300 | /* register access functions */ | ||
301 | |||
302 | static inline uint32_t read_gp(struct gxfb_par *par, int reg) | ||
303 | { | ||
304 | return readl(par->gp_regs + 4*reg); | ||
305 | } | ||
306 | |||
307 | static inline void write_gp(struct gxfb_par *par, int reg, uint32_t val) | ||
308 | { | ||
309 | writel(val, par->gp_regs + 4*reg); | ||
310 | } | ||
311 | |||
312 | static inline uint32_t read_dc(struct gxfb_par *par, int reg) | ||
313 | { | ||
314 | return readl(par->dc_regs + 4*reg); | ||
315 | } | ||
316 | |||
317 | static inline void write_dc(struct gxfb_par *par, int reg, uint32_t val) | ||
318 | { | ||
319 | writel(val, par->dc_regs + 4*reg); | ||
320 | } | ||
321 | |||
322 | static inline uint32_t read_vp(struct gxfb_par *par, int reg) | ||
323 | { | ||
324 | return readl(par->vid_regs + 8*reg); | ||
325 | } | ||
326 | |||
327 | static inline void write_vp(struct gxfb_par *par, int reg, uint32_t val) | ||
328 | { | ||
329 | writel(val, par->vid_regs + 8*reg); | ||
330 | } | ||
331 | |||
332 | static inline uint32_t read_fp(struct gxfb_par *par, int reg) | ||
333 | { | ||
334 | return readl(par->vid_regs + 8*reg + VP_FP_START); | ||
335 | } | ||
336 | |||
337 | static inline void write_fp(struct gxfb_par *par, int reg, uint32_t val) | ||
338 | { | ||
339 | writel(val, par->vid_regs + 8*reg + VP_FP_START); | ||
340 | } | ||
341 | |||
342 | |||
343 | /* MSRs are defined in asm/geode.h; their bitfields are here */ | ||
344 | |||
345 | #define MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 (1 << 3) | ||
346 | #define MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 (1 << 2) | ||
347 | #define MSR_GLCP_SYS_RSTPLL_DOTPREDIV2 (1 << 1) | ||
348 | |||
349 | #define MSR_GLCP_DOTPLL_LOCK (1 << 25) /* r/o */ | ||
350 | #define MSR_GLCP_DOTPLL_BYPASS (1 << 15) | ||
351 | #define MSR_GLCP_DOTPLL_DOTRESET (1 << 0) | ||
352 | |||
353 | #define MSR_GX_MSR_PADSEL_MASK 0x3FFFFFFF /* undocumented? */ | ||
354 | #define MSR_GX_MSR_PADSEL_TFT 0x1FFFFFFF /* undocumented? */ | ||
355 | |||
356 | #define MSR_GX_GLD_MSR_CONFIG_FP (1 << 3) | ||
357 | |||
358 | #endif | ||
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c index cf841efa229a..de2b8f9876a5 100644 --- a/drivers/video/geode/gxfb_core.c +++ b/drivers/video/geode/gxfb_core.c | |||
@@ -28,17 +28,20 @@ | |||
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/fb.h> | 30 | #include <linux/fb.h> |
31 | #include <linux/console.h> | ||
32 | #include <linux/suspend.h> | ||
31 | #include <linux/init.h> | 33 | #include <linux/init.h> |
32 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
35 | #include <asm/geode.h> | ||
33 | 36 | ||
34 | #include "geodefb.h" | 37 | #include "gxfb.h" |
35 | #include "display_gx.h" | ||
36 | #include "video_gx.h" | ||
37 | 38 | ||
38 | static char *mode_option; | 39 | static char *mode_option; |
40 | static int vram; | ||
41 | static int vt_switch; | ||
39 | 42 | ||
40 | /* Modes relevant to the GX (taken from modedb.c) */ | 43 | /* Modes relevant to the GX (taken from modedb.c) */ |
41 | static const struct fb_videomode gx_modedb[] __initdata = { | 44 | static struct fb_videomode gx_modedb[] __initdata = { |
42 | /* 640x480-60 VESA */ | 45 | /* 640x480-60 VESA */ |
43 | { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, | 46 | { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, |
44 | 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | 47 | 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, |
@@ -105,6 +108,35 @@ static const struct fb_videomode gx_modedb[] __initdata = { | |||
105 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | 108 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, |
106 | }; | 109 | }; |
107 | 110 | ||
111 | #ifdef CONFIG_OLPC | ||
112 | #include <asm/olpc.h> | ||
113 | |||
114 | static struct fb_videomode gx_dcon_modedb[] __initdata = { | ||
115 | /* The only mode the DCON has is 1200x900 */ | ||
116 | { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3, | ||
117 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
118 | FB_VMODE_NONINTERLACED, 0 } | ||
119 | }; | ||
120 | |||
121 | static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) | ||
122 | { | ||
123 | if (olpc_has_dcon()) { | ||
124 | *modedb = (struct fb_videomode *) gx_dcon_modedb; | ||
125 | *size = ARRAY_SIZE(gx_dcon_modedb); | ||
126 | } else { | ||
127 | *modedb = (struct fb_videomode *) gx_modedb; | ||
128 | *size = ARRAY_SIZE(gx_modedb); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | #else | ||
133 | static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) | ||
134 | { | ||
135 | *modedb = (struct fb_videomode *) gx_modedb; | ||
136 | *size = ARRAY_SIZE(gx_modedb); | ||
137 | } | ||
138 | #endif | ||
139 | |||
108 | static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | 140 | static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) |
109 | { | 141 | { |
110 | if (var->xres > 1600 || var->yres > 1200) | 142 | if (var->xres > 1600 || var->yres > 1200) |
@@ -139,8 +171,6 @@ static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
139 | 171 | ||
140 | static int gxfb_set_par(struct fb_info *info) | 172 | static int gxfb_set_par(struct fb_info *info) |
141 | { | 173 | { |
142 | struct geodefb_par *par = info->par; | ||
143 | |||
144 | if (info->var.bits_per_pixel > 8) { | 174 | if (info->var.bits_per_pixel > 8) { |
145 | info->fix.visual = FB_VISUAL_TRUECOLOR; | 175 | info->fix.visual = FB_VISUAL_TRUECOLOR; |
146 | fb_dealloc_cmap(&info->cmap); | 176 | fb_dealloc_cmap(&info->cmap); |
@@ -151,7 +181,7 @@ static int gxfb_set_par(struct fb_info *info) | |||
151 | 181 | ||
152 | info->fix.line_length = gx_line_delta(info->var.xres, info->var.bits_per_pixel); | 182 | info->fix.line_length = gx_line_delta(info->var.xres, info->var.bits_per_pixel); |
153 | 183 | ||
154 | par->dc_ops->set_mode(info); | 184 | gx_set_mode(info); |
155 | 185 | ||
156 | return 0; | 186 | return 0; |
157 | } | 187 | } |
@@ -167,8 +197,6 @@ static int gxfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
167 | unsigned blue, unsigned transp, | 197 | unsigned blue, unsigned transp, |
168 | struct fb_info *info) | 198 | struct fb_info *info) |
169 | { | 199 | { |
170 | struct geodefb_par *par = info->par; | ||
171 | |||
172 | if (info->var.grayscale) { | 200 | if (info->var.grayscale) { |
173 | /* grayscale = 0.30*R + 0.59*G + 0.11*B */ | 201 | /* grayscale = 0.30*R + 0.59*G + 0.11*B */ |
174 | red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; | 202 | red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; |
@@ -191,7 +219,7 @@ static int gxfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
191 | if (regno >= 256) | 219 | if (regno >= 256) |
192 | return -EINVAL; | 220 | return -EINVAL; |
193 | 221 | ||
194 | par->dc_ops->set_palette_reg(info, regno, red, green, blue); | 222 | gx_set_hw_palette_reg(info, regno, red, green, blue); |
195 | } | 223 | } |
196 | 224 | ||
197 | return 0; | 225 | return 0; |
@@ -199,15 +227,12 @@ static int gxfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
199 | 227 | ||
200 | static int gxfb_blank(int blank_mode, struct fb_info *info) | 228 | static int gxfb_blank(int blank_mode, struct fb_info *info) |
201 | { | 229 | { |
202 | struct geodefb_par *par = info->par; | 230 | return gx_blank_display(info, blank_mode); |
203 | |||
204 | return par->vid_ops->blank_display(info, blank_mode); | ||
205 | } | 231 | } |
206 | 232 | ||
207 | static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev) | 233 | static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev) |
208 | { | 234 | { |
209 | struct geodefb_par *par = info->par; | 235 | struct gxfb_par *par = info->par; |
210 | int fb_len; | ||
211 | int ret; | 236 | int ret; |
212 | 237 | ||
213 | ret = pci_enable_device(dev); | 238 | ret = pci_enable_device(dev); |
@@ -229,24 +254,31 @@ static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *de | |||
229 | if (!par->dc_regs) | 254 | if (!par->dc_regs) |
230 | return -ENOMEM; | 255 | return -ENOMEM; |
231 | 256 | ||
232 | ret = pci_request_region(dev, 0, "gxfb (framebuffer)"); | 257 | ret = pci_request_region(dev, 1, "gxfb (graphics processor)"); |
233 | if (ret < 0) | 258 | if (ret < 0) |
234 | return ret; | 259 | return ret; |
235 | if ((fb_len = gx_frame_buffer_size()) < 0) | 260 | par->gp_regs = ioremap(pci_resource_start(dev, 1), |
261 | pci_resource_len(dev, 1)); | ||
262 | |||
263 | if (!par->gp_regs) | ||
236 | return -ENOMEM; | 264 | return -ENOMEM; |
265 | |||
266 | ret = pci_request_region(dev, 0, "gxfb (framebuffer)"); | ||
267 | if (ret < 0) | ||
268 | return ret; | ||
269 | |||
237 | info->fix.smem_start = pci_resource_start(dev, 0); | 270 | info->fix.smem_start = pci_resource_start(dev, 0); |
238 | info->fix.smem_len = fb_len; | 271 | info->fix.smem_len = vram ? vram : gx_frame_buffer_size(); |
239 | info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); | 272 | info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); |
240 | if (!info->screen_base) | 273 | if (!info->screen_base) |
241 | return -ENOMEM; | 274 | return -ENOMEM; |
242 | 275 | ||
243 | /* Set the 16MB aligned base address of the graphics memory region | 276 | /* Set the 16MiB aligned base address of the graphics memory region |
244 | * in the display controller */ | 277 | * in the display controller */ |
245 | 278 | ||
246 | writel(info->fix.smem_start & 0xFF000000, | 279 | write_dc(par, DC_GLIU0_MEM_OFFSET, info->fix.smem_start & 0xFF000000); |
247 | par->dc_regs + DC_GLIU0_MEM_OFFSET); | ||
248 | 280 | ||
249 | dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n", | 281 | dev_info(&dev->dev, "%d KiB of video memory at 0x%lx\n", |
250 | info->fix.smem_len / 1024, info->fix.smem_start); | 282 | info->fix.smem_len / 1024, info->fix.smem_start); |
251 | 283 | ||
252 | return 0; | 284 | return 0; |
@@ -266,11 +298,12 @@ static struct fb_ops gxfb_ops = { | |||
266 | 298 | ||
267 | static struct fb_info * __init gxfb_init_fbinfo(struct device *dev) | 299 | static struct fb_info * __init gxfb_init_fbinfo(struct device *dev) |
268 | { | 300 | { |
269 | struct geodefb_par *par; | 301 | struct gxfb_par *par; |
270 | struct fb_info *info; | 302 | struct fb_info *info; |
271 | 303 | ||
272 | /* Alloc enough space for the pseudo palette. */ | 304 | /* Alloc enough space for the pseudo palette. */ |
273 | info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, dev); | 305 | info = framebuffer_alloc(sizeof(struct gxfb_par) + sizeof(u32) * 16, |
306 | dev); | ||
274 | if (!info) | 307 | if (!info) |
275 | return NULL; | 308 | return NULL; |
276 | 309 | ||
@@ -296,29 +329,64 @@ static struct fb_info * __init gxfb_init_fbinfo(struct device *dev) | |||
296 | info->flags = FBINFO_DEFAULT; | 329 | info->flags = FBINFO_DEFAULT; |
297 | info->node = -1; | 330 | info->node = -1; |
298 | 331 | ||
299 | info->pseudo_palette = (void *)par + sizeof(struct geodefb_par); | 332 | info->pseudo_palette = (void *)par + sizeof(struct gxfb_par); |
300 | 333 | ||
301 | info->var.grayscale = 0; | 334 | info->var.grayscale = 0; |
302 | 335 | ||
303 | return info; | 336 | return info; |
304 | } | 337 | } |
305 | 338 | ||
339 | #ifdef CONFIG_PM | ||
340 | static int gxfb_suspend(struct pci_dev *pdev, pm_message_t state) | ||
341 | { | ||
342 | struct fb_info *info = pci_get_drvdata(pdev); | ||
343 | |||
344 | if (state.event == PM_EVENT_SUSPEND) { | ||
345 | acquire_console_sem(); | ||
346 | gx_powerdown(info); | ||
347 | fb_set_suspend(info, 1); | ||
348 | release_console_sem(); | ||
349 | } | ||
350 | |||
351 | /* there's no point in setting PCI states; we emulate PCI, so | ||
352 | * we don't end up getting power savings anyways */ | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static int gxfb_resume(struct pci_dev *pdev) | ||
358 | { | ||
359 | struct fb_info *info = pci_get_drvdata(pdev); | ||
360 | int ret; | ||
361 | |||
362 | acquire_console_sem(); | ||
363 | ret = gx_powerup(info); | ||
364 | if (ret) { | ||
365 | printk(KERN_ERR "gxfb: power up failed!\n"); | ||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | fb_set_suspend(info, 0); | ||
370 | release_console_sem(); | ||
371 | return 0; | ||
372 | } | ||
373 | #endif | ||
374 | |||
306 | static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 375 | static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
307 | { | 376 | { |
308 | struct geodefb_par *par; | 377 | struct gxfb_par *par; |
309 | struct fb_info *info; | 378 | struct fb_info *info; |
310 | int ret; | 379 | int ret; |
311 | unsigned long val; | 380 | unsigned long val; |
312 | 381 | ||
382 | struct fb_videomode *modedb_ptr; | ||
383 | unsigned int modedb_size; | ||
384 | |||
313 | info = gxfb_init_fbinfo(&pdev->dev); | 385 | info = gxfb_init_fbinfo(&pdev->dev); |
314 | if (!info) | 386 | if (!info) |
315 | return -ENOMEM; | 387 | return -ENOMEM; |
316 | par = info->par; | 388 | par = info->par; |
317 | 389 | ||
318 | /* GX display controller and GX video device. */ | ||
319 | par->dc_ops = &gx_dc_ops; | ||
320 | par->vid_ops = &gx_vid_ops; | ||
321 | |||
322 | if ((ret = gxfb_map_video_memory(info, pdev)) < 0) { | 390 | if ((ret = gxfb_map_video_memory(info, pdev)) < 0) { |
323 | dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n"); | 391 | dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n"); |
324 | goto err; | 392 | goto err; |
@@ -326,15 +394,16 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i | |||
326 | 394 | ||
327 | /* Figure out if this is a TFT or CRT part */ | 395 | /* Figure out if this is a TFT or CRT part */ |
328 | 396 | ||
329 | rdmsrl(GLD_MSR_CONFIG, val); | 397 | rdmsrl(MSR_GX_GLD_MSR_CONFIG, val); |
330 | 398 | ||
331 | if ((val & GLD_MSR_CONFIG_DM_FP) == GLD_MSR_CONFIG_DM_FP) | 399 | if ((val & MSR_GX_GLD_MSR_CONFIG_FP) == MSR_GX_GLD_MSR_CONFIG_FP) |
332 | par->enable_crt = 0; | 400 | par->enable_crt = 0; |
333 | else | 401 | else |
334 | par->enable_crt = 1; | 402 | par->enable_crt = 1; |
335 | 403 | ||
404 | get_modedb(&modedb_ptr, &modedb_size); | ||
336 | ret = fb_find_mode(&info->var, info, mode_option, | 405 | ret = fb_find_mode(&info->var, info, mode_option, |
337 | gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16); | 406 | modedb_ptr, modedb_size, NULL, 16); |
338 | if (ret == 0 || ret == 4) { | 407 | if (ret == 0 || ret == 4) { |
339 | dev_err(&pdev->dev, "could not find valid video mode\n"); | 408 | dev_err(&pdev->dev, "could not find valid video mode\n"); |
340 | ret = -EINVAL; | 409 | ret = -EINVAL; |
@@ -348,6 +417,8 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i | |||
348 | gxfb_check_var(&info->var, info); | 417 | gxfb_check_var(&info->var, info); |
349 | gxfb_set_par(info); | 418 | gxfb_set_par(info); |
350 | 419 | ||
420 | pm_set_vt_switch(vt_switch); | ||
421 | |||
351 | if (register_framebuffer(info) < 0) { | 422 | if (register_framebuffer(info) < 0) { |
352 | ret = -EINVAL; | 423 | ret = -EINVAL; |
353 | goto err; | 424 | goto err; |
@@ -369,6 +440,10 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i | |||
369 | iounmap(par->dc_regs); | 440 | iounmap(par->dc_regs); |
370 | pci_release_region(pdev, 2); | 441 | pci_release_region(pdev, 2); |
371 | } | 442 | } |
443 | if (par->gp_regs) { | ||
444 | iounmap(par->gp_regs); | ||
445 | pci_release_region(pdev, 1); | ||
446 | } | ||
372 | 447 | ||
373 | if (info) | 448 | if (info) |
374 | framebuffer_release(info); | 449 | framebuffer_release(info); |
@@ -378,7 +453,7 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i | |||
378 | static void gxfb_remove(struct pci_dev *pdev) | 453 | static void gxfb_remove(struct pci_dev *pdev) |
379 | { | 454 | { |
380 | struct fb_info *info = pci_get_drvdata(pdev); | 455 | struct fb_info *info = pci_get_drvdata(pdev); |
381 | struct geodefb_par *par = info->par; | 456 | struct gxfb_par *par = info->par; |
382 | 457 | ||
383 | unregister_framebuffer(info); | 458 | unregister_framebuffer(info); |
384 | 459 | ||
@@ -391,15 +466,16 @@ static void gxfb_remove(struct pci_dev *pdev) | |||
391 | iounmap(par->dc_regs); | 466 | iounmap(par->dc_regs); |
392 | pci_release_region(pdev, 2); | 467 | pci_release_region(pdev, 2); |
393 | 468 | ||
469 | iounmap(par->gp_regs); | ||
470 | pci_release_region(pdev, 1); | ||
471 | |||
394 | pci_set_drvdata(pdev, NULL); | 472 | pci_set_drvdata(pdev, NULL); |
395 | 473 | ||
396 | framebuffer_release(info); | 474 | framebuffer_release(info); |
397 | } | 475 | } |
398 | 476 | ||
399 | static struct pci_device_id gxfb_id_table[] = { | 477 | static struct pci_device_id gxfb_id_table[] = { |
400 | { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO, | 478 | { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO) }, |
401 | PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, | ||
402 | 0xff0000, 0 }, | ||
403 | { 0, } | 479 | { 0, } |
404 | }; | 480 | }; |
405 | 481 | ||
@@ -410,6 +486,10 @@ static struct pci_driver gxfb_driver = { | |||
410 | .id_table = gxfb_id_table, | 486 | .id_table = gxfb_id_table, |
411 | .probe = gxfb_probe, | 487 | .probe = gxfb_probe, |
412 | .remove = gxfb_remove, | 488 | .remove = gxfb_remove, |
489 | #ifdef CONFIG_PM | ||
490 | .suspend = gxfb_suspend, | ||
491 | .resume = gxfb_resume, | ||
492 | #endif | ||
413 | }; | 493 | }; |
414 | 494 | ||
415 | #ifndef MODULE | 495 | #ifndef MODULE |
@@ -456,5 +536,11 @@ module_exit(gxfb_cleanup); | |||
456 | module_param(mode_option, charp, 0); | 536 | module_param(mode_option, charp, 0); |
457 | MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])"); | 537 | MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])"); |
458 | 538 | ||
539 | module_param(vram, int, 0); | ||
540 | MODULE_PARM_DESC(vram, "video memory size"); | ||
541 | |||
542 | module_param(vt_switch, int, 0); | ||
543 | MODULE_PARM_DESC(vt_switch, "enable VT switch during suspend/resume"); | ||
544 | |||
459 | MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX"); | 545 | MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX"); |
460 | MODULE_LICENSE("GPL"); | 546 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h index ca13c48d19b0..3b9416f4ee20 100644 --- a/drivers/video/geode/lxfb.h +++ b/drivers/video/geode/lxfb.h | |||
@@ -3,17 +3,46 @@ | |||
3 | 3 | ||
4 | #include <linux/fb.h> | 4 | #include <linux/fb.h> |
5 | 5 | ||
6 | #define GP_REG_COUNT (0x7c / 4) | ||
7 | #define DC_REG_COUNT (0xf0 / 4) | ||
8 | #define VP_REG_COUNT (0x158 / 8) | ||
9 | #define FP_REG_COUNT (0x60 / 8) | ||
10 | |||
11 | #define DC_PAL_COUNT 0x104 | ||
12 | #define DC_HFILT_COUNT 0x100 | ||
13 | #define DC_VFILT_COUNT 0x100 | ||
14 | #define VP_COEFF_SIZE 0x1000 | ||
15 | |||
6 | #define OUTPUT_CRT 0x01 | 16 | #define OUTPUT_CRT 0x01 |
7 | #define OUTPUT_PANEL 0x02 | 17 | #define OUTPUT_PANEL 0x02 |
8 | 18 | ||
9 | struct lxfb_par { | 19 | struct lxfb_par { |
10 | int output; | 20 | int output; |
11 | int panel_width; | ||
12 | int panel_height; | ||
13 | 21 | ||
14 | void __iomem *gp_regs; | 22 | void __iomem *gp_regs; |
15 | void __iomem *dc_regs; | 23 | void __iomem *dc_regs; |
16 | void __iomem *df_regs; | 24 | void __iomem *vp_regs; |
25 | #ifdef CONFIG_PM | ||
26 | int powered_down; | ||
27 | |||
28 | /* register state, for power mgmt functionality */ | ||
29 | struct { | ||
30 | uint64_t padsel; | ||
31 | uint64_t dotpll; | ||
32 | uint64_t dfglcfg; | ||
33 | uint64_t dcspare; | ||
34 | } msr; | ||
35 | |||
36 | uint32_t gp[GP_REG_COUNT]; | ||
37 | uint32_t dc[DC_REG_COUNT]; | ||
38 | uint64_t vp[VP_REG_COUNT]; | ||
39 | uint64_t fp[FP_REG_COUNT]; | ||
40 | |||
41 | uint32_t pal[DC_PAL_COUNT]; | ||
42 | uint32_t hcoeff[DC_HFILT_COUNT * 2]; | ||
43 | uint32_t vcoeff[DC_VFILT_COUNT]; | ||
44 | uint32_t vp_coeff[VP_COEFF_SIZE / 4]; | ||
45 | #endif | ||
17 | }; | 46 | }; |
18 | 47 | ||
19 | static inline unsigned int lx_get_pitch(unsigned int xres, int bpp) | 48 | static inline unsigned int lx_get_pitch(unsigned int xres, int bpp) |
@@ -29,171 +58,383 @@ int lx_blank_display(struct fb_info *, int); | |||
29 | void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int, | 58 | void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int, |
30 | unsigned int, unsigned int); | 59 | unsigned int, unsigned int); |
31 | 60 | ||
32 | /* MSRS */ | 61 | #ifdef CONFIG_PM |
62 | int lx_powerdown(struct fb_info *info); | ||
63 | int lx_powerup(struct fb_info *info); | ||
64 | #endif | ||
65 | |||
66 | |||
67 | /* Graphics Processor registers (table 6-29 from the data book) */ | ||
68 | enum gp_registers { | ||
69 | GP_DST_OFFSET = 0, | ||
70 | GP_SRC_OFFSET, | ||
71 | GP_STRIDE, | ||
72 | GP_WID_HEIGHT, | ||
73 | |||
74 | GP_SRC_COLOR_FG, | ||
75 | GP_SRC_COLOR_BG, | ||
76 | GP_PAT_COLOR_0, | ||
77 | GP_PAT_COLOR_1, | ||
78 | |||
79 | GP_PAT_COLOR_2, | ||
80 | GP_PAT_COLOR_3, | ||
81 | GP_PAT_COLOR_4, | ||
82 | GP_PAT_COLOR_5, | ||
83 | |||
84 | GP_PAT_DATA_0, | ||
85 | GP_PAT_DATA_1, | ||
86 | GP_RASTER_MODE, | ||
87 | GP_VECTOR_MODE, | ||
88 | |||
89 | GP_BLT_MODE, | ||
90 | GP_BLT_STATUS, | ||
91 | GP_HST_SRC, | ||
92 | GP_BASE_OFFSET, | ||
93 | |||
94 | GP_CMD_TOP, | ||
95 | GP_CMD_BOT, | ||
96 | GP_CMD_READ, | ||
97 | GP_CMD_WRITE, | ||
98 | |||
99 | GP_CH3_OFFSET, | ||
100 | GP_CH3_MODE_STR, | ||
101 | GP_CH3_WIDHI, | ||
102 | GP_CH3_HSRC, | ||
103 | |||
104 | GP_LUT_INDEX, | ||
105 | GP_LUT_DATA, | ||
106 | GP_INT_CNTRL, /* 0x78 */ | ||
107 | }; | ||
108 | |||
109 | #define GP_BLT_STATUS_CE (1 << 4) /* cmd buf empty */ | ||
110 | #define GP_BLT_STATUS_PB (1 << 0) /* primative busy */ | ||
111 | |||
112 | |||
113 | /* Display Controller registers (table 6-47 from the data book) */ | ||
114 | enum dc_registers { | ||
115 | DC_UNLOCK = 0, | ||
116 | DC_GENERAL_CFG, | ||
117 | DC_DISPLAY_CFG, | ||
118 | DC_ARB_CFG, | ||
119 | |||
120 | DC_FB_ST_OFFSET, | ||
121 | DC_CB_ST_OFFSET, | ||
122 | DC_CURS_ST_OFFSET, | ||
123 | DC_RSVD_0, | ||
124 | |||
125 | DC_VID_Y_ST_OFFSET, | ||
126 | DC_VID_U_ST_OFFSET, | ||
127 | DC_VID_V_ST_OFFSET, | ||
128 | DC_DV_TOP, | ||
129 | |||
130 | DC_LINE_SIZE, | ||
131 | DC_GFX_PITCH, | ||
132 | DC_VID_YUV_PITCH, | ||
133 | DC_RSVD_1, | ||
134 | |||
135 | DC_H_ACTIVE_TIMING, | ||
136 | DC_H_BLANK_TIMING, | ||
137 | DC_H_SYNC_TIMING, | ||
138 | DC_RSVD_2, | ||
139 | |||
140 | DC_V_ACTIVE_TIMING, | ||
141 | DC_V_BLANK_TIMING, | ||
142 | DC_V_SYNC_TIMING, | ||
143 | DC_FB_ACTIVE, | ||
144 | |||
145 | DC_CURSOR_X, | ||
146 | DC_CURSOR_Y, | ||
147 | DC_RSVD_3, | ||
148 | DC_LINE_CNT, | ||
149 | |||
150 | DC_PAL_ADDRESS, | ||
151 | DC_PAL_DATA, | ||
152 | DC_DFIFO_DIAG, | ||
153 | DC_CFIFO_DIAG, | ||
154 | |||
155 | DC_VID_DS_DELTA, | ||
156 | DC_GLIU0_MEM_OFFSET, | ||
157 | DC_DV_CTL, | ||
158 | DC_DV_ACCESS, | ||
159 | |||
160 | DC_GFX_SCALE, | ||
161 | DC_IRQ_FILT_CTL, | ||
162 | DC_FILT_COEFF1, | ||
163 | DC_FILT_COEFF2, | ||
164 | |||
165 | DC_VBI_EVEN_CTL, | ||
166 | DC_VBI_ODD_CTL, | ||
167 | DC_VBI_HOR, | ||
168 | DC_VBI_LN_ODD, | ||
169 | |||
170 | DC_VBI_LN_EVEN, | ||
171 | DC_VBI_PITCH, | ||
172 | DC_CLR_KEY, | ||
173 | DC_CLR_KEY_MASK, | ||
174 | |||
175 | DC_CLR_KEY_X, | ||
176 | DC_CLR_KEY_Y, | ||
177 | DC_IRQ, | ||
178 | DC_RSVD_4, | ||
179 | |||
180 | DC_RSVD_5, | ||
181 | DC_GENLK_CTL, | ||
182 | DC_VID_EVEN_Y_ST_OFFSET, | ||
183 | DC_VID_EVEN_U_ST_OFFSET, | ||
184 | |||
185 | DC_VID_EVEN_V_ST_OFFSET, | ||
186 | DC_V_ACTIVE_EVEN_TIMING, | ||
187 | DC_V_BLANK_EVEN_TIMING, | ||
188 | DC_V_SYNC_EVEN_TIMING, /* 0xec */ | ||
189 | }; | ||
190 | |||
191 | #define DC_UNLOCK_LOCK 0x00000000 | ||
192 | #define DC_UNLOCK_UNLOCK 0x00004758 /* magic value */ | ||
193 | |||
194 | #define DC_GENERAL_CFG_FDTY (1 << 17) | ||
195 | #define DC_GENERAL_CFG_DFHPEL_SHIFT (12) | ||
196 | #define DC_GENERAL_CFG_DFHPSL_SHIFT (8) | ||
197 | #define DC_GENERAL_CFG_VGAE (1 << 7) | ||
198 | #define DC_GENERAL_CFG_DECE (1 << 6) | ||
199 | #define DC_GENERAL_CFG_CMPE (1 << 5) | ||
200 | #define DC_GENERAL_CFG_VIDE (1 << 3) | ||
201 | #define DC_GENERAL_CFG_DFLE (1 << 0) | ||
202 | |||
203 | #define DC_DISPLAY_CFG_VISL (1 << 27) | ||
204 | #define DC_DISPLAY_CFG_PALB (1 << 25) | ||
205 | #define DC_DISPLAY_CFG_DCEN (1 << 24) | ||
206 | #define DC_DISPLAY_CFG_DISP_MODE_24BPP (1 << 9) | ||
207 | #define DC_DISPLAY_CFG_DISP_MODE_16BPP (1 << 8) | ||
208 | #define DC_DISPLAY_CFG_DISP_MODE_8BPP (0) | ||
209 | #define DC_DISPLAY_CFG_TRUP (1 << 6) | ||
210 | #define DC_DISPLAY_CFG_VDEN (1 << 4) | ||
211 | #define DC_DISPLAY_CFG_GDEN (1 << 3) | ||
212 | #define DC_DISPLAY_CFG_TGEN (1 << 0) | ||
213 | |||
214 | #define DC_DV_TOP_DV_TOP_EN (1 << 0) | ||
215 | |||
216 | #define DC_DV_CTL_DV_LINE_SIZE ((1 << 10) | (1 << 11)) | ||
217 | #define DC_DV_CTL_DV_LINE_SIZE_1K (0) | ||
218 | #define DC_DV_CTL_DV_LINE_SIZE_2K (1 << 10) | ||
219 | #define DC_DV_CTL_DV_LINE_SIZE_4K (1 << 11) | ||
220 | #define DC_DV_CTL_DV_LINE_SIZE_8K ((1 << 10) | (1 << 11)) | ||
221 | #define DC_DV_CTL_CLEAR_DV_RAM (1 << 0) | ||
222 | |||
223 | #define DC_IRQ_FILT_CTL_H_FILT_SEL (1 << 10) | ||
224 | |||
225 | #define DC_CLR_KEY_CLR_KEY_EN (1 << 24) | ||
226 | |||
227 | #define DC_IRQ_VIP_VSYNC_IRQ_STATUS (1 << 21) /* undocumented? */ | ||
228 | #define DC_IRQ_STATUS (1 << 20) /* undocumented? */ | ||
229 | #define DC_IRQ_VIP_VSYNC_LOSS_IRQ_MASK (1 << 1) | ||
230 | #define DC_IRQ_MASK (1 << 0) | ||
33 | 231 | ||
34 | #define MSR_LX_GLD_CONFIG 0x48002001 | 232 | #define DC_GENLK_CTL_FLICK_SEL_MASK (0x0F << 28) |
35 | #define MSR_LX_GLCP_DOTPLL 0x4c000015 | 233 | #define DC_GENLK_CTL_ALPHA_FLICK_EN (1 << 25) |
36 | #define MSR_LX_DF_PADSEL 0x48002011 | 234 | #define DC_GENLK_CTL_FLICK_EN (1 << 24) |
37 | #define MSR_LX_DC_SPARE 0x80000011 | 235 | #define DC_GENLK_CTL_GENLK_EN (1 << 18) |
38 | #define MSR_LX_DF_GLCONFIG 0x48002001 | ||
39 | |||
40 | #define MSR_LX_GLIU0_P2D_RO0 0x10000029 | ||
41 | |||
42 | #define GLCP_DOTPLL_RESET (1 << 0) | ||
43 | #define GLCP_DOTPLL_BYPASS (1 << 15) | ||
44 | #define GLCP_DOTPLL_HALFPIX (1 << 24) | ||
45 | #define GLCP_DOTPLL_LOCK (1 << 25) | ||
46 | |||
47 | #define DF_CONFIG_OUTPUT_MASK 0x38 | ||
48 | #define DF_OUTPUT_PANEL 0x08 | ||
49 | #define DF_OUTPUT_CRT 0x00 | ||
50 | #define DF_SIMULTANEOUS_CRT_AND_FP (1 << 15) | ||
51 | |||
52 | #define DF_DEFAULT_TFT_PAD_SEL_LOW 0xDFFFFFFF | ||
53 | #define DF_DEFAULT_TFT_PAD_SEL_HIGH 0x0000003F | ||
54 | |||
55 | #define DC_SPARE_DISABLE_CFIFO_HGO 0x00000800 | ||
56 | #define DC_SPARE_VFIFO_ARB_SELECT 0x00000400 | ||
57 | #define DC_SPARE_WM_LPEN_OVRD 0x00000200 | ||
58 | #define DC_SPARE_LOAD_WM_LPEN_MASK 0x00000100 | ||
59 | #define DC_SPARE_DISABLE_INIT_VID_PRI 0x00000080 | ||
60 | #define DC_SPARE_DISABLE_VFIFO_WM 0x00000040 | ||
61 | #define DC_SPARE_DISABLE_CWD_CHECK 0x00000020 | ||
62 | #define DC_SPARE_PIX8_PAN_FIX 0x00000010 | ||
63 | #define DC_SPARE_FIRST_REQ_MASK 0x00000002 | ||
64 | |||
65 | /* Registers */ | ||
66 | |||
67 | #define DC_UNLOCK 0x00 | ||
68 | #define DC_UNLOCK_CODE 0x4758 | ||
69 | 236 | ||
70 | #define DC_GENERAL_CFG 0x04 | ||
71 | #define DC_GCFG_DFLE (1 << 0) | ||
72 | #define DC_GCFG_VIDE (1 << 3) | ||
73 | #define DC_GCFG_VGAE (1 << 7) | ||
74 | #define DC_GCFG_CMPE (1 << 5) | ||
75 | #define DC_GCFG_DECE (1 << 6) | ||
76 | #define DC_GCFG_FDTY (1 << 17) | ||
77 | 237 | ||
78 | #define DC_DISPLAY_CFG 0x08 | 238 | /* |
79 | #define DC_DCFG_TGEN (1 << 0) | 239 | * Video Processor registers (table 6-71). |
80 | #define DC_DCFG_GDEN (1 << 3) | 240 | * There is space for 64 bit values, but we never use more than the |
81 | #define DC_DCFG_VDEN (1 << 4) | 241 | * lower 32 bits. The actual register save/restore code only bothers |
82 | #define DC_DCFG_TRUP (1 << 6) | 242 | * to restore those 32 bits. |
83 | #define DC_DCFG_DCEN (1 << 24) | 243 | */ |
84 | #define DC_DCFG_PALB (1 << 25) | 244 | enum vp_registers { |
85 | #define DC_DCFG_VISL (1 << 27) | 245 | VP_VCFG = 0, |
246 | VP_DCFG, | ||
86 | 247 | ||
87 | #define DC_DCFG_16BPP 0x0 | 248 | VP_VX, |
249 | VP_VY, | ||
88 | 250 | ||
89 | #define DC_DCFG_DISP_MODE_MASK 0x00000300 | 251 | VP_SCL, |
90 | #define DC_DCFG_DISP_MODE_8BPP 0x00000000 | 252 | VP_VCK, |
91 | #define DC_DCFG_DISP_MODE_16BPP 0x00000100 | ||
92 | #define DC_DCFG_DISP_MODE_24BPP 0x00000200 | ||
93 | #define DC_DCFG_DISP_MODE_32BPP 0x00000300 | ||
94 | 253 | ||
254 | VP_VCM, | ||
255 | VP_PAR, | ||
95 | 256 | ||
96 | #define DC_ARB_CFG 0x0C | 257 | VP_PDR, |
258 | VP_SLR, | ||
97 | 259 | ||
98 | #define DC_FB_START 0x10 | 260 | VP_MISC, |
99 | #define DC_CB_START 0x14 | 261 | VP_CCS, |
100 | #define DC_CURSOR_START 0x18 | ||
101 | 262 | ||
102 | #define DC_DV_TOP 0x2C | 263 | VP_VYS, |
103 | #define DC_DV_TOP_ENABLE (1 << 0) | 264 | VP_VXS, |
104 | 265 | ||
105 | #define DC_LINE_SIZE 0x30 | 266 | VP_RSVD_0, |
106 | #define DC_GRAPHICS_PITCH 0x34 | 267 | VP_VDC, |
107 | #define DC_H_ACTIVE_TIMING 0x40 | 268 | |
108 | #define DC_H_BLANK_TIMING 0x44 | 269 | VP_RSVD_1, |
109 | #define DC_H_SYNC_TIMING 0x48 | 270 | VP_CRC, |
110 | #define DC_V_ACTIVE_TIMING 0x50 | 271 | |
111 | #define DC_V_BLANK_TIMING 0x54 | 272 | VP_CRC32, |
112 | #define DC_V_SYNC_TIMING 0x58 | 273 | VP_VDE, |
113 | #define DC_FB_ACTIVE 0x5C | 274 | |
275 | VP_CCK, | ||
276 | VP_CCM, | ||
277 | |||
278 | VP_CC1, | ||
279 | VP_CC2, | ||
280 | |||
281 | VP_A1X, | ||
282 | VP_A1Y, | ||
283 | |||
284 | VP_A1C, | ||
285 | VP_A1T, | ||
286 | |||
287 | VP_A2X, | ||
288 | VP_A2Y, | ||
289 | |||
290 | VP_A2C, | ||
291 | VP_A2T, | ||
292 | |||
293 | VP_A3X, | ||
294 | VP_A3Y, | ||
295 | |||
296 | VP_A3C, | ||
297 | VP_A3T, | ||
298 | |||
299 | VP_VRR, | ||
300 | VP_AWT, | ||
301 | |||
302 | VP_VTM, | ||
303 | VP_VYE, | ||
304 | |||
305 | VP_A1YE, | ||
306 | VP_A2YE, | ||
307 | |||
308 | VP_A3YE, /* 0x150 */ | ||
309 | |||
310 | VP_VCR = 0x1000, /* 0x1000 - 0x1fff */ | ||
311 | }; | ||
114 | 312 | ||
115 | #define DC_PAL_ADDRESS 0x70 | 313 | #define VP_VCFG_VID_EN (1 << 0) |
116 | #define DC_PAL_DATA 0x74 | ||
117 | 314 | ||
118 | #define DC_PHY_MEM_OFFSET 0x84 | 315 | #define VP_DCFG_GV_GAM (1 << 21) |
316 | #define VP_DCFG_PWR_SEQ_DELAY ((1 << 17) | (1 << 18) | (1 << 19)) | ||
317 | #define VP_DCFG_PWR_SEQ_DELAY_DEFAULT (1 << 19) /* undocumented */ | ||
318 | #define VP_DCFG_CRT_SYNC_SKW ((1 << 14) | (1 << 15) | (1 << 16)) | ||
319 | #define VP_DCFG_CRT_SYNC_SKW_DEFAULT (1 << 16) | ||
320 | #define VP_DCFG_CRT_VSYNC_POL (1 << 9) | ||
321 | #define VP_DCFG_CRT_HSYNC_POL (1 << 8) | ||
322 | #define VP_DCFG_DAC_BL_EN (1 << 3) | ||
323 | #define VP_DCFG_VSYNC_EN (1 << 2) | ||
324 | #define VP_DCFG_HSYNC_EN (1 << 1) | ||
325 | #define VP_DCFG_CRT_EN (1 << 0) | ||
119 | 326 | ||
120 | #define DC_DV_CTL 0x88 | 327 | #define VP_MISC_APWRDN (1 << 11) |
121 | #define DC_DV_LINE_SIZE_MASK 0x00000C00 | 328 | #define VP_MISC_DACPWRDN (1 << 10) |
122 | #define DC_DV_LINE_SIZE_1024 0x00000000 | 329 | #define VP_MISC_BYP_BOTH (1 << 0) |
123 | #define DC_DV_LINE_SIZE_2048 0x00000400 | ||
124 | #define DC_DV_LINE_SIZE_4096 0x00000800 | ||
125 | #define DC_DV_LINE_SIZE_8192 0x00000C00 | ||
126 | 330 | ||
127 | 331 | ||
128 | #define DC_GFX_SCALE 0x90 | 332 | /* |
129 | #define DC_IRQ_FILT_CTL 0x94 | 333 | * Flat Panel registers (table 6-71). |
334 | * Also 64 bit registers; see above note about 32-bit handling. | ||
335 | */ | ||
130 | 336 | ||
337 | /* we're actually in the VP register space, starting at address 0x400 */ | ||
338 | #define VP_FP_START 0x400 | ||
131 | 339 | ||
132 | #define DC_IRQ 0xC8 | 340 | enum fp_registers { |
133 | #define DC_IRQ_MASK (1 << 0) | 341 | FP_PT1 = 0, |
134 | #define DC_VSYNC_IRQ_MASK (1 << 1) | 342 | FP_PT2, |
135 | #define DC_IRQ_STATUS (1 << 20) | ||
136 | #define DC_VSYNC_IRQ_STATUS (1 << 21) | ||
137 | |||
138 | #define DC_GENLCK_CTRL 0xD4 | ||
139 | #define DC_GENLCK_ENABLE (1 << 18) | ||
140 | #define DC_GC_ALPHA_FLICK_ENABLE (1 << 25) | ||
141 | #define DC_GC_FLICKER_FILTER_ENABLE (1 << 24) | ||
142 | #define DC_GC_FLICKER_FILTER_MASK (0x0F << 28) | ||
143 | |||
144 | #define DC_COLOR_KEY 0xB8 | ||
145 | #define DC_CLR_KEY_ENABLE (1 << 24) | ||
146 | |||
147 | |||
148 | #define DC3_DV_LINE_SIZE_MASK 0x00000C00 | ||
149 | #define DC3_DV_LINE_SIZE_1024 0x00000000 | ||
150 | #define DC3_DV_LINE_SIZE_2048 0x00000400 | ||
151 | #define DC3_DV_LINE_SIZE_4096 0x00000800 | ||
152 | #define DC3_DV_LINE_SIZE_8192 0x00000C00 | ||
153 | |||
154 | #define DF_VIDEO_CFG 0x0 | ||
155 | #define DF_VCFG_VID_EN (1 << 0) | ||
156 | |||
157 | #define DF_DISPLAY_CFG 0x08 | ||
158 | |||
159 | #define DF_DCFG_CRT_EN (1 << 0) | ||
160 | #define DF_DCFG_HSYNC_EN (1 << 1) | ||
161 | #define DF_DCFG_VSYNC_EN (1 << 2) | ||
162 | #define DF_DCFG_DAC_BL_EN (1 << 3) | ||
163 | #define DF_DCFG_CRT_HSYNC_POL (1 << 8) | ||
164 | #define DF_DCFG_CRT_VSYNC_POL (1 << 9) | ||
165 | #define DF_DCFG_GV_PAL_BYP (1 << 21) | ||
166 | 343 | ||
167 | #define DF_DCFG_CRT_SYNC_SKW_INIT 0x10000 | 344 | FP_PM, |
168 | #define DF_DCFG_CRT_SYNC_SKW_MASK 0x1c000 | 345 | FP_DFC, |
169 | 346 | ||
170 | #define DF_DCFG_PWR_SEQ_DLY_INIT 0x80000 | 347 | FP_RSVD_0, |
171 | #define DF_DCFG_PWR_SEQ_DLY_MASK 0xe0000 | 348 | FP_RSVD_1, |
172 | 349 | ||
173 | #define DF_MISC 0x50 | 350 | FP_RSVD_2, |
351 | FP_RSVD_3, | ||
352 | |||
353 | FP_RSVD_4, | ||
354 | FP_DCA, | ||
355 | |||
356 | FP_DMD, | ||
357 | FP_CRC, /* 0x458 */ | ||
358 | }; | ||
359 | |||
360 | #define FP_PT2_SCRC (1 << 27) /* shfclk free */ | ||
361 | |||
362 | #define FP_PM_P (1 << 24) /* panel power ctl */ | ||
363 | #define FP_PM_PANEL_PWR_UP (1 << 3) /* r/o */ | ||
364 | #define FP_PM_PANEL_PWR_DOWN (1 << 2) /* r/o */ | ||
365 | #define FP_PM_PANEL_OFF (1 << 1) /* r/o */ | ||
366 | #define FP_PM_PANEL_ON (1 << 0) /* r/o */ | ||
367 | |||
368 | #define FP_DFC_BC ((1 << 4) | (1 << 5) | (1 << 6)) | ||
369 | |||
370 | |||
371 | /* register access functions */ | ||
372 | |||
373 | static inline uint32_t read_gp(struct lxfb_par *par, int reg) | ||
374 | { | ||
375 | return readl(par->gp_regs + 4*reg); | ||
376 | } | ||
377 | |||
378 | static inline void write_gp(struct lxfb_par *par, int reg, uint32_t val) | ||
379 | { | ||
380 | writel(val, par->gp_regs + 4*reg); | ||
381 | } | ||
382 | |||
383 | static inline uint32_t read_dc(struct lxfb_par *par, int reg) | ||
384 | { | ||
385 | return readl(par->dc_regs + 4*reg); | ||
386 | } | ||
387 | |||
388 | static inline void write_dc(struct lxfb_par *par, int reg, uint32_t val) | ||
389 | { | ||
390 | writel(val, par->dc_regs + 4*reg); | ||
391 | } | ||
392 | |||
393 | static inline uint32_t read_vp(struct lxfb_par *par, int reg) | ||
394 | { | ||
395 | return readl(par->vp_regs + 8*reg); | ||
396 | } | ||
397 | |||
398 | static inline void write_vp(struct lxfb_par *par, int reg, uint32_t val) | ||
399 | { | ||
400 | writel(val, par->vp_regs + 8*reg); | ||
401 | } | ||
402 | |||
403 | static inline uint32_t read_fp(struct lxfb_par *par, int reg) | ||
404 | { | ||
405 | return readl(par->vp_regs + 8*reg + VP_FP_START); | ||
406 | } | ||
407 | |||
408 | static inline void write_fp(struct lxfb_par *par, int reg, uint32_t val) | ||
409 | { | ||
410 | writel(val, par->vp_regs + 8*reg + VP_FP_START); | ||
411 | } | ||
174 | 412 | ||
175 | #define DF_MISC_GAM_BYPASS (1 << 0) | ||
176 | #define DF_MISC_DAC_PWRDN (1 << 10) | ||
177 | #define DF_MISC_A_PWRDN (1 << 11) | ||
178 | 413 | ||
179 | #define DF_PAR 0x38 | 414 | /* MSRs are defined in asm/geode.h; their bitfields are here */ |
180 | #define DF_PDR 0x40 | ||
181 | #define DF_ALPHA_CONTROL_1 0xD8 | ||
182 | #define DF_VIDEO_REQUEST 0x120 | ||
183 | 415 | ||
184 | #define DF_PANEL_TIM1 0x400 | 416 | #define MSR_GLCP_DOTPLL_LOCK (1 << 25) /* r/o */ |
185 | #define DF_DEFAULT_TFT_PMTIM1 0x0 | 417 | #define MSR_GLCP_DOTPLL_HALFPIX (1 << 24) |
418 | #define MSR_GLCP_DOTPLL_BYPASS (1 << 15) | ||
419 | #define MSR_GLCP_DOTPLL_DOTRESET (1 << 0) | ||
186 | 420 | ||
187 | #define DF_PANEL_TIM2 0x408 | 421 | /* note: this is actually the VP's GLD_MSR_CONFIG */ |
188 | #define DF_DEFAULT_TFT_PMTIM2 0x08000000 | 422 | #define MSR_LX_GLD_MSR_CONFIG_FMT ((1 << 3) | (1 << 4) | (1 << 5)) |
423 | #define MSR_LX_GLD_MSR_CONFIG_FMT_FP (1 << 3) | ||
424 | #define MSR_LX_GLD_MSR_CONFIG_FMT_CRT (0) | ||
425 | #define MSR_LX_GLD_MSR_CONFIG_FPC (1 << 15) /* FP *and* CRT */ | ||
189 | 426 | ||
190 | #define DF_FP_PM 0x410 | 427 | #define MSR_LX_MSR_PADSEL_TFT_SEL_LOW 0xDFFFFFFF /* ??? */ |
191 | #define DF_FP_PM_P (1 << 24) | 428 | #define MSR_LX_MSR_PADSEL_TFT_SEL_HIGH 0x0000003F /* ??? */ |
192 | 429 | ||
193 | #define DF_DITHER_CONTROL 0x418 | 430 | #define MSR_LX_SPARE_MSR_DIS_CFIFO_HGO (1 << 11) /* undocumented */ |
194 | #define DF_DEFAULT_TFT_DITHCTL 0x00000070 | 431 | #define MSR_LX_SPARE_MSR_VFIFO_ARB_SEL (1 << 10) /* undocumented */ |
195 | #define GP_BLT_STATUS 0x44 | 432 | #define MSR_LX_SPARE_MSR_WM_LPEN_OVRD (1 << 9) /* undocumented */ |
196 | #define GP_BS_BLT_BUSY (1 << 0) | 433 | #define MSR_LX_SPARE_MSR_LOAD_WM_LPEN_M (1 << 8) /* undocumented */ |
197 | #define GP_BS_CB_EMPTY (1 << 4) | 434 | #define MSR_LX_SPARE_MSR_DIS_INIT_V_PRI (1 << 7) /* undocumented */ |
435 | #define MSR_LX_SPARE_MSR_DIS_VIFO_WM (1 << 6) | ||
436 | #define MSR_LX_SPARE_MSR_DIS_CWD_CHECK (1 << 5) /* undocumented */ | ||
437 | #define MSR_LX_SPARE_MSR_PIX8_PAN_FIX (1 << 4) /* undocumented */ | ||
438 | #define MSR_LX_SPARE_MSR_FIRST_REQ_MASK (1 << 1) /* undocumented */ | ||
198 | 439 | ||
199 | #endif | 440 | #endif |
diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c index eb6b88171538..2cd9b74d2225 100644 --- a/drivers/video/geode/lxfb_core.c +++ b/drivers/video/geode/lxfb_core.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/console.h> | 17 | #include <linux/console.h> |
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/suspend.h> | ||
20 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
21 | #include <linux/fb.h> | 22 | #include <linux/fb.h> |
22 | #include <linux/init.h> | 23 | #include <linux/init.h> |
@@ -27,14 +28,15 @@ | |||
27 | 28 | ||
28 | static char *mode_option; | 29 | static char *mode_option; |
29 | static int noclear, nopanel, nocrt; | 30 | static int noclear, nopanel, nocrt; |
30 | static int fbsize; | 31 | static int vram; |
32 | static int vt_switch; | ||
31 | 33 | ||
32 | /* Most of these modes are sorted in ascending order, but | 34 | /* Most of these modes are sorted in ascending order, but |
33 | * since the first entry in this table is the "default" mode, | 35 | * since the first entry in this table is the "default" mode, |
34 | * we try to make it something sane - 640x480-60 is sane | 36 | * we try to make it something sane - 640x480-60 is sane |
35 | */ | 37 | */ |
36 | 38 | ||
37 | static const struct fb_videomode geode_modedb[] __initdata = { | 39 | static struct fb_videomode geode_modedb[] __initdata = { |
38 | /* 640x480-60 */ | 40 | /* 640x480-60 */ |
39 | { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2, | 41 | { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2, |
40 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 42 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
@@ -215,6 +217,35 @@ static const struct fb_videomode geode_modedb[] __initdata = { | |||
215 | 0, FB_VMODE_NONINTERLACED, 0 }, | 217 | 0, FB_VMODE_NONINTERLACED, 0 }, |
216 | }; | 218 | }; |
217 | 219 | ||
220 | #ifdef CONFIG_OLPC | ||
221 | #include <asm/olpc.h> | ||
222 | |||
223 | static struct fb_videomode olpc_dcon_modedb[] __initdata = { | ||
224 | /* The only mode the DCON has is 1200x900 */ | ||
225 | { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3, | ||
226 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
227 | FB_VMODE_NONINTERLACED, 0 } | ||
228 | }; | ||
229 | |||
230 | static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) | ||
231 | { | ||
232 | if (olpc_has_dcon()) { | ||
233 | *modedb = (struct fb_videomode *) olpc_dcon_modedb; | ||
234 | *size = ARRAY_SIZE(olpc_dcon_modedb); | ||
235 | } else { | ||
236 | *modedb = (struct fb_videomode *) geode_modedb; | ||
237 | *size = ARRAY_SIZE(geode_modedb); | ||
238 | } | ||
239 | } | ||
240 | |||
241 | #else | ||
242 | static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) | ||
243 | { | ||
244 | *modedb = (struct fb_videomode *) geode_modedb; | ||
245 | *size = ARRAY_SIZE(geode_modedb); | ||
246 | } | ||
247 | #endif | ||
248 | |||
218 | static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | 249 | static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) |
219 | { | 250 | { |
220 | if (var->xres > 1920 || var->yres > 1440) | 251 | if (var->xres > 1920 || var->yres > 1440) |
@@ -333,13 +364,13 @@ static int __init lxfb_map_video_memory(struct fb_info *info, | |||
333 | if (ret) | 364 | if (ret) |
334 | return ret; | 365 | return ret; |
335 | 366 | ||
336 | ret = pci_request_region(dev, 3, "lxfb-vip"); | 367 | ret = pci_request_region(dev, 3, "lxfb-vp"); |
337 | 368 | ||
338 | if (ret) | 369 | if (ret) |
339 | return ret; | 370 | return ret; |
340 | 371 | ||
341 | info->fix.smem_start = pci_resource_start(dev, 0); | 372 | info->fix.smem_start = pci_resource_start(dev, 0); |
342 | info->fix.smem_len = fbsize ? fbsize : lx_framebuffer_size(); | 373 | info->fix.smem_len = vram ? vram : lx_framebuffer_size(); |
343 | 374 | ||
344 | info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); | 375 | info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); |
345 | 376 | ||
@@ -360,18 +391,15 @@ static int __init lxfb_map_video_memory(struct fb_info *info, | |||
360 | if (par->dc_regs == NULL) | 391 | if (par->dc_regs == NULL) |
361 | return ret; | 392 | return ret; |
362 | 393 | ||
363 | par->df_regs = ioremap(pci_resource_start(dev, 3), | 394 | par->vp_regs = ioremap(pci_resource_start(dev, 3), |
364 | pci_resource_len(dev, 3)); | 395 | pci_resource_len(dev, 3)); |
365 | 396 | ||
366 | if (par->df_regs == NULL) | 397 | if (par->vp_regs == NULL) |
367 | return ret; | 398 | return ret; |
368 | 399 | ||
369 | writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK); | 400 | write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); |
370 | 401 | write_dc(par, DC_GLIU0_MEM_OFFSET, info->fix.smem_start & 0xFF000000); | |
371 | writel(info->fix.smem_start & 0xFF000000, | 402 | write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK); |
372 | par->dc_regs + DC_PHY_MEM_OFFSET); | ||
373 | |||
374 | writel(0, par->dc_regs + DC_UNLOCK); | ||
375 | 403 | ||
376 | dev_info(&dev->dev, "%d KB of video memory at 0x%lx\n", | 404 | dev_info(&dev->dev, "%d KB of video memory at 0x%lx\n", |
377 | info->fix.smem_len / 1024, info->fix.smem_start); | 405 | info->fix.smem_len / 1024, info->fix.smem_start); |
@@ -431,6 +459,45 @@ static struct fb_info * __init lxfb_init_fbinfo(struct device *dev) | |||
431 | return info; | 459 | return info; |
432 | } | 460 | } |
433 | 461 | ||
462 | #ifdef CONFIG_PM | ||
463 | static int lxfb_suspend(struct pci_dev *pdev, pm_message_t state) | ||
464 | { | ||
465 | struct fb_info *info = pci_get_drvdata(pdev); | ||
466 | |||
467 | if (state.event == PM_EVENT_SUSPEND) { | ||
468 | acquire_console_sem(); | ||
469 | lx_powerdown(info); | ||
470 | fb_set_suspend(info, 1); | ||
471 | release_console_sem(); | ||
472 | } | ||
473 | |||
474 | /* there's no point in setting PCI states; we emulate PCI, so | ||
475 | * we don't end up getting power savings anyways */ | ||
476 | |||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static int lxfb_resume(struct pci_dev *pdev) | ||
481 | { | ||
482 | struct fb_info *info = pci_get_drvdata(pdev); | ||
483 | int ret; | ||
484 | |||
485 | acquire_console_sem(); | ||
486 | ret = lx_powerup(info); | ||
487 | if (ret) { | ||
488 | printk(KERN_ERR "lxfb: power up failed!\n"); | ||
489 | return ret; | ||
490 | } | ||
491 | |||
492 | fb_set_suspend(info, 0); | ||
493 | release_console_sem(); | ||
494 | return 0; | ||
495 | } | ||
496 | #else | ||
497 | #define lxfb_suspend NULL | ||
498 | #define lxfb_resume NULL | ||
499 | #endif | ||
500 | |||
434 | static int __init lxfb_probe(struct pci_dev *pdev, | 501 | static int __init lxfb_probe(struct pci_dev *pdev, |
435 | const struct pci_device_id *id) | 502 | const struct pci_device_id *id) |
436 | { | 503 | { |
@@ -439,7 +506,7 @@ static int __init lxfb_probe(struct pci_dev *pdev, | |||
439 | int ret; | 506 | int ret; |
440 | 507 | ||
441 | struct fb_videomode *modedb_ptr; | 508 | struct fb_videomode *modedb_ptr; |
442 | int modedb_size; | 509 | unsigned int modedb_size; |
443 | 510 | ||
444 | info = lxfb_init_fbinfo(&pdev->dev); | 511 | info = lxfb_init_fbinfo(&pdev->dev); |
445 | 512 | ||
@@ -464,9 +531,7 @@ static int __init lxfb_probe(struct pci_dev *pdev, | |||
464 | 531 | ||
465 | /* Set up the mode database */ | 532 | /* Set up the mode database */ |
466 | 533 | ||
467 | modedb_ptr = (struct fb_videomode *) geode_modedb; | 534 | get_modedb(&modedb_ptr, &modedb_size); |
468 | modedb_size = ARRAY_SIZE(geode_modedb); | ||
469 | |||
470 | ret = fb_find_mode(&info->var, info, mode_option, | 535 | ret = fb_find_mode(&info->var, info, mode_option, |
471 | modedb_ptr, modedb_size, NULL, 16); | 536 | modedb_ptr, modedb_size, NULL, 16); |
472 | 537 | ||
@@ -487,6 +552,8 @@ static int __init lxfb_probe(struct pci_dev *pdev, | |||
487 | lxfb_check_var(&info->var, info); | 552 | lxfb_check_var(&info->var, info); |
488 | lxfb_set_par(info); | 553 | lxfb_set_par(info); |
489 | 554 | ||
555 | pm_set_vt_switch(vt_switch); | ||
556 | |||
490 | if (register_framebuffer(info) < 0) { | 557 | if (register_framebuffer(info) < 0) { |
491 | ret = -EINVAL; | 558 | ret = -EINVAL; |
492 | goto err; | 559 | goto err; |
@@ -510,8 +577,8 @@ err: | |||
510 | iounmap(par->dc_regs); | 577 | iounmap(par->dc_regs); |
511 | pci_release_region(pdev, 2); | 578 | pci_release_region(pdev, 2); |
512 | } | 579 | } |
513 | if (par->df_regs) { | 580 | if (par->vp_regs) { |
514 | iounmap(par->df_regs); | 581 | iounmap(par->vp_regs); |
515 | pci_release_region(pdev, 3); | 582 | pci_release_region(pdev, 3); |
516 | } | 583 | } |
517 | 584 | ||
@@ -537,7 +604,7 @@ static void lxfb_remove(struct pci_dev *pdev) | |||
537 | iounmap(par->dc_regs); | 604 | iounmap(par->dc_regs); |
538 | pci_release_region(pdev, 2); | 605 | pci_release_region(pdev, 2); |
539 | 606 | ||
540 | iounmap(par->df_regs); | 607 | iounmap(par->vp_regs); |
541 | pci_release_region(pdev, 3); | 608 | pci_release_region(pdev, 3); |
542 | 609 | ||
543 | pci_set_drvdata(pdev, NULL); | 610 | pci_set_drvdata(pdev, NULL); |
@@ -556,6 +623,8 @@ static struct pci_driver lxfb_driver = { | |||
556 | .id_table = lxfb_id_table, | 623 | .id_table = lxfb_id_table, |
557 | .probe = lxfb_probe, | 624 | .probe = lxfb_probe, |
558 | .remove = lxfb_remove, | 625 | .remove = lxfb_remove, |
626 | .suspend = lxfb_suspend, | ||
627 | .resume = lxfb_resume, | ||
559 | }; | 628 | }; |
560 | 629 | ||
561 | #ifndef MODULE | 630 | #ifndef MODULE |
@@ -570,9 +639,7 @@ static int __init lxfb_setup(char *options) | |||
570 | if (!*opt) | 639 | if (!*opt) |
571 | continue; | 640 | continue; |
572 | 641 | ||
573 | if (!strncmp(opt, "fbsize:", 7)) | 642 | if (!strcmp(opt, "noclear")) |
574 | fbsize = simple_strtoul(opt+7, NULL, 0); | ||
575 | else if (!strcmp(opt, "noclear")) | ||
576 | noclear = 1; | 643 | noclear = 1; |
577 | else if (!strcmp(opt, "nopanel")) | 644 | else if (!strcmp(opt, "nopanel")) |
578 | nopanel = 1; | 645 | nopanel = 1; |
@@ -609,8 +676,11 @@ module_exit(lxfb_cleanup); | |||
609 | module_param(mode_option, charp, 0); | 676 | module_param(mode_option, charp, 0); |
610 | MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])"); | 677 | MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])"); |
611 | 678 | ||
612 | module_param(fbsize, int, 0); | 679 | module_param(vram, int, 0); |
613 | MODULE_PARM_DESC(fbsize, "video memory size"); | 680 | MODULE_PARM_DESC(vram, "video memory size"); |
681 | |||
682 | module_param(vt_switch, int, 0); | ||
683 | MODULE_PARM_DESC(vt_switch, "enable VT switch during suspend/resume"); | ||
614 | 684 | ||
615 | MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode LX"); | 685 | MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode LX"); |
616 | MODULE_LICENSE("GPL"); | 686 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c index 4fbc99be96ef..cd9d4cc26954 100644 --- a/drivers/video/geode/lxfb_ops.c +++ b/drivers/video/geode/lxfb_ops.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/fb.h> | 13 | #include <linux/fb.h> |
14 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <asm/geode.h> | ||
16 | 17 | ||
17 | #include "lxfb.h" | 18 | #include "lxfb.h" |
18 | 19 | ||
@@ -34,35 +35,85 @@ static const struct { | |||
34 | unsigned int pllval; | 35 | unsigned int pllval; |
35 | unsigned int freq; | 36 | unsigned int freq; |
36 | } pll_table[] = { | 37 | } pll_table[] = { |
37 | { 0x000031AC, 24923 }, | 38 | { 0x000131AC, 6231 }, |
38 | { 0x0000215D, 25175 }, | 39 | { 0x0001215D, 6294 }, |
39 | { 0x00001087, 27000 }, | 40 | { 0x00011087, 6750 }, |
40 | { 0x0000216C, 28322 }, | 41 | { 0x0001216C, 7081 }, |
41 | { 0x0000218D, 28560 }, | 42 | { 0x0001218D, 7140 }, |
42 | { 0x000010C9, 31200 }, | 43 | { 0x000110C9, 7800 }, |
43 | { 0x00003147, 31500 }, | 44 | { 0x00013147, 7875 }, |
44 | { 0x000010A7, 33032 }, | 45 | { 0x000110A7, 8258 }, |
45 | { 0x00002159, 35112 }, | 46 | { 0x00012159, 8778 }, |
46 | { 0x00004249, 35500 }, | 47 | { 0x00014249, 8875 }, |
47 | { 0x00000057, 36000 }, | 48 | { 0x00010057, 9000 }, |
48 | { 0x0000219A, 37889 }, | 49 | { 0x0001219A, 9472 }, |
49 | { 0x00002158, 39168 }, | 50 | { 0x00012158, 9792 }, |
50 | { 0x00000045, 40000 }, | 51 | { 0x00010045, 10000 }, |
51 | { 0x00000089, 43163 }, | 52 | { 0x00010089, 10791 }, |
52 | { 0x000010E7, 44900 }, | 53 | { 0x000110E7, 11225 }, |
53 | { 0x00002136, 45720 }, | 54 | { 0x00012136, 11430 }, |
54 | { 0x00003207, 49500 }, | 55 | { 0x00013207, 12375 }, |
55 | { 0x00002187, 50000 }, | 56 | { 0x00012187, 12500 }, |
56 | { 0x00004286, 56250 }, | 57 | { 0x00014286, 14063 }, |
57 | { 0x000010E5, 60065 }, | 58 | { 0x000110E5, 15016 }, |
58 | { 0x00004214, 65000 }, | 59 | { 0x00014214, 16250 }, |
59 | { 0x00001105, 68179 }, | 60 | { 0x00011105, 17045 }, |
60 | { 0x000031E4, 74250 }, | 61 | { 0x000131E4, 18563 }, |
61 | { 0x00003183, 75000 }, | 62 | { 0x00013183, 18750 }, |
62 | { 0x00004284, 78750 }, | 63 | { 0x00014284, 19688 }, |
63 | { 0x00001104, 81600 }, | 64 | { 0x00011104, 20400 }, |
64 | { 0x00006363, 94500 }, | 65 | { 0x00016363, 23625 }, |
65 | { 0x00005303, 97520 }, | 66 | { 0x00015303, 24380 }, |
67 | { 0x000031AC, 24923 }, | ||
68 | { 0x0000215D, 25175 }, | ||
69 | { 0x00001087, 27000 }, | ||
70 | { 0x0000216C, 28322 }, | ||
71 | { 0x0000218D, 28560 }, | ||
72 | { 0x00010041, 29913 }, | ||
73 | { 0x000010C9, 31200 }, | ||
74 | { 0x00003147, 31500 }, | ||
75 | { 0x000141A1, 32400 }, | ||
76 | { 0x000010A7, 33032 }, | ||
77 | { 0x00012182, 33375 }, | ||
78 | { 0x000141B1, 33750 }, | ||
79 | { 0x00002159, 35112 }, | ||
80 | { 0x00004249, 35500 }, | ||
81 | { 0x00000057, 36000 }, | ||
82 | { 0x000141E1, 37125 }, | ||
83 | { 0x0000219A, 37889 }, | ||
84 | { 0x00002158, 39168 }, | ||
85 | { 0x00000045, 40000 }, | ||
86 | { 0x000131A1, 40500 }, | ||
87 | { 0x00010061, 42301 }, | ||
88 | { 0x00000089, 43163 }, | ||
89 | { 0x00012151, 43875 }, | ||
90 | { 0x000010E7, 44900 }, | ||
91 | { 0x00002136, 45720 }, | ||
92 | { 0x000152E1, 47250 }, | ||
93 | { 0x00010071, 48000 }, | ||
94 | { 0x00003207, 49500 }, | ||
95 | { 0x00002187, 50000 }, | ||
96 | { 0x00014291, 50625 }, | ||
97 | { 0x00011101, 51188 }, | ||
98 | { 0x00017481, 54563 }, | ||
99 | { 0x00004286, 56250 }, | ||
100 | { 0x00014170, 57375 }, | ||
101 | { 0x00016210, 58500 }, | ||
102 | { 0x000010E5, 60065 }, | ||
103 | { 0x00013140, 62796 }, | ||
104 | { 0x00004214, 65000 }, | ||
105 | { 0x00016250, 65250 }, | ||
106 | { 0x00001105, 68179 }, | ||
107 | { 0x000141C0, 69600 }, | ||
108 | { 0x00015220, 70160 }, | ||
109 | { 0x00010050, 72000 }, | ||
110 | { 0x000031E4, 74250 }, | ||
111 | { 0x00003183, 75000 }, | ||
112 | { 0x00004284, 78750 }, | ||
113 | { 0x00012130, 80052 }, | ||
114 | { 0x00001104, 81600 }, | ||
115 | { 0x00006363, 94500 }, | ||
116 | { 0x00005303, 97520 }, | ||
66 | { 0x00002183, 100187 }, | 117 | { 0x00002183, 100187 }, |
67 | { 0x00002122, 101420 }, | 118 | { 0x00002122, 101420 }, |
68 | { 0x00001081, 108000 }, | 119 | { 0x00001081, 108000 }, |
@@ -101,16 +152,16 @@ static void lx_set_dotpll(u32 pllval) | |||
101 | u32 dotpll_lo, dotpll_hi; | 152 | u32 dotpll_lo, dotpll_hi; |
102 | int i; | 153 | int i; |
103 | 154 | ||
104 | rdmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); | 155 | rdmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi); |
105 | 156 | ||
106 | if ((dotpll_lo & GLCP_DOTPLL_LOCK) && (dotpll_hi == pllval)) | 157 | if ((dotpll_lo & MSR_GLCP_DOTPLL_LOCK) && (dotpll_hi == pllval)) |
107 | return; | 158 | return; |
108 | 159 | ||
109 | dotpll_hi = pllval; | 160 | dotpll_hi = pllval; |
110 | dotpll_lo &= ~(GLCP_DOTPLL_BYPASS | GLCP_DOTPLL_HALFPIX); | 161 | dotpll_lo &= ~(MSR_GLCP_DOTPLL_BYPASS | MSR_GLCP_DOTPLL_HALFPIX); |
111 | dotpll_lo |= GLCP_DOTPLL_RESET; | 162 | dotpll_lo |= MSR_GLCP_DOTPLL_DOTRESET; |
112 | 163 | ||
113 | wrmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); | 164 | wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi); |
114 | 165 | ||
115 | /* Wait 100us for the PLL to lock */ | 166 | /* Wait 100us for the PLL to lock */ |
116 | 167 | ||
@@ -119,15 +170,15 @@ static void lx_set_dotpll(u32 pllval) | |||
119 | /* Now, loop for the lock bit */ | 170 | /* Now, loop for the lock bit */ |
120 | 171 | ||
121 | for (i = 0; i < 1000; i++) { | 172 | for (i = 0; i < 1000; i++) { |
122 | rdmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); | 173 | rdmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi); |
123 | if (dotpll_lo & GLCP_DOTPLL_LOCK) | 174 | if (dotpll_lo & MSR_GLCP_DOTPLL_LOCK) |
124 | break; | 175 | break; |
125 | } | 176 | } |
126 | 177 | ||
127 | /* Clear the reset bit */ | 178 | /* Clear the reset bit */ |
128 | 179 | ||
129 | dotpll_lo &= ~GLCP_DOTPLL_RESET; | 180 | dotpll_lo &= ~MSR_GLCP_DOTPLL_DOTRESET; |
130 | wrmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); | 181 | wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi); |
131 | } | 182 | } |
132 | 183 | ||
133 | /* Set the clock based on the frequency specified by the current mode */ | 184 | /* Set the clock based on the frequency specified by the current mode */ |
@@ -137,7 +188,7 @@ static void lx_set_clock(struct fb_info *info) | |||
137 | unsigned int diff, min, best = 0; | 188 | unsigned int diff, min, best = 0; |
138 | unsigned int freq, i; | 189 | unsigned int freq, i; |
139 | 190 | ||
140 | freq = (unsigned int) (0x3b9aca00 / info->var.pixclock); | 191 | freq = (unsigned int) (1000000000 / info->var.pixclock); |
141 | 192 | ||
142 | min = abs(pll_table[0].freq - freq); | 193 | min = abs(pll_table[0].freq - freq); |
143 | 194 | ||
@@ -149,7 +200,7 @@ static void lx_set_clock(struct fb_info *info) | |||
149 | } | 200 | } |
150 | } | 201 | } |
151 | 202 | ||
152 | lx_set_dotpll(pll_table[best].pllval & 0x7FFF); | 203 | lx_set_dotpll(pll_table[best].pllval & 0x00017FFF); |
153 | } | 204 | } |
154 | 205 | ||
155 | static void lx_graphics_disable(struct fb_info *info) | 206 | static void lx_graphics_disable(struct fb_info *info) |
@@ -159,63 +210,62 @@ static void lx_graphics_disable(struct fb_info *info) | |||
159 | 210 | ||
160 | /* Note: This assumes that the video is in a quitet state */ | 211 | /* Note: This assumes that the video is in a quitet state */ |
161 | 212 | ||
162 | writel(0, par->df_regs + DF_ALPHA_CONTROL_1); | 213 | write_vp(par, VP_A1T, 0); |
163 | writel(0, par->df_regs + DF_ALPHA_CONTROL_1 + 32); | 214 | write_vp(par, VP_A2T, 0); |
164 | writel(0, par->df_regs + DF_ALPHA_CONTROL_1 + 64); | 215 | write_vp(par, VP_A3T, 0); |
165 | 216 | ||
166 | /* Turn off the VGA and video enable */ | 217 | /* Turn off the VGA and video enable */ |
167 | val = readl (par->dc_regs + DC_GENERAL_CFG) & | 218 | val = read_dc(par, DC_GENERAL_CFG) & ~(DC_GENERAL_CFG_VGAE | |
168 | ~(DC_GCFG_VGAE | DC_GCFG_VIDE); | 219 | DC_GENERAL_CFG_VIDE); |
169 | 220 | ||
170 | writel(val, par->dc_regs + DC_GENERAL_CFG); | 221 | write_dc(par, DC_GENERAL_CFG, val); |
171 | 222 | ||
172 | val = readl(par->df_regs + DF_VIDEO_CFG) & ~DF_VCFG_VID_EN; | 223 | val = read_vp(par, VP_VCFG) & ~VP_VCFG_VID_EN; |
173 | writel(val, par->df_regs + DF_VIDEO_CFG); | 224 | write_vp(par, VP_VCFG, val); |
174 | 225 | ||
175 | writel( DC_IRQ_MASK | DC_VSYNC_IRQ_MASK | | 226 | write_dc(par, DC_IRQ, DC_IRQ_MASK | DC_IRQ_VIP_VSYNC_LOSS_IRQ_MASK | |
176 | DC_IRQ_STATUS | DC_VSYNC_IRQ_STATUS, | 227 | DC_IRQ_STATUS | DC_IRQ_VIP_VSYNC_IRQ_STATUS); |
177 | par->dc_regs + DC_IRQ); | ||
178 | 228 | ||
179 | val = readl(par->dc_regs + DC_GENLCK_CTRL) & ~DC_GENLCK_ENABLE; | 229 | val = read_dc(par, DC_GENLK_CTL) & ~DC_GENLK_CTL_GENLK_EN; |
180 | writel(val, par->dc_regs + DC_GENLCK_CTRL); | 230 | write_dc(par, DC_GENLK_CTL, val); |
181 | 231 | ||
182 | val = readl(par->dc_regs + DC_COLOR_KEY) & ~DC_CLR_KEY_ENABLE; | 232 | val = read_dc(par, DC_CLR_KEY); |
183 | writel(val & ~DC_CLR_KEY_ENABLE, par->dc_regs + DC_COLOR_KEY); | 233 | write_dc(par, DC_CLR_KEY, val & ~DC_CLR_KEY_CLR_KEY_EN); |
184 | 234 | ||
185 | /* We don't actually blank the panel, due to the long latency | 235 | /* turn off the panel */ |
186 | involved with bringing it back */ | 236 | write_fp(par, FP_PM, read_fp(par, FP_PM) & ~FP_PM_P); |
187 | 237 | ||
188 | val = readl(par->df_regs + DF_MISC) | DF_MISC_DAC_PWRDN; | 238 | val = read_vp(par, VP_MISC) | VP_MISC_DACPWRDN; |
189 | writel(val, par->df_regs + DF_MISC); | 239 | write_vp(par, VP_MISC, val); |
190 | 240 | ||
191 | /* Turn off the display */ | 241 | /* Turn off the display */ |
192 | 242 | ||
193 | val = readl(par->df_regs + DF_DISPLAY_CFG); | 243 | val = read_vp(par, VP_DCFG); |
194 | writel(val & ~(DF_DCFG_CRT_EN | DF_DCFG_HSYNC_EN | DF_DCFG_VSYNC_EN | | 244 | write_vp(par, VP_DCFG, val & ~(VP_DCFG_CRT_EN | VP_DCFG_HSYNC_EN | |
195 | DF_DCFG_DAC_BL_EN), par->df_regs + DF_DISPLAY_CFG); | 245 | VP_DCFG_VSYNC_EN | VP_DCFG_DAC_BL_EN)); |
196 | 246 | ||
197 | gcfg = readl(par->dc_regs + DC_GENERAL_CFG); | 247 | gcfg = read_dc(par, DC_GENERAL_CFG); |
198 | gcfg &= ~(DC_GCFG_CMPE | DC_GCFG_DECE); | 248 | gcfg &= ~(DC_GENERAL_CFG_CMPE | DC_GENERAL_CFG_DECE); |
199 | writel(gcfg, par->dc_regs + DC_GENERAL_CFG); | 249 | write_dc(par, DC_GENERAL_CFG, gcfg); |
200 | 250 | ||
201 | /* Turn off the TGEN */ | 251 | /* Turn off the TGEN */ |
202 | val = readl(par->dc_regs + DC_DISPLAY_CFG); | 252 | val = read_dc(par, DC_DISPLAY_CFG); |
203 | val &= ~DC_DCFG_TGEN; | 253 | val &= ~DC_DISPLAY_CFG_TGEN; |
204 | writel(val, par->dc_regs + DC_DISPLAY_CFG); | 254 | write_dc(par, DC_DISPLAY_CFG, val); |
205 | 255 | ||
206 | /* Wait 1000 usecs to ensure that the TGEN is clear */ | 256 | /* Wait 1000 usecs to ensure that the TGEN is clear */ |
207 | udelay(1000); | 257 | udelay(1000); |
208 | 258 | ||
209 | /* Turn off the FIFO loader */ | 259 | /* Turn off the FIFO loader */ |
210 | 260 | ||
211 | gcfg &= ~DC_GCFG_DFLE; | 261 | gcfg &= ~DC_GENERAL_CFG_DFLE; |
212 | writel(gcfg, par->dc_regs + DC_GENERAL_CFG); | 262 | write_dc(par, DC_GENERAL_CFG, gcfg); |
213 | 263 | ||
214 | /* Lastly, wait for the GP to go idle */ | 264 | /* Lastly, wait for the GP to go idle */ |
215 | 265 | ||
216 | do { | 266 | do { |
217 | val = readl(par->gp_regs + GP_BLT_STATUS); | 267 | val = read_gp(par, GP_BLT_STATUS); |
218 | } while ((val & GP_BS_BLT_BUSY) || !(val & GP_BS_CB_EMPTY)); | 268 | } while ((val & GP_BLT_STATUS_PB) || !(val & GP_BLT_STATUS_CE)); |
219 | } | 269 | } |
220 | 270 | ||
221 | static void lx_graphics_enable(struct fb_info *info) | 271 | static void lx_graphics_enable(struct fb_info *info) |
@@ -224,80 +274,85 @@ static void lx_graphics_enable(struct fb_info *info) | |||
224 | u32 temp, config; | 274 | u32 temp, config; |
225 | 275 | ||
226 | /* Set the video request register */ | 276 | /* Set the video request register */ |
227 | writel(0, par->df_regs + DF_VIDEO_REQUEST); | 277 | write_vp(par, VP_VRR, 0); |
228 | 278 | ||
229 | /* Set up the polarities */ | 279 | /* Set up the polarities */ |
230 | 280 | ||
231 | config = readl(par->df_regs + DF_DISPLAY_CFG); | 281 | config = read_vp(par, VP_DCFG); |
232 | 282 | ||
233 | config &= ~(DF_DCFG_CRT_SYNC_SKW_MASK | DF_DCFG_PWR_SEQ_DLY_MASK | | 283 | config &= ~(VP_DCFG_CRT_SYNC_SKW | VP_DCFG_PWR_SEQ_DELAY | |
234 | DF_DCFG_CRT_HSYNC_POL | DF_DCFG_CRT_VSYNC_POL); | 284 | VP_DCFG_CRT_HSYNC_POL | VP_DCFG_CRT_VSYNC_POL); |
235 | 285 | ||
236 | config |= (DF_DCFG_CRT_SYNC_SKW_INIT | DF_DCFG_PWR_SEQ_DLY_INIT | | 286 | config |= (VP_DCFG_CRT_SYNC_SKW_DEFAULT | VP_DCFG_PWR_SEQ_DELAY_DEFAULT |
237 | DF_DCFG_GV_PAL_BYP); | 287 | | VP_DCFG_GV_GAM); |
238 | 288 | ||
239 | if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) | 289 | if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) |
240 | config |= DF_DCFG_CRT_HSYNC_POL; | 290 | config |= VP_DCFG_CRT_HSYNC_POL; |
241 | 291 | ||
242 | if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) | 292 | if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) |
243 | config |= DF_DCFG_CRT_VSYNC_POL; | 293 | config |= VP_DCFG_CRT_VSYNC_POL; |
244 | 294 | ||
245 | if (par->output & OUTPUT_PANEL) { | 295 | if (par->output & OUTPUT_PANEL) { |
246 | u32 msrlo, msrhi; | 296 | u32 msrlo, msrhi; |
247 | 297 | ||
248 | writel(DF_DEFAULT_TFT_PMTIM1, | 298 | write_fp(par, FP_PT1, 0); |
249 | par->df_regs + DF_PANEL_TIM1); | 299 | write_fp(par, FP_PT2, FP_PT2_SCRC); |
250 | writel(DF_DEFAULT_TFT_PMTIM2, | 300 | write_fp(par, FP_DFC, FP_DFC_BC); |
251 | par->df_regs + DF_PANEL_TIM2); | ||
252 | writel(DF_DEFAULT_TFT_DITHCTL, | ||
253 | par->df_regs + DF_DITHER_CONTROL); | ||
254 | 301 | ||
255 | msrlo = DF_DEFAULT_TFT_PAD_SEL_LOW; | 302 | msrlo = MSR_LX_MSR_PADSEL_TFT_SEL_LOW; |
256 | msrhi = DF_DEFAULT_TFT_PAD_SEL_HIGH; | 303 | msrhi = MSR_LX_MSR_PADSEL_TFT_SEL_HIGH; |
257 | 304 | ||
258 | wrmsr(MSR_LX_DF_PADSEL, msrlo, msrhi); | 305 | wrmsr(MSR_LX_MSR_PADSEL, msrlo, msrhi); |
259 | } | 306 | } |
260 | 307 | ||
261 | if (par->output & OUTPUT_CRT) { | 308 | if (par->output & OUTPUT_CRT) { |
262 | config |= DF_DCFG_CRT_EN | DF_DCFG_HSYNC_EN | | 309 | config |= VP_DCFG_CRT_EN | VP_DCFG_HSYNC_EN | |
263 | DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN; | 310 | VP_DCFG_VSYNC_EN | VP_DCFG_DAC_BL_EN; |
264 | } | 311 | } |
265 | 312 | ||
266 | writel(config, par->df_regs + DF_DISPLAY_CFG); | 313 | write_vp(par, VP_DCFG, config); |
267 | 314 | ||
268 | /* Turn the CRT dacs back on */ | 315 | /* Turn the CRT dacs back on */ |
269 | 316 | ||
270 | if (par->output & OUTPUT_CRT) { | 317 | if (par->output & OUTPUT_CRT) { |
271 | temp = readl(par->df_regs + DF_MISC); | 318 | temp = read_vp(par, VP_MISC); |
272 | temp &= ~(DF_MISC_DAC_PWRDN | DF_MISC_A_PWRDN); | 319 | temp &= ~(VP_MISC_DACPWRDN | VP_MISC_APWRDN); |
273 | writel(temp, par->df_regs + DF_MISC); | 320 | write_vp(par, VP_MISC, temp); |
274 | } | 321 | } |
275 | 322 | ||
276 | /* Turn the panel on (if it isn't already) */ | 323 | /* Turn the panel on (if it isn't already) */ |
277 | 324 | if (par->output & OUTPUT_PANEL) | |
278 | if (par->output & OUTPUT_PANEL) { | 325 | write_fp(par, FP_PM, read_fp(par, FP_PM) | FP_PM_P); |
279 | temp = readl(par->df_regs + DF_FP_PM); | ||
280 | |||
281 | if (!(temp & 0x09)) | ||
282 | writel(temp | DF_FP_PM_P, par->df_regs + DF_FP_PM); | ||
283 | } | ||
284 | |||
285 | temp = readl(par->df_regs + DF_MISC); | ||
286 | temp = readl(par->df_regs + DF_DISPLAY_CFG); | ||
287 | } | 326 | } |
288 | 327 | ||
289 | unsigned int lx_framebuffer_size(void) | 328 | unsigned int lx_framebuffer_size(void) |
290 | { | 329 | { |
291 | unsigned int val; | 330 | unsigned int val; |
292 | 331 | ||
332 | if (!geode_has_vsa2()) { | ||
333 | uint32_t hi, lo; | ||
334 | |||
335 | /* The number of pages is (PMAX - PMIN)+1 */ | ||
336 | rdmsr(MSR_GLIU_P2D_RO0, lo, hi); | ||
337 | |||
338 | /* PMAX */ | ||
339 | val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20); | ||
340 | /* PMIN */ | ||
341 | val -= (lo & 0x000fffff); | ||
342 | val += 1; | ||
343 | |||
344 | /* The page size is 4k */ | ||
345 | return (val << 12); | ||
346 | } | ||
347 | |||
293 | /* The frame buffer size is reported by a VSM in VSA II */ | 348 | /* The frame buffer size is reported by a VSM in VSA II */ |
294 | /* Virtual Register Class = 0x02 */ | 349 | /* Virtual Register Class = 0x02 */ |
295 | /* VG_MEM_SIZE (1MB units) = 0x00 */ | 350 | /* VG_MEM_SIZE (1MB units) = 0x00 */ |
296 | 351 | ||
297 | outw(0xFC53, 0xAC1C); | 352 | outw(VSA_VR_UNLOCK, VSA_VRC_INDEX); |
298 | outw(0x0200, 0xAC1C); | 353 | outw(VSA_VR_MEM_SIZE, VSA_VRC_INDEX); |
299 | 354 | ||
300 | val = (unsigned int)(inw(0xAC1E)) & 0xFE; | 355 | val = (unsigned int)(inw(VSA_VRC_DATA)) & 0xFE; |
301 | return (val << 20); | 356 | return (val << 20); |
302 | } | 357 | } |
303 | 358 | ||
@@ -313,7 +368,7 @@ void lx_set_mode(struct fb_info *info) | |||
313 | int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal; | 368 | int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal; |
314 | 369 | ||
315 | /* Unlock the DC registers */ | 370 | /* Unlock the DC registers */ |
316 | writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK); | 371 | write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); |
317 | 372 | ||
318 | lx_graphics_disable(info); | 373 | lx_graphics_disable(info); |
319 | 374 | ||
@@ -321,102 +376,104 @@ void lx_set_mode(struct fb_info *info) | |||
321 | 376 | ||
322 | /* Set output mode */ | 377 | /* Set output mode */ |
323 | 378 | ||
324 | rdmsrl(MSR_LX_DF_GLCONFIG, msrval); | 379 | rdmsrl(MSR_LX_GLD_MSR_CONFIG, msrval); |
325 | msrval &= ~DF_CONFIG_OUTPUT_MASK; | 380 | msrval &= ~MSR_LX_GLD_MSR_CONFIG_FMT; |
326 | 381 | ||
327 | if (par->output & OUTPUT_PANEL) { | 382 | if (par->output & OUTPUT_PANEL) { |
328 | msrval |= DF_OUTPUT_PANEL; | 383 | msrval |= MSR_LX_GLD_MSR_CONFIG_FMT_FP; |
329 | 384 | ||
330 | if (par->output & OUTPUT_CRT) | 385 | if (par->output & OUTPUT_CRT) |
331 | msrval |= DF_SIMULTANEOUS_CRT_AND_FP; | 386 | msrval |= MSR_LX_GLD_MSR_CONFIG_FPC; |
332 | else | 387 | else |
333 | msrval &= ~DF_SIMULTANEOUS_CRT_AND_FP; | 388 | msrval &= ~MSR_LX_GLD_MSR_CONFIG_FPC; |
334 | } else { | 389 | } else |
335 | msrval |= DF_OUTPUT_CRT; | 390 | msrval |= MSR_LX_GLD_MSR_CONFIG_FMT_CRT; |
336 | } | ||
337 | 391 | ||
338 | wrmsrl(MSR_LX_DF_GLCONFIG, msrval); | 392 | wrmsrl(MSR_LX_GLD_MSR_CONFIG, msrval); |
339 | 393 | ||
340 | /* Clear the various buffers */ | 394 | /* Clear the various buffers */ |
341 | /* FIXME: Adjust for panning here */ | 395 | /* FIXME: Adjust for panning here */ |
342 | 396 | ||
343 | writel(0, par->dc_regs + DC_FB_START); | 397 | write_dc(par, DC_FB_ST_OFFSET, 0); |
344 | writel(0, par->dc_regs + DC_CB_START); | 398 | write_dc(par, DC_CB_ST_OFFSET, 0); |
345 | writel(0, par->dc_regs + DC_CURSOR_START); | 399 | write_dc(par, DC_CURS_ST_OFFSET, 0); |
346 | 400 | ||
347 | /* FIXME: Add support for interlacing */ | 401 | /* FIXME: Add support for interlacing */ |
348 | /* FIXME: Add support for scaling */ | 402 | /* FIXME: Add support for scaling */ |
349 | 403 | ||
350 | val = readl(par->dc_regs + DC_GENLCK_CTRL); | 404 | val = read_dc(par, DC_GENLK_CTL); |
351 | val &= ~(DC_GC_ALPHA_FLICK_ENABLE | | 405 | val &= ~(DC_GENLK_CTL_ALPHA_FLICK_EN | DC_GENLK_CTL_FLICK_EN | |
352 | DC_GC_FLICKER_FILTER_ENABLE | DC_GC_FLICKER_FILTER_MASK); | 406 | DC_GENLK_CTL_FLICK_SEL_MASK); |
353 | 407 | ||
354 | /* Default scaling params */ | 408 | /* Default scaling params */ |
355 | 409 | ||
356 | writel((0x4000 << 16) | 0x4000, par->dc_regs + DC_GFX_SCALE); | 410 | write_dc(par, DC_GFX_SCALE, (0x4000 << 16) | 0x4000); |
357 | writel(0, par->dc_regs + DC_IRQ_FILT_CTL); | 411 | write_dc(par, DC_IRQ_FILT_CTL, 0); |
358 | writel(val, par->dc_regs + DC_GENLCK_CTRL); | 412 | write_dc(par, DC_GENLK_CTL, val); |
359 | 413 | ||
360 | /* FIXME: Support compression */ | 414 | /* FIXME: Support compression */ |
361 | 415 | ||
362 | if (info->fix.line_length > 4096) | 416 | if (info->fix.line_length > 4096) |
363 | dv = DC_DV_LINE_SIZE_8192; | 417 | dv = DC_DV_CTL_DV_LINE_SIZE_8K; |
364 | else if (info->fix.line_length > 2048) | 418 | else if (info->fix.line_length > 2048) |
365 | dv = DC_DV_LINE_SIZE_4096; | 419 | dv = DC_DV_CTL_DV_LINE_SIZE_4K; |
366 | else if (info->fix.line_length > 1024) | 420 | else if (info->fix.line_length > 1024) |
367 | dv = DC_DV_LINE_SIZE_2048; | 421 | dv = DC_DV_CTL_DV_LINE_SIZE_2K; |
368 | else | 422 | else |
369 | dv = DC_DV_LINE_SIZE_1024; | 423 | dv = DC_DV_CTL_DV_LINE_SIZE_1K; |
370 | 424 | ||
371 | max = info->fix.line_length * info->var.yres; | 425 | max = info->fix.line_length * info->var.yres; |
372 | max = (max + 0x3FF) & 0xFFFFFC00; | 426 | max = (max + 0x3FF) & 0xFFFFFC00; |
373 | 427 | ||
374 | writel(max | DC_DV_TOP_ENABLE, par->dc_regs + DC_DV_TOP); | 428 | write_dc(par, DC_DV_TOP, max | DC_DV_TOP_DV_TOP_EN); |
375 | 429 | ||
376 | val = readl(par->dc_regs + DC_DV_CTL) & ~DC_DV_LINE_SIZE_MASK; | 430 | val = read_dc(par, DC_DV_CTL) & ~DC_DV_CTL_DV_LINE_SIZE; |
377 | writel(val | dv, par->dc_regs + DC_DV_CTL); | 431 | write_dc(par, DC_DV_CTL, val | dv); |
378 | 432 | ||
379 | size = info->var.xres * (info->var.bits_per_pixel >> 3); | 433 | size = info->var.xres * (info->var.bits_per_pixel >> 3); |
380 | 434 | ||
381 | writel(info->fix.line_length >> 3, par->dc_regs + DC_GRAPHICS_PITCH); | 435 | write_dc(par, DC_GFX_PITCH, info->fix.line_length >> 3); |
382 | writel((size + 7) >> 3, par->dc_regs + DC_LINE_SIZE); | 436 | write_dc(par, DC_LINE_SIZE, (size + 7) >> 3); |
383 | 437 | ||
384 | /* Set default watermark values */ | 438 | /* Set default watermark values */ |
385 | 439 | ||
386 | rdmsrl(MSR_LX_DC_SPARE, msrval); | 440 | rdmsrl(MSR_LX_SPARE_MSR, msrval); |
387 | 441 | ||
388 | msrval &= ~(DC_SPARE_DISABLE_CFIFO_HGO | DC_SPARE_VFIFO_ARB_SELECT | | 442 | msrval &= ~(MSR_LX_SPARE_MSR_DIS_CFIFO_HGO |
389 | DC_SPARE_LOAD_WM_LPEN_MASK | DC_SPARE_WM_LPEN_OVRD | | 443 | | MSR_LX_SPARE_MSR_VFIFO_ARB_SEL |
390 | DC_SPARE_DISABLE_INIT_VID_PRI | DC_SPARE_DISABLE_VFIFO_WM); | 444 | | MSR_LX_SPARE_MSR_LOAD_WM_LPEN_M |
391 | msrval |= DC_SPARE_DISABLE_VFIFO_WM | DC_SPARE_DISABLE_INIT_VID_PRI; | 445 | | MSR_LX_SPARE_MSR_WM_LPEN_OVRD); |
392 | wrmsrl(MSR_LX_DC_SPARE, msrval); | 446 | msrval |= MSR_LX_SPARE_MSR_DIS_VIFO_WM | |
393 | 447 | MSR_LX_SPARE_MSR_DIS_INIT_V_PRI; | |
394 | gcfg = DC_GCFG_DFLE; /* Display fifo enable */ | 448 | wrmsrl(MSR_LX_SPARE_MSR, msrval); |
395 | gcfg |= 0xB600; /* Set default priority */ | 449 | |
396 | gcfg |= DC_GCFG_FDTY; /* Set the frame dirty mode */ | 450 | gcfg = DC_GENERAL_CFG_DFLE; /* Display fifo enable */ |
397 | 451 | gcfg |= (0x6 << DC_GENERAL_CFG_DFHPSL_SHIFT) | /* default priority */ | |
398 | dcfg = DC_DCFG_VDEN; /* Enable video data */ | 452 | (0xb << DC_GENERAL_CFG_DFHPEL_SHIFT); |
399 | dcfg |= DC_DCFG_GDEN; /* Enable graphics */ | 453 | gcfg |= DC_GENERAL_CFG_FDTY; /* Set the frame dirty mode */ |
400 | dcfg |= DC_DCFG_TGEN; /* Turn on the timing generator */ | 454 | |
401 | dcfg |= DC_DCFG_TRUP; /* Update timings immediately */ | 455 | dcfg = DC_DISPLAY_CFG_VDEN; /* Enable video data */ |
402 | dcfg |= DC_DCFG_PALB; /* Palette bypass in > 8 bpp modes */ | 456 | dcfg |= DC_DISPLAY_CFG_GDEN; /* Enable graphics */ |
403 | dcfg |= DC_DCFG_VISL; | 457 | dcfg |= DC_DISPLAY_CFG_TGEN; /* Turn on the timing generator */ |
404 | dcfg |= DC_DCFG_DCEN; /* Always center the display */ | 458 | dcfg |= DC_DISPLAY_CFG_TRUP; /* Update timings immediately */ |
459 | dcfg |= DC_DISPLAY_CFG_PALB; /* Palette bypass in > 8 bpp modes */ | ||
460 | dcfg |= DC_DISPLAY_CFG_VISL; | ||
461 | dcfg |= DC_DISPLAY_CFG_DCEN; /* Always center the display */ | ||
405 | 462 | ||
406 | /* Set the current BPP mode */ | 463 | /* Set the current BPP mode */ |
407 | 464 | ||
408 | switch (info->var.bits_per_pixel) { | 465 | switch (info->var.bits_per_pixel) { |
409 | case 8: | 466 | case 8: |
410 | dcfg |= DC_DCFG_DISP_MODE_8BPP; | 467 | dcfg |= DC_DISPLAY_CFG_DISP_MODE_8BPP; |
411 | break; | 468 | break; |
412 | 469 | ||
413 | case 16: | 470 | case 16: |
414 | dcfg |= DC_DCFG_DISP_MODE_16BPP | DC_DCFG_16BPP; | 471 | dcfg |= DC_DISPLAY_CFG_DISP_MODE_16BPP; |
415 | break; | 472 | break; |
416 | 473 | ||
417 | case 32: | 474 | case 32: |
418 | case 24: | 475 | case 24: |
419 | dcfg |= DC_DCFG_DISP_MODE_24BPP; | 476 | dcfg |= DC_DISPLAY_CFG_DISP_MODE_24BPP; |
420 | break; | 477 | break; |
421 | } | 478 | } |
422 | 479 | ||
@@ -436,35 +493,31 @@ void lx_set_mode(struct fb_info *info) | |||
436 | vblankend = vsyncend + info->var.upper_margin; | 493 | vblankend = vsyncend + info->var.upper_margin; |
437 | vtotal = vblankend; | 494 | vtotal = vblankend; |
438 | 495 | ||
439 | writel((hactive - 1) | ((htotal - 1) << 16), | 496 | write_dc(par, DC_H_ACTIVE_TIMING, (hactive - 1) | ((htotal - 1) << 16)); |
440 | par->dc_regs + DC_H_ACTIVE_TIMING); | 497 | write_dc(par, DC_H_BLANK_TIMING, |
441 | writel((hblankstart - 1) | ((hblankend - 1) << 16), | 498 | (hblankstart - 1) | ((hblankend - 1) << 16)); |
442 | par->dc_regs + DC_H_BLANK_TIMING); | 499 | write_dc(par, DC_H_SYNC_TIMING, |
443 | writel((hsyncstart - 1) | ((hsyncend - 1) << 16), | 500 | (hsyncstart - 1) | ((hsyncend - 1) << 16)); |
444 | par->dc_regs + DC_H_SYNC_TIMING); | ||
445 | |||
446 | writel((vactive - 1) | ((vtotal - 1) << 16), | ||
447 | par->dc_regs + DC_V_ACTIVE_TIMING); | ||
448 | 501 | ||
449 | writel((vblankstart - 1) | ((vblankend - 1) << 16), | 502 | write_dc(par, DC_V_ACTIVE_TIMING, (vactive - 1) | ((vtotal - 1) << 16)); |
450 | par->dc_regs + DC_V_BLANK_TIMING); | 503 | write_dc(par, DC_V_BLANK_TIMING, |
504 | (vblankstart - 1) | ((vblankend - 1) << 16)); | ||
505 | write_dc(par, DC_V_SYNC_TIMING, | ||
506 | (vsyncstart - 1) | ((vsyncend - 1) << 16)); | ||
451 | 507 | ||
452 | writel((vsyncstart - 1) | ((vsyncend - 1) << 16), | 508 | write_dc(par, DC_FB_ACTIVE, |
453 | par->dc_regs + DC_V_SYNC_TIMING); | 509 | (info->var.xres - 1) << 16 | (info->var.yres - 1)); |
454 | |||
455 | writel( (info->var.xres - 1) << 16 | (info->var.yres - 1), | ||
456 | par->dc_regs + DC_FB_ACTIVE); | ||
457 | 510 | ||
458 | /* And re-enable the graphics output */ | 511 | /* And re-enable the graphics output */ |
459 | lx_graphics_enable(info); | 512 | lx_graphics_enable(info); |
460 | 513 | ||
461 | /* Write the two main configuration registers */ | 514 | /* Write the two main configuration registers */ |
462 | writel(dcfg, par->dc_regs + DC_DISPLAY_CFG); | 515 | write_dc(par, DC_DISPLAY_CFG, dcfg); |
463 | writel(0, par->dc_regs + DC_ARB_CFG); | 516 | write_dc(par, DC_ARB_CFG, 0); |
464 | writel(gcfg, par->dc_regs + DC_GENERAL_CFG); | 517 | write_dc(par, DC_GENERAL_CFG, gcfg); |
465 | 518 | ||
466 | /* Lock the DC registers */ | 519 | /* Lock the DC registers */ |
467 | writel(0, par->dc_regs + DC_UNLOCK); | 520 | write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK); |
468 | } | 521 | } |
469 | 522 | ||
470 | void lx_set_palette_reg(struct fb_info *info, unsigned regno, | 523 | void lx_set_palette_reg(struct fb_info *info, unsigned regno, |
@@ -479,58 +532,310 @@ void lx_set_palette_reg(struct fb_info *info, unsigned regno, | |||
479 | val |= (green) & 0x00ff00; | 532 | val |= (green) & 0x00ff00; |
480 | val |= (blue >> 8) & 0x0000ff; | 533 | val |= (blue >> 8) & 0x0000ff; |
481 | 534 | ||
482 | writel(regno, par->dc_regs + DC_PAL_ADDRESS); | 535 | write_dc(par, DC_PAL_ADDRESS, regno); |
483 | writel(val, par->dc_regs + DC_PAL_DATA); | 536 | write_dc(par, DC_PAL_DATA, val); |
484 | } | 537 | } |
485 | 538 | ||
486 | int lx_blank_display(struct fb_info *info, int blank_mode) | 539 | int lx_blank_display(struct fb_info *info, int blank_mode) |
487 | { | 540 | { |
488 | struct lxfb_par *par = info->par; | 541 | struct lxfb_par *par = info->par; |
489 | u32 dcfg, fp_pm; | 542 | u32 dcfg, fp_pm; |
490 | int blank, hsync, vsync; | 543 | int blank, hsync, vsync, crt; |
491 | 544 | ||
492 | /* CRT power saving modes. */ | 545 | /* CRT power saving modes. */ |
493 | switch (blank_mode) { | 546 | switch (blank_mode) { |
494 | case FB_BLANK_UNBLANK: | 547 | case FB_BLANK_UNBLANK: |
495 | blank = 0; hsync = 1; vsync = 1; | 548 | blank = 0; hsync = 1; vsync = 1; crt = 1; |
496 | break; | 549 | break; |
497 | case FB_BLANK_NORMAL: | 550 | case FB_BLANK_NORMAL: |
498 | blank = 1; hsync = 1; vsync = 1; | 551 | blank = 1; hsync = 1; vsync = 1; crt = 1; |
499 | break; | 552 | break; |
500 | case FB_BLANK_VSYNC_SUSPEND: | 553 | case FB_BLANK_VSYNC_SUSPEND: |
501 | blank = 1; hsync = 1; vsync = 0; | 554 | blank = 1; hsync = 1; vsync = 0; crt = 1; |
502 | break; | 555 | break; |
503 | case FB_BLANK_HSYNC_SUSPEND: | 556 | case FB_BLANK_HSYNC_SUSPEND: |
504 | blank = 1; hsync = 0; vsync = 1; | 557 | blank = 1; hsync = 0; vsync = 1; crt = 1; |
505 | break; | 558 | break; |
506 | case FB_BLANK_POWERDOWN: | 559 | case FB_BLANK_POWERDOWN: |
507 | blank = 1; hsync = 0; vsync = 0; | 560 | blank = 1; hsync = 0; vsync = 0; crt = 0; |
508 | break; | 561 | break; |
509 | default: | 562 | default: |
510 | return -EINVAL; | 563 | return -EINVAL; |
511 | } | 564 | } |
512 | 565 | ||
513 | dcfg = readl(par->df_regs + DF_DISPLAY_CFG); | 566 | dcfg = read_vp(par, VP_DCFG); |
514 | dcfg &= ~(DF_DCFG_DAC_BL_EN | 567 | dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN | |
515 | | DF_DCFG_HSYNC_EN | DF_DCFG_VSYNC_EN); | 568 | VP_DCFG_CRT_EN); |
516 | if (!blank) | 569 | if (!blank) |
517 | dcfg |= DF_DCFG_DAC_BL_EN; | 570 | dcfg |= VP_DCFG_DAC_BL_EN; |
518 | if (hsync) | 571 | if (hsync) |
519 | dcfg |= DF_DCFG_HSYNC_EN; | 572 | dcfg |= VP_DCFG_HSYNC_EN; |
520 | if (vsync) | 573 | if (vsync) |
521 | dcfg |= DF_DCFG_VSYNC_EN; | 574 | dcfg |= VP_DCFG_VSYNC_EN; |
522 | writel(dcfg, par->df_regs + DF_DISPLAY_CFG); | 575 | if (crt) |
576 | dcfg |= VP_DCFG_CRT_EN; | ||
577 | write_vp(par, VP_DCFG, dcfg); | ||
523 | 578 | ||
524 | /* Power on/off flat panel */ | 579 | /* Power on/off flat panel */ |
525 | 580 | ||
526 | if (par->output & OUTPUT_PANEL) { | 581 | if (par->output & OUTPUT_PANEL) { |
527 | fp_pm = readl(par->df_regs + DF_FP_PM); | 582 | fp_pm = read_fp(par, FP_PM); |
528 | if (blank_mode == FB_BLANK_POWERDOWN) | 583 | if (blank_mode == FB_BLANK_POWERDOWN) |
529 | fp_pm &= ~DF_FP_PM_P; | 584 | fp_pm &= ~FP_PM_P; |
530 | else | 585 | else |
531 | fp_pm |= DF_FP_PM_P; | 586 | fp_pm |= FP_PM_P; |
532 | writel(fp_pm, par->df_regs + DF_FP_PM); | 587 | write_fp(par, FP_PM, fp_pm); |
533 | } | 588 | } |
534 | 589 | ||
535 | return 0; | 590 | return 0; |
536 | } | 591 | } |
592 | |||
593 | #ifdef CONFIG_PM | ||
594 | |||
595 | static void lx_save_regs(struct lxfb_par *par) | ||
596 | { | ||
597 | uint32_t filt; | ||
598 | int i; | ||
599 | |||
600 | /* wait for the BLT engine to stop being busy */ | ||
601 | do { | ||
602 | i = read_gp(par, GP_BLT_STATUS); | ||
603 | } while ((i & GP_BLT_STATUS_PB) || !(i & GP_BLT_STATUS_CE)); | ||
604 | |||
605 | /* save MSRs */ | ||
606 | rdmsrl(MSR_LX_MSR_PADSEL, par->msr.padsel); | ||
607 | rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll); | ||
608 | rdmsrl(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg); | ||
609 | rdmsrl(MSR_LX_SPARE_MSR, par->msr.dcspare); | ||
610 | |||
611 | write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); | ||
612 | |||
613 | /* save registers */ | ||
614 | memcpy(par->gp, par->gp_regs, sizeof(par->gp)); | ||
615 | memcpy(par->dc, par->dc_regs, sizeof(par->dc)); | ||
616 | memcpy(par->vp, par->vp_regs, sizeof(par->vp)); | ||
617 | memcpy(par->fp, par->vp_regs + VP_FP_START, sizeof(par->fp)); | ||
618 | |||
619 | /* save the palette */ | ||
620 | write_dc(par, DC_PAL_ADDRESS, 0); | ||
621 | for (i = 0; i < ARRAY_SIZE(par->pal); i++) | ||
622 | par->pal[i] = read_dc(par, DC_PAL_DATA); | ||
623 | |||
624 | /* save the horizontal filter coefficients */ | ||
625 | filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL; | ||
626 | for (i = 0; i < ARRAY_SIZE(par->hcoeff); i += 2) { | ||
627 | write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i); | ||
628 | par->hcoeff[i] = read_dc(par, DC_FILT_COEFF1); | ||
629 | par->hcoeff[i + 1] = read_dc(par, DC_FILT_COEFF2); | ||
630 | } | ||
631 | |||
632 | /* save the vertical filter coefficients */ | ||
633 | filt &= ~DC_IRQ_FILT_CTL_H_FILT_SEL; | ||
634 | for (i = 0; i < ARRAY_SIZE(par->vcoeff); i++) { | ||
635 | write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i); | ||
636 | par->vcoeff[i] = read_dc(par, DC_FILT_COEFF1); | ||
637 | } | ||
638 | |||
639 | /* save video coeff ram */ | ||
640 | memcpy(par->vp_coeff, par->vp_regs + VP_VCR, sizeof(par->vp_coeff)); | ||
641 | } | ||
642 | |||
643 | static void lx_restore_gfx_proc(struct lxfb_par *par) | ||
644 | { | ||
645 | int i; | ||
646 | |||
647 | /* a bunch of registers require GP_RASTER_MODE to be set first */ | ||
648 | write_gp(par, GP_RASTER_MODE, par->gp[GP_RASTER_MODE]); | ||
649 | |||
650 | for (i = 0; i < ARRAY_SIZE(par->gp); i++) { | ||
651 | switch (i) { | ||
652 | case GP_RASTER_MODE: | ||
653 | case GP_VECTOR_MODE: | ||
654 | case GP_BLT_MODE: | ||
655 | case GP_BLT_STATUS: | ||
656 | case GP_HST_SRC: | ||
657 | /* FIXME: restore LUT data */ | ||
658 | case GP_LUT_INDEX: | ||
659 | case GP_LUT_DATA: | ||
660 | /* don't restore these registers */ | ||
661 | break; | ||
662 | |||
663 | default: | ||
664 | write_gp(par, i, par->gp[i]); | ||
665 | } | ||
666 | } | ||
667 | } | ||
668 | |||
669 | static void lx_restore_display_ctlr(struct lxfb_par *par) | ||
670 | { | ||
671 | uint32_t filt; | ||
672 | int i; | ||
673 | |||
674 | wrmsrl(MSR_LX_SPARE_MSR, par->msr.dcspare); | ||
675 | |||
676 | for (i = 0; i < ARRAY_SIZE(par->dc); i++) { | ||
677 | switch (i) { | ||
678 | case DC_UNLOCK: | ||
679 | /* unlock the DC; runs first */ | ||
680 | write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); | ||
681 | break; | ||
682 | |||
683 | case DC_GENERAL_CFG: | ||
684 | case DC_DISPLAY_CFG: | ||
685 | /* disable all while restoring */ | ||
686 | write_dc(par, i, 0); | ||
687 | break; | ||
688 | |||
689 | case DC_DV_CTL: | ||
690 | /* set all ram to dirty */ | ||
691 | write_dc(par, i, par->dc[i] | DC_DV_CTL_CLEAR_DV_RAM); | ||
692 | |||
693 | case DC_RSVD_1: | ||
694 | case DC_RSVD_2: | ||
695 | case DC_RSVD_3: | ||
696 | case DC_LINE_CNT: | ||
697 | case DC_PAL_ADDRESS: | ||
698 | case DC_PAL_DATA: | ||
699 | case DC_DFIFO_DIAG: | ||
700 | case DC_CFIFO_DIAG: | ||
701 | case DC_FILT_COEFF1: | ||
702 | case DC_FILT_COEFF2: | ||
703 | case DC_RSVD_4: | ||
704 | case DC_RSVD_5: | ||
705 | /* don't restore these registers */ | ||
706 | break; | ||
707 | |||
708 | default: | ||
709 | write_dc(par, i, par->dc[i]); | ||
710 | } | ||
711 | } | ||
712 | |||
713 | /* restore the palette */ | ||
714 | write_dc(par, DC_PAL_ADDRESS, 0); | ||
715 | for (i = 0; i < ARRAY_SIZE(par->pal); i++) | ||
716 | write_dc(par, DC_PAL_DATA, par->pal[i]); | ||
717 | |||
718 | /* restore the horizontal filter coefficients */ | ||
719 | filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL; | ||
720 | for (i = 0; i < ARRAY_SIZE(par->hcoeff); i += 2) { | ||
721 | write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i); | ||
722 | write_dc(par, DC_FILT_COEFF1, par->hcoeff[i]); | ||
723 | write_dc(par, DC_FILT_COEFF2, par->hcoeff[i + 1]); | ||
724 | } | ||
725 | |||
726 | /* restore the vertical filter coefficients */ | ||
727 | filt &= ~DC_IRQ_FILT_CTL_H_FILT_SEL; | ||
728 | for (i = 0; i < ARRAY_SIZE(par->vcoeff); i++) { | ||
729 | write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i); | ||
730 | write_dc(par, DC_FILT_COEFF1, par->vcoeff[i]); | ||
731 | } | ||
732 | } | ||
733 | |||
734 | static void lx_restore_video_proc(struct lxfb_par *par) | ||
735 | { | ||
736 | int i; | ||
737 | |||
738 | wrmsrl(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg); | ||
739 | wrmsrl(MSR_LX_MSR_PADSEL, par->msr.padsel); | ||
740 | |||
741 | for (i = 0; i < ARRAY_SIZE(par->vp); i++) { | ||
742 | switch (i) { | ||
743 | case VP_VCFG: | ||
744 | case VP_DCFG: | ||
745 | case VP_PAR: | ||
746 | case VP_PDR: | ||
747 | case VP_CCS: | ||
748 | case VP_RSVD_0: | ||
749 | /* case VP_VDC: */ /* why should this not be restored? */ | ||
750 | case VP_RSVD_1: | ||
751 | case VP_CRC32: | ||
752 | /* don't restore these registers */ | ||
753 | break; | ||
754 | |||
755 | default: | ||
756 | write_vp(par, i, par->vp[i]); | ||
757 | } | ||
758 | } | ||
759 | |||
760 | /* restore video coeff ram */ | ||
761 | memcpy(par->vp_regs + VP_VCR, par->vp_coeff, sizeof(par->vp_coeff)); | ||
762 | } | ||
763 | |||
764 | static void lx_restore_regs(struct lxfb_par *par) | ||
765 | { | ||
766 | int i; | ||
767 | |||
768 | lx_set_dotpll((u32) (par->msr.dotpll >> 32)); | ||
769 | lx_restore_gfx_proc(par); | ||
770 | lx_restore_display_ctlr(par); | ||
771 | lx_restore_video_proc(par); | ||
772 | |||
773 | /* Flat Panel */ | ||
774 | for (i = 0; i < ARRAY_SIZE(par->fp); i++) { | ||
775 | switch (i) { | ||
776 | case FP_PM: | ||
777 | case FP_RSVD_0: | ||
778 | case FP_RSVD_1: | ||
779 | case FP_RSVD_2: | ||
780 | case FP_RSVD_3: | ||
781 | case FP_RSVD_4: | ||
782 | /* don't restore these registers */ | ||
783 | break; | ||
784 | |||
785 | default: | ||
786 | write_fp(par, i, par->fp[i]); | ||
787 | } | ||
788 | } | ||
789 | |||
790 | /* control the panel */ | ||
791 | if (par->fp[FP_PM] & FP_PM_P) { | ||
792 | /* power on the panel if not already power{ed,ing} on */ | ||
793 | if (!(read_fp(par, FP_PM) & | ||
794 | (FP_PM_PANEL_ON|FP_PM_PANEL_PWR_UP))) | ||
795 | write_fp(par, FP_PM, par->fp[FP_PM]); | ||
796 | } else { | ||
797 | /* power down the panel if not already power{ed,ing} down */ | ||
798 | if (!(read_fp(par, FP_PM) & | ||
799 | (FP_PM_PANEL_OFF|FP_PM_PANEL_PWR_DOWN))) | ||
800 | write_fp(par, FP_PM, par->fp[FP_PM]); | ||
801 | } | ||
802 | |||
803 | /* turn everything on */ | ||
804 | write_vp(par, VP_VCFG, par->vp[VP_VCFG]); | ||
805 | write_vp(par, VP_DCFG, par->vp[VP_DCFG]); | ||
806 | write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG]); | ||
807 | /* do this last; it will enable the FIFO load */ | ||
808 | write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]); | ||
809 | |||
810 | /* lock the door behind us */ | ||
811 | write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK); | ||
812 | } | ||
813 | |||
814 | int lx_powerdown(struct fb_info *info) | ||
815 | { | ||
816 | struct lxfb_par *par = info->par; | ||
817 | |||
818 | if (par->powered_down) | ||
819 | return 0; | ||
820 | |||
821 | lx_save_regs(par); | ||
822 | lx_graphics_disable(info); | ||
823 | |||
824 | par->powered_down = 1; | ||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | int lx_powerup(struct fb_info *info) | ||
829 | { | ||
830 | struct lxfb_par *par = info->par; | ||
831 | |||
832 | if (!par->powered_down) | ||
833 | return 0; | ||
834 | |||
835 | lx_restore_regs(par); | ||
836 | |||
837 | par->powered_down = 0; | ||
838 | return 0; | ||
839 | } | ||
840 | |||
841 | #endif | ||
diff --git a/drivers/video/geode/suspend_gx.c b/drivers/video/geode/suspend_gx.c new file mode 100644 index 000000000000..9aff32ef8bb6 --- /dev/null +++ b/drivers/video/geode/suspend_gx.c | |||
@@ -0,0 +1,267 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Advanced Micro Devices, Inc. | ||
3 | * Copyright (C) 2008 Andres Salomon <dilinger@debian.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | */ | ||
10 | #include <linux/fb.h> | ||
11 | #include <asm/io.h> | ||
12 | #include <asm/msr.h> | ||
13 | #include <asm/geode.h> | ||
14 | #include <asm/delay.h> | ||
15 | |||
16 | #include "gxfb.h" | ||
17 | |||
18 | #ifdef CONFIG_PM | ||
19 | |||
20 | static void gx_save_regs(struct gxfb_par *par) | ||
21 | { | ||
22 | int i; | ||
23 | |||
24 | /* wait for the BLT engine to stop being busy */ | ||
25 | do { | ||
26 | i = read_gp(par, GP_BLT_STATUS); | ||
27 | } while (i & (GP_BLT_STATUS_BLT_PENDING | GP_BLT_STATUS_BLT_BUSY)); | ||
28 | |||
29 | /* save MSRs */ | ||
30 | rdmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel); | ||
31 | rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll); | ||
32 | |||
33 | write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); | ||
34 | |||
35 | /* save registers */ | ||
36 | memcpy(par->gp, par->gp_regs, sizeof(par->gp)); | ||
37 | memcpy(par->dc, par->dc_regs, sizeof(par->dc)); | ||
38 | memcpy(par->vp, par->vid_regs, sizeof(par->vp)); | ||
39 | memcpy(par->fp, par->vid_regs + VP_FP_START, sizeof(par->fp)); | ||
40 | |||
41 | /* save the palette */ | ||
42 | write_dc(par, DC_PAL_ADDRESS, 0); | ||
43 | for (i = 0; i < ARRAY_SIZE(par->pal); i++) | ||
44 | par->pal[i] = read_dc(par, DC_PAL_DATA); | ||
45 | } | ||
46 | |||
47 | static void gx_set_dotpll(uint32_t dotpll_hi) | ||
48 | { | ||
49 | uint32_t dotpll_lo; | ||
50 | int i; | ||
51 | |||
52 | rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo); | ||
53 | dotpll_lo |= MSR_GLCP_DOTPLL_DOTRESET; | ||
54 | dotpll_lo &= ~MSR_GLCP_DOTPLL_BYPASS; | ||
55 | wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi); | ||
56 | |||
57 | /* wait for the PLL to lock */ | ||
58 | for (i = 0; i < 200; i++) { | ||
59 | rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo); | ||
60 | if (dotpll_lo & MSR_GLCP_DOTPLL_LOCK) | ||
61 | break; | ||
62 | udelay(1); | ||
63 | } | ||
64 | |||
65 | /* PLL set, unlock */ | ||
66 | dotpll_lo &= ~MSR_GLCP_DOTPLL_DOTRESET; | ||
67 | wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi); | ||
68 | } | ||
69 | |||
70 | static void gx_restore_gfx_proc(struct gxfb_par *par) | ||
71 | { | ||
72 | int i; | ||
73 | |||
74 | for (i = 0; i < ARRAY_SIZE(par->gp); i++) { | ||
75 | switch (i) { | ||
76 | case GP_VECTOR_MODE: | ||
77 | case GP_BLT_MODE: | ||
78 | case GP_BLT_STATUS: | ||
79 | case GP_HST_SRC: | ||
80 | /* don't restore these registers */ | ||
81 | break; | ||
82 | default: | ||
83 | write_gp(par, i, par->gp[i]); | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static void gx_restore_display_ctlr(struct gxfb_par *par) | ||
89 | { | ||
90 | int i; | ||
91 | |||
92 | for (i = 0; i < ARRAY_SIZE(par->dc); i++) { | ||
93 | switch (i) { | ||
94 | case DC_UNLOCK: | ||
95 | /* unlock the DC; runs first */ | ||
96 | write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); | ||
97 | break; | ||
98 | |||
99 | case DC_GENERAL_CFG: | ||
100 | /* write without the enables */ | ||
101 | write_dc(par, i, par->dc[i] & ~(DC_GENERAL_CFG_VIDE | | ||
102 | DC_GENERAL_CFG_ICNE | | ||
103 | DC_GENERAL_CFG_CURE | | ||
104 | DC_GENERAL_CFG_DFLE)); | ||
105 | break; | ||
106 | |||
107 | case DC_DISPLAY_CFG: | ||
108 | /* write without the enables */ | ||
109 | write_dc(par, i, par->dc[i] & ~(DC_DISPLAY_CFG_VDEN | | ||
110 | DC_DISPLAY_CFG_GDEN | | ||
111 | DC_DISPLAY_CFG_TGEN)); | ||
112 | break; | ||
113 | |||
114 | case DC_RSVD_0: | ||
115 | case DC_RSVD_1: | ||
116 | case DC_RSVD_2: | ||
117 | case DC_RSVD_3: | ||
118 | case DC_RSVD_4: | ||
119 | case DC_LINE_CNT: | ||
120 | case DC_PAL_ADDRESS: | ||
121 | case DC_PAL_DATA: | ||
122 | case DC_DFIFO_DIAG: | ||
123 | case DC_CFIFO_DIAG: | ||
124 | case DC_RSVD_5: | ||
125 | /* don't restore these registers */ | ||
126 | break; | ||
127 | default: | ||
128 | write_dc(par, i, par->dc[i]); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | /* restore the palette */ | ||
133 | write_dc(par, DC_PAL_ADDRESS, 0); | ||
134 | for (i = 0; i < ARRAY_SIZE(par->pal); i++) | ||
135 | write_dc(par, DC_PAL_DATA, par->pal[i]); | ||
136 | } | ||
137 | |||
138 | static void gx_restore_video_proc(struct gxfb_par *par) | ||
139 | { | ||
140 | int i; | ||
141 | |||
142 | wrmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel); | ||
143 | |||
144 | for (i = 0; i < ARRAY_SIZE(par->vp); i++) { | ||
145 | switch (i) { | ||
146 | case VP_VCFG: | ||
147 | /* don't enable video yet */ | ||
148 | write_vp(par, i, par->vp[i] & ~VP_VCFG_VID_EN); | ||
149 | break; | ||
150 | |||
151 | case VP_DCFG: | ||
152 | /* don't enable CRT yet */ | ||
153 | write_vp(par, i, par->vp[i] & | ||
154 | ~(VP_DCFG_DAC_BL_EN | VP_DCFG_VSYNC_EN | | ||
155 | VP_DCFG_HSYNC_EN | VP_DCFG_CRT_EN)); | ||
156 | break; | ||
157 | |||
158 | case VP_GAR: | ||
159 | case VP_GDR: | ||
160 | case VP_RSVD_0: | ||
161 | case VP_RSVD_1: | ||
162 | case VP_RSVD_2: | ||
163 | case VP_RSVD_3: | ||
164 | case VP_CRC32: | ||
165 | case VP_AWT: | ||
166 | case VP_VTM: | ||
167 | /* don't restore these registers */ | ||
168 | break; | ||
169 | default: | ||
170 | write_vp(par, i, par->vp[i]); | ||
171 | } | ||
172 | } | ||
173 | } | ||
174 | |||
175 | static void gx_restore_regs(struct gxfb_par *par) | ||
176 | { | ||
177 | int i; | ||
178 | |||
179 | gx_set_dotpll((uint32_t) (par->msr.dotpll >> 32)); | ||
180 | gx_restore_gfx_proc(par); | ||
181 | gx_restore_display_ctlr(par); | ||
182 | gx_restore_video_proc(par); | ||
183 | |||
184 | /* Flat Panel */ | ||
185 | for (i = 0; i < ARRAY_SIZE(par->fp); i++) { | ||
186 | if (i != FP_PM && i != FP_RSVD_0) | ||
187 | write_fp(par, i, par->fp[i]); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | static void gx_disable_graphics(struct gxfb_par *par) | ||
192 | { | ||
193 | /* shut down the engine */ | ||
194 | write_vp(par, VP_VCFG, par->vp[VP_VCFG] & ~VP_VCFG_VID_EN); | ||
195 | write_vp(par, VP_DCFG, par->vp[VP_DCFG] & ~(VP_DCFG_DAC_BL_EN | | ||
196 | VP_DCFG_VSYNC_EN | VP_DCFG_HSYNC_EN | VP_DCFG_CRT_EN)); | ||
197 | |||
198 | /* turn off the flat panel */ | ||
199 | write_fp(par, FP_PM, par->fp[FP_PM] & ~FP_PM_P); | ||
200 | |||
201 | |||
202 | /* turn off display */ | ||
203 | write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); | ||
204 | write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG] & | ||
205 | ~(DC_GENERAL_CFG_VIDE | DC_GENERAL_CFG_ICNE | | ||
206 | DC_GENERAL_CFG_CURE | DC_GENERAL_CFG_DFLE)); | ||
207 | write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG] & | ||
208 | ~(DC_DISPLAY_CFG_VDEN | DC_DISPLAY_CFG_GDEN | | ||
209 | DC_DISPLAY_CFG_TGEN)); | ||
210 | write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK); | ||
211 | } | ||
212 | |||
213 | static void gx_enable_graphics(struct gxfb_par *par) | ||
214 | { | ||
215 | uint32_t fp; | ||
216 | |||
217 | fp = read_fp(par, FP_PM); | ||
218 | if (par->fp[FP_PM] & FP_PM_P) { | ||
219 | /* power on the panel if not already power{ed,ing} on */ | ||
220 | if (!(fp & (FP_PM_PANEL_ON|FP_PM_PANEL_PWR_UP))) | ||
221 | write_fp(par, FP_PM, par->fp[FP_PM]); | ||
222 | } else { | ||
223 | /* power down the panel if not already power{ed,ing} down */ | ||
224 | if (!(fp & (FP_PM_PANEL_OFF|FP_PM_PANEL_PWR_DOWN))) | ||
225 | write_fp(par, FP_PM, par->fp[FP_PM]); | ||
226 | } | ||
227 | |||
228 | /* turn everything on */ | ||
229 | write_vp(par, VP_VCFG, par->vp[VP_VCFG]); | ||
230 | write_vp(par, VP_DCFG, par->vp[VP_DCFG]); | ||
231 | write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG]); | ||
232 | /* do this last; it will enable the FIFO load */ | ||
233 | write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]); | ||
234 | |||
235 | /* lock the door behind us */ | ||
236 | write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK); | ||
237 | } | ||
238 | |||
239 | int gx_powerdown(struct fb_info *info) | ||
240 | { | ||
241 | struct gxfb_par *par = info->par; | ||
242 | |||
243 | if (par->powered_down) | ||
244 | return 0; | ||
245 | |||
246 | gx_save_regs(par); | ||
247 | gx_disable_graphics(par); | ||
248 | |||
249 | par->powered_down = 1; | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | int gx_powerup(struct fb_info *info) | ||
254 | { | ||
255 | struct gxfb_par *par = info->par; | ||
256 | |||
257 | if (!par->powered_down) | ||
258 | return 0; | ||
259 | |||
260 | gx_restore_regs(par); | ||
261 | gx_enable_graphics(par); | ||
262 | |||
263 | par->powered_down = 0; | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | #endif | ||
diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c index febf09c63492..b8d52a8360db 100644 --- a/drivers/video/geode/video_gx.c +++ b/drivers/video/geode/video_gx.c | |||
@@ -16,9 +16,9 @@ | |||
16 | #include <asm/io.h> | 16 | #include <asm/io.h> |
17 | #include <asm/delay.h> | 17 | #include <asm/delay.h> |
18 | #include <asm/msr.h> | 18 | #include <asm/msr.h> |
19 | #include <asm/geode.h> | ||
19 | 20 | ||
20 | #include "geodefb.h" | 21 | #include "gxfb.h" |
21 | #include "video_gx.h" | ||
22 | 22 | ||
23 | 23 | ||
24 | /* | 24 | /* |
@@ -117,7 +117,7 @@ static const struct gx_pll_entry gx_pll_table_14MHz[] = { | |||
117 | { 4357, 0, 0x0000057D }, /* 229.5000 */ | 117 | { 4357, 0, 0x0000057D }, /* 229.5000 */ |
118 | }; | 118 | }; |
119 | 119 | ||
120 | static void gx_set_dclk_frequency(struct fb_info *info) | 120 | void gx_set_dclk_frequency(struct fb_info *info) |
121 | { | 121 | { |
122 | const struct gx_pll_entry *pll_table; | 122 | const struct gx_pll_entry *pll_table; |
123 | int pll_table_len; | 123 | int pll_table_len; |
@@ -178,110 +178,116 @@ static void gx_set_dclk_frequency(struct fb_info *info) | |||
178 | static void | 178 | static void |
179 | gx_configure_tft(struct fb_info *info) | 179 | gx_configure_tft(struct fb_info *info) |
180 | { | 180 | { |
181 | struct geodefb_par *par = info->par; | 181 | struct gxfb_par *par = info->par; |
182 | unsigned long val; | 182 | unsigned long val; |
183 | unsigned long fp; | 183 | unsigned long fp; |
184 | 184 | ||
185 | /* Set up the DF pad select MSR */ | 185 | /* Set up the DF pad select MSR */ |
186 | 186 | ||
187 | rdmsrl(GX_VP_MSR_PAD_SELECT, val); | 187 | rdmsrl(MSR_GX_MSR_PADSEL, val); |
188 | val &= ~GX_VP_PAD_SELECT_MASK; | 188 | val &= ~MSR_GX_MSR_PADSEL_MASK; |
189 | val |= GX_VP_PAD_SELECT_TFT; | 189 | val |= MSR_GX_MSR_PADSEL_TFT; |
190 | wrmsrl(GX_VP_MSR_PAD_SELECT, val); | 190 | wrmsrl(MSR_GX_MSR_PADSEL, val); |
191 | 191 | ||
192 | /* Turn off the panel */ | 192 | /* Turn off the panel */ |
193 | 193 | ||
194 | fp = readl(par->vid_regs + GX_FP_PM); | 194 | fp = read_fp(par, FP_PM); |
195 | fp &= ~GX_FP_PM_P; | 195 | fp &= ~FP_PM_P; |
196 | writel(fp, par->vid_regs + GX_FP_PM); | 196 | write_fp(par, FP_PM, fp); |
197 | 197 | ||
198 | /* Set timing 1 */ | 198 | /* Set timing 1 */ |
199 | 199 | ||
200 | fp = readl(par->vid_regs + GX_FP_PT1); | 200 | fp = read_fp(par, FP_PT1); |
201 | fp &= GX_FP_PT1_VSIZE_MASK; | 201 | fp &= FP_PT1_VSIZE_MASK; |
202 | fp |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT; | 202 | fp |= info->var.yres << FP_PT1_VSIZE_SHIFT; |
203 | writel(fp, par->vid_regs + GX_FP_PT1); | 203 | write_fp(par, FP_PT1, fp); |
204 | 204 | ||
205 | /* Timing 2 */ | 205 | /* Timing 2 */ |
206 | /* Set bits that are always on for TFT */ | 206 | /* Set bits that are always on for TFT */ |
207 | 207 | ||
208 | fp = 0x0F100000; | 208 | fp = 0x0F100000; |
209 | 209 | ||
210 | /* Add sync polarity */ | 210 | /* Configure sync polarity */ |
211 | 211 | ||
212 | if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) | 212 | if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) |
213 | fp |= GX_FP_PT2_VSP; | 213 | fp |= FP_PT2_VSP; |
214 | 214 | ||
215 | if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) | 215 | if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) |
216 | fp |= GX_FP_PT2_HSP; | 216 | fp |= FP_PT2_HSP; |
217 | 217 | ||
218 | writel(fp, par->vid_regs + GX_FP_PT2); | 218 | write_fp(par, FP_PT2, fp); |
219 | 219 | ||
220 | /* Set the dither control */ | 220 | /* Set the dither control */ |
221 | writel(0x70, par->vid_regs + GX_FP_DFC); | 221 | write_fp(par, FP_DFC, FP_DFC_NFI); |
222 | 222 | ||
223 | /* Enable the FP data and power (in case the BIOS didn't) */ | 223 | /* Enable the FP data and power (in case the BIOS didn't) */ |
224 | 224 | ||
225 | fp = readl(par->vid_regs + GX_DCFG); | 225 | fp = read_vp(par, VP_DCFG); |
226 | fp |= GX_DCFG_FP_PWR_EN | GX_DCFG_FP_DATA_EN; | 226 | fp |= VP_DCFG_FP_PWR_EN | VP_DCFG_FP_DATA_EN; |
227 | writel(fp, par->vid_regs + GX_DCFG); | 227 | write_vp(par, VP_DCFG, fp); |
228 | 228 | ||
229 | /* Unblank the panel */ | 229 | /* Unblank the panel */ |
230 | 230 | ||
231 | fp = readl(par->vid_regs + GX_FP_PM); | 231 | fp = read_fp(par, FP_PM); |
232 | fp |= GX_FP_PM_P; | 232 | fp |= FP_PM_P; |
233 | writel(fp, par->vid_regs + GX_FP_PM); | 233 | write_fp(par, FP_PM, fp); |
234 | } | 234 | } |
235 | 235 | ||
236 | static void gx_configure_display(struct fb_info *info) | 236 | void gx_configure_display(struct fb_info *info) |
237 | { | 237 | { |
238 | struct geodefb_par *par = info->par; | 238 | struct gxfb_par *par = info->par; |
239 | u32 dcfg, misc; | 239 | u32 dcfg, misc; |
240 | 240 | ||
241 | /* Set up the MISC register */ | ||
242 | |||
243 | misc = readl(par->vid_regs + GX_MISC); | ||
244 | |||
245 | /* Power up the DAC */ | ||
246 | misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN); | ||
247 | |||
248 | /* Disable gamma correction */ | ||
249 | misc |= GX_MISC_GAM_EN; | ||
250 | |||
251 | writel(misc, par->vid_regs + GX_MISC); | ||
252 | |||
253 | /* Write the display configuration */ | 241 | /* Write the display configuration */ |
254 | dcfg = readl(par->vid_regs + GX_DCFG); | 242 | dcfg = read_vp(par, VP_DCFG); |
255 | 243 | ||
256 | /* Disable hsync and vsync */ | 244 | /* Disable hsync and vsync */ |
257 | dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN); | 245 | dcfg &= ~(VP_DCFG_VSYNC_EN | VP_DCFG_HSYNC_EN); |
258 | writel(dcfg, par->vid_regs + GX_DCFG); | 246 | write_vp(par, VP_DCFG, dcfg); |
259 | 247 | ||
260 | /* Clear bits from existing mode. */ | 248 | /* Clear bits from existing mode. */ |
261 | dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK | 249 | dcfg &= ~(VP_DCFG_CRT_SYNC_SKW |
262 | | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL | 250 | | VP_DCFG_CRT_HSYNC_POL | VP_DCFG_CRT_VSYNC_POL |
263 | | GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN); | 251 | | VP_DCFG_VSYNC_EN | VP_DCFG_HSYNC_EN); |
264 | 252 | ||
265 | /* Set default sync skew. */ | 253 | /* Set default sync skew. */ |
266 | dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT; | 254 | dcfg |= VP_DCFG_CRT_SYNC_SKW_DEFAULT; |
267 | 255 | ||
268 | /* Enable hsync and vsync. */ | 256 | /* Enable hsync and vsync. */ |
269 | dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN; | 257 | dcfg |= VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN; |
270 | 258 | ||
271 | /* Sync polarities. */ | 259 | misc = read_vp(par, VP_MISC); |
272 | if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) | 260 | |
273 | dcfg |= GX_DCFG_CRT_HSYNC_POL; | 261 | /* Disable gamma correction */ |
274 | if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) | 262 | misc |= VP_MISC_GAM_EN; |
275 | dcfg |= GX_DCFG_CRT_VSYNC_POL; | 263 | |
264 | if (par->enable_crt) { | ||
265 | |||
266 | /* Power up the CRT DACs */ | ||
267 | misc &= ~(VP_MISC_APWRDN | VP_MISC_DACPWRDN); | ||
268 | write_vp(par, VP_MISC, misc); | ||
269 | |||
270 | /* Only change the sync polarities if we are running | ||
271 | * in CRT mode. The FP polarities will be handled in | ||
272 | * gxfb_configure_tft */ | ||
273 | if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) | ||
274 | dcfg |= VP_DCFG_CRT_HSYNC_POL; | ||
275 | if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) | ||
276 | dcfg |= VP_DCFG_CRT_VSYNC_POL; | ||
277 | } else { | ||
278 | /* Power down the CRT DACs if in FP mode */ | ||
279 | misc |= (VP_MISC_APWRDN | VP_MISC_DACPWRDN); | ||
280 | write_vp(par, VP_MISC, misc); | ||
281 | } | ||
276 | 282 | ||
277 | /* Enable the display logic */ | 283 | /* Enable the display logic */ |
278 | /* Set up the DACS to blank normally */ | 284 | /* Set up the DACS to blank normally */ |
279 | 285 | ||
280 | dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN; | 286 | dcfg |= VP_DCFG_CRT_EN | VP_DCFG_DAC_BL_EN; |
281 | 287 | ||
282 | /* Enable the external DAC VREF? */ | 288 | /* Enable the external DAC VREF? */ |
283 | 289 | ||
284 | writel(dcfg, par->vid_regs + GX_DCFG); | 290 | write_vp(par, VP_DCFG, dcfg); |
285 | 291 | ||
286 | /* Set up the flat panel (if it is enabled) */ | 292 | /* Set up the flat panel (if it is enabled) */ |
287 | 293 | ||
@@ -289,59 +295,55 @@ static void gx_configure_display(struct fb_info *info) | |||
289 | gx_configure_tft(info); | 295 | gx_configure_tft(info); |
290 | } | 296 | } |
291 | 297 | ||
292 | static int gx_blank_display(struct fb_info *info, int blank_mode) | 298 | int gx_blank_display(struct fb_info *info, int blank_mode) |
293 | { | 299 | { |
294 | struct geodefb_par *par = info->par; | 300 | struct gxfb_par *par = info->par; |
295 | u32 dcfg, fp_pm; | 301 | u32 dcfg, fp_pm; |
296 | int blank, hsync, vsync; | 302 | int blank, hsync, vsync, crt; |
297 | 303 | ||
298 | /* CRT power saving modes. */ | 304 | /* CRT power saving modes. */ |
299 | switch (blank_mode) { | 305 | switch (blank_mode) { |
300 | case FB_BLANK_UNBLANK: | 306 | case FB_BLANK_UNBLANK: |
301 | blank = 0; hsync = 1; vsync = 1; | 307 | blank = 0; hsync = 1; vsync = 1; crt = 1; |
302 | break; | 308 | break; |
303 | case FB_BLANK_NORMAL: | 309 | case FB_BLANK_NORMAL: |
304 | blank = 1; hsync = 1; vsync = 1; | 310 | blank = 1; hsync = 1; vsync = 1; crt = 1; |
305 | break; | 311 | break; |
306 | case FB_BLANK_VSYNC_SUSPEND: | 312 | case FB_BLANK_VSYNC_SUSPEND: |
307 | blank = 1; hsync = 1; vsync = 0; | 313 | blank = 1; hsync = 1; vsync = 0; crt = 1; |
308 | break; | 314 | break; |
309 | case FB_BLANK_HSYNC_SUSPEND: | 315 | case FB_BLANK_HSYNC_SUSPEND: |
310 | blank = 1; hsync = 0; vsync = 1; | 316 | blank = 1; hsync = 0; vsync = 1; crt = 1; |
311 | break; | 317 | break; |
312 | case FB_BLANK_POWERDOWN: | 318 | case FB_BLANK_POWERDOWN: |
313 | blank = 1; hsync = 0; vsync = 0; | 319 | blank = 1; hsync = 0; vsync = 0; crt = 0; |
314 | break; | 320 | break; |
315 | default: | 321 | default: |
316 | return -EINVAL; | 322 | return -EINVAL; |
317 | } | 323 | } |
318 | dcfg = readl(par->vid_regs + GX_DCFG); | 324 | dcfg = read_vp(par, VP_DCFG); |
319 | dcfg &= ~(GX_DCFG_DAC_BL_EN | 325 | dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN | |
320 | | GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN); | 326 | VP_DCFG_CRT_EN); |
321 | if (!blank) | 327 | if (!blank) |
322 | dcfg |= GX_DCFG_DAC_BL_EN; | 328 | dcfg |= VP_DCFG_DAC_BL_EN; |
323 | if (hsync) | 329 | if (hsync) |
324 | dcfg |= GX_DCFG_HSYNC_EN; | 330 | dcfg |= VP_DCFG_HSYNC_EN; |
325 | if (vsync) | 331 | if (vsync) |
326 | dcfg |= GX_DCFG_VSYNC_EN; | 332 | dcfg |= VP_DCFG_VSYNC_EN; |
327 | writel(dcfg, par->vid_regs + GX_DCFG); | 333 | if (crt) |
334 | dcfg |= VP_DCFG_CRT_EN; | ||
335 | write_vp(par, VP_DCFG, dcfg); | ||
328 | 336 | ||
329 | /* Power on/off flat panel. */ | 337 | /* Power on/off flat panel. */ |
330 | 338 | ||
331 | if (par->enable_crt == 0) { | 339 | if (par->enable_crt == 0) { |
332 | fp_pm = readl(par->vid_regs + GX_FP_PM); | 340 | fp_pm = read_fp(par, FP_PM); |
333 | if (blank_mode == FB_BLANK_POWERDOWN) | 341 | if (blank_mode == FB_BLANK_POWERDOWN) |
334 | fp_pm &= ~GX_FP_PM_P; | 342 | fp_pm &= ~FP_PM_P; |
335 | else | 343 | else |
336 | fp_pm |= GX_FP_PM_P; | 344 | fp_pm |= FP_PM_P; |
337 | writel(fp_pm, par->vid_regs + GX_FP_PM); | 345 | write_fp(par, FP_PM, fp_pm); |
338 | } | 346 | } |
339 | 347 | ||
340 | return 0; | 348 | return 0; |
341 | } | 349 | } |
342 | |||
343 | struct geode_vid_ops gx_vid_ops = { | ||
344 | .set_dclk = gx_set_dclk_frequency, | ||
345 | .configure_display = gx_configure_display, | ||
346 | .blank_display = gx_blank_display, | ||
347 | }; | ||
diff --git a/drivers/video/geode/video_gx.h b/drivers/video/geode/video_gx.h deleted file mode 100644 index ce28d8f382dc..000000000000 --- a/drivers/video/geode/video_gx.h +++ /dev/null | |||
@@ -1,72 +0,0 @@ | |||
1 | /* | ||
2 | * Geode GX video device | ||
3 | * | ||
4 | * Copyright (C) 2006 Arcom Control Systems Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | #ifndef __VIDEO_GX_H__ | ||
12 | #define __VIDEO_GX_H__ | ||
13 | |||
14 | extern struct geode_vid_ops gx_vid_ops; | ||
15 | |||
16 | /* GX Flatpanel control MSR */ | ||
17 | #define GX_VP_MSR_PAD_SELECT 0xC0002011 | ||
18 | #define GX_VP_PAD_SELECT_MASK 0x3FFFFFFF | ||
19 | #define GX_VP_PAD_SELECT_TFT 0x1FFFFFFF | ||
20 | |||
21 | /* Geode GX video processor registers */ | ||
22 | |||
23 | #define GX_DCFG 0x0008 | ||
24 | # define GX_DCFG_CRT_EN 0x00000001 | ||
25 | # define GX_DCFG_HSYNC_EN 0x00000002 | ||
26 | # define GX_DCFG_VSYNC_EN 0x00000004 | ||
27 | # define GX_DCFG_DAC_BL_EN 0x00000008 | ||
28 | # define GX_DCFG_FP_PWR_EN 0x00000040 | ||
29 | # define GX_DCFG_FP_DATA_EN 0x00000080 | ||
30 | # define GX_DCFG_CRT_HSYNC_POL 0x00000100 | ||
31 | # define GX_DCFG_CRT_VSYNC_POL 0x00000200 | ||
32 | # define GX_DCFG_CRT_SYNC_SKW_MASK 0x0001C000 | ||
33 | # define GX_DCFG_CRT_SYNC_SKW_DFLT 0x00010000 | ||
34 | # define GX_DCFG_VG_CK 0x00100000 | ||
35 | # define GX_DCFG_GV_GAM 0x00200000 | ||
36 | # define GX_DCFG_DAC_VREF 0x04000000 | ||
37 | |||
38 | /* Geode GX MISC video configuration */ | ||
39 | |||
40 | #define GX_MISC 0x50 | ||
41 | #define GX_MISC_GAM_EN 0x00000001 | ||
42 | #define GX_MISC_DAC_PWRDN 0x00000400 | ||
43 | #define GX_MISC_A_PWRDN 0x00000800 | ||
44 | |||
45 | /* Geode GX flat panel display control registers */ | ||
46 | |||
47 | #define GX_FP_PT1 0x0400 | ||
48 | #define GX_FP_PT1_VSIZE_MASK 0x7FF0000 | ||
49 | #define GX_FP_PT1_VSIZE_SHIFT 16 | ||
50 | |||
51 | #define GX_FP_PT2 0x408 | ||
52 | #define GX_FP_PT2_VSP (1 << 23) | ||
53 | #define GX_FP_PT2_HSP (1 << 22) | ||
54 | |||
55 | #define GX_FP_PM 0x410 | ||
56 | # define GX_FP_PM_P 0x01000000 | ||
57 | |||
58 | #define GX_FP_DFC 0x418 | ||
59 | |||
60 | /* Geode GX clock control MSRs */ | ||
61 | |||
62 | #define MSR_GLCP_SYS_RSTPLL 0x4c000014 | ||
63 | # define MSR_GLCP_SYS_RSTPLL_DOTPREDIV2 (0x0000000000000002ull) | ||
64 | # define MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 (0x0000000000000004ull) | ||
65 | # define MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 (0x0000000000000008ull) | ||
66 | |||
67 | #define MSR_GLCP_DOTPLL 0x4c000015 | ||
68 | # define MSR_GLCP_DOTPLL_DOTRESET (0x0000000000000001ull) | ||
69 | # define MSR_GLCP_DOTPLL_BYPASS (0x0000000000008000ull) | ||
70 | # define MSR_GLCP_DOTPLL_LOCK (0x0000000002000000ull) | ||
71 | |||
72 | #endif /* !__VIDEO_GX_H__ */ | ||