Orange Pi5 kernel

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

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^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");