diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/geode/display_gx.h | 4 | ||||
-rw-r--r-- | drivers/video/geode/gxfb_core.c | 10 | ||||
-rw-r--r-- | drivers/video/geode/video_gx.c | 76 | ||||
-rw-r--r-- | drivers/video/geode/video_gx.h | 16 |
4 files changed, 95 insertions, 11 deletions
diff --git a/drivers/video/geode/display_gx.h b/drivers/video/geode/display_gx.h index e962c7679d08..ba0ccc82bf22 100644 --- a/drivers/video/geode/display_gx.h +++ b/drivers/video/geode/display_gx.h | |||
@@ -16,6 +16,10 @@ int gx_line_delta(int xres, int bpp); | |||
16 | 16 | ||
17 | extern struct geode_dc_ops gx_dc_ops; | 17 | extern struct geode_dc_ops gx_dc_ops; |
18 | 18 | ||
19 | /* MSR that tells us if a TFT or CRT is attached */ | ||
20 | #define GLD_MSR_CONFIG 0xC0002001 | ||
21 | #define GLD_MSR_CONFIG_FMT_FP 0x01 | ||
22 | |||
19 | /* Display controller registers */ | 23 | /* Display controller registers */ |
20 | 24 | ||
21 | #define DC_UNLOCK 0x00 | 25 | #define DC_UNLOCK 0x00 |
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c index 742fd04178c3..1e0d47ea0e43 100644 --- a/drivers/video/geode/gxfb_core.c +++ b/drivers/video/geode/gxfb_core.c | |||
@@ -308,6 +308,7 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i | |||
308 | struct geodefb_par *par; | 308 | struct geodefb_par *par; |
309 | struct fb_info *info; | 309 | struct fb_info *info; |
310 | int ret; | 310 | int ret; |
311 | unsigned long val; | ||
311 | 312 | ||
312 | info = gxfb_init_fbinfo(&pdev->dev); | 313 | info = gxfb_init_fbinfo(&pdev->dev); |
313 | if (!info) | 314 | if (!info) |
@@ -323,6 +324,15 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i | |||
323 | goto err; | 324 | goto err; |
324 | } | 325 | } |
325 | 326 | ||
327 | /* Figure out if this is a TFT or CRT part */ | ||
328 | |||
329 | rdmsrl(GLD_MSR_CONFIG, val); | ||
330 | |||
331 | if (val & GLD_MSR_CONFIG_FMT_FP) | ||
332 | par->enable_crt = 0; | ||
333 | else | ||
334 | par->enable_crt = 1; | ||
335 | |||
326 | ret = fb_find_mode(&info->var, info, mode_option, | 336 | ret = fb_find_mode(&info->var, info, mode_option, |
327 | gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16); | 337 | gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16); |
328 | if (ret == 0 || ret == 4) { | 338 | if (ret == 0 || ret == 4) { |
diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c index 616ce339c5fa..bee0741794a3 100644 --- a/drivers/video/geode/video_gx.c +++ b/drivers/video/geode/video_gx.c | |||
@@ -175,10 +175,62 @@ static void gx_set_dclk_frequency(struct fb_info *info) | |||
175 | } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK)); | 175 | } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK)); |
176 | } | 176 | } |
177 | 177 | ||
178 | static void | ||
179 | gx_configure_tft(struct fb_info *info) | ||
180 | { | ||
181 | struct geodefb_par *par = info->par; | ||
182 | unsigned long val; | ||
183 | unsigned long fp; | ||
184 | |||
185 | /* Set up the DF pad select MSR */ | ||
186 | |||
187 | rdmsrl(GX_VP_MSR_PAD_SELECT, val); | ||
188 | val &= ~GX_VP_PAD_SELECT_MASK; | ||
189 | val |= GX_VP_PAD_SELECT_TFT; | ||
190 | wrmsrl(GX_VP_MSR_PAD_SELECT, val); | ||
191 | |||
192 | /* Turn off the panel */ | ||
193 | |||
194 | fp = readl(par->vid_regs + GX_FP_PM); | ||
195 | fp &= ~GX_FP_PM_P; | ||
196 | writel(fp, par->vid_regs + GX_FP_PM); | ||
197 | |||
198 | /* Set timing 1 */ | ||
199 | |||
200 | fp = readl(par->vid_regs + GX_FP_PT1); | ||
201 | fp &= GX_FP_PT1_VSIZE_MASK; | ||
202 | fp |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT; | ||
203 | writel(fp, par->vid_regs + GX_FP_PT1); | ||
204 | |||
205 | /* Timing 2 */ | ||
206 | /* Set bits that are always on for TFT */ | ||
207 | |||
208 | fp = 0x0F100000; | ||
209 | |||
210 | /* Add sync polarity */ | ||
211 | |||
212 | if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) | ||
213 | fp |= GX_FP_PT2_VSP; | ||
214 | |||
215 | if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) | ||
216 | fp |= GX_FP_PT2_HSP; | ||
217 | |||
218 | writel(fp, par->vid_regs + GX_FP_PT2); | ||
219 | |||
220 | /* Set the dither control */ | ||
221 | writel(0x70, par->vid_regs + GX_FP_DFC); | ||
222 | |||
223 | /* Turn on the device */ | ||
224 | |||
225 | fp = readl(par->vid_regs + GX_FP_PM); | ||
226 | fp |= GX_FP_PM_P; | ||
227 | writel(fp, par->vid_regs + GX_FP_PM); | ||
228 | } | ||
229 | |||
178 | static void gx_configure_display(struct fb_info *info) | 230 | static void gx_configure_display(struct fb_info *info) |
179 | { | 231 | { |
180 | struct geodefb_par *par = info->par; | 232 | struct geodefb_par *par = info->par; |
181 | u32 dcfg, fp_pm, misc; | 233 | u32 dcfg, misc; |
182 | 234 | ||
183 | /* Set up the MISC register */ | 235 | /* Set up the MISC register */ |
184 | 236 | ||
@@ -222,11 +274,10 @@ static void gx_configure_display(struct fb_info *info) | |||
222 | 274 | ||
223 | writel(dcfg, par->vid_regs + GX_DCFG); | 275 | writel(dcfg, par->vid_regs + GX_DCFG); |
224 | 276 | ||
225 | /* Power on flat panel. */ | 277 | /* Set up the flat panel (if it is enabled) */ |
226 | 278 | ||
227 | fp_pm = readl(par->vid_regs + GX_FP_PM); | 279 | if (par->enable_crt == 0) |
228 | fp_pm |= GX_FP_PM_P; | 280 | gx_configure_tft(info); |
229 | writel(fp_pm, par->vid_regs + GX_FP_PM); | ||
230 | } | 281 | } |
231 | 282 | ||
232 | static int gx_blank_display(struct fb_info *info, int blank_mode) | 283 | static int gx_blank_display(struct fb_info *info, int blank_mode) |
@@ -267,12 +318,15 @@ static int gx_blank_display(struct fb_info *info, int blank_mode) | |||
267 | writel(dcfg, par->vid_regs + GX_DCFG); | 318 | writel(dcfg, par->vid_regs + GX_DCFG); |
268 | 319 | ||
269 | /* Power on/off flat panel. */ | 320 | /* Power on/off flat panel. */ |
270 | fp_pm = readl(par->vid_regs + GX_FP_PM); | 321 | |
271 | if (blank_mode == FB_BLANK_POWERDOWN) | 322 | if (par->enable_crt == 0) { |
272 | fp_pm &= ~GX_FP_PM_P; | 323 | fp_pm = readl(par->vid_regs + GX_FP_PM); |
273 | else | 324 | if (blank_mode == FB_BLANK_POWERDOWN) |
274 | fp_pm |= GX_FP_PM_P; | 325 | fp_pm &= ~GX_FP_PM_P; |
275 | writel(fp_pm, par->vid_regs + GX_FP_PM); | 326 | else |
327 | fp_pm |= GX_FP_PM_P; | ||
328 | writel(fp_pm, par->vid_regs + GX_FP_PM); | ||
329 | } | ||
276 | 330 | ||
277 | return 0; | 331 | return 0; |
278 | } | 332 | } |
diff --git a/drivers/video/geode/video_gx.h b/drivers/video/geode/video_gx.h index 238181a7d536..8f1e85bfa945 100644 --- a/drivers/video/geode/video_gx.h +++ b/drivers/video/geode/video_gx.h | |||
@@ -13,6 +13,11 @@ | |||
13 | 13 | ||
14 | extern struct geode_vid_ops gx_vid_ops; | 14 | extern struct geode_vid_ops gx_vid_ops; |
15 | 15 | ||
16 | /* GX Flatpanel control MSR */ | ||
17 | #define GX_VP_MSR_PAD_SELECT 0x2011 | ||
18 | #define GX_VP_PAD_SELECT_MASK 0x3FFFFFFF | ||
19 | #define GX_VP_PAD_SELECT_TFT 0x1FFFFFFF | ||
20 | |||
16 | /* Geode GX video processor registers */ | 21 | /* Geode GX video processor registers */ |
17 | 22 | ||
18 | #define GX_DCFG 0x0008 | 23 | #define GX_DCFG 0x0008 |
@@ -36,9 +41,20 @@ extern struct geode_vid_ops gx_vid_ops; | |||
36 | #define GX_MISC_A_PWRDN 0x00000800 | 41 | #define GX_MISC_A_PWRDN 0x00000800 |
37 | 42 | ||
38 | /* Geode GX flat panel display control registers */ | 43 | /* Geode GX flat panel display control registers */ |
44 | |||
45 | #define GX_FP_PT1 0x0400 | ||
46 | #define GX_FP_PT1_VSIZE_MASK 0x7FF0000 | ||
47 | #define GX_FP_PT1_VSIZE_SHIFT 16 | ||
48 | |||
49 | #define GX_FP_PT2 0x408 | ||
50 | #define GX_FP_PT2_VSP (1 << 23) | ||
51 | #define GX_FP_PT2_HSP (1 << 22) | ||
52 | |||
39 | #define GX_FP_PM 0x410 | 53 | #define GX_FP_PM 0x410 |
40 | # define GX_FP_PM_P 0x01000000 | 54 | # define GX_FP_PM_P 0x01000000 |
41 | 55 | ||
56 | #define GX_FP_DFC 0x418 | ||
57 | |||
42 | /* Geode GX clock control MSRs */ | 58 | /* Geode GX clock control MSRs */ |
43 | 59 | ||
44 | #define MSR_GLCP_SYS_RSTPLL 0x4c000014 | 60 | #define MSR_GLCP_SYS_RSTPLL 0x4c000014 |