aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-03-27 02:18:09 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-03-27 02:18:09 -0400
commit37db9a348ad4250bd6009cec1bb108a653d1d220 (patch)
tree1e8785cfb31001481527933bcafe172c740d2495 /drivers
parent74e61dee2a98b5e538ee1448ca803fc0ad8e307f (diff)
[VIDEO] ffb: Fix two DAC handling bugs.
The determination of whether the DAC has inverted cursor logic is broken, import the version checks the X.org driver uses to fix this. Next, when we change the timing generator, borrow code from X.org that does 10 NOP reads of the timing generator register afterwards to make sure the video-enable transition occurs cleanly. Finally, use macros for the DAC registers and fields in order to provide documentation for the next person who reads this code. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/ffb.c84
1 files changed, 60 insertions, 24 deletions
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 15854aec3180..1d4e8354b561 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -336,14 +336,30 @@ struct ffb_dac {
336 u32 value2; 336 u32 value2;
337}; 337};
338 338
339#define FFB_DAC_UCTRL 0x1001 /* User Control */
340#define FFB_DAC_UCTRL_MANREV 0x00000f00 /* 4-bit Manufacturing Revision */
341#define FFB_DAC_UCTRL_MANREV_SHIFT 8
342#define FFB_DAC_TGEN 0x6000 /* Timing Generator */
343#define FFB_DAC_TGEN_VIDE 0x00000001 /* Video Enable */
344#define FFB_DAC_DID 0x8000 /* Device Identification */
345#define FFB_DAC_DID_PNUM 0x0ffff000 /* Device Part Number */
346#define FFB_DAC_DID_PNUM_SHIFT 12
347#define FFB_DAC_DID_REV 0xf0000000 /* Device Revision */
348#define FFB_DAC_DID_REV_SHIFT 28
349
350#define FFB_DAC_CUR_CTRL 0x100
351#define FFB_DAC_CUR_CTRL_P0 0x00000001
352#define FFB_DAC_CUR_CTRL_P1 0x00000002
353
339struct ffb_par { 354struct ffb_par {
340 spinlock_t lock; 355 spinlock_t lock;
341 struct ffb_fbc __iomem *fbc; 356 struct ffb_fbc __iomem *fbc;
342 struct ffb_dac __iomem *dac; 357 struct ffb_dac __iomem *dac;
343 358
344 u32 flags; 359 u32 flags;
345#define FFB_FLAG_AFB 0x00000001 360#define FFB_FLAG_AFB 0x00000001 /* AFB m3 or m6 */
346#define FFB_FLAG_BLANKED 0x00000002 361#define FFB_FLAG_BLANKED 0x00000002 /* screen is blanked */
362#define FFB_FLAG_INVCURSOR 0x00000004 /* DAC has inverted cursor logic */
347 363
348 u32 fg_cache __attribute__((aligned (8))); 364 u32 fg_cache __attribute__((aligned (8)));
349 u32 bg_cache; 365 u32 bg_cache;
@@ -354,7 +370,6 @@ struct ffb_par {
354 unsigned long physbase; 370 unsigned long physbase;
355 unsigned long fbsize; 371 unsigned long fbsize;
356 372
357 int dac_rev;
358 int board_type; 373 int board_type;
359}; 374};
360 375
@@ -426,11 +441,12 @@ static void ffb_switch_from_graph(struct ffb_par *par)
426 FFBWait(par); 441 FFBWait(par);
427 442
428 /* Disable cursor. */ 443 /* Disable cursor. */
429 upa_writel(0x100, &dac->type2); 444 upa_writel(FFB_DAC_CUR_CTRL, &dac->type2);
430 if (par->dac_rev <= 2) 445 if (par->flags & FFB_FLAG_INVCURSOR)
431 upa_writel(0, &dac->value2); 446 upa_writel(0, &dac->value2);
432 else 447 else
433 upa_writel(3, &dac->value2); 448 upa_writel((FFB_DAC_CUR_CTRL_P0 |
449 FFB_DAC_CUR_CTRL_P1), &dac->value2);
434 450
435 spin_unlock_irqrestore(&par->lock, flags); 451 spin_unlock_irqrestore(&par->lock, flags);
436} 452}
@@ -664,18 +680,18 @@ ffb_blank(int blank, struct fb_info *info)
664 struct ffb_par *par = (struct ffb_par *) info->par; 680 struct ffb_par *par = (struct ffb_par *) info->par;
665 struct ffb_dac __iomem *dac = par->dac; 681 struct ffb_dac __iomem *dac = par->dac;
666 unsigned long flags; 682 unsigned long flags;
667 u32 tmp; 683 u32 val;
684 int i;
668 685
669 spin_lock_irqsave(&par->lock, flags); 686 spin_lock_irqsave(&par->lock, flags);
670 687
671 FFBWait(par); 688 FFBWait(par);
672 689
690 upa_writel(FFB_DAC_TGEN, &dac->type);
691 val = upa_readl(&dac->value);
673 switch (blank) { 692 switch (blank) {
674 case FB_BLANK_UNBLANK: /* Unblanking */ 693 case FB_BLANK_UNBLANK: /* Unblanking */
675 upa_writel(0x6000, &dac->type); 694 val |= FFB_DAC_TGEN_VIDE;
676 tmp = (upa_readl(&dac->value) | 0x1);
677 upa_writel(0x6000, &dac->type);
678 upa_writel(tmp, &dac->value);
679 par->flags &= ~FFB_FLAG_BLANKED; 695 par->flags &= ~FFB_FLAG_BLANKED;
680 break; 696 break;
681 697
@@ -683,13 +699,16 @@ ffb_blank(int blank, struct fb_info *info)
683 case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */ 699 case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
684 case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */ 700 case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
685 case FB_BLANK_POWERDOWN: /* Poweroff */ 701 case FB_BLANK_POWERDOWN: /* Poweroff */
686 upa_writel(0x6000, &dac->type); 702 val &= ~FFB_DAC_TGEN_VIDE;
687 tmp = (upa_readl(&dac->value) & ~0x1);
688 upa_writel(0x6000, &dac->type);
689 upa_writel(tmp, &dac->value);
690 par->flags |= FFB_FLAG_BLANKED; 703 par->flags |= FFB_FLAG_BLANKED;
691 break; 704 break;
692 } 705 }
706 upa_writel(FFB_DAC_TGEN, &dac->type);
707 upa_writel(val, &dac->value);
708 for (i = 0; i < 10; i++) {
709 upa_writel(FFB_DAC_TGEN, &dac->type);
710 upa_readl(&dac->value);
711 }
693 712
694 spin_unlock_irqrestore(&par->lock, flags); 713 spin_unlock_irqrestore(&par->lock, flags);
695 714
@@ -894,6 +913,7 @@ static int ffb_init_one(struct of_device *op)
894 struct ffb_dac __iomem *dac; 913 struct ffb_dac __iomem *dac;
895 struct all_info *all; 914 struct all_info *all;
896 int err; 915 int err;
916 u32 dac_pnum, dac_rev, dac_mrev;
897 917
898 all = kzalloc(sizeof(*all), GFP_KERNEL); 918 all = kzalloc(sizeof(*all), GFP_KERNEL);
899 if (!all) 919 if (!all)
@@ -948,17 +968,31 @@ static int ffb_init_one(struct of_device *op)
948 if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) 968 if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
949 upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr); 969 upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
950 970
951 ffb_switch_from_graph(&all->par);
952
953 dac = all->par.dac; 971 dac = all->par.dac;
954 upa_writel(0x8000, &dac->type); 972 upa_writel(FFB_DAC_DID, &dac->type);
955 all->par.dac_rev = upa_readl(&dac->value) >> 0x1c; 973 dac_pnum = upa_readl(&dac->value);
974 dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT;
975 dac_pnum = (dac_pnum & FFB_DAC_DID_PNUM) >> FFB_DAC_DID_PNUM_SHIFT;
976
977 upa_writel(FFB_DAC_UCTRL, &dac->type);
978 dac_mrev = upa_readl(&dac->value);
979 dac_mrev = (dac_mrev & FFB_DAC_UCTRL_MANREV) >>
980 FFB_DAC_UCTRL_MANREV_SHIFT;
956 981
957 /* Elite3D has different DAC revision numbering, and no DAC revisions 982 /* Elite3D has different DAC revision numbering, and no DAC revisions
958 * have the reversed meaning of cursor enable. 983 * have the reversed meaning of cursor enable. Otherwise, Pacifica 1
984 * ramdacs with manufacturing revision less than 3 have inverted
985 * cursor logic. We identify Pacifica 1 as not Pacifica 2, the
986 * latter having a part number value of 0x236e.
959 */ 987 */
960 if (all->par.flags & FFB_FLAG_AFB) 988 if ((all->par.flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) {
961 all->par.dac_rev = 10; 989 all->par.flags &= ~FFB_FLAG_INVCURSOR;
990 } else {
991 if (dac_mrev < 3)
992 all->par.flags |= FFB_FLAG_INVCURSOR;
993 }
994
995 ffb_switch_from_graph(&all->par);
962 996
963 /* Unblank it just to be sure. When there are multiple 997 /* Unblank it just to be sure. When there are multiple
964 * FFB/AFB cards in the system, or it is not the OBP 998 * FFB/AFB cards in the system, or it is not the OBP
@@ -993,10 +1027,12 @@ static int ffb_init_one(struct of_device *op)
993 1027
994 dev_set_drvdata(&op->dev, all); 1028 dev_set_drvdata(&op->dev, all);
995 1029
996 printk("%s: %s at %016lx, type %d, DAC revision %d\n", 1030 printk("%s: %s at %016lx, type %d, "
1031 "DAC pnum[%x] rev[%d] manuf_rev[%d]\n",
997 dp->full_name, 1032 dp->full_name,
998 ((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"), 1033 ((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
999 all->par.physbase, all->par.board_type, all->par.dac_rev); 1034 all->par.physbase, all->par.board_type,
1035 dac_pnum, dac_rev, dac_mrev);
1000 1036
1001 return 0; 1037 return 0;
1002} 1038}