aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/neofb.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-10-03 13:28:46 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-03 13:28:46 -0400
commitf68ec0c24755e5cdb779be6240925f2175311d84 (patch)
treea7b7128e61a8456385d82bd1c7ca5f14eecbf2ca /drivers/video/neofb.c
parent98920dc3d1113b883cbc73e3293446d3525c6042 (diff)
parent94aca1dac6f6d21f4b07e4864baf7768cabcc6e7 (diff)
Merge commit 'v2.6.27-rc8' into x86/setup
Diffstat (limited to 'drivers/video/neofb.c')
-rw-r--r--drivers/video/neofb.c215
1 files changed, 76 insertions, 139 deletions
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 5246b0402d76..25172b2a2a94 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -201,7 +201,6 @@ static int neoFindMode(int xres, int yres, int depth)
201 * 201 *
202 * Determine the closest clock frequency to the one requested. 202 * Determine the closest clock frequency to the one requested.
203 */ 203 */
204#define REF_FREQ 0xe517 /* 14.31818 in 20.12 fixed point */
205#define MAX_N 127 204#define MAX_N 127
206#define MAX_D 31 205#define MAX_D 31
207#define MAX_F 1 206#define MAX_F 1
@@ -211,27 +210,24 @@ static void neoCalcVCLK(const struct fb_info *info,
211{ 210{
212 int n, d, f; 211 int n, d, f;
213 int n_best = 0, d_best = 0, f_best = 0; 212 int n_best = 0, d_best = 0, f_best = 0;
214 long f_best_diff = (0x7ffff << 12); /* 20.12 */ 213 long f_best_diff = 0x7ffff;
215 long f_target = (freq << 12) / 1000; /* 20.12 */
216 214
217 for (f = 0; f <= MAX_F; f++) 215 for (f = 0; f <= MAX_F; f++)
218 for (n = 0; n <= MAX_N; n++) 216 for (d = 0; d <= MAX_D; d++)
219 for (d = 0; d <= MAX_D; d++) { 217 for (n = 0; n <= MAX_N; n++) {
220 long f_out; /* 20.12 */ 218 long f_out;
221 long f_diff; /* 20.12 */ 219 long f_diff;
222 220
223 f_out = 221 f_out = ((14318 * (n + 1)) / (d + 1)) >> f;
224 ((((n + 1) << 12) / ((d + 222 f_diff = abs(f_out - freq);
225 1) * 223 if (f_diff <= f_best_diff) {
226 (1 << f))) >> 12)
227 * REF_FREQ;
228 f_diff = abs(f_out - f_target);
229 if (f_diff < f_best_diff) {
230 f_best_diff = f_diff; 224 f_best_diff = f_diff;
231 n_best = n; 225 n_best = n;
232 d_best = d; 226 d_best = d;
233 f_best = f; 227 f_best = f;
234 } 228 }
229 if (f_out > freq)
230 break;
235 } 231 }
236 232
237 if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 || 233 if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
@@ -248,11 +244,11 @@ static void neoCalcVCLK(const struct fb_info *info,
248 par->VCLK3Denominator = d_best; 244 par->VCLK3Denominator = d_best;
249 245
250#ifdef NEOFB_DEBUG 246#ifdef NEOFB_DEBUG
251 printk("neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%d\n", 247 printk(KERN_DEBUG "neoVCLK: f:%ld NumLow=%d NumHi=%d Den=%d Df=%ld\n",
252 f_target >> 12, 248 freq,
253 par->VCLK3NumeratorLow, 249 par->VCLK3NumeratorLow,
254 par->VCLK3NumeratorHigh, 250 par->VCLK3NumeratorHigh,
255 par->VCLK3Denominator, f_best_diff >> 12); 251 par->VCLK3Denominator, f_best_diff);
256#endif 252#endif
257} 253}
258 254
@@ -263,15 +259,20 @@ static void neoCalcVCLK(const struct fb_info *info,
263 */ 259 */
264 260
265static int vgaHWInit(const struct fb_var_screeninfo *var, 261static int vgaHWInit(const struct fb_var_screeninfo *var,
266 const struct fb_info *info, 262 struct neofb_par *par)
267 struct neofb_par *par, struct xtimings *timings)
268{ 263{
264 int hsync_end = var->xres + var->right_margin + var->hsync_len;
265 int htotal = (hsync_end + var->left_margin) >> 3;
266 int vsync_start = var->yres + var->lower_margin;
267 int vsync_end = vsync_start + var->vsync_len;
268 int vtotal = vsync_end + var->upper_margin;
269
269 par->MiscOutReg = 0x23; 270 par->MiscOutReg = 0x23;
270 271
271 if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT)) 272 if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
272 par->MiscOutReg |= 0x40; 273 par->MiscOutReg |= 0x40;
273 274
274 if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT)) 275 if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
275 par->MiscOutReg |= 0x80; 276 par->MiscOutReg |= 0x80;
276 277
277 /* 278 /*
@@ -286,25 +287,25 @@ static int vgaHWInit(const struct fb_var_screeninfo *var,
286 /* 287 /*
287 * CRTC Controller 288 * CRTC Controller
288 */ 289 */
289 par->CRTC[0] = (timings->HTotal >> 3) - 5; 290 par->CRTC[0] = htotal - 5;
290 par->CRTC[1] = (timings->HDisplay >> 3) - 1; 291 par->CRTC[1] = (var->xres >> 3) - 1;
291 par->CRTC[2] = (timings->HDisplay >> 3) - 1; 292 par->CRTC[2] = (var->xres >> 3) - 1;
292 par->CRTC[3] = (((timings->HTotal >> 3) - 1) & 0x1F) | 0x80; 293 par->CRTC[3] = ((htotal - 1) & 0x1F) | 0x80;
293 par->CRTC[4] = (timings->HSyncStart >> 3); 294 par->CRTC[4] = ((var->xres + var->right_margin) >> 3);
294 par->CRTC[5] = ((((timings->HTotal >> 3) - 1) & 0x20) << 2) 295 par->CRTC[5] = (((htotal - 1) & 0x20) << 2)
295 | (((timings->HSyncEnd >> 3)) & 0x1F); 296 | (((hsync_end >> 3)) & 0x1F);
296 par->CRTC[6] = (timings->VTotal - 2) & 0xFF; 297 par->CRTC[6] = (vtotal - 2) & 0xFF;
297 par->CRTC[7] = (((timings->VTotal - 2) & 0x100) >> 8) 298 par->CRTC[7] = (((vtotal - 2) & 0x100) >> 8)
298 | (((timings->VDisplay - 1) & 0x100) >> 7) 299 | (((var->yres - 1) & 0x100) >> 7)
299 | ((timings->VSyncStart & 0x100) >> 6) 300 | ((vsync_start & 0x100) >> 6)
300 | (((timings->VDisplay - 1) & 0x100) >> 5) 301 | (((var->yres - 1) & 0x100) >> 5)
301 | 0x10 | (((timings->VTotal - 2) & 0x200) >> 4) 302 | 0x10 | (((vtotal - 2) & 0x200) >> 4)
302 | (((timings->VDisplay - 1) & 0x200) >> 3) 303 | (((var->yres - 1) & 0x200) >> 3)
303 | ((timings->VSyncStart & 0x200) >> 2); 304 | ((vsync_start & 0x200) >> 2);
304 par->CRTC[8] = 0x00; 305 par->CRTC[8] = 0x00;
305 par->CRTC[9] = (((timings->VDisplay - 1) & 0x200) >> 4) | 0x40; 306 par->CRTC[9] = (((var->yres - 1) & 0x200) >> 4) | 0x40;
306 307
307 if (timings->dblscan) 308 if (var->vmode & FB_VMODE_DOUBLE)
308 par->CRTC[9] |= 0x80; 309 par->CRTC[9] |= 0x80;
309 310
310 par->CRTC[10] = 0x00; 311 par->CRTC[10] = 0x00;
@@ -313,13 +314,13 @@ static int vgaHWInit(const struct fb_var_screeninfo *var,
313 par->CRTC[13] = 0x00; 314 par->CRTC[13] = 0x00;
314 par->CRTC[14] = 0x00; 315 par->CRTC[14] = 0x00;
315 par->CRTC[15] = 0x00; 316 par->CRTC[15] = 0x00;
316 par->CRTC[16] = timings->VSyncStart & 0xFF; 317 par->CRTC[16] = vsync_start & 0xFF;
317 par->CRTC[17] = (timings->VSyncEnd & 0x0F) | 0x20; 318 par->CRTC[17] = (vsync_end & 0x0F) | 0x20;
318 par->CRTC[18] = (timings->VDisplay - 1) & 0xFF; 319 par->CRTC[18] = (var->yres - 1) & 0xFF;
319 par->CRTC[19] = var->xres_virtual >> 4; 320 par->CRTC[19] = var->xres_virtual >> 4;
320 par->CRTC[20] = 0x00; 321 par->CRTC[20] = 0x00;
321 par->CRTC[21] = (timings->VDisplay - 1) & 0xFF; 322 par->CRTC[21] = (var->yres - 1) & 0xFF;
322 par->CRTC[22] = (timings->VTotal - 1) & 0xFF; 323 par->CRTC[22] = (vtotal - 1) & 0xFF;
323 par->CRTC[23] = 0xC3; 324 par->CRTC[23] = 0xC3;
324 par->CRTC[24] = 0xFF; 325 par->CRTC[24] = 0xFF;
325 326
@@ -483,7 +484,8 @@ static inline int neo2200_sync(struct fb_info *info)
483{ 484{
484 struct neofb_par *par = info->par; 485 struct neofb_par *par = info->par;
485 486
486 while (readl(&par->neo2200->bltStat) & 1); 487 while (readl(&par->neo2200->bltStat) & 1)
488 cpu_relax();
487 return 0; 489 return 0;
488} 490}
489 491
@@ -591,34 +593,14 @@ static int
591neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 593neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
592{ 594{
593 struct neofb_par *par = info->par; 595 struct neofb_par *par = info->par;
594 unsigned int pixclock = var->pixclock;
595 struct xtimings timings;
596 int memlen, vramlen; 596 int memlen, vramlen;
597 int mode_ok = 0; 597 int mode_ok = 0;
598 598
599 DBG("neofb_check_var"); 599 DBG("neofb_check_var");
600 600
601 if (!pixclock) 601 if (PICOS2KHZ(var->pixclock) > par->maxClock)
602 pixclock = 10000; /* 10ns = 100MHz */
603 timings.pixclock = 1000000000 / pixclock;
604 if (timings.pixclock < 1)
605 timings.pixclock = 1;
606
607 if (timings.pixclock > par->maxClock)
608 return -EINVAL; 602 return -EINVAL;
609 603
610 timings.dblscan = var->vmode & FB_VMODE_DOUBLE;
611 timings.interlaced = var->vmode & FB_VMODE_INTERLACED;
612 timings.HDisplay = var->xres;
613 timings.HSyncStart = timings.HDisplay + var->right_margin;
614 timings.HSyncEnd = timings.HSyncStart + var->hsync_len;
615 timings.HTotal = timings.HSyncEnd + var->left_margin;
616 timings.VDisplay = var->yres;
617 timings.VSyncStart = timings.VDisplay + var->lower_margin;
618 timings.VSyncEnd = timings.VSyncStart + var->vsync_len;
619 timings.VTotal = timings.VSyncEnd + var->upper_margin;
620 timings.sync = var->sync;
621
622 /* Is the mode larger than the LCD panel? */ 604 /* Is the mode larger than the LCD panel? */
623 if (par->internal_display && 605 if (par->internal_display &&
624 ((var->xres > par->NeoPanelWidth) || 606 ((var->xres > par->NeoPanelWidth) ||
@@ -759,11 +741,11 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
759static int neofb_set_par(struct fb_info *info) 741static int neofb_set_par(struct fb_info *info)
760{ 742{
761 struct neofb_par *par = info->par; 743 struct neofb_par *par = info->par;
762 struct xtimings timings;
763 unsigned char temp; 744 unsigned char temp;
764 int i, clock_hi = 0; 745 int i, clock_hi = 0;
765 int lcd_stretch; 746 int lcd_stretch;
766 int hoffset, voffset; 747 int hoffset, voffset;
748 int vsync_start, vtotal;
767 749
768 DBG("neofb_set_par"); 750 DBG("neofb_set_par");
769 751
@@ -771,28 +753,15 @@ static int neofb_set_par(struct fb_info *info)
771 753
772 vgaHWProtect(1); /* Blank the screen */ 754 vgaHWProtect(1); /* Blank the screen */
773 755
774 timings.dblscan = info->var.vmode & FB_VMODE_DOUBLE; 756 vsync_start = info->var.yres + info->var.lower_margin;
775 timings.interlaced = info->var.vmode & FB_VMODE_INTERLACED; 757 vtotal = vsync_start + info->var.vsync_len + info->var.upper_margin;
776 timings.HDisplay = info->var.xres;
777 timings.HSyncStart = timings.HDisplay + info->var.right_margin;
778 timings.HSyncEnd = timings.HSyncStart + info->var.hsync_len;
779 timings.HTotal = timings.HSyncEnd + info->var.left_margin;
780 timings.VDisplay = info->var.yres;
781 timings.VSyncStart = timings.VDisplay + info->var.lower_margin;
782 timings.VSyncEnd = timings.VSyncStart + info->var.vsync_len;
783 timings.VTotal = timings.VSyncEnd + info->var.upper_margin;
784 timings.sync = info->var.sync;
785 timings.pixclock = PICOS2KHZ(info->var.pixclock);
786
787 if (timings.pixclock < 1)
788 timings.pixclock = 1;
789 758
790 /* 759 /*
791 * This will allocate the datastructure and initialize all of the 760 * This will allocate the datastructure and initialize all of the
792 * generic VGA registers. 761 * generic VGA registers.
793 */ 762 */
794 763
795 if (vgaHWInit(&info->var, info, par, &timings)) 764 if (vgaHWInit(&info->var, par))
796 return -EINVAL; 765 return -EINVAL;
797 766
798 /* 767 /*
@@ -831,10 +800,10 @@ static int neofb_set_par(struct fb_info *info)
831 par->ExtCRTDispAddr = 0x10; 800 par->ExtCRTDispAddr = 0x10;
832 801
833 /* Vertical Extension */ 802 /* Vertical Extension */
834 par->VerticalExt = (((timings.VTotal - 2) & 0x400) >> 10) 803 par->VerticalExt = (((vtotal - 2) & 0x400) >> 10)
835 | (((timings.VDisplay - 1) & 0x400) >> 9) 804 | (((info->var.yres - 1) & 0x400) >> 9)
836 | (((timings.VSyncStart) & 0x400) >> 8) 805 | (((vsync_start) & 0x400) >> 8)
837 | (((timings.VSyncStart) & 0x400) >> 7); 806 | (((vsync_start) & 0x400) >> 7);
838 807
839 /* Fast write bursts on unless disabled. */ 808 /* Fast write bursts on unless disabled. */
840 if (par->pci_burst) 809 if (par->pci_burst)
@@ -995,7 +964,7 @@ static int neofb_set_par(struct fb_info *info)
995 * Calculate the VCLK that most closely matches the requested dot 964 * Calculate the VCLK that most closely matches the requested dot
996 * clock. 965 * clock.
997 */ 966 */
998 neoCalcVCLK(info, par, timings.pixclock); 967 neoCalcVCLK(info, par, PICOS2KHZ(info->var.pixclock));
999 968
1000 /* Since we program the clocks ourselves, always use VCLK3. */ 969 /* Since we program the clocks ourselves, always use VCLK3. */
1001 par->MiscOutReg |= 0x0C; 970 par->MiscOutReg |= 0x0C;
@@ -1927,9 +1896,6 @@ static int __devinit neo_init_hw(struct fb_info *info)
1927 int maxClock = 65000; 1896 int maxClock = 65000;
1928 int CursorMem = 1024; 1897 int CursorMem = 1024;
1929 int CursorOff = 0x100; 1898 int CursorOff = 0x100;
1930 int linearSize = 1024;
1931 int maxWidth = 1024;
1932 int maxHeight = 1024;
1933 1899
1934 DBG("neo_init_hw"); 1900 DBG("neo_init_hw");
1935 1901
@@ -1948,81 +1914,52 @@ static int __devinit neo_init_hw(struct fb_info *info)
1948 case FB_ACCEL_NEOMAGIC_NM2070: 1914 case FB_ACCEL_NEOMAGIC_NM2070:
1949 videoRam = 896; 1915 videoRam = 896;
1950 maxClock = 65000; 1916 maxClock = 65000;
1951 CursorMem = 2048;
1952 CursorOff = 0x100;
1953 linearSize = 1024;
1954 maxWidth = 1024;
1955 maxHeight = 1024;
1956 break; 1917 break;
1957 case FB_ACCEL_NEOMAGIC_NM2090: 1918 case FB_ACCEL_NEOMAGIC_NM2090:
1958 case FB_ACCEL_NEOMAGIC_NM2093: 1919 case FB_ACCEL_NEOMAGIC_NM2093:
1959 videoRam = 1152;
1960 maxClock = 80000;
1961 CursorMem = 2048;
1962 CursorOff = 0x100;
1963 linearSize = 2048;
1964 maxWidth = 1024;
1965 maxHeight = 1024;
1966 break;
1967 case FB_ACCEL_NEOMAGIC_NM2097: 1920 case FB_ACCEL_NEOMAGIC_NM2097:
1968 videoRam = 1152; 1921 videoRam = 1152;
1969 maxClock = 80000; 1922 maxClock = 80000;
1970 CursorMem = 1024;
1971 CursorOff = 0x100;
1972 linearSize = 2048;
1973 maxWidth = 1024;
1974 maxHeight = 1024;
1975 break; 1923 break;
1976 case FB_ACCEL_NEOMAGIC_NM2160: 1924 case FB_ACCEL_NEOMAGIC_NM2160:
1977 videoRam = 2048; 1925 videoRam = 2048;
1978 maxClock = 90000; 1926 maxClock = 90000;
1979 CursorMem = 1024;
1980 CursorOff = 0x100;
1981 linearSize = 2048;
1982 maxWidth = 1024;
1983 maxHeight = 1024;
1984 break; 1927 break;
1985 case FB_ACCEL_NEOMAGIC_NM2200: 1928 case FB_ACCEL_NEOMAGIC_NM2200:
1986 videoRam = 2560; 1929 videoRam = 2560;
1987 maxClock = 110000; 1930 maxClock = 110000;
1988 CursorMem = 1024;
1989 CursorOff = 0x1000;
1990 linearSize = 4096;
1991 maxWidth = 1280;
1992 maxHeight = 1024; /* ???? */
1993
1994 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
1995 break; 1931 break;
1996 case FB_ACCEL_NEOMAGIC_NM2230: 1932 case FB_ACCEL_NEOMAGIC_NM2230:
1997 videoRam = 3008; 1933 videoRam = 3008;
1998 maxClock = 110000; 1934 maxClock = 110000;
1999 CursorMem = 1024;
2000 CursorOff = 0x1000;
2001 linearSize = 4096;
2002 maxWidth = 1280;
2003 maxHeight = 1024; /* ???? */
2004
2005 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
2006 break; 1935 break;
2007 case FB_ACCEL_NEOMAGIC_NM2360: 1936 case FB_ACCEL_NEOMAGIC_NM2360:
2008 videoRam = 4096; 1937 videoRam = 4096;
2009 maxClock = 110000; 1938 maxClock = 110000;
2010 CursorMem = 1024;
2011 CursorOff = 0x1000;
2012 linearSize = 4096;
2013 maxWidth = 1280;
2014 maxHeight = 1024; /* ???? */
2015
2016 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
2017 break; 1939 break;
2018 case FB_ACCEL_NEOMAGIC_NM2380: 1940 case FB_ACCEL_NEOMAGIC_NM2380:
2019 videoRam = 6144; 1941 videoRam = 6144;
2020 maxClock = 110000; 1942 maxClock = 110000;
1943 break;
1944 }
1945 switch (info->fix.accel) {
1946 case FB_ACCEL_NEOMAGIC_NM2070:
1947 case FB_ACCEL_NEOMAGIC_NM2090:
1948 case FB_ACCEL_NEOMAGIC_NM2093:
1949 CursorMem = 2048;
1950 CursorOff = 0x100;
1951 break;
1952 case FB_ACCEL_NEOMAGIC_NM2097:
1953 case FB_ACCEL_NEOMAGIC_NM2160:
1954 CursorMem = 1024;
1955 CursorOff = 0x100;
1956 break;
1957 case FB_ACCEL_NEOMAGIC_NM2200:
1958 case FB_ACCEL_NEOMAGIC_NM2230:
1959 case FB_ACCEL_NEOMAGIC_NM2360:
1960 case FB_ACCEL_NEOMAGIC_NM2380:
2021 CursorMem = 1024; 1961 CursorMem = 1024;
2022 CursorOff = 0x1000; 1962 CursorOff = 0x1000;
2023 linearSize = 8192;
2024 maxWidth = 1280;
2025 maxHeight = 1024; /* ???? */
2026 1963
2027 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase; 1964 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
2028 break; 1965 break;
@@ -2036,7 +1973,7 @@ static int __devinit neo_init_hw(struct fb_info *info)
2036*/ 1973*/
2037 par->maxClock = maxClock; 1974 par->maxClock = maxClock;
2038 par->cursorOff = CursorOff; 1975 par->cursorOff = CursorOff;
2039 return ((videoRam * 1024)); 1976 return videoRam * 1024;
2040} 1977}
2041 1978
2042 1979