^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * linux/drivers/video/pmag-ba-fb.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * PMAG-BA TURBOchannel Color Frame Buffer (CFB) card support,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * derived from:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * "HP300 Topcat framebuffer support (derived from macfb of all things)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Phil Blundell <philb@gnu.org> 1998", the original code can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * found in the file hpfb.c in the same directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Based on digital document:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * "PMAG-BA TURBOchannel Color Frame Buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Functional Specification", Revision 1.2, August 27, 1990
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * DECstation related code Copyright (C) 1999, 2000, 2001 by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Michael Engel <engel@unix-ag.org>,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Karsten Merker <merker@linuxtag.org> and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Harald Koerfgen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Copyright (c) 2005, 2006 Maciej W. Rozycki
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Copyright (c) 2005 James Simmons
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * This file is subject to the terms and conditions of the GNU General
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Public License. See the file COPYING in the main directory of this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * archive for more details.
^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) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/tc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <video/pmag-ba-fb.h>
^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) struct pmagbafb_par {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) volatile void __iomem *mmio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) volatile u32 __iomem *dac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static const struct fb_var_screeninfo pmagbafb_defined = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .xres = 1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .yres = 864,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .xres_virtual = 1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .yres_virtual = 864,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .bits_per_pixel = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .red.length = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .green.length = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .blue.length = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .activate = FB_ACTIVATE_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .height = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .width = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .accel_flags = FB_ACCEL_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .pixclock = 14452,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .left_margin = 116,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .right_margin = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .upper_margin = 34,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) .lower_margin = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) .hsync_len = 128,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .vsync_len = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .sync = FB_SYNC_ON_GREEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .vmode = FB_VMODE_NONINTERLACED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static const struct fb_fix_screeninfo pmagbafb_fix = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .id = "PMAG-BA",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .smem_len = (1024 * 1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .type = FB_TYPE_PACKED_PIXELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .visual = FB_VISUAL_PSEUDOCOLOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .line_length = 1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .mmio_len = PMAG_BA_SIZE - PMAG_BA_BT459,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static inline void dac_write(struct pmagbafb_par *par, unsigned int reg, u8 v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) writeb(v, par->dac + reg / 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static inline u8 dac_read(struct pmagbafb_par *par, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return readb(par->dac + reg / 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * Set the palette.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int pmagbafb_setcolreg(unsigned int regno, unsigned int red,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned int green, unsigned int blue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned int transp, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct pmagbafb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (regno >= info->cmap.len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) red >>= 8; /* The cmap fields are 16 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) green >>= 8; /* wide, but the hardware colormap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) blue >>= 8; /* registers are only 8 bits wide */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) dac_write(par, BT459_ADDR_LO, regno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) dac_write(par, BT459_ADDR_HI, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) dac_write(par, BT459_CMAP, red);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) dac_write(par, BT459_CMAP, green);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) dac_write(par, BT459_CMAP, blue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static const struct fb_ops pmagbafb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .fb_setcolreg = pmagbafb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .fb_fillrect = cfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .fb_copyarea = cfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .fb_imageblit = cfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^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) * Turn the hardware cursor off.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static void pmagbafb_erase_cursor(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct pmagbafb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) dac_write(par, BT459_ADDR_LO, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) dac_write(par, BT459_ADDR_HI, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) dac_write(par, BT459_DATA, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static int pmagbafb_probe(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct tc_dev *tdev = to_tc_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) resource_size_t start, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct pmagbafb_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) info = framebuffer_alloc(sizeof(struct pmagbafb_par), dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) dev_set_drvdata(dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) printk(KERN_ERR "%s: Cannot allocate color map\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) goto err_alloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) info->fbops = &pmagbafb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) info->fix = pmagbafb_fix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) info->var = pmagbafb_defined;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) info->flags = FBINFO_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* Request the I/O MEM resource. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) start = tdev->resource.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) len = tdev->resource.end - start + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (!request_mem_region(start, len, dev_name(dev))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) printk(KERN_ERR "%s: Cannot reserve FB region\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) goto err_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /* MMIO mapping setup. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) info->fix.mmio_start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) par->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (!par->mmio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) goto err_resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) par->dac = par->mmio + PMAG_BA_BT459;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* Frame buffer mapping setup. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) info->fix.smem_start = start + PMAG_BA_FBMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) info->screen_base = ioremap(info->fix.smem_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (!info->screen_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) goto err_mmio_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) info->screen_size = info->fix.smem_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) pmagbafb_erase_cursor(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) err = register_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) printk(KERN_ERR "%s: Cannot register framebuffer\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) goto err_smem_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) get_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) fb_info(info, "%s frame buffer device at %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) info->fix.id, dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) err_smem_map:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) iounmap(info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) err_mmio_map:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) iounmap(par->mmio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) err_resource:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) release_mem_region(start, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) err_cmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) err_alloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static int pmagbafb_remove(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct tc_dev *tdev = to_tc_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct fb_info *info = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct pmagbafb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) resource_size_t start, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) put_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) iounmap(info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) iounmap(par->mmio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) start = tdev->resource.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) len = tdev->resource.end - start + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) release_mem_region(start, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * Initialize the framebuffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static const struct tc_device_id pmagbafb_tc_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) { "DEC ", "PMAG-BA " },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) MODULE_DEVICE_TABLE(tc, pmagbafb_tc_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static struct tc_driver pmagbafb_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .id_table = pmagbafb_tc_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) .name = "pmagbafb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) .bus = &tc_bus_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .probe = pmagbafb_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .remove = pmagbafb_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static int __init pmagbafb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (fb_get_options("pmagbafb", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return tc_register_driver(&pmagbafb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static void __exit pmagbafb_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) tc_unregister_driver(&pmagbafb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) module_init(pmagbafb_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) module_exit(pmagbafb_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) MODULE_LICENSE("GPL");