^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Frame Buffer Device for Toshiba Mobile IO(TMIO) controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright(C) 2005-2006 Chris Humbert
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright(C) 2005 Dirk Opfer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copytight(C) 2007,2008 Dmitry Baryshkov
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Based on:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * drivers/video/w100fb.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * code written by Sharp/Lineo for 2.4 kernels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/platform_device.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/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* Why should fb driver call console functions? because console_lock() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/mfd/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/mfd/tmio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * accelerator commands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define TMIOFB_ACC_CSADR(x) (0x00000000 | ((x) & 0x001ffffe))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define TMIOFB_ACC_CHPIX(x) (0x01000000 | ((x) & 0x000003ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define TMIOFB_ACC_CVPIX(x) (0x02000000 | ((x) & 0x000003ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define TMIOFB_ACC_PSADR(x) (0x03000000 | ((x) & 0x00fffffe))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define TMIOFB_ACC_PHPIX(x) (0x04000000 | ((x) & 0x000003ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define TMIOFB_ACC_PVPIX(x) (0x05000000 | ((x) & 0x000003ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define TMIOFB_ACC_PHOFS(x) (0x06000000 | ((x) & 0x000003ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define TMIOFB_ACC_PVOFS(x) (0x07000000 | ((x) & 0x000003ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define TMIOFB_ACC_POADR(x) (0x08000000 | ((x) & 0x00fffffe))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define TMIOFB_ACC_RSTR(x) (0x09000000 | ((x) & 0x000000ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define TMIOFB_ACC_TCLOR(x) (0x0A000000 | ((x) & 0x0000ffff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define TMIOFB_ACC_FILL(x) (0x0B000000 | ((x) & 0x0000ffff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define TMIOFB_ACC_DSADR(x) (0x0C000000 | ((x) & 0x00fffffe))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define TMIOFB_ACC_SSADR(x) (0x0D000000 | ((x) & 0x00fffffe))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define TMIOFB_ACC_DHPIX(x) (0x0E000000 | ((x) & 0x000003ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define TMIOFB_ACC_DVPIX(x) (0x0F000000 | ((x) & 0x000003ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define TMIOFB_ACC_SHPIX(x) (0x10000000 | ((x) & 0x000003ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define TMIOFB_ACC_SVPIX(x) (0x11000000 | ((x) & 0x000003ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define TMIOFB_ACC_LBINI(x) (0x12000000 | ((x) & 0x0000ffff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define TMIOFB_ACC_LBK2(x) (0x13000000 | ((x) & 0x0000ffff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define TMIOFB_ACC_SHBINI(x) (0x14000000 | ((x) & 0x0000ffff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define TMIOFB_ACC_SHBK2(x) (0x15000000 | ((x) & 0x0000ffff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define TMIOFB_ACC_SVBINI(x) (0x16000000 | ((x) & 0x0000ffff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define TMIOFB_ACC_SVBK2(x) (0x17000000 | ((x) & 0x0000ffff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define TMIOFB_ACC_CMGO 0x20000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define TMIOFB_ACC_CMGO_CEND 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define TMIOFB_ACC_CMGO_INT 0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define TMIOFB_ACC_CMGO_CMOD 0x00000010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define TMIOFB_ACC_CMGO_CDVRV 0x00000020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define TMIOFB_ACC_CMGO_CDHRV 0x00000040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define TMIOFB_ACC_CMGO_RUND 0x00008000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define TMIOFB_ACC_SCGO 0x21000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define TMIOFB_ACC_SCGO_CEND 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define TMIOFB_ACC_SCGO_INT 0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define TMIOFB_ACC_SCGO_ROP3 0x00000004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define TMIOFB_ACC_SCGO_TRNS 0x00000008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define TMIOFB_ACC_SCGO_DVRV 0x00000010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define TMIOFB_ACC_SCGO_DHRV 0x00000020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define TMIOFB_ACC_SCGO_SVRV 0x00000040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define TMIOFB_ACC_SCGO_SHRV 0x00000080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define TMIOFB_ACC_SCGO_DSTXY 0x00008000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define TMIOFB_ACC_SBGO 0x22000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define TMIOFB_ACC_SBGO_CEND 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define TMIOFB_ACC_SBGO_INT 0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define TMIOFB_ACC_SBGO_DVRV 0x00000010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define TMIOFB_ACC_SBGO_DHRV 0x00000020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define TMIOFB_ACC_SBGO_SVRV 0x00000040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define TMIOFB_ACC_SBGO_SHRV 0x00000080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define TMIOFB_ACC_SBGO_SBMD 0x00000100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define TMIOFB_ACC_FLGO 0x23000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define TMIOFB_ACC_FLGO_CEND 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define TMIOFB_ACC_FLGO_INT 0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define TMIOFB_ACC_FLGO_ROP3 0x00000004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define TMIOFB_ACC_LDGO 0x24000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define TMIOFB_ACC_LDGO_CEND 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define TMIOFB_ACC_LDGO_INT 0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define TMIOFB_ACC_LDGO_ROP3 0x00000004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define TMIOFB_ACC_LDGO_ENDPX 0x00000008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define TMIOFB_ACC_LDGO_LVRV 0x00000010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define TMIOFB_ACC_LDGO_LHRV 0x00000020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define TMIOFB_ACC_LDGO_LDMOD 0x00000040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* a FIFO is always allocated, even if acceleration is not used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define TMIOFB_FIFO_SIZE 512
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * LCD Host Controller Configuration Register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * This iomem area supports only 16-bit IO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define CCR_CMD 0x04 /* Command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define CCR_REVID 0x08 /* Revision ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define CCR_BASEL 0x10 /* LCD Control Reg Base Addr Low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define CCR_BASEH 0x12 /* LCD Control Reg Base Addr High */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define CCR_UGCC 0x40 /* Unified Gated Clock Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define CCR_GCC 0x42 /* Gated Clock Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define CCR_USC 0x50 /* Unified Software Clear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define CCR_VRAMRTC 0x60 /* VRAM Timing Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* 0x61 VRAM Refresh Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define CCR_VRAMSAC 0x62 /* VRAM Access Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* 0x63 VRAM Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define CCR_VRAMBC 0x64 /* VRAM Block Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * LCD Control Register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * This iomem area supports only 16-bit IO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define LCR_UIS 0x000 /* Unified Interrupt Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define LCR_VHPN 0x008 /* VRAM Horizontal Pixel Number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define LCR_CFSAL 0x00a /* Command FIFO Start Address Low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define LCR_CFSAH 0x00c /* Command FIFO Start Address High */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define LCR_CFS 0x00e /* Command FIFO Size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define LCR_CFWS 0x010 /* Command FIFO Writeable Size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define LCR_BBIE 0x012 /* BitBLT Interrupt Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define LCR_BBISC 0x014 /* BitBLT Interrupt Status and Clear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define LCR_CCS 0x016 /* Command Count Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define LCR_BBES 0x018 /* BitBLT Execution Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define LCR_CMDL 0x01c /* Command Low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define LCR_CMDH 0x01e /* Command High */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define LCR_CFC 0x022 /* Command FIFO Clear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define LCR_CCIFC 0x024 /* CMOS Camera IF Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define LCR_HWT 0x026 /* Hardware Test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define LCR_LCDCCRC 0x100 /* LCDC Clock and Reset Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define LCR_LCDCC 0x102 /* LCDC Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define LCR_LCDCOPC 0x104 /* LCDC Output Pin Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define LCR_LCDIS 0x108 /* LCD Interrupt Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define LCR_LCDIM 0x10a /* LCD Interrupt Mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define LCR_LCDIE 0x10c /* LCD Interrupt Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define LCR_GDSAL 0x122 /* Graphics Display Start Address Low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define LCR_GDSAH 0x124 /* Graphics Display Start Address High */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define LCR_VHPCL 0x12a /* VRAM Horizontal Pixel Count Low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define LCR_VHPCH 0x12c /* VRAM Horizontal Pixel Count High */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define LCR_GM 0x12e /* Graphic Mode(VRAM access enable) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define LCR_HT 0x140 /* Horizontal Total */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define LCR_HDS 0x142 /* Horizontal Display Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define LCR_HSS 0x144 /* H-Sync Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define LCR_HSE 0x146 /* H-Sync End */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define LCR_HNP 0x14c /* Horizontal Number of Pixels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define LCR_VT 0x150 /* Vertical Total */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define LCR_VDS 0x152 /* Vertical Display Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define LCR_VSS 0x154 /* V-Sync Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define LCR_VSE 0x156 /* V-Sync End */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define LCR_CDLN 0x160 /* Current Display Line Number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define LCR_ILN 0x162 /* Interrupt Line Number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define LCR_SP 0x164 /* Sync Polarity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define LCR_MISC 0x166 /* MISC(RGB565 mode) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define LCR_VIHSS 0x16a /* Video Interface H-Sync Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define LCR_VIVS 0x16c /* Video Interface Vertical Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define LCR_VIVE 0x16e /* Video Interface Vertical End */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define LCR_VIVSS 0x170 /* Video Interface V-Sync Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define LCR_VCCIS 0x17e /* Video / CMOS Camera Interface Select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define LCR_VIDWSAL 0x180 /* VI Data Write Start Address Low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define LCR_VIDWSAH 0x182 /* VI Data Write Start Address High */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define LCR_VIDRSAL 0x184 /* VI Data Read Start Address Low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define LCR_VIDRSAH 0x186 /* VI Data Read Start Address High */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define LCR_VIPDDST 0x188 /* VI Picture Data Display Start Timing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define LCR_VIPDDET 0x186 /* VI Picture Data Display End Timing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define LCR_VIE 0x18c /* Video Interface Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define LCR_VCS 0x18e /* Video/Camera Select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #define LCR_VPHWC 0x194 /* Video Picture Horizontal Wait Count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define LCR_VPHS 0x196 /* Video Picture Horizontal Size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #define LCR_VPVWC 0x198 /* Video Picture Vertical Wait Count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define LCR_VPVS 0x19a /* Video Picture Vertical Size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define LCR_PLHPIX 0x1a0 /* PLHPIX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #define LCR_XS 0x1a2 /* XStart */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #define LCR_XCKHW 0x1a4 /* XCK High Width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define LCR_STHS 0x1a8 /* STH Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define LCR_VT2 0x1aa /* Vertical Total */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #define LCR_YCKSW 0x1ac /* YCK Start Wait */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define LCR_YSTS 0x1ae /* YST Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define LCR_PPOLS 0x1b0 /* #PPOL Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define LCR_PRECW 0x1b2 /* PREC Width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define LCR_VCLKHW 0x1b4 /* VCLK High Width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define LCR_OC 0x1b6 /* Output Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static char *mode_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct tmiofb_par {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) u32 pseudo_palette[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #ifdef CONFIG_FB_TMIO_ACCELL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) wait_queue_head_t wait_acc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) bool use_polling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) void __iomem *ccr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) void __iomem *lcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /*--------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * reasons for an interrupt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * uis bbisc lcdis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * 0100 0001 accelerator command completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * 2000 0001 vsync start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * 2000 0002 display start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * 2000 0004 line number match(0x1ff mask???)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static irqreturn_t tmiofb_irq(int irq, void *__info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct fb_info *info = __info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct tmiofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) unsigned int bbisc = tmio_ioread16(par->lcr + LCR_BBISC);
^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) tmio_iowrite16(bbisc, par->lcr + LCR_BBISC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) #ifdef CONFIG_FB_TMIO_ACCELL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * We were in polling mode and now we got correct irq.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * Switch back to IRQ-based sync of command FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (unlikely(par->use_polling && irq != -1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) printk(KERN_INFO "tmiofb: switching to waitq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) par->use_polling = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (bbisc & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) wake_up(&par->wait_acc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /*--------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * Turns off the LCD controller and LCD host controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static int tmiofb_hw_stop(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct tmio_fb_data *data = dev_get_platdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct fb_info *info = platform_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct tmiofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) tmio_iowrite16(0, par->ccr + CCR_UGCC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) tmio_iowrite16(0, par->lcr + LCR_GM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) data->lcd_set_power(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * Initializes the LCD host controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static int tmiofb_hw_init(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) const struct mfd_cell *cell = mfd_get_cell(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct fb_info *info = platform_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct tmiofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) const struct resource *nlcr = &cell->resources[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) const struct resource *vram = &cell->resources[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) unsigned long base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (nlcr == NULL || vram == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) base = nlcr->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) tmio_iowrite16(0x003a, par->ccr + CCR_UGCC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) tmio_iowrite16(0x003a, par->ccr + CCR_GCC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) tmio_iowrite16(0x3f00, par->ccr + CCR_USC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) msleep(2); /* wait for device to settle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) tmio_iowrite16(0x0000, par->ccr + CCR_USC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) tmio_iowrite16(base >> 16, par->ccr + CCR_BASEH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) tmio_iowrite16(base, par->ccr + CCR_BASEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) tmio_iowrite16(0x0002, par->ccr + CCR_CMD); /* base address enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) tmio_iowrite16(0x40a8, par->ccr + CCR_VRAMRTC); /* VRAMRC, VRAMTC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) tmio_iowrite16(0x0018, par->ccr + CCR_VRAMSAC); /* VRAMSTS, VRAMAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) tmio_iowrite16(0x0002, par->ccr + CCR_VRAMBC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) msleep(2); /* wait for device to settle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) tmio_iowrite16(0x000b, par->ccr + CCR_VRAMBC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) base = vram->start + info->screen_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) tmio_iowrite16(base >> 16, par->lcr + LCR_CFSAH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) tmio_iowrite16(base, par->lcr + LCR_CFSAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) tmio_iowrite16(TMIOFB_FIFO_SIZE - 1, par->lcr + LCR_CFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) tmio_iowrite16(1, par->lcr + LCR_CFC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) tmio_iowrite16(1, par->lcr + LCR_BBIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) tmio_iowrite16(0, par->lcr + LCR_CFWS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * Sets the LCD controller's output resolution and pixel clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static void tmiofb_hw_mode(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct tmio_fb_data *data = dev_get_platdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) struct fb_info *info = platform_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct fb_videomode *mode = info->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct tmiofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) tmio_iowrite16(0, par->lcr + LCR_GM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) data->lcd_set_power(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) data->lcd_mode(dev, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) data->lcd_set_power(dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) tmio_iowrite16(info->fix.line_length, par->lcr + LCR_VHPN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) tmio_iowrite16(0, par->lcr + LCR_GDSAH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) tmio_iowrite16(0, par->lcr + LCR_GDSAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) tmio_iowrite16(info->fix.line_length >> 16, par->lcr + LCR_VHPCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) tmio_iowrite16(info->fix.line_length, par->lcr + LCR_VHPCL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) tmio_iowrite16(i = 0, par->lcr + LCR_HSS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) tmio_iowrite16(i += mode->hsync_len, par->lcr + LCR_HSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) tmio_iowrite16(i += mode->left_margin, par->lcr + LCR_HDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) tmio_iowrite16(i += mode->xres + mode->right_margin, par->lcr + LCR_HT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) tmio_iowrite16(mode->xres, par->lcr + LCR_HNP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) tmio_iowrite16(i = 0, par->lcr + LCR_VSS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) tmio_iowrite16(i += mode->vsync_len, par->lcr + LCR_VSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) tmio_iowrite16(i += mode->upper_margin, par->lcr + LCR_VDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) tmio_iowrite16(i += mode->yres, par->lcr + LCR_ILN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) tmio_iowrite16(i += mode->lower_margin, par->lcr + LCR_VT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) tmio_iowrite16(3, par->lcr + LCR_MISC); /* RGB565 mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) tmio_iowrite16(1, par->lcr + LCR_GM); /* VRAM enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) tmio_iowrite16(0x4007, par->lcr + LCR_LCDCC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) tmio_iowrite16(3, par->lcr + LCR_SP); /* sync polarity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) msleep(5); /* wait for device to settle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) tmio_iowrite16(0x0014, par->lcr + LCR_LCDCCRC); /* STOP_CKP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) msleep(5); /* wait for device to settle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) tmio_iowrite16(0x0015, par->lcr + LCR_LCDCCRC); /* STOP_CKP|SOFT_RESET*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) tmio_iowrite16(0xfffa, par->lcr + LCR_VCS);
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) #ifdef CONFIG_FB_TMIO_ACCELL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static int __must_check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) tmiofb_acc_wait(struct fb_info *info, unsigned int ccs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct tmiofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * This code can be called with interrupts disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * So instead of relaying on irq to trigger the event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * poll the state till the necessary command is executed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (irqs_disabled() || par->use_polling) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) while (tmio_ioread16(par->lcr + LCR_CCS) > ccs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (i > 10000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) pr_err("tmiofb: timeout waiting for %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) ccs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) tmiofb_irq(-1, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (!wait_event_interruptible_timeout(par->wait_acc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) tmio_ioread16(par->lcr + LCR_CCS) <= ccs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 1000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) pr_err("tmiofb: timeout waiting for %d\n", ccs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * Writes an accelerator command to the accelerator's FIFO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) tmiofb_acc_write(struct fb_info *info, const u32 *cmd, unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) struct tmiofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) ret = tmiofb_acc_wait(info, TMIOFB_FIFO_SIZE - count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) for (; count; count--, cmd++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) tmio_iowrite16(*cmd >> 16, par->lcr + LCR_CMDH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) tmio_iowrite16(*cmd, par->lcr + LCR_CMDL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * Wait for the accelerator to finish its operations before writing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * to the framebuffer for consistent display output.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static int tmiofb_sync(struct fb_info *fbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct tmiofb_par *par = fbi->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) ret = tmiofb_acc_wait(fbi, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) while (tmio_ioread16(par->lcr + LCR_BBES) & 2) { /* blit active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) i++ ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (i > 10000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) printk(KERN_ERR "timeout waiting for blit to end!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) tmiofb_fillrect(struct fb_info *fbi, const struct fb_fillrect *rect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) const u32 cmd[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) TMIOFB_ACC_DSADR((rect->dy * fbi->mode->xres + rect->dx) * 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) TMIOFB_ACC_DHPIX(rect->width - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) TMIOFB_ACC_DVPIX(rect->height - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) TMIOFB_ACC_FILL(rect->color),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) TMIOFB_ACC_FLGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (fbi->state != FBINFO_STATE_RUNNING ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) fbi->flags & FBINFO_HWACCEL_DISABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) cfb_fillrect(fbi, rect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd));
^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
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) tmiofb_copyarea(struct fb_info *fbi, const struct fb_copyarea *area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) const u32 cmd[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) TMIOFB_ACC_DSADR((area->dy * fbi->mode->xres + area->dx) * 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) TMIOFB_ACC_DHPIX(area->width - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) TMIOFB_ACC_DVPIX(area->height - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) TMIOFB_ACC_SSADR((area->sy * fbi->mode->xres + area->sx) * 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) TMIOFB_ACC_SCGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (fbi->state != FBINFO_STATE_RUNNING ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) fbi->flags & FBINFO_HWACCEL_DISABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) cfb_copyarea(fbi, area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return;
^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) tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) static void tmiofb_clearscreen(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) const struct fb_fillrect rect = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) .dx = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) .dy = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) .width = info->mode->xres,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) .height = info->mode->yres,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) .color = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) .rop = ROP_COPY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) info->fbops->fb_fillrect(info, &rect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static int tmiofb_vblank(struct fb_info *fbi, struct fb_vblank *vblank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) struct tmiofb_par *par = fbi->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) struct fb_videomode *mode = fbi->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) unsigned int vcount = tmio_ioread16(par->lcr + LCR_CDLN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) unsigned int vds = mode->vsync_len + mode->upper_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) vblank->vcount = vcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) vblank->flags = FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_VCOUNT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) | FB_VBLANK_HAVE_VSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (vcount < mode->vsync_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) vblank->flags |= FB_VBLANK_VSYNCING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (vcount < vds || vcount > vds + mode->yres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) vblank->flags |= FB_VBLANK_VBLANKING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static int tmiofb_ioctl(struct fb_info *fbi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) case FBIOGET_VBLANK: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct fb_vblank vblank = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) void __user *argp = (void __user *) arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) tmiofb_vblank(fbi, &vblank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (copy_to_user(argp, &vblank, sizeof vblank))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) #ifdef CONFIG_FB_TMIO_ACCELL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) case FBIO_TMIO_ACC_SYNC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) tmiofb_sync(fbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) case FBIO_TMIO_ACC_WRITE: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) u32 __user *argp = (void __user *) arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) u32 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) u32 acc[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (get_user(len, argp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (len > ARRAY_SIZE(acc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (copy_from_user(acc, argp + 1, sizeof(u32) * len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return tmiofb_acc_write(fbi, acc, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /*--------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /* Select the smallest mode that allows the desired resolution to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * displayed. If desired, the x and y parameters can be rounded up to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * match the selected mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) static struct fb_videomode *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) struct tmio_fb_data *data = dev_get_platdata(info->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct fb_videomode *best = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) for (i = 0; i < data->num_modes; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct fb_videomode *mode = data->modes + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (mode->xres >= var->xres && mode->yres >= var->yres
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) && (!best || (mode->xres < best->xres
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) && mode->yres < best->yres)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) best = mode;
^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) return best;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) struct fb_videomode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) struct tmio_fb_data *data = dev_get_platdata(info->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) mode = tmiofb_find_mode(info, var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (!mode || var->bits_per_pixel > 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) fb_videomode_to_var(var, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) var->xres_virtual = mode->xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) var->yres_virtual = info->screen_size / (mode->xres * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (var->yres_virtual < var->yres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) var->xoffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) var->yoffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) var->bits_per_pixel = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) var->grayscale = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) var->red.offset = 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) var->red.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) var->green.offset = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) var->green.length = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) var->blue.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) var->transp.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) var->transp.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) var->nonstd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) var->height = data->height; /* mm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) var->width = data->width; /* mm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) var->rotate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) static int tmiofb_set_par(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) struct fb_var_screeninfo *var = &info->var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) struct fb_videomode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) mode = tmiofb_find_mode(info, var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (!mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) info->mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) info->fix.line_length = info->mode->xres *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) var->bits_per_pixel / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) tmiofb_hw_mode(to_platform_device(info->device));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) tmiofb_clearscreen(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) static int tmiofb_setcolreg(unsigned regno, unsigned red, unsigned green,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) unsigned blue, unsigned transp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) struct tmiofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (regno < ARRAY_SIZE(par->pseudo_palette)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) par->pseudo_palette[regno] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) ((red & 0xf800)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) ((green & 0xfc00) >> 5) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ((blue & 0xf800) >> 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static int tmiofb_blank(int blank, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * everything is done in lcd/bl drivers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * this is purely to make sysfs happy and work.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) static const struct fb_ops tmiofb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) .fb_ioctl = tmiofb_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) .fb_check_var = tmiofb_check_var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) .fb_set_par = tmiofb_set_par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) .fb_setcolreg = tmiofb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) .fb_blank = tmiofb_blank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) .fb_imageblit = cfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) #ifdef CONFIG_FB_TMIO_ACCELL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) .fb_sync = tmiofb_sync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) .fb_fillrect = tmiofb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) .fb_copyarea = tmiofb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) .fb_fillrect = cfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) .fb_copyarea = cfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /*--------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) static int tmiofb_probe(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) const struct mfd_cell *cell = mfd_get_cell(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) struct tmio_fb_data *data = dev_get_platdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) int irq = platform_get_irq(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct tmiofb_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * This is the only way ATM to disable the fb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (data == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) dev_err(&dev->dev, "NULL platform data!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (ccr == NULL || lcr == NULL || vram == NULL || irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) dev_err(&dev->dev, "missing resources\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) info = framebuffer_alloc(sizeof(struct tmiofb_par), &dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) #ifdef CONFIG_FB_TMIO_ACCELL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) init_waitqueue_head(&par->wait_acc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) par->use_polling = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) | FBINFO_HWACCEL_FILLRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) info->flags = FBINFO_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) info->fbops = &tmiofb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) strcpy(info->fix.id, "tmio-fb");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) info->fix.smem_start = vram->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) info->fix.smem_len = resource_size(vram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) info->fix.type = FB_TYPE_PACKED_PIXELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) info->fix.visual = FB_VISUAL_TRUECOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) info->fix.mmio_start = lcr->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) info->fix.mmio_len = resource_size(lcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) info->fix.accel = FB_ACCEL_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) info->screen_size = info->fix.smem_len - (4 * TMIOFB_FIFO_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) info->pseudo_palette = par->pseudo_palette;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) par->ccr = ioremap(ccr->start, resource_size(ccr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (!par->ccr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) goto err_ioremap_ccr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) par->lcr = ioremap(info->fix.mmio_start, info->fix.mmio_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (!par->lcr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) goto err_ioremap_lcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (!info->screen_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) goto err_ioremap_vram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) retval = request_irq(irq, &tmiofb_irq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) dev_name(&dev->dev), info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) goto err_request_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) platform_set_drvdata(dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) retval = fb_find_mode(&info->var, info, mode_option,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) data->modes, data->num_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) data->modes, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (!retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) goto err_find_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (cell->enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) retval = cell->enable(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) goto err_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) retval = tmiofb_hw_init(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) goto err_hw_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) fb_videomode_to_modelist(data->modes, data->num_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) &info->modelist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) retval = register_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) goto err_register_framebuffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) fb_info(info, "%s frame buffer device\n", info->fix.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) err_register_framebuffer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) /*err_set_par:*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) tmiofb_hw_stop(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) err_hw_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (cell->disable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) cell->disable(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) err_enable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) err_find_mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) free_irq(irq, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) err_request_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) iounmap(info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) err_ioremap_vram:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) iounmap(par->lcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) err_ioremap_lcr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) iounmap(par->ccr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) err_ioremap_ccr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) static int tmiofb_remove(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) const struct mfd_cell *cell = mfd_get_cell(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) struct fb_info *info = platform_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) int irq = platform_get_irq(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) struct tmiofb_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) tmiofb_hw_stop(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (cell->disable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) cell->disable(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) free_irq(irq, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) iounmap(info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) iounmap(par->lcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) iounmap(par->ccr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) static void tmiofb_dump_regs(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) struct fb_info *info = platform_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) struct tmiofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) printk(KERN_DEBUG "lhccr:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) #define CCR_PR(n) printk(KERN_DEBUG "\t" #n " = \t%04x\n",\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) tmio_ioread16(par->ccr + CCR_ ## n));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) CCR_PR(CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) CCR_PR(REVID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) CCR_PR(BASEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) CCR_PR(BASEH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) CCR_PR(UGCC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) CCR_PR(GCC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) CCR_PR(USC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) CCR_PR(VRAMRTC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) CCR_PR(VRAMSAC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) CCR_PR(VRAMBC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) #undef CCR_PR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) printk(KERN_DEBUG "lcr: \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) #define LCR_PR(n) printk(KERN_DEBUG "\t" #n " = \t%04x\n",\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) tmio_ioread16(par->lcr + LCR_ ## n));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) LCR_PR(UIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) LCR_PR(VHPN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) LCR_PR(CFSAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) LCR_PR(CFSAH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) LCR_PR(CFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) LCR_PR(CFWS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) LCR_PR(BBIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) LCR_PR(BBISC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) LCR_PR(CCS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) LCR_PR(BBES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) LCR_PR(CMDL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) LCR_PR(CMDH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) LCR_PR(CFC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) LCR_PR(CCIFC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) LCR_PR(HWT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) LCR_PR(LCDCCRC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) LCR_PR(LCDCC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) LCR_PR(LCDCOPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) LCR_PR(LCDIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) LCR_PR(LCDIM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) LCR_PR(LCDIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) LCR_PR(GDSAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) LCR_PR(GDSAH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) LCR_PR(VHPCL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) LCR_PR(VHPCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) LCR_PR(GM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) LCR_PR(HT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) LCR_PR(HDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) LCR_PR(HSS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) LCR_PR(HSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) LCR_PR(HNP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) LCR_PR(VT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) LCR_PR(VDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) LCR_PR(VSS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) LCR_PR(VSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) LCR_PR(CDLN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) LCR_PR(ILN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) LCR_PR(SP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) LCR_PR(MISC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) LCR_PR(VIHSS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) LCR_PR(VIVS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) LCR_PR(VIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) LCR_PR(VIVSS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) LCR_PR(VCCIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) LCR_PR(VIDWSAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) LCR_PR(VIDWSAH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) LCR_PR(VIDRSAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) LCR_PR(VIDRSAH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) LCR_PR(VIPDDST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) LCR_PR(VIPDDET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) LCR_PR(VIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) LCR_PR(VCS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) LCR_PR(VPHWC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) LCR_PR(VPHS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) LCR_PR(VPVWC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) LCR_PR(VPVS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) LCR_PR(PLHPIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) LCR_PR(XS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) LCR_PR(XCKHW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) LCR_PR(STHS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) LCR_PR(VT2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) LCR_PR(YCKSW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) LCR_PR(YSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) LCR_PR(PPOLS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) LCR_PR(PRECW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) LCR_PR(VCLKHW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) LCR_PR(OC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) #undef LCR_PR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) struct fb_info *info = platform_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) #ifdef CONFIG_FB_TMIO_ACCELL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) struct tmiofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) const struct mfd_cell *cell = mfd_get_cell(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) fb_set_suspend(info, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (info->fbops->fb_sync)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) info->fbops->fb_sync(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) #ifdef CONFIG_FB_TMIO_ACCELL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) * The fb should be usable even if interrupts are disabled (and they are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) * during suspend/resume). Switch temporary to forced polling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) printk(KERN_INFO "tmiofb: switching to polling\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) par->use_polling = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) tmiofb_hw_stop(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (cell->suspend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) retval = cell->suspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) static int tmiofb_resume(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) struct fb_info *info = platform_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) const struct mfd_cell *cell = mfd_get_cell(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (cell->resume) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) retval = cell->resume(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) tmiofb_irq(-1, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) tmiofb_hw_init(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) tmiofb_hw_mode(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) fb_set_suspend(info, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) #define tmiofb_suspend NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) #define tmiofb_resume NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) static struct platform_driver tmiofb_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) .driver.name = "tmio-fb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) .driver.owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) .probe = tmiofb_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) .remove = tmiofb_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) .suspend = tmiofb_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) .resume = tmiofb_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) /*--------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) static void __init tmiofb_setup(char *options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) char *this_opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (!options || !*options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) while ((this_opt = strsep(&options, ",")) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (!*this_opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) * FIXME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) static int __init tmiofb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) char *option = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (fb_get_options("tmiofb", &option))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) tmiofb_setup(option);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) return platform_driver_register(&tmiofb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) static void __exit tmiofb_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) platform_driver_unregister(&tmiofb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) module_init(tmiofb_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) module_exit(tmiofb_cleanup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) MODULE_DESCRIPTION("TMIO framebuffer driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) MODULE_AUTHOR("Chris Humbert, Dirk Opfer, Dmitry Baryshkov");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) MODULE_LICENSE("GPL");