^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) /* cg6.c: CGSIX (GX, GXplus, TGX) 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) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Driver layout based loosely on tgafb.c, see that file for credits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/mm.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 cg6_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) static int cg6_blank(int, struct fb_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static void cg6_imageblit(struct fb_info *, const struct fb_image *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static int cg6_sync(struct fb_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int cg6_mmap(struct fb_info *, struct vm_area_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static int cg6_pan_display(struct fb_var_screeninfo *, struct fb_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * Frame buffer operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static const struct fb_ops cg6_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .fb_setcolreg = cg6_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .fb_blank = cg6_blank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .fb_pan_display = cg6_pan_display,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .fb_fillrect = cg6_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .fb_copyarea = cg6_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .fb_imageblit = cg6_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .fb_sync = cg6_sync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .fb_mmap = cg6_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .fb_ioctl = cg6_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .fb_compat_ioctl = sbusfb_compat_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* Offset of interesting structures in the OBIO space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * Brooktree is the video dac and is funny to program on the cg6.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * (it's even funnier on the cg3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * The FBC could be the frame buffer control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * The FHC could is the frame buffer hardware control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define CG6_ROM_OFFSET 0x0UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define CG6_BROOKTREE_OFFSET 0x200000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define CG6_DHC_OFFSET 0x240000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define CG6_ALT_OFFSET 0x280000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define CG6_FHC_OFFSET 0x300000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define CG6_THC_OFFSET 0x301000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define CG6_FBC_OFFSET 0x700000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define CG6_TEC_OFFSET 0x701000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define CG6_RAM_OFFSET 0x800000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* FHC definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define CG6_FHC_FBID_SHIFT 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define CG6_FHC_FBID_MASK 255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define CG6_FHC_REV_SHIFT 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define CG6_FHC_REV_MASK 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define CG6_FHC_FROP_DISABLE (1 << 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define CG6_FHC_ROW_DISABLE (1 << 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define CG6_FHC_SRC_DISABLE (1 << 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define CG6_FHC_DST_DISABLE (1 << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define CG6_FHC_RESET (1 << 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define CG6_FHC_LITTLE_ENDIAN (1 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define CG6_FHC_RES_MASK (3 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define CG6_FHC_1024 (0 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define CG6_FHC_1152 (1 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define CG6_FHC_1280 (2 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define CG6_FHC_1600 (3 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define CG6_FHC_CPU_MASK (3 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define CG6_FHC_CPU_SPARC (0 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define CG6_FHC_CPU_68020 (1 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define CG6_FHC_CPU_386 (2 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define CG6_FHC_TEST (1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define CG6_FHC_TEST_X_SHIFT 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define CG6_FHC_TEST_X_MASK 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define CG6_FHC_TEST_Y_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define CG6_FHC_TEST_Y_MASK 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* FBC mode definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define CG6_FBC_BLIT_IGNORE 0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define CG6_FBC_BLIT_NOSRC 0x00100000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define CG6_FBC_BLIT_SRC 0x00200000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define CG6_FBC_BLIT_ILLEGAL 0x00300000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define CG6_FBC_BLIT_MASK 0x00300000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define CG6_FBC_VBLANK 0x00080000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define CG6_FBC_MODE_IGNORE 0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define CG6_FBC_MODE_COLOR8 0x00020000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define CG6_FBC_MODE_COLOR1 0x00040000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define CG6_FBC_MODE_HRMONO 0x00060000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define CG6_FBC_MODE_MASK 0x00060000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define CG6_FBC_DRAW_IGNORE 0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define CG6_FBC_DRAW_RENDER 0x00008000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define CG6_FBC_DRAW_PICK 0x00010000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define CG6_FBC_DRAW_ILLEGAL 0x00018000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define CG6_FBC_DRAW_MASK 0x00018000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define CG6_FBC_BWRITE0_IGNORE 0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define CG6_FBC_BWRITE0_ENABLE 0x00002000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define CG6_FBC_BWRITE0_DISABLE 0x00004000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define CG6_FBC_BWRITE0_ILLEGAL 0x00006000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define CG6_FBC_BWRITE0_MASK 0x00006000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define CG6_FBC_BWRITE1_IGNORE 0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define CG6_FBC_BWRITE1_ENABLE 0x00000800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define CG6_FBC_BWRITE1_DISABLE 0x00001000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define CG6_FBC_BWRITE1_ILLEGAL 0x00001800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define CG6_FBC_BWRITE1_MASK 0x00001800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define CG6_FBC_BREAD_IGNORE 0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define CG6_FBC_BREAD_0 0x00000200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define CG6_FBC_BREAD_1 0x00000400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define CG6_FBC_BREAD_ILLEGAL 0x00000600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define CG6_FBC_BREAD_MASK 0x00000600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define CG6_FBC_BDISP_IGNORE 0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define CG6_FBC_BDISP_0 0x00000080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define CG6_FBC_BDISP_1 0x00000100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define CG6_FBC_BDISP_ILLEGAL 0x00000180
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define CG6_FBC_BDISP_MASK 0x00000180
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define CG6_FBC_INDEX_MOD 0x00000040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define CG6_FBC_INDEX_MASK 0x00000030
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* THC definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define CG6_THC_MISC_REV_SHIFT 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define CG6_THC_MISC_REV_MASK 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define CG6_THC_MISC_RESET (1 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define CG6_THC_MISC_VIDEO (1 << 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define CG6_THC_MISC_SYNC (1 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define CG6_THC_MISC_VSYNC (1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define CG6_THC_MISC_SYNC_ENAB (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define CG6_THC_MISC_CURS_RES (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define CG6_THC_MISC_INT_ENAB (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define CG6_THC_MISC_INT (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define CG6_THC_MISC_INIT 0x9f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define CG6_THC_CURSOFF ((65536-32) | ((65536-32) << 16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /* The contents are unknown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct cg6_tec {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int tec_matrix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) int tec_clip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int tec_vdc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct cg6_thc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) u32 thc_pad0[512];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) u32 thc_hs; /* hsync timing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) u32 thc_hsdvs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) u32 thc_hd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) u32 thc_vs; /* vsync timing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) u32 thc_vd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) u32 thc_refresh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) u32 thc_misc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) u32 thc_pad1[56];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) u32 thc_cursxy; /* cursor x,y position (16 bits each) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) u32 thc_cursmask[32]; /* cursor mask bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) u32 thc_cursbits[32]; /* what to show where mask enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct cg6_fbc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) u32 xxx0[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) u32 mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) u32 clip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) u32 xxx1[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) u32 s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) u32 draw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) u32 blit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) u32 font;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u32 xxx2[24];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) u32 x0, y0, z0, color0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) u32 x1, y1, z1, color1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) u32 x2, y2, z2, color2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) u32 x3, y3, z3, color3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) u32 offx, offy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) u32 xxx3[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) u32 incx, incy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) u32 xxx4[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) u32 clipminx, clipminy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) u32 xxx5[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) u32 clipmaxx, clipmaxy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) u32 xxx6[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) u32 fg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) u32 bg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) u32 alu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) u32 pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) u32 pixelm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) u32 xxx7[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) u32 patalign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) u32 pattern[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) u32 xxx8[432];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) u32 apointx, apointy, apointz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) u32 xxx9[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) u32 rpointx, rpointy, rpointz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) u32 xxx10[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) u32 pointr, pointg, pointb, pointa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) u32 alinex, aliney, alinez;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) u32 xxx11[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) u32 rlinex, rliney, rlinez;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) u32 xxx12[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) u32 liner, lineg, lineb, linea;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) u32 atrix, atriy, atriz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) u32 xxx13[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) u32 rtrix, rtriy, rtriz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) u32 xxx14[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) u32 trir, trig, trib, tria;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u32 aquadx, aquady, aquadz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u32 xxx15[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) u32 rquadx, rquady, rquadz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) u32 xxx16[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) u32 quadr, quadg, quadb, quada;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) u32 arectx, arecty, arectz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) u32 xxx17[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) u32 rrectx, rrecty, rrectz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) u32 xxx18[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) u32 rectr, rectg, rectb, recta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct bt_regs {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) u32 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) u32 color_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) u32 control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) u32 cursor;
^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) struct cg6_par {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) struct bt_regs __iomem *bt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct cg6_fbc __iomem *fbc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct cg6_thc __iomem *thc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct cg6_tec __iomem *tec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) u32 __iomem *fhc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) u32 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) #define CG6_FLAG_BLANKED 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) unsigned long which_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static int cg6_sync(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct cg6_par *par = (struct cg6_par *)info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct cg6_fbc __iomem *fbc = par->fbc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) int limit = 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (!(sbus_readl(&fbc->s) & 0x10000000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) } while (--limit > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return 0;
^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 cg6_switch_from_graph(struct cg6_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) struct cg6_thc __iomem *thc = par->thc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) spin_lock_irqsave(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* Hide the cursor. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) spin_unlock_irqrestore(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static int cg6_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct cg6_par *par = (struct cg6_par *)info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* We just use this to catch switches out of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * graphics mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) cg6_switch_from_graph(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (var->xoffset || var->yoffset || var->vmode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * cg6_fillrect - Draws a rectangle on the screen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * @info: frame buffer structure that represents a single frame buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * @rect: structure defining the rectagle and operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static void cg6_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct cg6_par *par = (struct cg6_par *)info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct cg6_fbc __iomem *fbc = par->fbc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) s32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /* CG6 doesn't handle ROP_XOR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) spin_lock_irqsave(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) cg6_sync(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) sbus_writel(rect->color, &fbc->fg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) sbus_writel(~(u32)0, &fbc->pixelm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) sbus_writel(0xea80ff00, &fbc->alu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) sbus_writel(0, &fbc->s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) sbus_writel(0, &fbc->clip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) sbus_writel(~(u32)0, &fbc->pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) sbus_writel(rect->dy, &fbc->arecty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) sbus_writel(rect->dx, &fbc->arectx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) sbus_writel(rect->dy + rect->height, &fbc->arecty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) sbus_writel(rect->dx + rect->width, &fbc->arectx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) val = sbus_readl(&fbc->draw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) } while (val < 0 && (val & 0x20000000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) spin_unlock_irqrestore(&par->lock, flags);
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * cg6_copyarea - Copies one area of the screen to another area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * @info: frame buffer structure that represents a single frame buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * @area: Structure providing the data to copy the framebuffer contents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * from one region to another.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * This drawing operation copies a rectangular area from one area of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * screen to another area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct cg6_par *par = (struct cg6_par *)info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) struct cg6_fbc __iomem *fbc = par->fbc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) spin_lock_irqsave(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) cg6_sync(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) sbus_writel(0xff, &fbc->fg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) sbus_writel(0x00, &fbc->bg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) sbus_writel(~0, &fbc->pixelm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) sbus_writel(0xe880cccc, &fbc->alu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) sbus_writel(0, &fbc->s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) sbus_writel(0, &fbc->clip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) sbus_writel(area->sy, &fbc->y0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) sbus_writel(area->sx, &fbc->x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) sbus_writel(area->sy + area->height - 1, &fbc->y1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) sbus_writel(area->sx + area->width - 1, &fbc->x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) sbus_writel(area->dy, &fbc->y2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) sbus_writel(area->dx, &fbc->x2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) sbus_writel(area->dy + area->height - 1, &fbc->y3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) sbus_writel(area->dx + area->width - 1, &fbc->x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) i = sbus_readl(&fbc->blit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) } while (i < 0 && (i & 0x20000000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) spin_unlock_irqrestore(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * cg6_imageblit - Copies a image from system memory to the screen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) * @info: frame buffer structure that represents a single frame buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * @image: structure defining the image.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static void cg6_imageblit(struct fb_info *info, const struct fb_image *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct cg6_par *par = (struct cg6_par *)info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) struct cg6_fbc __iomem *fbc = par->fbc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) const u8 *data = image->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) u32 x, y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int i, width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (image->depth > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) cfb_imageblit(info, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) spin_lock_irqsave(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) cg6_sync(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) sbus_writel(image->fg_color, &fbc->fg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) sbus_writel(image->bg_color, &fbc->bg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) sbus_writel(0x140000, &fbc->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) sbus_writel(0xe880fc30, &fbc->alu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) sbus_writel(~(u32)0, &fbc->pixelm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) sbus_writel(0, &fbc->s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) sbus_writel(0, &fbc->clip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) sbus_writel(0xff, &fbc->pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) sbus_writel(32, &fbc->incx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) sbus_writel(0, &fbc->incy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) x = image->dx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) y = image->dy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) for (i = 0; i < image->height; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) width = image->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) while (width >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) sbus_writel(y, &fbc->y0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) sbus_writel(x, &fbc->x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) sbus_writel(x + 32 - 1, &fbc->x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) val = ((u32)data[0] << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) ((u32)data[1] << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) ((u32)data[2] << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) ((u32)data[3] << 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) sbus_writel(val, &fbc->font);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) data += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) x += 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) width -= 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) sbus_writel(y, &fbc->y0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) sbus_writel(x, &fbc->x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) sbus_writel(x + width - 1, &fbc->x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (width <= 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) val = (u32) data[0] << 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) data += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) } else if (width <= 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) val = ((u32) data[0] << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ((u32) data[1] << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) data += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) val = ((u32) data[0] << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ((u32) data[1] << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) ((u32) data[2] << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) data += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) sbus_writel(val, &fbc->font);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) y += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) x = image->dx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) spin_unlock_irqrestore(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * cg6_setcolreg - Sets a color register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * @regno: boolean, 0 copy local, 1 get_user() function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * @red: frame buffer colormap structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * @green: The green value which can be up to 16 bits wide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * @blue: The blue value which can be up to 16 bits wide.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * @transp: If supported the alpha value which can be up to 16 bits wide.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) * @info: frame buffer info structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static int cg6_setcolreg(unsigned regno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) unsigned red, unsigned green, unsigned blue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) unsigned transp, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct cg6_par *par = (struct cg6_par *)info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct bt_regs __iomem *bt = par->bt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (regno >= 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) red >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) green >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) blue >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) spin_lock_irqsave(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) sbus_writel((u32)regno << 24, &bt->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) sbus_writel((u32)red << 24, &bt->color_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) sbus_writel((u32)green << 24, &bt->color_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) sbus_writel((u32)blue << 24, &bt->color_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) spin_unlock_irqrestore(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * cg6_blank - Blanks the display.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * @blank_mode: the blank mode we want.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) * @info: frame buffer structure that represents a single frame buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static int cg6_blank(int blank, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct cg6_par *par = (struct cg6_par *)info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) struct cg6_thc __iomem *thc = par->thc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) spin_lock_irqsave(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) val = sbus_readl(&thc->thc_misc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) switch (blank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) case FB_BLANK_UNBLANK: /* Unblanking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) val |= CG6_THC_MISC_VIDEO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) par->flags &= ~CG6_FLAG_BLANKED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) case FB_BLANK_NORMAL: /* Normal blanking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) case FB_BLANK_POWERDOWN: /* Poweroff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) val &= ~CG6_THC_MISC_VIDEO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) par->flags |= CG6_FLAG_BLANKED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) sbus_writel(val, &thc->thc_misc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) spin_unlock_irqrestore(&par->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static struct sbus_mmap_map cg6_mmap_map[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) .voff = CG6_FBC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) .poff = CG6_FBC_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) .size = PAGE_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) .voff = CG6_TEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) .poff = CG6_TEC_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) .size = PAGE_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) .voff = CG6_BTREGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) .poff = CG6_BROOKTREE_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) .size = PAGE_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) .voff = CG6_FHC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) .poff = CG6_FHC_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) .size = PAGE_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) .voff = CG6_THC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) .poff = CG6_THC_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) .size = PAGE_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) .voff = CG6_ROM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) .poff = CG6_ROM_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) .size = 0x10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) .voff = CG6_RAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) .poff = CG6_RAM_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) .size = SBUS_MMAP_FBSIZE(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) .voff = CG6_DHC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) .poff = CG6_DHC_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) .size = 0x40000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) { .size = 0 }
^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) static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct cg6_par *par = (struct cg6_par *)info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return sbusfb_mmap_helper(cg6_mmap_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) info->fix.smem_start, info->fix.smem_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) par->which_io, vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return sbusfb_ioctl_helper(cmd, arg, info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) FBTYPE_SUNFAST_COLOR, 8, info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) * Initialisation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) static void cg6_init_fix(struct fb_info *info, int linebytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) struct cg6_par *par = (struct cg6_par *)info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) const char *cg6_cpu_name, *cg6_card_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) u32 conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) conf = sbus_readl(par->fhc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) switch (conf & CG6_FHC_CPU_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) case CG6_FHC_CPU_SPARC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) cg6_cpu_name = "sparc";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) case CG6_FHC_CPU_68020:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) cg6_cpu_name = "68020";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) cg6_cpu_name = "i386";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (info->fix.smem_len <= 0x100000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) cg6_card_name = "TGX";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) cg6_card_name = "TGX+";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (info->fix.smem_len <= 0x100000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) cg6_card_name = "GX";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) cg6_card_name = "GX+";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) sprintf(info->fix.id, "%s %s", cg6_card_name, cg6_cpu_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) info->fix.id[sizeof(info->fix.id) - 1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) info->fix.type = FB_TYPE_PACKED_PIXELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) info->fix.line_length = linebytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) info->fix.accel = FB_ACCEL_SUN_CGSIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) /* Initialize Brooktree DAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) static void cg6_bt_init(struct cg6_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) struct bt_regs __iomem *bt = par->bt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) sbus_writel(0x04 << 24, &bt->addr); /* color planes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) sbus_writel(0xff << 24, &bt->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) sbus_writel(0x05 << 24, &bt->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) sbus_writel(0x00 << 24, &bt->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) sbus_writel(0x06 << 24, &bt->addr); /* overlay plane */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) sbus_writel(0x73 << 24, &bt->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) sbus_writel(0x07 << 24, &bt->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) sbus_writel(0x00 << 24, &bt->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) static void cg6_chip_init(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct cg6_par *par = (struct cg6_par *)info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) struct cg6_tec __iomem *tec = par->tec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct cg6_fbc __iomem *fbc = par->fbc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct cg6_thc __iomem *thc = par->thc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) u32 rev, conf, mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) /* Hide the cursor. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) /* Turn off stuff in the Transform Engine. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) sbus_writel(0, &tec->tec_matrix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) sbus_writel(0, &tec->tec_clip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) sbus_writel(0, &tec->tec_vdc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /* Take care of bugs in old revisions. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) rev = (sbus_readl(par->fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (rev < 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) conf = (sbus_readl(par->fhc) & CG6_FHC_RES_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) CG6_FHC_CPU_68020 | CG6_FHC_TEST |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) (11 << CG6_FHC_TEST_X_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) (11 << CG6_FHC_TEST_Y_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (rev < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) conf |= CG6_FHC_DST_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) sbus_writel(conf, par->fhc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /* Set things in the FBC. Bad things appear to happen if we do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * back to back store/loads on the mode register, so copy it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * out instead. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) mode = sbus_readl(&fbc->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) i = sbus_readl(&fbc->s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) } while (i & 0x10000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) CG6_FBC_BDISP_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) CG6_FBC_BDISP_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) sbus_writel(mode, &fbc->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) sbus_writel(0, &fbc->clip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) sbus_writel(0, &fbc->offx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) sbus_writel(0, &fbc->offy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) sbus_writel(0, &fbc->clipminx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) sbus_writel(0, &fbc->clipminy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) sbus_writel(info->var.xres - 1, &fbc->clipmaxx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) sbus_writel(info->var.yres - 1, &fbc->clipmaxy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) static void cg6_unmap_regs(struct platform_device *op, struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) struct cg6_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (par->fbc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) of_iounmap(&op->resource[0], par->fbc, 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (par->tec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) of_iounmap(&op->resource[0], par->tec, sizeof(struct cg6_tec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (par->thc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) of_iounmap(&op->resource[0], par->thc, sizeof(struct cg6_thc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (par->bt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) of_iounmap(&op->resource[0], par->bt, sizeof(struct bt_regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (par->fhc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) of_iounmap(&op->resource[0], par->fhc, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (info->screen_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) of_iounmap(&op->resource[0], info->screen_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) static int cg6_probe(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) struct device_node *dp = op->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) struct cg6_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) int linebytes, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) int dblbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) info = framebuffer_alloc(sizeof(struct cg6_par), &op->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) spin_lock_init(&par->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) info->fix.smem_start = op->resource[0].start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) par->which_io = op->resource[0].flags & IORESOURCE_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) sbusfb_fill_var(&info->var, dp, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) info->var.red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) info->var.green.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) info->var.blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) linebytes = of_getintprop_default(dp, "linebytes",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) info->var.xres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) dblbuf = of_getintprop_default(dp, "dblbuf", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (dblbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) info->fix.smem_len *= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) par->fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 4096, "cgsix fbc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) par->tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) sizeof(struct cg6_tec), "cgsix tec");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) par->thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) sizeof(struct cg6_thc), "cgsix thc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) par->bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) sizeof(struct bt_regs), "cgsix dac");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) par->fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) sizeof(u32), "cgsix fhc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) FBINFO_READS_FAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) info->fbops = &cg6_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) info->screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) info->fix.smem_len, "cgsix ram");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (!par->fbc || !par->tec || !par->thc ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) !par->bt || !par->fhc || !info->screen_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) goto out_unmap_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) info->var.accel_flags = FB_ACCELF_TEXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) cg6_bt_init(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) cg6_chip_init(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) cg6_blank(FB_BLANK_UNBLANK, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (fb_alloc_cmap(&info->cmap, 256, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) goto out_unmap_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) fb_set_cmap(&info->cmap, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) cg6_init_fix(info, linebytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) err = register_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) goto out_dealloc_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) dev_set_drvdata(&op->dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) printk(KERN_INFO "%pOF: CGsix [%s] at %lx:%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) dp, info->fix.id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) par->which_io, info->fix.smem_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) out_dealloc_cmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) out_unmap_regs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) cg6_unmap_regs(op, info, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) static int cg6_remove(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) struct fb_info *info = dev_get_drvdata(&op->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) struct cg6_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) cg6_unmap_regs(op, info, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) static const struct of_device_id cg6_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) .name = "cgsix",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) .name = "cgthree+",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) MODULE_DEVICE_TABLE(of, cg6_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) static struct platform_driver cg6_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) .name = "cg6",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) .of_match_table = cg6_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) .probe = cg6_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) .remove = cg6_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) static int __init cg6_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (fb_get_options("cg6fb", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return platform_driver_register(&cg6_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) static void __exit cg6_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) platform_driver_unregister(&cg6_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) module_init(cg6_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) module_exit(cg6_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) MODULE_DESCRIPTION("framebuffer driver for CGsix chipsets");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) MODULE_VERSION("2.0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) MODULE_LICENSE("GPL");