Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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), &regs->ramdac_cmap_wridx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	sbus_writel((red << 16), &regs->ramdac_palette_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	sbus_writel((green << 16), &regs->ramdac_palette_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	sbus_writel((blue << 16), &regs->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(&regs->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, &regs->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(&regs->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, &regs->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");