diff options
Diffstat (limited to 'drivers/video/ffb.c')
| -rw-r--r-- | drivers/video/ffb.c | 170 |
1 files changed, 79 insertions, 91 deletions
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 3f6c98fad437..4b520b573911 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c | |||
| @@ -371,6 +371,8 @@ struct ffb_par { | |||
| 371 | unsigned long fbsize; | 371 | unsigned long fbsize; |
| 372 | 372 | ||
| 373 | int board_type; | 373 | int board_type; |
| 374 | |||
| 375 | u32 pseudo_palette[16]; | ||
| 374 | }; | 376 | }; |
| 375 | 377 | ||
| 376 | static void FFBFifo(struct ffb_par *par, int n) | 378 | static void FFBFifo(struct ffb_par *par, int n) |
| @@ -900,75 +902,67 @@ ffb_init_fix(struct fb_info *info) | |||
| 900 | info->fix.accel = FB_ACCEL_SUN_CREATOR; | 902 | info->fix.accel = FB_ACCEL_SUN_CREATOR; |
| 901 | } | 903 | } |
| 902 | 904 | ||
| 903 | struct all_info { | 905 | static int __devinit ffb_probe(struct of_device *op, const struct of_device_id *match) |
| 904 | struct fb_info info; | ||
| 905 | struct ffb_par par; | ||
| 906 | u32 pseudo_palette[16]; | ||
| 907 | }; | ||
| 908 | |||
| 909 | static int ffb_init_one(struct of_device *op) | ||
| 910 | { | 906 | { |
| 911 | struct device_node *dp = op->node; | 907 | struct device_node *dp = op->node; |
| 912 | struct ffb_fbc __iomem *fbc; | 908 | struct ffb_fbc __iomem *fbc; |
| 913 | struct ffb_dac __iomem *dac; | 909 | struct ffb_dac __iomem *dac; |
| 914 | struct all_info *all; | 910 | struct fb_info *info; |
| 915 | int err; | 911 | struct ffb_par *par; |
| 916 | u32 dac_pnum, dac_rev, dac_mrev; | 912 | u32 dac_pnum, dac_rev, dac_mrev; |
| 913 | int err; | ||
| 917 | 914 | ||
| 918 | all = kzalloc(sizeof(*all), GFP_KERNEL); | 915 | info = framebuffer_alloc(sizeof(struct ffb_par), &op->dev); |
| 919 | if (!all) | ||
| 920 | return -ENOMEM; | ||
| 921 | 916 | ||
| 922 | spin_lock_init(&all->par.lock); | 917 | err = -ENOMEM; |
| 923 | all->par.fbc = of_ioremap(&op->resource[2], 0, | 918 | if (!info) |
| 924 | sizeof(struct ffb_fbc), "ffb fbc"); | 919 | goto out_err; |
| 925 | if (!all->par.fbc) { | ||
| 926 | kfree(all); | ||
| 927 | return -ENOMEM; | ||
| 928 | } | ||
| 929 | 920 | ||
| 930 | all->par.dac = of_ioremap(&op->resource[1], 0, | 921 | par = info->par; |
| 931 | sizeof(struct ffb_dac), "ffb dac"); | 922 | |
| 932 | if (!all->par.dac) { | 923 | spin_lock_init(&par->lock); |
| 933 | of_iounmap(&op->resource[2], | 924 | par->fbc = of_ioremap(&op->resource[2], 0, |
| 934 | all->par.fbc, sizeof(struct ffb_fbc)); | 925 | sizeof(struct ffb_fbc), "ffb fbc"); |
| 935 | kfree(all); | 926 | if (!par->fbc) |
| 936 | return -ENOMEM; | 927 | goto out_release_fb; |
| 937 | } | 928 | |
| 929 | par->dac = of_ioremap(&op->resource[1], 0, | ||
| 930 | sizeof(struct ffb_dac), "ffb dac"); | ||
| 931 | if (!par->dac) | ||
| 932 | goto out_unmap_fbc; | ||
| 938 | 933 | ||
| 939 | all->par.rop_cache = FFB_ROP_NEW; | 934 | par->rop_cache = FFB_ROP_NEW; |
| 940 | all->par.physbase = op->resource[0].start; | 935 | par->physbase = op->resource[0].start; |
| 941 | 936 | ||
| 942 | /* Don't mention copyarea, so SCROLL_REDRAW is always | 937 | /* Don't mention copyarea, so SCROLL_REDRAW is always |
| 943 | * used. It is the fastest on this chip. | 938 | * used. It is the fastest on this chip. |
| 944 | */ | 939 | */ |
| 945 | all->info.flags = (FBINFO_DEFAULT | | 940 | info->flags = (FBINFO_DEFAULT | |
| 946 | /* FBINFO_HWACCEL_COPYAREA | */ | 941 | /* FBINFO_HWACCEL_COPYAREA | */ |
| 947 | FBINFO_HWACCEL_FILLRECT | | 942 | FBINFO_HWACCEL_FILLRECT | |
| 948 | FBINFO_HWACCEL_IMAGEBLIT); | 943 | FBINFO_HWACCEL_IMAGEBLIT); |
| 949 | all->info.fbops = &ffb_ops; | 944 | |
| 950 | all->info.screen_base = (char *) all->par.physbase + FFB_DFB24_POFF; | 945 | info->fbops = &ffb_ops; |
| 951 | all->info.par = &all->par; | 946 | |
| 952 | all->info.pseudo_palette = all->pseudo_palette; | 947 | info->screen_base = (char *) par->physbase + FFB_DFB24_POFF; |
| 953 | 948 | info->pseudo_palette = par->pseudo_palette; | |
| 954 | sbusfb_fill_var(&all->info.var, dp->node, 32); | 949 | |
| 955 | all->par.fbsize = PAGE_ALIGN(all->info.var.xres * | 950 | sbusfb_fill_var(&info->var, dp->node, 32); |
| 956 | all->info.var.yres * | 951 | par->fbsize = PAGE_ALIGN(info->var.xres * info->var.yres * 4); |
| 957 | 4); | 952 | ffb_fixup_var_rgb(&info->var); |
| 958 | ffb_fixup_var_rgb(&all->info.var); | 953 | |
| 959 | 954 | info->var.accel_flags = FB_ACCELF_TEXT; | |
| 960 | all->info.var.accel_flags = FB_ACCELF_TEXT; | ||
| 961 | 955 | ||
| 962 | if (!strcmp(dp->name, "SUNW,afb")) | 956 | if (!strcmp(dp->name, "SUNW,afb")) |
| 963 | all->par.flags |= FFB_FLAG_AFB; | 957 | par->flags |= FFB_FLAG_AFB; |
| 964 | 958 | ||
| 965 | all->par.board_type = of_getintprop_default(dp, "board_type", 0); | 959 | par->board_type = of_getintprop_default(dp, "board_type", 0); |
| 966 | 960 | ||
| 967 | fbc = all->par.fbc; | 961 | fbc = par->fbc; |
| 968 | if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) | 962 | if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) |
| 969 | upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr); | 963 | upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr); |
| 970 | 964 | ||
| 971 | dac = all->par.dac; | 965 | dac = par->dac; |
| 972 | upa_writel(FFB_DAC_DID, &dac->type); | 966 | upa_writel(FFB_DAC_DID, &dac->type); |
| 973 | dac_pnum = upa_readl(&dac->value); | 967 | dac_pnum = upa_readl(&dac->value); |
| 974 | dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT; | 968 | dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT; |
| @@ -985,76 +979,70 @@ static int ffb_init_one(struct of_device *op) | |||
| 985 | * cursor logic. We identify Pacifica 1 as not Pacifica 2, the | 979 | * cursor logic. We identify Pacifica 1 as not Pacifica 2, the |
| 986 | * latter having a part number value of 0x236e. | 980 | * latter having a part number value of 0x236e. |
| 987 | */ | 981 | */ |
| 988 | if ((all->par.flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) { | 982 | if ((par->flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) { |
| 989 | all->par.flags &= ~FFB_FLAG_INVCURSOR; | 983 | par->flags &= ~FFB_FLAG_INVCURSOR; |
| 990 | } else { | 984 | } else { |
| 991 | if (dac_mrev < 3) | 985 | if (dac_mrev < 3) |
| 992 | all->par.flags |= FFB_FLAG_INVCURSOR; | 986 | par->flags |= FFB_FLAG_INVCURSOR; |
| 993 | } | 987 | } |
| 994 | 988 | ||
| 995 | ffb_switch_from_graph(&all->par); | 989 | ffb_switch_from_graph(par); |
| 996 | 990 | ||
| 997 | /* Unblank it just to be sure. When there are multiple | 991 | /* Unblank it just to be sure. When there are multiple |
| 998 | * FFB/AFB cards in the system, or it is not the OBP | 992 | * FFB/AFB cards in the system, or it is not the OBP |
| 999 | * chosen console, it will have video outputs off in | 993 | * chosen console, it will have video outputs off in |
| 1000 | * the DAC. | 994 | * the DAC. |
| 1001 | */ | 995 | */ |
| 1002 | ffb_blank(0, &all->info); | 996 | ffb_blank(0, info); |
| 1003 | |||
| 1004 | if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { | ||
| 1005 | printk(KERN_ERR "ffb: Could not allocate color map.\n"); | ||
| 1006 | of_iounmap(&op->resource[2], | ||
| 1007 | all->par.fbc, sizeof(struct ffb_fbc)); | ||
| 1008 | of_iounmap(&op->resource[1], | ||
| 1009 | all->par.dac, sizeof(struct ffb_dac)); | ||
| 1010 | kfree(all); | ||
| 1011 | return -ENOMEM; | ||
| 1012 | } | ||
| 1013 | 997 | ||
| 1014 | ffb_init_fix(&all->info); | 998 | if (fb_alloc_cmap(&info->cmap, 256, 0)) |
| 1015 | 999 | goto out_unmap_dac; | |
| 1016 | err = register_framebuffer(&all->info); | 1000 | |
| 1017 | if (err < 0) { | 1001 | ffb_init_fix(info); |
| 1018 | printk(KERN_ERR "ffb: Could not register framebuffer.\n"); | ||
| 1019 | fb_dealloc_cmap(&all->info.cmap); | ||
| 1020 | of_iounmap(&op->resource[2], | ||
| 1021 | all->par.fbc, sizeof(struct ffb_fbc)); | ||
| 1022 | of_iounmap(&op->resource[1], | ||
| 1023 | all->par.dac, sizeof(struct ffb_dac)); | ||
| 1024 | kfree(all); | ||
| 1025 | return err; | ||
| 1026 | } | ||
| 1027 | 1002 | ||
| 1028 | dev_set_drvdata(&op->dev, all); | 1003 | err = register_framebuffer(info); |
| 1004 | if (err < 0) | ||
| 1005 | goto out_dealloc_cmap; | ||
| 1006 | |||
| 1007 | dev_set_drvdata(&op->dev, info); | ||
| 1029 | 1008 | ||
| 1030 | printk("%s: %s at %016lx, type %d, " | 1009 | printk("%s: %s at %016lx, type %d, " |
| 1031 | "DAC pnum[%x] rev[%d] manuf_rev[%d]\n", | 1010 | "DAC pnum[%x] rev[%d] manuf_rev[%d]\n", |
| 1032 | dp->full_name, | 1011 | dp->full_name, |
| 1033 | ((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"), | 1012 | ((par->flags & FFB_FLAG_AFB) ? "AFB" : "FFB"), |
| 1034 | all->par.physbase, all->par.board_type, | 1013 | par->physbase, par->board_type, |
| 1035 | dac_pnum, dac_rev, dac_mrev); | 1014 | dac_pnum, dac_rev, dac_mrev); |
| 1036 | 1015 | ||
| 1037 | return 0; | 1016 | return 0; |
| 1038 | } | ||
| 1039 | 1017 | ||
| 1040 | static int __devinit ffb_probe(struct of_device *dev, const struct of_device_id *match) | 1018 | out_dealloc_cmap: |
| 1041 | { | 1019 | fb_dealloc_cmap(&info->cmap); |
| 1042 | struct of_device *op = to_of_device(&dev->dev); | 1020 | |
| 1021 | out_unmap_dac: | ||
| 1022 | of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc)); | ||
| 1023 | |||
| 1024 | out_unmap_fbc: | ||
| 1025 | of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc)); | ||
| 1026 | |||
| 1027 | out_release_fb: | ||
| 1028 | framebuffer_release(info); | ||
| 1043 | 1029 | ||
| 1044 | return ffb_init_one(op); | 1030 | out_err: |
| 1031 | return err; | ||
| 1045 | } | 1032 | } |
| 1046 | 1033 | ||
| 1047 | static int __devexit ffb_remove(struct of_device *op) | 1034 | static int __devexit ffb_remove(struct of_device *op) |
| 1048 | { | 1035 | { |
| 1049 | struct all_info *all = dev_get_drvdata(&op->dev); | 1036 | struct fb_info *info = dev_get_drvdata(&op->dev); |
| 1037 | struct ffb_par *par = info->par; | ||
| 1050 | 1038 | ||
| 1051 | unregister_framebuffer(&all->info); | 1039 | unregister_framebuffer(info); |
| 1052 | fb_dealloc_cmap(&all->info.cmap); | 1040 | fb_dealloc_cmap(&info->cmap); |
| 1053 | 1041 | ||
| 1054 | of_iounmap(&op->resource[2], all->par.fbc, sizeof(struct ffb_fbc)); | 1042 | of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc)); |
| 1055 | of_iounmap(&op->resource[1], all->par.dac, sizeof(struct ffb_dac)); | 1043 | of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac)); |
| 1056 | 1044 | ||
| 1057 | kfree(all); | 1045 | framebuffer_release(info); |
| 1058 | 1046 | ||
| 1059 | dev_set_drvdata(&op->dev, NULL); | 1047 | dev_set_drvdata(&op->dev, NULL); |
| 1060 | 1048 | ||
