^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* p9100.c: P9100 frame buffer driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 1999 Derrick J Brashear (shadow@dementia.org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Driver layout based loosely on tgafb.c, see that file for credits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/fbio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "sbuslib.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Local functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) unsigned, struct fb_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int p9100_blank(int, struct fb_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static int p9100_mmap(struct fb_info *, struct vm_area_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Frame buffer operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static const struct fb_ops p9100_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .fb_setcolreg = p9100_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .fb_blank = p9100_blank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .fb_fillrect = cfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) .fb_copyarea = cfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .fb_imageblit = cfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .fb_mmap = p9100_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .fb_ioctl = p9100_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .fb_compat_ioctl = sbusfb_compat_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* P9100 control registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define P9100_SYSCTL_OFF 0x0UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define P9100_VIDEOCTL_OFF 0x100UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define P9100_VRAMCTL_OFF 0x180UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define P9100_RAMDAC_OFF 0x200UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define P9100_VIDEOCOPROC_OFF 0x400UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* P9100 command registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define P9100_CMD_OFF 0x0UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* P9100 framebuffer memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define P9100_FB_OFF 0x0UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* 3 bits: 2=8bpp 3=16bpp 5=32bpp 7=24bpp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define SYS_CONFIG_PIXELSIZE_SHIFT 26
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define SCREENPAINT_TIMECTL1_ENABLE_VIDEO 0x20 /* 0 = off, 1 = on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct p9100_regs {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Registers for the system control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u32 sys_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u32 sys_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u32 sys_intr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u32 sys_int_ena;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u32 sys_alt_rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u32 sys_alt_wr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u32 sys_xxx[58];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* Registers for the video control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) u32 vid_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) u32 vid_hcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) u32 vid_htotal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) u32 vid_hsync_rise;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) u32 vid_hblank_rise;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u32 vid_hblank_fall;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) u32 vid_hcnt_preload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) u32 vid_vcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) u32 vid_vlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u32 vid_vsync_rise;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) u32 vid_vblank_rise;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u32 vid_vblank_fall;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u32 vid_vcnt_preload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) u32 vid_screenpaint_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u32 vid_screenpaint_timectl1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u32 vid_screenpaint_qsfcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) u32 vid_screenpaint_timectl2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) u32 vid_xxx[15];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* Registers for the video control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u32 vram_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u32 vram_memcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u32 vram_refresh_pd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u32 vram_refresh_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u32 vram_raslo_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u32 vram_raslo_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) u32 pwrup_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u32 vram_xxx[25];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* Registers for IBM RGB528 Palette */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) u32 ramdac_cmap_wridx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) u32 ramdac_palette_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) u32 ramdac_pixel_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) u32 ramdac_palette_rdaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) u32 ramdac_idx_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u32 ramdac_idx_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) u32 ramdac_idx_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u32 ramdac_idx_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) u32 ramdac_xxx[1784];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct p9100_cmd_parameng {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) u32 parameng_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) u32 parameng_bltcmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u32 parameng_quadcmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct p9100_par {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct p9100_regs __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u32 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define P9100_FLAG_BLANKED 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) unsigned long which_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * p9100_setcolreg - Optional function. Sets a color register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * @regno: boolean, 0 copy local, 1 get_user() function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * @red: frame buffer colormap structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * @green: The green value which can be up to 16 bits wide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * @blue: The blue value which can be up to 16 bits wide.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * @transp: If supported the alpha value which can be up to 16 bits wide.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * @info: frame buffer info structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int p9100_setcolreg(unsigned regno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) unsigned red, unsigned green, unsigned blue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) unsigned transp, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct p9100_par *par = (struct p9100_par *) info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct p9100_regs __iomem *regs = par->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (regno >= 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) red >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) green >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) blue >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) spin_lock_irqsave(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) sbus_writel((regno << 16), ®s->ramdac_cmap_wridx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) sbus_writel((red << 16), ®s->ramdac_palette_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) sbus_writel((green << 16), ®s->ramdac_palette_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) sbus_writel((blue << 16), ®s->ramdac_palette_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) spin_unlock_irqrestore(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * p9100_blank - Optional function. Blanks the display.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * @blank_mode: the blank mode we want.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * @info: frame buffer structure that represents a single frame buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) p9100_blank(int blank, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct p9100_par *par = (struct p9100_par *) info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct p9100_regs __iomem *regs = par->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) spin_lock_irqsave(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) switch (blank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) case FB_BLANK_UNBLANK: /* Unblanking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) val = sbus_readl(®s->vid_screenpaint_timectl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) val |= SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) sbus_writel(val, ®s->vid_screenpaint_timectl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) par->flags &= ~P9100_FLAG_BLANKED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) case FB_BLANK_NORMAL: /* Normal blanking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) case FB_BLANK_POWERDOWN: /* Poweroff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) val = sbus_readl(®s->vid_screenpaint_timectl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) val &= ~SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) sbus_writel(val, ®s->vid_screenpaint_timectl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) par->flags |= P9100_FLAG_BLANKED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) spin_unlock_irqrestore(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static struct sbus_mmap_map p9100_mmap_map[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) { CG3_MMAP_OFFSET, 0, SBUS_MMAP_FBSIZE(1) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) { 0, 0, 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct p9100_par *par = (struct p9100_par *)info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return sbusfb_mmap_helper(p9100_mmap_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) info->fix.smem_start, info->fix.smem_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) par->which_io, vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static int p9100_ioctl(struct fb_info *info, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /* Make it look like a cg3. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return sbusfb_ioctl_helper(cmd, arg, info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) FBTYPE_SUN3COLOR, 8, info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * Initialisation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) snprintf(info->fix.id, sizeof(info->fix.id), "%pOFn", dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) info->fix.type = FB_TYPE_PACKED_PIXELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) info->fix.line_length = linebytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) info->fix.accel = FB_ACCEL_SUN_CGTHREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static int p9100_probe(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct device_node *dp = op->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) struct p9100_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int linebytes, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) info = framebuffer_alloc(sizeof(struct p9100_par), &op->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) spin_lock_init(&par->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* This is the framebuffer and the only resource apps can mmap. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) info->fix.smem_start = op->resource[2].start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) par->which_io = op->resource[2].flags & IORESOURCE_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) sbusfb_fill_var(&info->var, dp, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) info->var.red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) info->var.green.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) info->var.blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) linebytes = of_getintprop_default(dp, "linebytes", info->var.xres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) par->regs = of_ioremap(&op->resource[0], 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) sizeof(struct p9100_regs), "p9100 regs");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (!par->regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) goto out_release_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) info->flags = FBINFO_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) info->fbops = &p9100_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) info->screen_base = of_ioremap(&op->resource[2], 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) info->fix.smem_len, "p9100 ram");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (!info->screen_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) goto out_unmap_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) p9100_blank(FB_BLANK_UNBLANK, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (fb_alloc_cmap(&info->cmap, 256, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) goto out_unmap_screen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) p9100_init_fix(info, linebytes, dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) err = register_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) goto out_dealloc_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) fb_set_cmap(&info->cmap, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) dev_set_drvdata(&op->dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) printk(KERN_INFO "%pOF: p9100 at %lx:%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) par->which_io, info->fix.smem_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) out_dealloc_cmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) out_unmap_screen:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) of_iounmap(&op->resource[2], info->screen_base, info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) out_unmap_regs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) out_release_fb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static int p9100_remove(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) struct fb_info *info = dev_get_drvdata(&op->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct p9100_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) of_iounmap(&op->resource[2], info->screen_base, info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static const struct of_device_id p9100_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) .name = "p9100",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) MODULE_DEVICE_TABLE(of, p9100_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static struct platform_driver p9100_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) .name = "p9100",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) .of_match_table = p9100_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) .probe = p9100_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) .remove = p9100_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static int __init p9100_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (fb_get_options("p9100fb", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return platform_driver_register(&p9100_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) static void __exit p9100_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) platform_driver_unregister(&p9100_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) module_init(p9100_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) module_exit(p9100_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) MODULE_DESCRIPTION("framebuffer driver for P9100 chipsets");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) MODULE_VERSION("2.0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) MODULE_LICENSE("GPL");