^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) /* cg14.c: CGFOURTEEN 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 (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Driver layout based loosely on tgafb.c, see that file for credits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/fbio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "sbuslib.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Local functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) unsigned, struct fb_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int cg14_mmap(struct fb_info *, struct vm_area_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static int cg14_ioctl(struct fb_info *, unsigned int, unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static int cg14_pan_display(struct fb_var_screeninfo *, struct fb_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * Frame buffer operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static const struct fb_ops cg14_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .fb_setcolreg = cg14_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) .fb_pan_display = cg14_pan_display,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .fb_fillrect = cfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .fb_copyarea = cfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .fb_imageblit = cfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .fb_mmap = cg14_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .fb_ioctl = cg14_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .fb_compat_ioctl = sbusfb_compat_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define CG14_MCR_INTENABLE_SHIFT 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define CG14_MCR_INTENABLE_MASK 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define CG14_MCR_VIDENABLE_SHIFT 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define CG14_MCR_VIDENABLE_MASK 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define CG14_MCR_PIXMODE_SHIFT 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define CG14_MCR_PIXMODE_MASK 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define CG14_MCR_TMR_SHIFT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define CG14_MCR_TMR_MASK 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define CG14_MCR_TMENABLE_SHIFT 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define CG14_MCR_TMENABLE_MASK 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define CG14_MCR_RESET_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define CG14_MCR_RESET_MASK 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define CG14_REV_REVISION_SHIFT 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define CG14_REV_REVISION_MASK 0xf0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define CG14_REV_IMPL_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define CG14_REV_IMPL_MASK 0x0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define CG14_VBR_FRAMEBASE_SHIFT 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define CG14_VBR_FRAMEBASE_MASK 0x00fff000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define CG14_VMCR1_SETUP_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define CG14_VMCR1_SETUP_MASK 0x000001ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define CG14_VMCR1_VCONFIG_SHIFT 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define CG14_VMCR1_VCONFIG_MASK 0x00000e00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define CG14_VMCR2_REFRESH_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define CG14_VMCR2_REFRESH_MASK 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define CG14_VMCR2_TESTROWCNT_SHIFT 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define CG14_VMCR2_TESTROWCNT_MASK 0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define CG14_VMCR2_FBCONFIG_SHIFT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define CG14_VMCR2_FBCONFIG_MASK 0x0000000c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define CG14_VCR_REFRESHREQ_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define CG14_VCR_REFRESHREQ_MASK 0x000003ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define CG14_VCR1_REFRESHENA_SHIFT 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define CG14_VCR1_REFRESHENA_MASK 0x00000400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define CG14_VCA_CAD_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define CG14_VCA_CAD_MASK 0x000003ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define CG14_VCA_VERS_SHIFT 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define CG14_VCA_VERS_MASK 0x00000c00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define CG14_VCA_RAMSPEED_SHIFT 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define CG14_VCA_RAMSPEED_MASK 0x00001000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define CG14_VCA_8MB_SHIFT 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define CG14_VCA_8MB_MASK 0x00002000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define CG14_MCR_PIXMODE_8 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define CG14_MCR_PIXMODE_16 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define CG14_MCR_PIXMODE_32 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct cg14_regs{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u8 mcr; /* Master Control Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u8 ppr; /* Packed Pixel Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u8 tms[2]; /* Test Mode Status Regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u8 msr; /* Master Status Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u8 fsr; /* Fault Status Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u8 rev; /* Revision & Impl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u8 ccr; /* Clock Control Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) u32 tmr; /* Test Mode Read Back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u8 mod; /* Monitor Operation Data Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) u8 acr; /* Aux Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) u8 xxx0[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) u16 hct; /* Hor Counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) u16 vct; /* Vert Counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) u16 hbs; /* Hor Blank Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) u16 hbc; /* Hor Blank Clear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) u16 hss; /* Hor Sync Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u16 hsc; /* Hor Sync Clear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) u16 csc; /* Composite Sync Clear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u16 vbs; /* Vert Blank Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) u16 vbc; /* Vert Blank Clear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u16 vss; /* Vert Sync Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) u16 vsc; /* Vert Sync Clear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) u16 xcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) u16 xcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) u16 fsa; /* Fault Status Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u16 adr; /* Address Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) u8 xxx1[0xce];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) u8 pcg[0x100]; /* Pixel Clock Generator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) u32 vbr; /* Frame Base Row */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) u32 vmcr; /* VBC Master Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) u32 vcr; /* VBC refresh */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) u32 vca; /* VBC Config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define CG14_CCR_ENABLE 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define CG14_CCR_SELECT 0x02 /* HW/Full screen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct cg14_cursor {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) u32 cpl0[32]; /* Enable plane 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) u32 cpl1[32]; /* Color selection plane */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) u8 ccr; /* Cursor Control Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) u8 xxx0[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) u16 cursx; /* Cursor x,y position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) u16 cursy; /* Cursor x,y position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) u32 color0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) u32 color1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) u32 xxx1[0x1bc];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) u32 cpl0i[32]; /* Enable plane 0 autoinc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) u32 cpl1i[32]; /* Color selection autoinc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct cg14_dac {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) u8 addr; /* Address Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) u8 xxx0[255];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) u8 glut; /* Gamma table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) u8 xxx1[255];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) u8 select; /* Register Select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) u8 xxx2[255];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) u8 mode; /* Mode Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct cg14_xlut{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) u8 x_xlut [256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) u8 x_xlutd [256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) u8 xxx0[0x600];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) u8 x_xlut_inc [256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) u8 x_xlutd_inc [256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* Color look up table (clut) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /* Each one of these arrays hold the color lookup table (for 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * colors) for each MDI page (I assume then there should be 4 MDI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * pages, I still wonder what they are. I have seen NeXTStep split
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * the screen in four parts, while operating in 24 bits mode. Each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * integer holds 4 values: alpha value (transparency channel, thanks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * go to John Stone (johns@umr.edu) from OpenBSD), red, green and blue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * I currently use the clut instead of the Xlut
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct cg14_clut {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) u32 c_clut [256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) u32 c_clutd [256]; /* i wonder what the 'd' is for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) u32 c_clut_inc [256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) u32 c_clutd_inc [256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #define CG14_MMAP_ENTRIES 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct cg14_par {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct cg14_regs __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct cg14_clut __iomem *clut;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct cg14_cursor __iomem *cursor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) u32 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #define CG14_FLAG_BLANKED 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) unsigned long iospace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct sbus_mmap_map mmap_map[CG14_MMAP_ENTRIES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int ramsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static void __cg14_reset(struct cg14_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct cg14_regs __iomem *regs = par->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) val = sbus_readb(®s->mcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) val &= ~(CG14_MCR_PIXMODE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) sbus_writeb(val, ®s->mcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static int cg14_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct cg14_par *par = (struct cg14_par *) info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* We just use this to catch switches out of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * graphics mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) spin_lock_irqsave(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) __cg14_reset(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) spin_unlock_irqrestore(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (var->xoffset || var->yoffset || var->vmode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * cg14_setcolreg - Optional function. Sets a color register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * @regno: boolean, 0 copy local, 1 get_user() function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * @red: frame buffer colormap structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * @green: The green value which can be up to 16 bits wide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * @blue: The blue value which can be up to 16 bits wide.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * @transp: If supported the alpha value which can be up to 16 bits wide.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * @info: frame buffer info structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static int cg14_setcolreg(unsigned regno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unsigned red, unsigned green, unsigned blue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) unsigned transp, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct cg14_par *par = (struct cg14_par *) info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct cg14_clut __iomem *clut = par->clut;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (regno >= 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) red >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) green >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) blue >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) val = (red | (green << 8) | (blue << 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) spin_lock_irqsave(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) sbus_writel(val, &clut->c_clut[regno]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) spin_unlock_irqrestore(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static int cg14_mmap(struct fb_info *info, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct cg14_par *par = (struct cg14_par *) info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return sbusfb_mmap_helper(par->mmap_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) info->fix.smem_start, info->fix.smem_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) par->iospace, vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct cg14_par *par = (struct cg14_par *) info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct cg14_regs __iomem *regs = par->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct mdi_cfginfo kmdi, __user *mdii;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) int cur_mode, mode, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) case MDI_RESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) spin_lock_irqsave(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) __cg14_reset(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) spin_unlock_irqrestore(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) case MDI_GET_CFGINFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) memset(&kmdi, 0, sizeof(kmdi));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) spin_lock_irqsave(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) kmdi.mdi_type = FBTYPE_MDICOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) kmdi.mdi_height = info->var.yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) kmdi.mdi_width = info->var.xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) kmdi.mdi_mode = par->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) kmdi.mdi_pixfreq = 72; /* FIXME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) kmdi.mdi_size = par->ramsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) spin_unlock_irqrestore(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) mdii = (struct mdi_cfginfo __user *) arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (copy_to_user(mdii, &kmdi, sizeof(kmdi)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) case MDI_SET_PIXELMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (get_user(mode, (int __user *) arg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) spin_lock_irqsave(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) cur_mode = sbus_readb(®s->mcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) cur_mode &= ~CG14_MCR_PIXMODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) switch(mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) case MDI_32_PIX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) cur_mode |= (CG14_MCR_PIXMODE_32 <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) CG14_MCR_PIXMODE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) case MDI_16_PIX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) cur_mode |= (CG14_MCR_PIXMODE_16 <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) CG14_MCR_PIXMODE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) case MDI_8_PIX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) ret = -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) sbus_writeb(cur_mode, ®s->mcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) par->mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) spin_unlock_irqrestore(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) ret = sbusfb_ioctl_helper(cmd, arg, info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) FBTYPE_MDICOLOR, 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return ret;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * Initialisation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static void cg14_init_fix(struct fb_info *info, int linebytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct device_node *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) snprintf(info->fix.id, sizeof(info->fix.id), "%pOFn", dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) info->fix.type = FB_TYPE_PACKED_PIXELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) info->fix.line_length = linebytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) info->fix.accel = FB_ACCEL_SUN_CG14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) .voff = CG14_REGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) .poff = 0x80000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .size = 0x1000
^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) .voff = CG14_XLUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) .poff = 0x80003000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) .size = 0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .voff = CG14_CLUT1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .poff = 0x80004000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .size = 0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) .voff = CG14_CLUT2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) .poff = 0x80005000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) .size = 0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) .voff = CG14_CLUT3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) .poff = 0x80006000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) .size = 0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) .voff = CG3_MMAP_OFFSET - 0x7000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) .poff = 0x80000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) .size = 0x7000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) .voff = CG3_MMAP_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) .poff = 0x00000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) .size = SBUS_MMAP_FBSIZE(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) .voff = MDI_CURSOR_MAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) .poff = 0x80001000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) .size = 0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) .voff = MDI_CHUNKY_BGR_MAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .poff = 0x01000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) .size = 0x400000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) .voff = MDI_PLANAR_X16_MAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) .poff = 0x02000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) .size = 0x200000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) .voff = MDI_PLANAR_C16_MAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) .poff = 0x02800000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) .size = 0x200000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) .voff = MDI_PLANAR_X32_MAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) .poff = 0x03000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) .size = 0x100000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) .voff = MDI_PLANAR_B32_MAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) .poff = 0x03400000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) .size = 0x100000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) .voff = MDI_PLANAR_G32_MAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) .poff = 0x03800000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) .size = 0x100000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) .voff = MDI_PLANAR_R32_MAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) .poff = 0x03c00000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) .size = 0x100000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) { .size = 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static void cg14_unmap_regs(struct platform_device *op, struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct cg14_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (par->regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) of_iounmap(&op->resource[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) par->regs, sizeof(struct cg14_regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (par->clut)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) of_iounmap(&op->resource[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) par->clut, sizeof(struct cg14_clut));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (par->cursor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) of_iounmap(&op->resource[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) par->cursor, sizeof(struct cg14_cursor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (info->screen_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) of_iounmap(&op->resource[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) info->screen_base, info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static int cg14_probe(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct device_node *dp = op->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct cg14_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int is_8mb, linebytes, i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) info = framebuffer_alloc(sizeof(struct cg14_par), &op->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) spin_lock_init(&par->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) sbusfb_fill_var(&info->var, dp, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) info->var.red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) info->var.green.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) info->var.blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) linebytes = of_getintprop_default(dp, "linebytes",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) info->var.xres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (of_node_name_eq(dp->parent, "sbus") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) of_node_name_eq(dp->parent, "sbi")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) info->fix.smem_start = op->resource[0].start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) par->iospace = op->resource[0].flags & IORESOURCE_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) info->fix.smem_start = op->resource[1].start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) par->iospace = op->resource[0].flags & IORESOURCE_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) par->regs = of_ioremap(&op->resource[0], 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) sizeof(struct cg14_regs), "cg14 regs");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) par->clut = of_ioremap(&op->resource[0], CG14_CLUT1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) sizeof(struct cg14_clut), "cg14 clut");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) par->cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) sizeof(struct cg14_cursor), "cg14 cursor");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) info->screen_base = of_ioremap(&op->resource[1], 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) info->fix.smem_len, "cg14 ram");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (!par->regs || !par->clut || !par->cursor || !info->screen_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) goto out_unmap_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) is_8mb = (resource_size(&op->resource[1]) == (8 * 1024 * 1024));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) BUILD_BUG_ON(sizeof(par->mmap_map) != sizeof(__cg14_mmap_map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) memcpy(&par->mmap_map, &__cg14_mmap_map, sizeof(par->mmap_map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) for (i = 0; i < CG14_MMAP_ENTRIES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct sbus_mmap_map *map = &par->mmap_map[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (!map->size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (map->poff & 0x80000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) map->poff = (map->poff & 0x7fffffff) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) (op->resource[0].start -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) op->resource[1].start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (is_8mb &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) map->size >= 0x100000 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) map->size <= 0x400000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) map->size *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) par->mode = MDI_8_PIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) par->ramsize = (is_8mb ? 0x800000 : 0x400000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) info->fbops = &cg14_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) __cg14_reset(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (fb_alloc_cmap(&info->cmap, 256, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) goto out_unmap_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) fb_set_cmap(&info->cmap, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) cg14_init_fix(info, linebytes, dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) err = register_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) goto out_dealloc_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) dev_set_drvdata(&op->dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) printk(KERN_INFO "%pOF: cgfourteen at %lx:%lx, %dMB\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) par->iospace, info->fix.smem_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) par->ramsize >> 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) out_dealloc_cmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) out_unmap_regs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) cg14_unmap_regs(op, info, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static int cg14_remove(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) struct fb_info *info = dev_get_drvdata(&op->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) struct cg14_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) cg14_unmap_regs(op, info, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) static const struct of_device_id cg14_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) .name = "cgfourteen",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) MODULE_DEVICE_TABLE(of, cg14_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) static struct platform_driver cg14_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) .name = "cg14",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) .of_match_table = cg14_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) .probe = cg14_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) .remove = cg14_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) static int __init cg14_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (fb_get_options("cg14fb", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) return platform_driver_register(&cg14_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) static void __exit cg14_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) platform_driver_unregister(&cg14_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) module_init(cg14_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) module_exit(cg14_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) MODULE_DESCRIPTION("framebuffer driver for CGfourteen chipsets");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) MODULE_VERSION("2.0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) MODULE_LICENSE("GPL");