18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * BRIEF MODULE DESCRIPTION
38c2ecf20Sopenharmony_ci *	Au1200 LCD Driver.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2004-2005 AMD
68c2ecf20Sopenharmony_ci * Author: AMD
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Based on:
98c2ecf20Sopenharmony_ci * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
108c2ecf20Sopenharmony_ci *  Created 28 Dec 1997 by Geert Uytterhoeven
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci *  This program is free software; you can redistribute	 it and/or modify it
138c2ecf20Sopenharmony_ci *  under  the terms of	 the GNU General  Public License as published by the
148c2ecf20Sopenharmony_ci *  Free Software Foundation;  either version 2 of the	License, or (at your
158c2ecf20Sopenharmony_ci *  option) any later version.
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
188c2ecf20Sopenharmony_ci *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
198c2ecf20Sopenharmony_ci *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
208c2ecf20Sopenharmony_ci *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
218c2ecf20Sopenharmony_ci *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
228c2ecf20Sopenharmony_ci *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
238c2ecf20Sopenharmony_ci *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
248c2ecf20Sopenharmony_ci *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
258c2ecf20Sopenharmony_ci *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
268c2ecf20Sopenharmony_ci *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
278c2ecf20Sopenharmony_ci *
288c2ecf20Sopenharmony_ci *  You should have received a copy of the  GNU General Public License along
298c2ecf20Sopenharmony_ci *  with this program; if not, write  to the Free Software Foundation, Inc.,
308c2ecf20Sopenharmony_ci *  675 Mass Ave, Cambridge, MA 02139, USA.
318c2ecf20Sopenharmony_ci */
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#include <linux/clk.h>
348c2ecf20Sopenharmony_ci#include <linux/module.h>
358c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
368c2ecf20Sopenharmony_ci#include <linux/kernel.h>
378c2ecf20Sopenharmony_ci#include <linux/errno.h>
388c2ecf20Sopenharmony_ci#include <linux/string.h>
398c2ecf20Sopenharmony_ci#include <linux/mm.h>
408c2ecf20Sopenharmony_ci#include <linux/fb.h>
418c2ecf20Sopenharmony_ci#include <linux/init.h>
428c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
438c2ecf20Sopenharmony_ci#include <linux/ctype.h>
448c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
458c2ecf20Sopenharmony_ci#include <linux/slab.h>
468c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#include <asm/mach-au1x00/au1000.h>
498c2ecf20Sopenharmony_ci#include <asm/mach-au1x00/au1200fb.h>	/* platform_data */
508c2ecf20Sopenharmony_ci#include "au1200fb.h"
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#define DRIVER_NAME "au1200fb"
538c2ecf20Sopenharmony_ci#define DRIVER_DESC "LCD controller driver for AU1200 processors"
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define DEBUG 0
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)
588c2ecf20Sopenharmony_ci#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)
598c2ecf20Sopenharmony_ci#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg)
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#if DEBUG
628c2ecf20Sopenharmony_ci#define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg)
638c2ecf20Sopenharmony_ci#else
648c2ecf20Sopenharmony_ci#define print_dbg(f, arg...) do {} while (0)
658c2ecf20Sopenharmony_ci#endif
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci#define AU1200_LCD_FB_IOCTL 0x46FF
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci#define AU1200_LCD_SET_SCREEN 1
718c2ecf20Sopenharmony_ci#define AU1200_LCD_GET_SCREEN 2
728c2ecf20Sopenharmony_ci#define AU1200_LCD_SET_WINDOW 3
738c2ecf20Sopenharmony_ci#define AU1200_LCD_GET_WINDOW 4
748c2ecf20Sopenharmony_ci#define AU1200_LCD_SET_PANEL  5
758c2ecf20Sopenharmony_ci#define AU1200_LCD_GET_PANEL  6
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci#define SCREEN_SIZE		    (1<< 1)
788c2ecf20Sopenharmony_ci#define SCREEN_BACKCOLOR    (1<< 2)
798c2ecf20Sopenharmony_ci#define SCREEN_BRIGHTNESS   (1<< 3)
808c2ecf20Sopenharmony_ci#define SCREEN_COLORKEY     (1<< 4)
818c2ecf20Sopenharmony_ci#define SCREEN_MASK         (1<< 5)
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_cistruct au1200_lcd_global_regs_t {
848c2ecf20Sopenharmony_ci	unsigned int flags;
858c2ecf20Sopenharmony_ci	unsigned int xsize;
868c2ecf20Sopenharmony_ci	unsigned int ysize;
878c2ecf20Sopenharmony_ci	unsigned int backcolor;
888c2ecf20Sopenharmony_ci	unsigned int brightness;
898c2ecf20Sopenharmony_ci	unsigned int colorkey;
908c2ecf20Sopenharmony_ci	unsigned int mask;
918c2ecf20Sopenharmony_ci	unsigned int panel_choice;
928c2ecf20Sopenharmony_ci	char panel_desc[80];
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci};
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci#define WIN_POSITION            (1<< 0)
978c2ecf20Sopenharmony_ci#define WIN_ALPHA_COLOR         (1<< 1)
988c2ecf20Sopenharmony_ci#define WIN_ALPHA_MODE          (1<< 2)
998c2ecf20Sopenharmony_ci#define WIN_PRIORITY            (1<< 3)
1008c2ecf20Sopenharmony_ci#define WIN_CHANNEL             (1<< 4)
1018c2ecf20Sopenharmony_ci#define WIN_BUFFER_FORMAT       (1<< 5)
1028c2ecf20Sopenharmony_ci#define WIN_COLOR_ORDER         (1<< 6)
1038c2ecf20Sopenharmony_ci#define WIN_PIXEL_ORDER         (1<< 7)
1048c2ecf20Sopenharmony_ci#define WIN_SIZE                (1<< 8)
1058c2ecf20Sopenharmony_ci#define WIN_COLORKEY_MODE       (1<< 9)
1068c2ecf20Sopenharmony_ci#define WIN_DOUBLE_BUFFER_MODE  (1<< 10)
1078c2ecf20Sopenharmony_ci#define WIN_RAM_ARRAY_MODE      (1<< 11)
1088c2ecf20Sopenharmony_ci#define WIN_BUFFER_SCALE        (1<< 12)
1098c2ecf20Sopenharmony_ci#define WIN_ENABLE	            (1<< 13)
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cistruct au1200_lcd_window_regs_t {
1128c2ecf20Sopenharmony_ci	unsigned int flags;
1138c2ecf20Sopenharmony_ci	unsigned int xpos;
1148c2ecf20Sopenharmony_ci	unsigned int ypos;
1158c2ecf20Sopenharmony_ci	unsigned int alpha_color;
1168c2ecf20Sopenharmony_ci	unsigned int alpha_mode;
1178c2ecf20Sopenharmony_ci	unsigned int priority;
1188c2ecf20Sopenharmony_ci	unsigned int channel;
1198c2ecf20Sopenharmony_ci	unsigned int buffer_format;
1208c2ecf20Sopenharmony_ci	unsigned int color_order;
1218c2ecf20Sopenharmony_ci	unsigned int pixel_order;
1228c2ecf20Sopenharmony_ci	unsigned int xsize;
1238c2ecf20Sopenharmony_ci	unsigned int ysize;
1248c2ecf20Sopenharmony_ci	unsigned int colorkey_mode;
1258c2ecf20Sopenharmony_ci	unsigned int double_buffer_mode;
1268c2ecf20Sopenharmony_ci	unsigned int ram_array_mode;
1278c2ecf20Sopenharmony_ci	unsigned int xscale;
1288c2ecf20Sopenharmony_ci	unsigned int yscale;
1298c2ecf20Sopenharmony_ci	unsigned int enable;
1308c2ecf20Sopenharmony_ci};
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistruct au1200_lcd_iodata_t {
1348c2ecf20Sopenharmony_ci	unsigned int subcmd;
1358c2ecf20Sopenharmony_ci	struct au1200_lcd_global_regs_t global;
1368c2ecf20Sopenharmony_ci	struct au1200_lcd_window_regs_t window;
1378c2ecf20Sopenharmony_ci};
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci#if defined(__BIG_ENDIAN)
1408c2ecf20Sopenharmony_ci#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11
1418c2ecf20Sopenharmony_ci#else
1428c2ecf20Sopenharmony_ci#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00
1438c2ecf20Sopenharmony_ci#endif
1448c2ecf20Sopenharmony_ci#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci/* Private, per-framebuffer management information (independent of the panel itself) */
1478c2ecf20Sopenharmony_cistruct au1200fb_device {
1488c2ecf20Sopenharmony_ci	struct fb_info *fb_info;		/* FB driver info record */
1498c2ecf20Sopenharmony_ci	struct au1200fb_platdata *pd;
1508c2ecf20Sopenharmony_ci	struct device *dev;
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	int					plane;
1538c2ecf20Sopenharmony_ci	unsigned char* 		fb_mem;		/* FrameBuffer memory map */
1548c2ecf20Sopenharmony_ci	unsigned int		fb_len;
1558c2ecf20Sopenharmony_ci	dma_addr_t    		fb_phys;
1568c2ecf20Sopenharmony_ci};
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci/********************************************************************/
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci/* LCD controller restrictions */
1618c2ecf20Sopenharmony_ci#define AU1200_LCD_MAX_XRES	1280
1628c2ecf20Sopenharmony_ci#define AU1200_LCD_MAX_YRES	1024
1638c2ecf20Sopenharmony_ci#define AU1200_LCD_MAX_BPP	32
1648c2ecf20Sopenharmony_ci#define AU1200_LCD_MAX_CLK	96000000 /* fixme: this needs to go away ? */
1658c2ecf20Sopenharmony_ci#define AU1200_LCD_NBR_PALETTE_ENTRIES 256
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci/* Default number of visible screen buffer to allocate */
1688c2ecf20Sopenharmony_ci#define AU1200FB_NBR_VIDEO_BUFFERS 1
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci/* Default maximum number of fb devices to create */
1718c2ecf20Sopenharmony_ci#define MAX_DEVICE_COUNT	4
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci/* Default window configuration entry to use (see windows[]) */
1748c2ecf20Sopenharmony_ci#define DEFAULT_WINDOW_INDEX	2
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci/********************************************************************/
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_cistatic struct fb_info *_au1200fb_infos[MAX_DEVICE_COUNT];
1798c2ecf20Sopenharmony_cistatic struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR;
1808c2ecf20Sopenharmony_cistatic int device_count = MAX_DEVICE_COUNT;
1818c2ecf20Sopenharmony_cistatic int window_index = DEFAULT_WINDOW_INDEX;	/* default is zero */
1828c2ecf20Sopenharmony_cistatic int panel_index = 2; /* default is zero */
1838c2ecf20Sopenharmony_cistatic struct window_settings *win;
1848c2ecf20Sopenharmony_cistatic struct panel_settings *panel;
1858c2ecf20Sopenharmony_cistatic int noblanking = 1;
1868c2ecf20Sopenharmony_cistatic int nohwcursor = 0;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_cistruct window_settings {
1898c2ecf20Sopenharmony_ci	unsigned char name[64];
1908c2ecf20Sopenharmony_ci	uint32 mode_backcolor;
1918c2ecf20Sopenharmony_ci	uint32 mode_colorkey;
1928c2ecf20Sopenharmony_ci	uint32 mode_colorkeymsk;
1938c2ecf20Sopenharmony_ci	struct {
1948c2ecf20Sopenharmony_ci		int xres;
1958c2ecf20Sopenharmony_ci		int yres;
1968c2ecf20Sopenharmony_ci		int xpos;
1978c2ecf20Sopenharmony_ci		int ypos;
1988c2ecf20Sopenharmony_ci		uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */
1998c2ecf20Sopenharmony_ci		uint32 mode_winenable;
2008c2ecf20Sopenharmony_ci	} w[4];
2018c2ecf20Sopenharmony_ci};
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci#if defined(__BIG_ENDIAN)
2048c2ecf20Sopenharmony_ci#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00
2058c2ecf20Sopenharmony_ci#else
2068c2ecf20Sopenharmony_ci#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01
2078c2ecf20Sopenharmony_ci#endif
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci/*
2108c2ecf20Sopenharmony_ci * Default window configurations
2118c2ecf20Sopenharmony_ci */
2128c2ecf20Sopenharmony_cistatic struct window_settings windows[] = {
2138c2ecf20Sopenharmony_ci	{ /* Index 0 */
2148c2ecf20Sopenharmony_ci		"0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
2158c2ecf20Sopenharmony_ci		/* mode_backcolor	*/ 0x006600ff,
2168c2ecf20Sopenharmony_ci		/* mode_colorkey,msk*/ 0, 0,
2178c2ecf20Sopenharmony_ci		{
2188c2ecf20Sopenharmony_ci			{
2198c2ecf20Sopenharmony_ci			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
2208c2ecf20Sopenharmony_ci			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
2218c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PO_16BPP,
2228c2ecf20Sopenharmony_ci			/* mode_winenable*/ LCD_WINENABLE_WEN0,
2238c2ecf20Sopenharmony_ci			},
2248c2ecf20Sopenharmony_ci			{
2258c2ecf20Sopenharmony_ci			/* xres, yres, xpos, ypos */ 100, 100, 100, 100,
2268c2ecf20Sopenharmony_ci			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
2278c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PO_16BPP |
2288c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PIPE,
2298c2ecf20Sopenharmony_ci			/* mode_winenable*/ LCD_WINENABLE_WEN1,
2308c2ecf20Sopenharmony_ci			},
2318c2ecf20Sopenharmony_ci			{
2328c2ecf20Sopenharmony_ci			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
2338c2ecf20Sopenharmony_ci			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
2348c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PO_16BPP,
2358c2ecf20Sopenharmony_ci			/* mode_winenable*/ 0,
2368c2ecf20Sopenharmony_ci			},
2378c2ecf20Sopenharmony_ci			{
2388c2ecf20Sopenharmony_ci			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
2398c2ecf20Sopenharmony_ci			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
2408c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PO_16BPP |
2418c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PIPE,
2428c2ecf20Sopenharmony_ci			/* mode_winenable*/ 0,
2438c2ecf20Sopenharmony_ci			},
2448c2ecf20Sopenharmony_ci		},
2458c2ecf20Sopenharmony_ci	},
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	{ /* Index 1 */
2488c2ecf20Sopenharmony_ci		"0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
2498c2ecf20Sopenharmony_ci		/* mode_backcolor	*/ 0x006600ff,
2508c2ecf20Sopenharmony_ci		/* mode_colorkey,msk*/ 0, 0,
2518c2ecf20Sopenharmony_ci		{
2528c2ecf20Sopenharmony_ci			{
2538c2ecf20Sopenharmony_ci			/* xres, yres, xpos, ypos */ 320, 240, 5, 5,
2548c2ecf20Sopenharmony_ci			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP |
2558c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PO_00,
2568c2ecf20Sopenharmony_ci			/* mode_winenable*/ LCD_WINENABLE_WEN0,
2578c2ecf20Sopenharmony_ci			},
2588c2ecf20Sopenharmony_ci			{
2598c2ecf20Sopenharmony_ci			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
2608c2ecf20Sopenharmony_ci			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565
2618c2ecf20Sopenharmony_ci				| LCD_WINCTRL1_PO_16BPP,
2628c2ecf20Sopenharmony_ci			/* mode_winenable*/ 0,
2638c2ecf20Sopenharmony_ci			},
2648c2ecf20Sopenharmony_ci			{
2658c2ecf20Sopenharmony_ci			/* xres, yres, xpos, ypos */ 100, 100, 0, 0,
2668c2ecf20Sopenharmony_ci			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
2678c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PO_16BPP |
2688c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PIPE,
2698c2ecf20Sopenharmony_ci			/* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
2708c2ecf20Sopenharmony_ci			},
2718c2ecf20Sopenharmony_ci			{
2728c2ecf20Sopenharmony_ci			/* xres, yres, xpos, ypos */ 200, 25, 0, 0,
2738c2ecf20Sopenharmony_ci			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
2748c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PO_16BPP |
2758c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PIPE,
2768c2ecf20Sopenharmony_ci			/* mode_winenable*/ 0,
2778c2ecf20Sopenharmony_ci			},
2788c2ecf20Sopenharmony_ci		},
2798c2ecf20Sopenharmony_ci	},
2808c2ecf20Sopenharmony_ci	{ /* Index 2 */
2818c2ecf20Sopenharmony_ci		"0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
2828c2ecf20Sopenharmony_ci		/* mode_backcolor	*/ 0x006600ff,
2838c2ecf20Sopenharmony_ci		/* mode_colorkey,msk*/ 0, 0,
2848c2ecf20Sopenharmony_ci		{
2858c2ecf20Sopenharmony_ci			{
2868c2ecf20Sopenharmony_ci			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
2878c2ecf20Sopenharmony_ci			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
2888c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PO_16BPP,
2898c2ecf20Sopenharmony_ci			/* mode_winenable*/ LCD_WINENABLE_WEN0,
2908c2ecf20Sopenharmony_ci			},
2918c2ecf20Sopenharmony_ci			{
2928c2ecf20Sopenharmony_ci			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
2938c2ecf20Sopenharmony_ci			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
2948c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PO_16BPP,
2958c2ecf20Sopenharmony_ci			/* mode_winenable*/ 0,
2968c2ecf20Sopenharmony_ci			},
2978c2ecf20Sopenharmony_ci			{
2988c2ecf20Sopenharmony_ci			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
2998c2ecf20Sopenharmony_ci			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP |
3008c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE,
3018c2ecf20Sopenharmony_ci			/* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
3028c2ecf20Sopenharmony_ci			},
3038c2ecf20Sopenharmony_ci			{
3048c2ecf20Sopenharmony_ci			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
3058c2ecf20Sopenharmony_ci			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
3068c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PO_16BPP |
3078c2ecf20Sopenharmony_ci				LCD_WINCTRL1_PIPE,
3088c2ecf20Sopenharmony_ci			/* mode_winenable*/ 0,
3098c2ecf20Sopenharmony_ci			},
3108c2ecf20Sopenharmony_ci		},
3118c2ecf20Sopenharmony_ci	},
3128c2ecf20Sopenharmony_ci	/* Need VGA 640 @ 24bpp, @ 32bpp */
3138c2ecf20Sopenharmony_ci	/* Need VGA 800 @ 24bpp, @ 32bpp */
3148c2ecf20Sopenharmony_ci	/* Need VGA 1024 @ 24bpp, @ 32bpp */
3158c2ecf20Sopenharmony_ci};
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci/*
3188c2ecf20Sopenharmony_ci * Controller configurations for various panels.
3198c2ecf20Sopenharmony_ci */
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cistruct panel_settings
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	const char name[25];		/* Full name <vendor>_<model> */
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	struct 	fb_monspecs monspecs; 	/* FB monitor specs */
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	/* panel timings */
3288c2ecf20Sopenharmony_ci	uint32 mode_screen;
3298c2ecf20Sopenharmony_ci	uint32 mode_horztiming;
3308c2ecf20Sopenharmony_ci	uint32 mode_verttiming;
3318c2ecf20Sopenharmony_ci	uint32 mode_clkcontrol;
3328c2ecf20Sopenharmony_ci	uint32 mode_pwmdiv;
3338c2ecf20Sopenharmony_ci	uint32 mode_pwmhi;
3348c2ecf20Sopenharmony_ci	uint32 mode_outmask;
3358c2ecf20Sopenharmony_ci	uint32 mode_fifoctrl;
3368c2ecf20Sopenharmony_ci	uint32 mode_backlight;
3378c2ecf20Sopenharmony_ci	uint32 lcdclk;
3388c2ecf20Sopenharmony_ci#define Xres min_xres
3398c2ecf20Sopenharmony_ci#define Yres min_yres
3408c2ecf20Sopenharmony_ci	u32	min_xres;		/* Minimum horizontal resolution */
3418c2ecf20Sopenharmony_ci	u32	max_xres;		/* Maximum horizontal resolution */
3428c2ecf20Sopenharmony_ci	u32 	min_yres;		/* Minimum vertical resolution */
3438c2ecf20Sopenharmony_ci	u32 	max_yres;		/* Maximum vertical resolution */
3448c2ecf20Sopenharmony_ci};
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci/********************************************************************/
3478c2ecf20Sopenharmony_ci/* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is */
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci/* List of panels known to work with the AU1200 LCD controller.
3508c2ecf20Sopenharmony_ci * To add a new panel, enter the same specifications as the
3518c2ecf20Sopenharmony_ci * Generic_TFT one, and MAKE SURE that it doesn't conflicts
3528c2ecf20Sopenharmony_ci * with the controller restrictions. Restrictions are:
3538c2ecf20Sopenharmony_ci *
3548c2ecf20Sopenharmony_ci * STN color panels: max_bpp <= 12
3558c2ecf20Sopenharmony_ci * STN mono panels: max_bpp <= 4
3568c2ecf20Sopenharmony_ci * TFT panels: max_bpp <= 16
3578c2ecf20Sopenharmony_ci * max_xres <= 800
3588c2ecf20Sopenharmony_ci * max_yres <= 600
3598c2ecf20Sopenharmony_ci */
3608c2ecf20Sopenharmony_cistatic struct panel_settings known_lcd_panels[] =
3618c2ecf20Sopenharmony_ci{
3628c2ecf20Sopenharmony_ci	[0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */
3638c2ecf20Sopenharmony_ci		.name = "QVGA_320x240",
3648c2ecf20Sopenharmony_ci		.monspecs = {
3658c2ecf20Sopenharmony_ci			.modedb = NULL,
3668c2ecf20Sopenharmony_ci			.modedb_len = 0,
3678c2ecf20Sopenharmony_ci			.hfmin = 30000,
3688c2ecf20Sopenharmony_ci			.hfmax = 70000,
3698c2ecf20Sopenharmony_ci			.vfmin = 60,
3708c2ecf20Sopenharmony_ci			.vfmax = 60,
3718c2ecf20Sopenharmony_ci			.dclkmin = 6000000,
3728c2ecf20Sopenharmony_ci			.dclkmax = 28000000,
3738c2ecf20Sopenharmony_ci			.input = FB_DISP_RGB,
3748c2ecf20Sopenharmony_ci		},
3758c2ecf20Sopenharmony_ci		.mode_screen		= LCD_SCREEN_SX_N(320) |
3768c2ecf20Sopenharmony_ci			LCD_SCREEN_SY_N(240),
3778c2ecf20Sopenharmony_ci		.mode_horztiming	= 0x00c4623b,
3788c2ecf20Sopenharmony_ci		.mode_verttiming	= 0x00502814,
3798c2ecf20Sopenharmony_ci		.mode_clkcontrol	= 0x00020002, /* /4=24Mhz */
3808c2ecf20Sopenharmony_ci		.mode_pwmdiv		= 0x00000000,
3818c2ecf20Sopenharmony_ci		.mode_pwmhi		= 0x00000000,
3828c2ecf20Sopenharmony_ci		.mode_outmask	= 0x00FFFFFF,
3838c2ecf20Sopenharmony_ci		.mode_fifoctrl	= 0x2f2f2f2f,
3848c2ecf20Sopenharmony_ci		.mode_backlight	= 0x00000000,
3858c2ecf20Sopenharmony_ci		.lcdclk		= 96,
3868c2ecf20Sopenharmony_ci		320, 320,
3878c2ecf20Sopenharmony_ci		240, 240,
3888c2ecf20Sopenharmony_ci	},
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	[1] = { /* VGA 640x480 H:30.3kHz V:58Hz */
3918c2ecf20Sopenharmony_ci		.name = "VGA_640x480",
3928c2ecf20Sopenharmony_ci		.monspecs = {
3938c2ecf20Sopenharmony_ci			.modedb = NULL,
3948c2ecf20Sopenharmony_ci			.modedb_len = 0,
3958c2ecf20Sopenharmony_ci			.hfmin = 30000,
3968c2ecf20Sopenharmony_ci			.hfmax = 70000,
3978c2ecf20Sopenharmony_ci			.vfmin = 60,
3988c2ecf20Sopenharmony_ci			.vfmax = 60,
3998c2ecf20Sopenharmony_ci			.dclkmin = 6000000,
4008c2ecf20Sopenharmony_ci			.dclkmax = 28000000,
4018c2ecf20Sopenharmony_ci			.input = FB_DISP_RGB,
4028c2ecf20Sopenharmony_ci		},
4038c2ecf20Sopenharmony_ci		.mode_screen		= 0x13f9df80,
4048c2ecf20Sopenharmony_ci		.mode_horztiming	= 0x003c5859,
4058c2ecf20Sopenharmony_ci		.mode_verttiming	= 0x00741201,
4068c2ecf20Sopenharmony_ci		.mode_clkcontrol	= 0x00020001, /* /4=24Mhz */
4078c2ecf20Sopenharmony_ci		.mode_pwmdiv		= 0x00000000,
4088c2ecf20Sopenharmony_ci		.mode_pwmhi		= 0x00000000,
4098c2ecf20Sopenharmony_ci		.mode_outmask	= 0x00FFFFFF,
4108c2ecf20Sopenharmony_ci		.mode_fifoctrl	= 0x2f2f2f2f,
4118c2ecf20Sopenharmony_ci		.mode_backlight	= 0x00000000,
4128c2ecf20Sopenharmony_ci		.lcdclk		= 96,
4138c2ecf20Sopenharmony_ci		640, 480,
4148c2ecf20Sopenharmony_ci		640, 480,
4158c2ecf20Sopenharmony_ci	},
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	[2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */
4188c2ecf20Sopenharmony_ci		.name = "SVGA_800x600",
4198c2ecf20Sopenharmony_ci		.monspecs = {
4208c2ecf20Sopenharmony_ci			.modedb = NULL,
4218c2ecf20Sopenharmony_ci			.modedb_len = 0,
4228c2ecf20Sopenharmony_ci			.hfmin = 30000,
4238c2ecf20Sopenharmony_ci			.hfmax = 70000,
4248c2ecf20Sopenharmony_ci			.vfmin = 60,
4258c2ecf20Sopenharmony_ci			.vfmax = 60,
4268c2ecf20Sopenharmony_ci			.dclkmin = 6000000,
4278c2ecf20Sopenharmony_ci			.dclkmax = 28000000,
4288c2ecf20Sopenharmony_ci			.input = FB_DISP_RGB,
4298c2ecf20Sopenharmony_ci		},
4308c2ecf20Sopenharmony_ci		.mode_screen		= 0x18fa5780,
4318c2ecf20Sopenharmony_ci		.mode_horztiming	= 0x00dc7e77,
4328c2ecf20Sopenharmony_ci		.mode_verttiming	= 0x00584805,
4338c2ecf20Sopenharmony_ci		.mode_clkcontrol	= 0x00020000, /* /2=48Mhz */
4348c2ecf20Sopenharmony_ci		.mode_pwmdiv		= 0x00000000,
4358c2ecf20Sopenharmony_ci		.mode_pwmhi		= 0x00000000,
4368c2ecf20Sopenharmony_ci		.mode_outmask	= 0x00FFFFFF,
4378c2ecf20Sopenharmony_ci		.mode_fifoctrl	= 0x2f2f2f2f,
4388c2ecf20Sopenharmony_ci		.mode_backlight	= 0x00000000,
4398c2ecf20Sopenharmony_ci		.lcdclk		= 96,
4408c2ecf20Sopenharmony_ci		800, 800,
4418c2ecf20Sopenharmony_ci		600, 600,
4428c2ecf20Sopenharmony_ci	},
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	[3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */
4458c2ecf20Sopenharmony_ci		.name = "XVGA_1024x768",
4468c2ecf20Sopenharmony_ci		.monspecs = {
4478c2ecf20Sopenharmony_ci			.modedb = NULL,
4488c2ecf20Sopenharmony_ci			.modedb_len = 0,
4498c2ecf20Sopenharmony_ci			.hfmin = 30000,
4508c2ecf20Sopenharmony_ci			.hfmax = 70000,
4518c2ecf20Sopenharmony_ci			.vfmin = 60,
4528c2ecf20Sopenharmony_ci			.vfmax = 60,
4538c2ecf20Sopenharmony_ci			.dclkmin = 6000000,
4548c2ecf20Sopenharmony_ci			.dclkmax = 28000000,
4558c2ecf20Sopenharmony_ci			.input = FB_DISP_RGB,
4568c2ecf20Sopenharmony_ci		},
4578c2ecf20Sopenharmony_ci		.mode_screen		= 0x1ffaff80,
4588c2ecf20Sopenharmony_ci		.mode_horztiming	= 0x007d0e57,
4598c2ecf20Sopenharmony_ci		.mode_verttiming	= 0x00740a01,
4608c2ecf20Sopenharmony_ci		.mode_clkcontrol	= 0x000A0000, /* /1 */
4618c2ecf20Sopenharmony_ci		.mode_pwmdiv		= 0x00000000,
4628c2ecf20Sopenharmony_ci		.mode_pwmhi		= 0x00000000,
4638c2ecf20Sopenharmony_ci		.mode_outmask	= 0x00FFFFFF,
4648c2ecf20Sopenharmony_ci		.mode_fifoctrl	= 0x2f2f2f2f,
4658c2ecf20Sopenharmony_ci		.mode_backlight	= 0x00000000,
4668c2ecf20Sopenharmony_ci		.lcdclk		= 72,
4678c2ecf20Sopenharmony_ci		1024, 1024,
4688c2ecf20Sopenharmony_ci		768, 768,
4698c2ecf20Sopenharmony_ci	},
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	[4] = { /* XVGA XVGA 1280x1024 H:68.5kHz V:65Hz */
4728c2ecf20Sopenharmony_ci		.name = "XVGA_1280x1024",
4738c2ecf20Sopenharmony_ci		.monspecs = {
4748c2ecf20Sopenharmony_ci			.modedb = NULL,
4758c2ecf20Sopenharmony_ci			.modedb_len = 0,
4768c2ecf20Sopenharmony_ci			.hfmin = 30000,
4778c2ecf20Sopenharmony_ci			.hfmax = 70000,
4788c2ecf20Sopenharmony_ci			.vfmin = 60,
4798c2ecf20Sopenharmony_ci			.vfmax = 60,
4808c2ecf20Sopenharmony_ci			.dclkmin = 6000000,
4818c2ecf20Sopenharmony_ci			.dclkmax = 28000000,
4828c2ecf20Sopenharmony_ci			.input = FB_DISP_RGB,
4838c2ecf20Sopenharmony_ci		},
4848c2ecf20Sopenharmony_ci		.mode_screen		= 0x27fbff80,
4858c2ecf20Sopenharmony_ci		.mode_horztiming	= 0x00cdb2c7,
4868c2ecf20Sopenharmony_ci		.mode_verttiming	= 0x00600002,
4878c2ecf20Sopenharmony_ci		.mode_clkcontrol	= 0x000A0000, /* /1 */
4888c2ecf20Sopenharmony_ci		.mode_pwmdiv		= 0x00000000,
4898c2ecf20Sopenharmony_ci		.mode_pwmhi		= 0x00000000,
4908c2ecf20Sopenharmony_ci		.mode_outmask	= 0x00FFFFFF,
4918c2ecf20Sopenharmony_ci		.mode_fifoctrl	= 0x2f2f2f2f,
4928c2ecf20Sopenharmony_ci		.mode_backlight	= 0x00000000,
4938c2ecf20Sopenharmony_ci		.lcdclk		= 120,
4948c2ecf20Sopenharmony_ci		1280, 1280,
4958c2ecf20Sopenharmony_ci		1024, 1024,
4968c2ecf20Sopenharmony_ci	},
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	[5] = { /* Samsung 1024x768 TFT */
4998c2ecf20Sopenharmony_ci		.name = "Samsung_1024x768_TFT",
5008c2ecf20Sopenharmony_ci		.monspecs = {
5018c2ecf20Sopenharmony_ci			.modedb = NULL,
5028c2ecf20Sopenharmony_ci			.modedb_len = 0,
5038c2ecf20Sopenharmony_ci			.hfmin = 30000,
5048c2ecf20Sopenharmony_ci			.hfmax = 70000,
5058c2ecf20Sopenharmony_ci			.vfmin = 60,
5068c2ecf20Sopenharmony_ci			.vfmax = 60,
5078c2ecf20Sopenharmony_ci			.dclkmin = 6000000,
5088c2ecf20Sopenharmony_ci			.dclkmax = 28000000,
5098c2ecf20Sopenharmony_ci			.input = FB_DISP_RGB,
5108c2ecf20Sopenharmony_ci		},
5118c2ecf20Sopenharmony_ci		.mode_screen		= 0x1ffaff80,
5128c2ecf20Sopenharmony_ci		.mode_horztiming	= 0x018cc677,
5138c2ecf20Sopenharmony_ci		.mode_verttiming	= 0x00241217,
5148c2ecf20Sopenharmony_ci		.mode_clkcontrol	= 0x00000000, /* SCB 0x1 /4=24Mhz */
5158c2ecf20Sopenharmony_ci		.mode_pwmdiv		= 0x8000063f, /* SCB 0x0 */
5168c2ecf20Sopenharmony_ci		.mode_pwmhi		= 0x03400000, /* SCB 0x0 */
5178c2ecf20Sopenharmony_ci		.mode_outmask	= 0x00FFFFFF,
5188c2ecf20Sopenharmony_ci		.mode_fifoctrl	= 0x2f2f2f2f,
5198c2ecf20Sopenharmony_ci		.mode_backlight	= 0x00000000,
5208c2ecf20Sopenharmony_ci		.lcdclk		= 96,
5218c2ecf20Sopenharmony_ci		1024, 1024,
5228c2ecf20Sopenharmony_ci		768, 768,
5238c2ecf20Sopenharmony_ci	},
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	[6] = { /* Toshiba 640x480 TFT */
5268c2ecf20Sopenharmony_ci		.name = "Toshiba_640x480_TFT",
5278c2ecf20Sopenharmony_ci		.monspecs = {
5288c2ecf20Sopenharmony_ci			.modedb = NULL,
5298c2ecf20Sopenharmony_ci			.modedb_len = 0,
5308c2ecf20Sopenharmony_ci			.hfmin = 30000,
5318c2ecf20Sopenharmony_ci			.hfmax = 70000,
5328c2ecf20Sopenharmony_ci			.vfmin = 60,
5338c2ecf20Sopenharmony_ci			.vfmax = 60,
5348c2ecf20Sopenharmony_ci			.dclkmin = 6000000,
5358c2ecf20Sopenharmony_ci			.dclkmax = 28000000,
5368c2ecf20Sopenharmony_ci			.input = FB_DISP_RGB,
5378c2ecf20Sopenharmony_ci		},
5388c2ecf20Sopenharmony_ci		.mode_screen		= LCD_SCREEN_SX_N(640) |
5398c2ecf20Sopenharmony_ci			LCD_SCREEN_SY_N(480),
5408c2ecf20Sopenharmony_ci		.mode_horztiming	= LCD_HORZTIMING_HPW_N(96) |
5418c2ecf20Sopenharmony_ci			LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51),
5428c2ecf20Sopenharmony_ci		.mode_verttiming	= LCD_VERTTIMING_VPW_N(2) |
5438c2ecf20Sopenharmony_ci			LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32),
5448c2ecf20Sopenharmony_ci		.mode_clkcontrol	= 0x00000000, /* /4=24Mhz */
5458c2ecf20Sopenharmony_ci		.mode_pwmdiv		= 0x8000063f,
5468c2ecf20Sopenharmony_ci		.mode_pwmhi		= 0x03400000,
5478c2ecf20Sopenharmony_ci		.mode_outmask	= 0x00fcfcfc,
5488c2ecf20Sopenharmony_ci		.mode_fifoctrl	= 0x2f2f2f2f,
5498c2ecf20Sopenharmony_ci		.mode_backlight	= 0x00000000,
5508c2ecf20Sopenharmony_ci		.lcdclk		= 96,
5518c2ecf20Sopenharmony_ci		640, 480,
5528c2ecf20Sopenharmony_ci		640, 480,
5538c2ecf20Sopenharmony_ci	},
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	[7] = { /* Sharp 320x240 TFT */
5568c2ecf20Sopenharmony_ci		.name = "Sharp_320x240_TFT",
5578c2ecf20Sopenharmony_ci		.monspecs = {
5588c2ecf20Sopenharmony_ci			.modedb = NULL,
5598c2ecf20Sopenharmony_ci			.modedb_len = 0,
5608c2ecf20Sopenharmony_ci			.hfmin = 12500,
5618c2ecf20Sopenharmony_ci			.hfmax = 20000,
5628c2ecf20Sopenharmony_ci			.vfmin = 38,
5638c2ecf20Sopenharmony_ci			.vfmax = 81,
5648c2ecf20Sopenharmony_ci			.dclkmin = 4500000,
5658c2ecf20Sopenharmony_ci			.dclkmax = 6800000,
5668c2ecf20Sopenharmony_ci			.input = FB_DISP_RGB,
5678c2ecf20Sopenharmony_ci		},
5688c2ecf20Sopenharmony_ci		.mode_screen		= LCD_SCREEN_SX_N(320) |
5698c2ecf20Sopenharmony_ci			LCD_SCREEN_SY_N(240),
5708c2ecf20Sopenharmony_ci		.mode_horztiming	= LCD_HORZTIMING_HPW_N(60) |
5718c2ecf20Sopenharmony_ci			LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2),
5728c2ecf20Sopenharmony_ci		.mode_verttiming	= LCD_VERTTIMING_VPW_N(2) |
5738c2ecf20Sopenharmony_ci			LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5),
5748c2ecf20Sopenharmony_ci		.mode_clkcontrol	= LCD_CLKCONTROL_PCD_N(7), /*16=6Mhz*/
5758c2ecf20Sopenharmony_ci		.mode_pwmdiv		= 0x8000063f,
5768c2ecf20Sopenharmony_ci		.mode_pwmhi		= 0x03400000,
5778c2ecf20Sopenharmony_ci		.mode_outmask	= 0x00fcfcfc,
5788c2ecf20Sopenharmony_ci		.mode_fifoctrl	= 0x2f2f2f2f,
5798c2ecf20Sopenharmony_ci		.mode_backlight	= 0x00000000,
5808c2ecf20Sopenharmony_ci		.lcdclk		= 96, /* 96MHz AUXPLL */
5818c2ecf20Sopenharmony_ci		320, 320,
5828c2ecf20Sopenharmony_ci		240, 240,
5838c2ecf20Sopenharmony_ci	},
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	[8] = { /* Toppoly TD070WGCB2 7" 856x480 TFT */
5868c2ecf20Sopenharmony_ci		.name = "Toppoly_TD070WGCB2",
5878c2ecf20Sopenharmony_ci		.monspecs = {
5888c2ecf20Sopenharmony_ci			.modedb = NULL,
5898c2ecf20Sopenharmony_ci			.modedb_len = 0,
5908c2ecf20Sopenharmony_ci			.hfmin = 30000,
5918c2ecf20Sopenharmony_ci			.hfmax = 70000,
5928c2ecf20Sopenharmony_ci			.vfmin = 60,
5938c2ecf20Sopenharmony_ci			.vfmax = 60,
5948c2ecf20Sopenharmony_ci			.dclkmin = 6000000,
5958c2ecf20Sopenharmony_ci			.dclkmax = 28000000,
5968c2ecf20Sopenharmony_ci			.input = FB_DISP_RGB,
5978c2ecf20Sopenharmony_ci		},
5988c2ecf20Sopenharmony_ci		.mode_screen		= LCD_SCREEN_SX_N(856) |
5998c2ecf20Sopenharmony_ci			LCD_SCREEN_SY_N(480),
6008c2ecf20Sopenharmony_ci		.mode_horztiming	= LCD_HORZTIMING_HND2_N(43) |
6018c2ecf20Sopenharmony_ci			LCD_HORZTIMING_HND1_N(43) | LCD_HORZTIMING_HPW_N(114),
6028c2ecf20Sopenharmony_ci		.mode_verttiming	= LCD_VERTTIMING_VND2_N(20) |
6038c2ecf20Sopenharmony_ci			LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4),
6048c2ecf20Sopenharmony_ci		.mode_clkcontrol	= 0x00020001, /* /4=24Mhz */
6058c2ecf20Sopenharmony_ci		.mode_pwmdiv		= 0x8000063f,
6068c2ecf20Sopenharmony_ci		.mode_pwmhi		= 0x03400000,
6078c2ecf20Sopenharmony_ci		.mode_outmask	= 0x00fcfcfc,
6088c2ecf20Sopenharmony_ci		.mode_fifoctrl	= 0x2f2f2f2f,
6098c2ecf20Sopenharmony_ci		.mode_backlight	= 0x00000000,
6108c2ecf20Sopenharmony_ci		.lcdclk		= 96,
6118c2ecf20Sopenharmony_ci		856, 856,
6128c2ecf20Sopenharmony_ci		480, 480,
6138c2ecf20Sopenharmony_ci	},
6148c2ecf20Sopenharmony_ci	[9] = {
6158c2ecf20Sopenharmony_ci		.name = "DB1300_800x480",
6168c2ecf20Sopenharmony_ci		.monspecs = {
6178c2ecf20Sopenharmony_ci			.modedb = NULL,
6188c2ecf20Sopenharmony_ci			.modedb_len = 0,
6198c2ecf20Sopenharmony_ci			.hfmin = 30000,
6208c2ecf20Sopenharmony_ci			.hfmax = 70000,
6218c2ecf20Sopenharmony_ci			.vfmin = 60,
6228c2ecf20Sopenharmony_ci			.vfmax = 60,
6238c2ecf20Sopenharmony_ci			.dclkmin = 6000000,
6248c2ecf20Sopenharmony_ci			.dclkmax = 28000000,
6258c2ecf20Sopenharmony_ci			.input = FB_DISP_RGB,
6268c2ecf20Sopenharmony_ci		},
6278c2ecf20Sopenharmony_ci		.mode_screen		= LCD_SCREEN_SX_N(800) |
6288c2ecf20Sopenharmony_ci					  LCD_SCREEN_SY_N(480),
6298c2ecf20Sopenharmony_ci		.mode_horztiming	= LCD_HORZTIMING_HPW_N(5) |
6308c2ecf20Sopenharmony_ci					  LCD_HORZTIMING_HND1_N(16) |
6318c2ecf20Sopenharmony_ci					  LCD_HORZTIMING_HND2_N(8),
6328c2ecf20Sopenharmony_ci		.mode_verttiming	= LCD_VERTTIMING_VPW_N(4) |
6338c2ecf20Sopenharmony_ci					  LCD_VERTTIMING_VND1_N(8) |
6348c2ecf20Sopenharmony_ci					  LCD_VERTTIMING_VND2_N(5),
6358c2ecf20Sopenharmony_ci		.mode_clkcontrol	= LCD_CLKCONTROL_PCD_N(1) |
6368c2ecf20Sopenharmony_ci					  LCD_CLKCONTROL_IV |
6378c2ecf20Sopenharmony_ci					  LCD_CLKCONTROL_IH,
6388c2ecf20Sopenharmony_ci		.mode_pwmdiv		= 0x00000000,
6398c2ecf20Sopenharmony_ci		.mode_pwmhi		= 0x00000000,
6408c2ecf20Sopenharmony_ci		.mode_outmask		= 0x00FFFFFF,
6418c2ecf20Sopenharmony_ci		.mode_fifoctrl		= 0x2f2f2f2f,
6428c2ecf20Sopenharmony_ci		.mode_backlight		= 0x00000000,
6438c2ecf20Sopenharmony_ci		.lcdclk			= 96,
6448c2ecf20Sopenharmony_ci		800, 800,
6458c2ecf20Sopenharmony_ci		480, 480,
6468c2ecf20Sopenharmony_ci	},
6478c2ecf20Sopenharmony_ci};
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci#define NUM_PANELS (ARRAY_SIZE(known_lcd_panels))
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci/********************************************************************/
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_cistatic int winbpp (unsigned int winctrl1)
6548c2ecf20Sopenharmony_ci{
6558c2ecf20Sopenharmony_ci	int bits = 0;
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	/* how many bits are needed for each pixel format */
6588c2ecf20Sopenharmony_ci	switch (winctrl1 & LCD_WINCTRL1_FRM) {
6598c2ecf20Sopenharmony_ci	case LCD_WINCTRL1_FRM_1BPP:
6608c2ecf20Sopenharmony_ci		bits = 1;
6618c2ecf20Sopenharmony_ci		break;
6628c2ecf20Sopenharmony_ci	case LCD_WINCTRL1_FRM_2BPP:
6638c2ecf20Sopenharmony_ci		bits = 2;
6648c2ecf20Sopenharmony_ci		break;
6658c2ecf20Sopenharmony_ci	case LCD_WINCTRL1_FRM_4BPP:
6668c2ecf20Sopenharmony_ci		bits = 4;
6678c2ecf20Sopenharmony_ci		break;
6688c2ecf20Sopenharmony_ci	case LCD_WINCTRL1_FRM_8BPP:
6698c2ecf20Sopenharmony_ci		bits = 8;
6708c2ecf20Sopenharmony_ci		break;
6718c2ecf20Sopenharmony_ci	case LCD_WINCTRL1_FRM_12BPP:
6728c2ecf20Sopenharmony_ci	case LCD_WINCTRL1_FRM_16BPP655:
6738c2ecf20Sopenharmony_ci	case LCD_WINCTRL1_FRM_16BPP565:
6748c2ecf20Sopenharmony_ci	case LCD_WINCTRL1_FRM_16BPP556:
6758c2ecf20Sopenharmony_ci	case LCD_WINCTRL1_FRM_16BPPI1555:
6768c2ecf20Sopenharmony_ci	case LCD_WINCTRL1_FRM_16BPPI5551:
6778c2ecf20Sopenharmony_ci	case LCD_WINCTRL1_FRM_16BPPA1555:
6788c2ecf20Sopenharmony_ci	case LCD_WINCTRL1_FRM_16BPPA5551:
6798c2ecf20Sopenharmony_ci		bits = 16;
6808c2ecf20Sopenharmony_ci		break;
6818c2ecf20Sopenharmony_ci	case LCD_WINCTRL1_FRM_24BPP:
6828c2ecf20Sopenharmony_ci	case LCD_WINCTRL1_FRM_32BPP:
6838c2ecf20Sopenharmony_ci		bits = 32;
6848c2ecf20Sopenharmony_ci		break;
6858c2ecf20Sopenharmony_ci	}
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	return bits;
6888c2ecf20Sopenharmony_ci}
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_cistatic int fbinfo2index (struct fb_info *fb_info)
6918c2ecf20Sopenharmony_ci{
6928c2ecf20Sopenharmony_ci	int i;
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	for (i = 0; i < device_count; ++i) {
6958c2ecf20Sopenharmony_ci		if (fb_info == _au1200fb_infos[i])
6968c2ecf20Sopenharmony_ci			return i;
6978c2ecf20Sopenharmony_ci	}
6988c2ecf20Sopenharmony_ci	printk("au1200fb: ERROR: fbinfo2index failed!\n");
6998c2ecf20Sopenharmony_ci	return -1;
7008c2ecf20Sopenharmony_ci}
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_cistatic int au1200_setlocation (struct au1200fb_device *fbdev, int plane,
7038c2ecf20Sopenharmony_ci	int xpos, int ypos)
7048c2ecf20Sopenharmony_ci{
7058c2ecf20Sopenharmony_ci	uint32 winctrl0, winctrl1, winenable, fb_offset = 0;
7068c2ecf20Sopenharmony_ci	int xsz, ysz;
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci	/* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	winctrl0 = lcd->window[plane].winctrl0;
7118c2ecf20Sopenharmony_ci	winctrl1 = lcd->window[plane].winctrl1;
7128c2ecf20Sopenharmony_ci	winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN);
7138c2ecf20Sopenharmony_ci	winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY);
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	/* Check for off-screen adjustments */
7168c2ecf20Sopenharmony_ci	xsz = win->w[plane].xres;
7178c2ecf20Sopenharmony_ci	ysz = win->w[plane].yres;
7188c2ecf20Sopenharmony_ci	if ((xpos + win->w[plane].xres) > panel->Xres) {
7198c2ecf20Sopenharmony_ci		/* Off-screen to the right */
7208c2ecf20Sopenharmony_ci		xsz = panel->Xres - xpos; /* off by 1 ??? */
7218c2ecf20Sopenharmony_ci		/*printk("off screen right\n");*/
7228c2ecf20Sopenharmony_ci	}
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci	if ((ypos + win->w[plane].yres) > panel->Yres) {
7258c2ecf20Sopenharmony_ci		/* Off-screen to the bottom */
7268c2ecf20Sopenharmony_ci		ysz = panel->Yres - ypos; /* off by 1 ??? */
7278c2ecf20Sopenharmony_ci		/*printk("off screen bottom\n");*/
7288c2ecf20Sopenharmony_ci	}
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	if (xpos < 0) {
7318c2ecf20Sopenharmony_ci		/* Off-screen to the left */
7328c2ecf20Sopenharmony_ci		xsz = win->w[plane].xres + xpos;
7338c2ecf20Sopenharmony_ci		fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8);
7348c2ecf20Sopenharmony_ci		xpos = 0;
7358c2ecf20Sopenharmony_ci		/*printk("off screen left\n");*/
7368c2ecf20Sopenharmony_ci	}
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	if (ypos < 0) {
7398c2ecf20Sopenharmony_ci		/* Off-screen to the top */
7408c2ecf20Sopenharmony_ci		ysz = win->w[plane].yres + ypos;
7418c2ecf20Sopenharmony_ci		/* fixme: fb_offset += ((0-ypos)*fb_pars[plane].line_length); */
7428c2ecf20Sopenharmony_ci		ypos = 0;
7438c2ecf20Sopenharmony_ci		/*printk("off screen top\n");*/
7448c2ecf20Sopenharmony_ci	}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	/* record settings */
7478c2ecf20Sopenharmony_ci	win->w[plane].xpos = xpos;
7488c2ecf20Sopenharmony_ci	win->w[plane].ypos = ypos;
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	xsz -= 1;
7518c2ecf20Sopenharmony_ci	ysz -= 1;
7528c2ecf20Sopenharmony_ci	winctrl0 |= (xpos << 21);
7538c2ecf20Sopenharmony_ci	winctrl0 |= (ypos << 10);
7548c2ecf20Sopenharmony_ci	winctrl1 |= (xsz << 11);
7558c2ecf20Sopenharmony_ci	winctrl1 |= (ysz << 0);
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	/* Disable the window while making changes, then restore WINEN */
7588c2ecf20Sopenharmony_ci	winenable = lcd->winenable & (1 << plane);
7598c2ecf20Sopenharmony_ci	wmb(); /* drain writebuffer */
7608c2ecf20Sopenharmony_ci	lcd->winenable &= ~(1 << plane);
7618c2ecf20Sopenharmony_ci	lcd->window[plane].winctrl0 = winctrl0;
7628c2ecf20Sopenharmony_ci	lcd->window[plane].winctrl1 = winctrl1;
7638c2ecf20Sopenharmony_ci	lcd->window[plane].winbuf0 =
7648c2ecf20Sopenharmony_ci	lcd->window[plane].winbuf1 = fbdev->fb_phys;
7658c2ecf20Sopenharmony_ci	lcd->window[plane].winbufctrl = 0; /* select winbuf0 */
7668c2ecf20Sopenharmony_ci	lcd->winenable |= winenable;
7678c2ecf20Sopenharmony_ci	wmb(); /* drain writebuffer */
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	return 0;
7708c2ecf20Sopenharmony_ci}
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_cistatic void au1200_setpanel(struct panel_settings *newpanel,
7738c2ecf20Sopenharmony_ci			    struct au1200fb_platdata *pd)
7748c2ecf20Sopenharmony_ci{
7758c2ecf20Sopenharmony_ci	/*
7768c2ecf20Sopenharmony_ci	 * Perform global setup/init of LCD controller
7778c2ecf20Sopenharmony_ci	 */
7788c2ecf20Sopenharmony_ci	uint32 winenable;
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	/* Make sure all windows disabled */
7818c2ecf20Sopenharmony_ci	winenable = lcd->winenable;
7828c2ecf20Sopenharmony_ci	lcd->winenable = 0;
7838c2ecf20Sopenharmony_ci	wmb(); /* drain writebuffer */
7848c2ecf20Sopenharmony_ci	/*
7858c2ecf20Sopenharmony_ci	 * Ensure everything is disabled before reconfiguring
7868c2ecf20Sopenharmony_ci	 */
7878c2ecf20Sopenharmony_ci	if (lcd->screen & LCD_SCREEN_SEN) {
7888c2ecf20Sopenharmony_ci		/* Wait for vertical sync period */
7898c2ecf20Sopenharmony_ci		lcd->intstatus = LCD_INT_SS;
7908c2ecf20Sopenharmony_ci		while ((lcd->intstatus & LCD_INT_SS) == 0)
7918c2ecf20Sopenharmony_ci			;
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci		lcd->screen &= ~LCD_SCREEN_SEN;	/*disable the controller*/
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci		do {
7968c2ecf20Sopenharmony_ci			lcd->intstatus = lcd->intstatus; /*clear interrupts*/
7978c2ecf20Sopenharmony_ci			wmb(); /* drain writebuffer */
7988c2ecf20Sopenharmony_ci		/*wait for controller to shut down*/
7998c2ecf20Sopenharmony_ci		} while ((lcd->intstatus & LCD_INT_SD) == 0);
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci		/* Call shutdown of current panel (if up) */
8028c2ecf20Sopenharmony_ci		/* this must occur last, because if an external clock is driving
8038c2ecf20Sopenharmony_ci		    the controller, the clock cannot be turned off before first
8048c2ecf20Sopenharmony_ci			shutting down the controller.
8058c2ecf20Sopenharmony_ci		 */
8068c2ecf20Sopenharmony_ci		if (pd->panel_shutdown)
8078c2ecf20Sopenharmony_ci			pd->panel_shutdown();
8088c2ecf20Sopenharmony_ci	}
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci	/* Newpanel == NULL indicates a shutdown operation only */
8118c2ecf20Sopenharmony_ci	if (newpanel == NULL)
8128c2ecf20Sopenharmony_ci		return;
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	panel = newpanel;
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci	printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres);
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	/*
8198c2ecf20Sopenharmony_ci	 * Setup clocking if internal LCD clock source (assumes sys_auxpll valid)
8208c2ecf20Sopenharmony_ci	 */
8218c2ecf20Sopenharmony_ci	if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT))
8228c2ecf20Sopenharmony_ci	{
8238c2ecf20Sopenharmony_ci		struct clk *c = clk_get(NULL, "lcd_intclk");
8248c2ecf20Sopenharmony_ci		long r, pc = panel->lcdclk * 1000000;
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci		if (!IS_ERR(c)) {
8278c2ecf20Sopenharmony_ci			r = clk_round_rate(c, pc);
8288c2ecf20Sopenharmony_ci			if ((pc - r) < (pc / 10)) {	/* 10% slack */
8298c2ecf20Sopenharmony_ci				clk_set_rate(c, r);
8308c2ecf20Sopenharmony_ci				clk_prepare_enable(c);
8318c2ecf20Sopenharmony_ci			}
8328c2ecf20Sopenharmony_ci			clk_put(c);
8338c2ecf20Sopenharmony_ci		}
8348c2ecf20Sopenharmony_ci	}
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	/*
8378c2ecf20Sopenharmony_ci	 * Configure panel timings
8388c2ecf20Sopenharmony_ci	 */
8398c2ecf20Sopenharmony_ci	lcd->screen = panel->mode_screen;
8408c2ecf20Sopenharmony_ci	lcd->horztiming = panel->mode_horztiming;
8418c2ecf20Sopenharmony_ci	lcd->verttiming = panel->mode_verttiming;
8428c2ecf20Sopenharmony_ci	lcd->clkcontrol = panel->mode_clkcontrol;
8438c2ecf20Sopenharmony_ci	lcd->pwmdiv = panel->mode_pwmdiv;
8448c2ecf20Sopenharmony_ci	lcd->pwmhi = panel->mode_pwmhi;
8458c2ecf20Sopenharmony_ci	lcd->outmask = panel->mode_outmask;
8468c2ecf20Sopenharmony_ci	lcd->fifoctrl = panel->mode_fifoctrl;
8478c2ecf20Sopenharmony_ci	wmb(); /* drain writebuffer */
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	/* fixme: Check window settings to make sure still valid
8508c2ecf20Sopenharmony_ci	 * for new geometry */
8518c2ecf20Sopenharmony_ci#if 0
8528c2ecf20Sopenharmony_ci	au1200_setlocation(fbdev, 0, win->w[0].xpos, win->w[0].ypos);
8538c2ecf20Sopenharmony_ci	au1200_setlocation(fbdev, 1, win->w[1].xpos, win->w[1].ypos);
8548c2ecf20Sopenharmony_ci	au1200_setlocation(fbdev, 2, win->w[2].xpos, win->w[2].ypos);
8558c2ecf20Sopenharmony_ci	au1200_setlocation(fbdev, 3, win->w[3].xpos, win->w[3].ypos);
8568c2ecf20Sopenharmony_ci#endif
8578c2ecf20Sopenharmony_ci	lcd->winenable = winenable;
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	/*
8608c2ecf20Sopenharmony_ci	 * Re-enable screen now that it is configured
8618c2ecf20Sopenharmony_ci	 */
8628c2ecf20Sopenharmony_ci	lcd->screen |= LCD_SCREEN_SEN;
8638c2ecf20Sopenharmony_ci	wmb(); /* drain writebuffer */
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci	/* Call init of panel */
8668c2ecf20Sopenharmony_ci	if (pd->panel_init)
8678c2ecf20Sopenharmony_ci		pd->panel_init();
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	/* FIX!!!! not appropriate on panel change!!! Global setup/init */
8708c2ecf20Sopenharmony_ci	lcd->intenable = 0;
8718c2ecf20Sopenharmony_ci	lcd->intstatus = ~0;
8728c2ecf20Sopenharmony_ci	lcd->backcolor = win->mode_backcolor;
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_ci	/* Setup Color Key - FIX!!! */
8758c2ecf20Sopenharmony_ci	lcd->colorkey = win->mode_colorkey;
8768c2ecf20Sopenharmony_ci	lcd->colorkeymsk = win->mode_colorkeymsk;
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	/* Setup HWCursor - FIX!!! Need to support this eventually */
8798c2ecf20Sopenharmony_ci	lcd->hwc.cursorctrl = 0;
8808c2ecf20Sopenharmony_ci	lcd->hwc.cursorpos = 0;
8818c2ecf20Sopenharmony_ci	lcd->hwc.cursorcolor0 = 0;
8828c2ecf20Sopenharmony_ci	lcd->hwc.cursorcolor1 = 0;
8838c2ecf20Sopenharmony_ci	lcd->hwc.cursorcolor2 = 0;
8848c2ecf20Sopenharmony_ci	lcd->hwc.cursorcolor3 = 0;
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci#if 0
8888c2ecf20Sopenharmony_ci#define D(X) printk("%25s: %08X\n", #X, X)
8898c2ecf20Sopenharmony_ci	D(lcd->screen);
8908c2ecf20Sopenharmony_ci	D(lcd->horztiming);
8918c2ecf20Sopenharmony_ci	D(lcd->verttiming);
8928c2ecf20Sopenharmony_ci	D(lcd->clkcontrol);
8938c2ecf20Sopenharmony_ci	D(lcd->pwmdiv);
8948c2ecf20Sopenharmony_ci	D(lcd->pwmhi);
8958c2ecf20Sopenharmony_ci	D(lcd->outmask);
8968c2ecf20Sopenharmony_ci	D(lcd->fifoctrl);
8978c2ecf20Sopenharmony_ci	D(lcd->window[0].winctrl0);
8988c2ecf20Sopenharmony_ci	D(lcd->window[0].winctrl1);
8998c2ecf20Sopenharmony_ci	D(lcd->window[0].winctrl2);
9008c2ecf20Sopenharmony_ci	D(lcd->window[0].winbuf0);
9018c2ecf20Sopenharmony_ci	D(lcd->window[0].winbuf1);
9028c2ecf20Sopenharmony_ci	D(lcd->window[0].winbufctrl);
9038c2ecf20Sopenharmony_ci	D(lcd->window[1].winctrl0);
9048c2ecf20Sopenharmony_ci	D(lcd->window[1].winctrl1);
9058c2ecf20Sopenharmony_ci	D(lcd->window[1].winctrl2);
9068c2ecf20Sopenharmony_ci	D(lcd->window[1].winbuf0);
9078c2ecf20Sopenharmony_ci	D(lcd->window[1].winbuf1);
9088c2ecf20Sopenharmony_ci	D(lcd->window[1].winbufctrl);
9098c2ecf20Sopenharmony_ci	D(lcd->window[2].winctrl0);
9108c2ecf20Sopenharmony_ci	D(lcd->window[2].winctrl1);
9118c2ecf20Sopenharmony_ci	D(lcd->window[2].winctrl2);
9128c2ecf20Sopenharmony_ci	D(lcd->window[2].winbuf0);
9138c2ecf20Sopenharmony_ci	D(lcd->window[2].winbuf1);
9148c2ecf20Sopenharmony_ci	D(lcd->window[2].winbufctrl);
9158c2ecf20Sopenharmony_ci	D(lcd->window[3].winctrl0);
9168c2ecf20Sopenharmony_ci	D(lcd->window[3].winctrl1);
9178c2ecf20Sopenharmony_ci	D(lcd->window[3].winctrl2);
9188c2ecf20Sopenharmony_ci	D(lcd->window[3].winbuf0);
9198c2ecf20Sopenharmony_ci	D(lcd->window[3].winbuf1);
9208c2ecf20Sopenharmony_ci	D(lcd->window[3].winbufctrl);
9218c2ecf20Sopenharmony_ci	D(lcd->winenable);
9228c2ecf20Sopenharmony_ci	D(lcd->intenable);
9238c2ecf20Sopenharmony_ci	D(lcd->intstatus);
9248c2ecf20Sopenharmony_ci	D(lcd->backcolor);
9258c2ecf20Sopenharmony_ci	D(lcd->winenable);
9268c2ecf20Sopenharmony_ci	D(lcd->colorkey);
9278c2ecf20Sopenharmony_ci    D(lcd->colorkeymsk);
9288c2ecf20Sopenharmony_ci	D(lcd->hwc.cursorctrl);
9298c2ecf20Sopenharmony_ci	D(lcd->hwc.cursorpos);
9308c2ecf20Sopenharmony_ci	D(lcd->hwc.cursorcolor0);
9318c2ecf20Sopenharmony_ci	D(lcd->hwc.cursorcolor1);
9328c2ecf20Sopenharmony_ci	D(lcd->hwc.cursorcolor2);
9338c2ecf20Sopenharmony_ci	D(lcd->hwc.cursorcolor3);
9348c2ecf20Sopenharmony_ci#endif
9358c2ecf20Sopenharmony_ci}
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_cistatic void au1200_setmode(struct au1200fb_device *fbdev)
9388c2ecf20Sopenharmony_ci{
9398c2ecf20Sopenharmony_ci	int plane = fbdev->plane;
9408c2ecf20Sopenharmony_ci	/* Window/plane setup */
9418c2ecf20Sopenharmony_ci	lcd->window[plane].winctrl1 = ( 0
9428c2ecf20Sopenharmony_ci		| LCD_WINCTRL1_PRI_N(plane)
9438c2ecf20Sopenharmony_ci		| win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */
9448c2ecf20Sopenharmony_ci		) ;
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci	au1200_setlocation(fbdev, plane, win->w[plane].xpos, win->w[plane].ypos);
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci	lcd->window[plane].winctrl2 = ( 0
9498c2ecf20Sopenharmony_ci		| LCD_WINCTRL2_CKMODE_00
9508c2ecf20Sopenharmony_ci		| LCD_WINCTRL2_DBM
9518c2ecf20Sopenharmony_ci		| LCD_WINCTRL2_BX_N(fbdev->fb_info->fix.line_length)
9528c2ecf20Sopenharmony_ci		| LCD_WINCTRL2_SCX_1
9538c2ecf20Sopenharmony_ci		| LCD_WINCTRL2_SCY_1
9548c2ecf20Sopenharmony_ci		) ;
9558c2ecf20Sopenharmony_ci	lcd->winenable |= win->w[plane].mode_winenable;
9568c2ecf20Sopenharmony_ci	wmb(); /* drain writebuffer */
9578c2ecf20Sopenharmony_ci}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci/* Inline helpers */
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci/*#define panel_is_dual(panel)  ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/
9638c2ecf20Sopenharmony_ci/*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_ci#define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN)
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci/* Bitfields format supported by the controller. */
9688c2ecf20Sopenharmony_cistatic struct fb_bitfield rgb_bitfields[][4] = {
9698c2ecf20Sopenharmony_ci  	/*     Red, 	   Green, 	 Blue, 	     Transp   */
9708c2ecf20Sopenharmony_ci	[LCD_WINCTRL1_FRM_16BPP655 >> 25] =
9718c2ecf20Sopenharmony_ci		{ { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	[LCD_WINCTRL1_FRM_16BPP565 >> 25] =
9748c2ecf20Sopenharmony_ci		{ { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	[LCD_WINCTRL1_FRM_16BPP556 >> 25] =
9778c2ecf20Sopenharmony_ci		{ { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } },
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci	[LCD_WINCTRL1_FRM_16BPPI1555 >> 25] =
9808c2ecf20Sopenharmony_ci		{ { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	[LCD_WINCTRL1_FRM_16BPPI5551 >> 25] =
9838c2ecf20Sopenharmony_ci		{ { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } },
9848c2ecf20Sopenharmony_ci
9858c2ecf20Sopenharmony_ci	[LCD_WINCTRL1_FRM_16BPPA1555 >> 25] =
9868c2ecf20Sopenharmony_ci		{ { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } },
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	[LCD_WINCTRL1_FRM_16BPPA5551 >> 25] =
9898c2ecf20Sopenharmony_ci		{ { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } },
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	[LCD_WINCTRL1_FRM_24BPP >> 25] =
9928c2ecf20Sopenharmony_ci		{ { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } },
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	[LCD_WINCTRL1_FRM_32BPP >> 25] =
9958c2ecf20Sopenharmony_ci		{ { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } },
9968c2ecf20Sopenharmony_ci};
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci/*-------------------------------------------------------------------------*/
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci/* Helpers */
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_cistatic void au1200fb_update_fbinfo(struct fb_info *fbi)
10038c2ecf20Sopenharmony_ci{
10048c2ecf20Sopenharmony_ci	/* FIX!!!! This also needs to take the window pixel format into account!!! */
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci	/* Update var-dependent FB info */
10078c2ecf20Sopenharmony_ci	if (panel_is_color(panel)) {
10088c2ecf20Sopenharmony_ci		if (fbi->var.bits_per_pixel <= 8) {
10098c2ecf20Sopenharmony_ci			/* palettized */
10108c2ecf20Sopenharmony_ci			fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR;
10118c2ecf20Sopenharmony_ci			fbi->fix.line_length = fbi->var.xres_virtual /
10128c2ecf20Sopenharmony_ci				(8/fbi->var.bits_per_pixel);
10138c2ecf20Sopenharmony_ci		} else {
10148c2ecf20Sopenharmony_ci			/* non-palettized */
10158c2ecf20Sopenharmony_ci			fbi->fix.visual = FB_VISUAL_TRUECOLOR;
10168c2ecf20Sopenharmony_ci			fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8);
10178c2ecf20Sopenharmony_ci		}
10188c2ecf20Sopenharmony_ci	} else {
10198c2ecf20Sopenharmony_ci		/* mono FIX!!! mono 8 and 4 bits */
10208c2ecf20Sopenharmony_ci		fbi->fix.visual = FB_VISUAL_MONO10;
10218c2ecf20Sopenharmony_ci		fbi->fix.line_length = fbi->var.xres_virtual / 8;
10228c2ecf20Sopenharmony_ci	}
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual;
10258c2ecf20Sopenharmony_ci	print_dbg("line length: %d\n", fbi->fix.line_length);
10268c2ecf20Sopenharmony_ci	print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel);
10278c2ecf20Sopenharmony_ci}
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci/*-------------------------------------------------------------------------*/
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci/* AU1200 framebuffer driver */
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci/* fb_check_var
10348c2ecf20Sopenharmony_ci * Validate var settings with hardware restrictions and modify it if necessary
10358c2ecf20Sopenharmony_ci */
10368c2ecf20Sopenharmony_cistatic int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
10378c2ecf20Sopenharmony_ci	struct fb_info *fbi)
10388c2ecf20Sopenharmony_ci{
10398c2ecf20Sopenharmony_ci	struct au1200fb_device *fbdev = fbi->par;
10408c2ecf20Sopenharmony_ci	u32 pixclock;
10418c2ecf20Sopenharmony_ci	int screen_size, plane;
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	if (!var->pixclock)
10448c2ecf20Sopenharmony_ci		return -EINVAL;
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci	plane = fbdev->plane;
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci	/* Make sure that the mode respect all LCD controller and
10498c2ecf20Sopenharmony_ci	 * panel restrictions. */
10508c2ecf20Sopenharmony_ci	var->xres = win->w[plane].xres;
10518c2ecf20Sopenharmony_ci	var->yres = win->w[plane].yres;
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci	/* No need for virtual resolution support */
10548c2ecf20Sopenharmony_ci	var->xres_virtual = var->xres;
10558c2ecf20Sopenharmony_ci	var->yres_virtual = var->yres;
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_ci	var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1);
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci	screen_size = var->xres_virtual * var->yres_virtual;
10608c2ecf20Sopenharmony_ci	if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8);
10618c2ecf20Sopenharmony_ci	else screen_size /= (8/var->bits_per_pixel);
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci	if (fbdev->fb_len < screen_size)
10648c2ecf20Sopenharmony_ci		return -EINVAL; /* Virtual screen is to big, abort */
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci	/* FIX!!!! what are the implicaitons of ignoring this for windows ??? */
10678c2ecf20Sopenharmony_ci	/* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel
10688c2ecf20Sopenharmony_ci	 * clock can only be obtain by dividing this value by an even integer.
10698c2ecf20Sopenharmony_ci	 * Fallback to a slower pixel clock if necessary. */
10708c2ecf20Sopenharmony_ci	pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin);
10718c2ecf20Sopenharmony_ci	pixclock = min3(pixclock, fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2);
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_ci	if (AU1200_LCD_MAX_CLK % pixclock) {
10748c2ecf20Sopenharmony_ci		int diff = AU1200_LCD_MAX_CLK % pixclock;
10758c2ecf20Sopenharmony_ci		pixclock -= diff;
10768c2ecf20Sopenharmony_ci	}
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	var->pixclock = KHZ2PICOS(pixclock/1000);
10798c2ecf20Sopenharmony_ci#if 0
10808c2ecf20Sopenharmony_ci	if (!panel_is_active(panel)) {
10818c2ecf20Sopenharmony_ci		int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1;
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ci		if (!panel_is_color(panel)
10848c2ecf20Sopenharmony_ci			&& (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) {
10858c2ecf20Sopenharmony_ci			/* STN 8bit mono panel support is up to 6MHz pixclock */
10868c2ecf20Sopenharmony_ci			var->pixclock = KHZ2PICOS(6000);
10878c2ecf20Sopenharmony_ci		} else if (!pcd) {
10888c2ecf20Sopenharmony_ci			/* Other STN panel support is up to 12MHz  */
10898c2ecf20Sopenharmony_ci			var->pixclock = KHZ2PICOS(12000);
10908c2ecf20Sopenharmony_ci		}
10918c2ecf20Sopenharmony_ci	}
10928c2ecf20Sopenharmony_ci#endif
10938c2ecf20Sopenharmony_ci	/* Set bitfield accordingly */
10948c2ecf20Sopenharmony_ci	switch (var->bits_per_pixel) {
10958c2ecf20Sopenharmony_ci		case 16:
10968c2ecf20Sopenharmony_ci		{
10978c2ecf20Sopenharmony_ci			/* 16bpp True color.
10988c2ecf20Sopenharmony_ci			 * These must be set to MATCH WINCTRL[FORM] */
10998c2ecf20Sopenharmony_ci			int idx;
11008c2ecf20Sopenharmony_ci			idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;
11018c2ecf20Sopenharmony_ci			var->red    = rgb_bitfields[idx][0];
11028c2ecf20Sopenharmony_ci			var->green  = rgb_bitfields[idx][1];
11038c2ecf20Sopenharmony_ci			var->blue   = rgb_bitfields[idx][2];
11048c2ecf20Sopenharmony_ci			var->transp = rgb_bitfields[idx][3];
11058c2ecf20Sopenharmony_ci			break;
11068c2ecf20Sopenharmony_ci		}
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_ci		case 32:
11098c2ecf20Sopenharmony_ci		{
11108c2ecf20Sopenharmony_ci			/* 32bpp True color.
11118c2ecf20Sopenharmony_ci			 * These must be set to MATCH WINCTRL[FORM] */
11128c2ecf20Sopenharmony_ci			int idx;
11138c2ecf20Sopenharmony_ci			idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;
11148c2ecf20Sopenharmony_ci			var->red    = rgb_bitfields[idx][0];
11158c2ecf20Sopenharmony_ci			var->green  = rgb_bitfields[idx][1];
11168c2ecf20Sopenharmony_ci			var->blue   = rgb_bitfields[idx][2];
11178c2ecf20Sopenharmony_ci			var->transp = rgb_bitfields[idx][3];
11188c2ecf20Sopenharmony_ci			break;
11198c2ecf20Sopenharmony_ci		}
11208c2ecf20Sopenharmony_ci		default:
11218c2ecf20Sopenharmony_ci			print_dbg("Unsupported depth %dbpp", var->bits_per_pixel);
11228c2ecf20Sopenharmony_ci			return -EINVAL;
11238c2ecf20Sopenharmony_ci	}
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci	return 0;
11268c2ecf20Sopenharmony_ci}
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci/* fb_set_par
11298c2ecf20Sopenharmony_ci * Set hardware with var settings. This will enable the controller with a
11308c2ecf20Sopenharmony_ci * specific mode, normally validated with the fb_check_var method
11318c2ecf20Sopenharmony_ci */
11328c2ecf20Sopenharmony_cistatic int au1200fb_fb_set_par(struct fb_info *fbi)
11338c2ecf20Sopenharmony_ci{
11348c2ecf20Sopenharmony_ci	struct au1200fb_device *fbdev = fbi->par;
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci	au1200fb_update_fbinfo(fbi);
11378c2ecf20Sopenharmony_ci	au1200_setmode(fbdev);
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci	return 0;
11408c2ecf20Sopenharmony_ci}
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_ci/* fb_setcolreg
11438c2ecf20Sopenharmony_ci * Set color in LCD palette.
11448c2ecf20Sopenharmony_ci */
11458c2ecf20Sopenharmony_cistatic int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
11468c2ecf20Sopenharmony_ci	unsigned blue, unsigned transp, struct fb_info *fbi)
11478c2ecf20Sopenharmony_ci{
11488c2ecf20Sopenharmony_ci	volatile u32 *palette = lcd->palette;
11498c2ecf20Sopenharmony_ci	u32 value;
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ci	if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1))
11528c2ecf20Sopenharmony_ci		return -EINVAL;
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_ci	if (fbi->var.grayscale) {
11558c2ecf20Sopenharmony_ci		/* Convert color to grayscale */
11568c2ecf20Sopenharmony_ci		red = green = blue =
11578c2ecf20Sopenharmony_ci			(19595 * red + 38470 * green + 7471 * blue) >> 16;
11588c2ecf20Sopenharmony_ci	}
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci	if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) {
11618c2ecf20Sopenharmony_ci		/* Place color in the pseudopalette */
11628c2ecf20Sopenharmony_ci		if (regno > 16)
11638c2ecf20Sopenharmony_ci			return -EINVAL;
11648c2ecf20Sopenharmony_ci
11658c2ecf20Sopenharmony_ci		palette = (u32*) fbi->pseudo_palette;
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci		red   >>= (16 - fbi->var.red.length);
11688c2ecf20Sopenharmony_ci		green >>= (16 - fbi->var.green.length);
11698c2ecf20Sopenharmony_ci		blue  >>= (16 - fbi->var.blue.length);
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci		value = (red   << fbi->var.red.offset) 	|
11728c2ecf20Sopenharmony_ci			(green << fbi->var.green.offset)|
11738c2ecf20Sopenharmony_ci			(blue  << fbi->var.blue.offset);
11748c2ecf20Sopenharmony_ci		value &= 0xFFFF;
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci	} else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) {
11778c2ecf20Sopenharmony_ci		/* COLOR TFT PALLETTIZED (use RGB 565) */
11788c2ecf20Sopenharmony_ci		value = (red & 0xF800)|((green >> 5) &
11798c2ecf20Sopenharmony_ci				0x07E0)|((blue >> 11) & 0x001F);
11808c2ecf20Sopenharmony_ci		value &= 0xFFFF;
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci	} else if (0 /*panel_is_color(fbdev->panel)*/) {
11838c2ecf20Sopenharmony_ci		/* COLOR STN MODE */
11848c2ecf20Sopenharmony_ci		value = 0x1234;
11858c2ecf20Sopenharmony_ci		value &= 0xFFF;
11868c2ecf20Sopenharmony_ci	} else {
11878c2ecf20Sopenharmony_ci		/* MONOCHROME MODE */
11888c2ecf20Sopenharmony_ci		value = (green >> 12) & 0x000F;
11898c2ecf20Sopenharmony_ci		value &= 0xF;
11908c2ecf20Sopenharmony_ci	}
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci	palette[regno] = value;
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	return 0;
11958c2ecf20Sopenharmony_ci}
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci/* fb_blank
11988c2ecf20Sopenharmony_ci * Blank the screen. Depending on the mode, the screen will be
11998c2ecf20Sopenharmony_ci * activated with the backlight color, or desactivated
12008c2ecf20Sopenharmony_ci */
12018c2ecf20Sopenharmony_cistatic int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi)
12028c2ecf20Sopenharmony_ci{
12038c2ecf20Sopenharmony_ci	struct au1200fb_device *fbdev = fbi->par;
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	/* Short-circuit screen blanking */
12068c2ecf20Sopenharmony_ci	if (noblanking)
12078c2ecf20Sopenharmony_ci		return 0;
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	switch (blank_mode) {
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci	case FB_BLANK_UNBLANK:
12128c2ecf20Sopenharmony_ci	case FB_BLANK_NORMAL:
12138c2ecf20Sopenharmony_ci		/* printk("turn on panel\n"); */
12148c2ecf20Sopenharmony_ci		au1200_setpanel(panel, fbdev->pd);
12158c2ecf20Sopenharmony_ci		break;
12168c2ecf20Sopenharmony_ci	case FB_BLANK_VSYNC_SUSPEND:
12178c2ecf20Sopenharmony_ci	case FB_BLANK_HSYNC_SUSPEND:
12188c2ecf20Sopenharmony_ci	case FB_BLANK_POWERDOWN:
12198c2ecf20Sopenharmony_ci		/* printk("turn off panel\n"); */
12208c2ecf20Sopenharmony_ci		au1200_setpanel(NULL, fbdev->pd);
12218c2ecf20Sopenharmony_ci		break;
12228c2ecf20Sopenharmony_ci	default:
12238c2ecf20Sopenharmony_ci		break;
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ci	}
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	/* FB_BLANK_NORMAL is a soft blank */
12288c2ecf20Sopenharmony_ci	return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0;
12298c2ecf20Sopenharmony_ci}
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci/* fb_mmap
12328c2ecf20Sopenharmony_ci * Map video memory in user space. We don't use the generic fb_mmap
12338c2ecf20Sopenharmony_ci * method mainly to allow the use of the TLB streaming flag (CCA=6)
12348c2ecf20Sopenharmony_ci */
12358c2ecf20Sopenharmony_cistatic int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
12368c2ecf20Sopenharmony_ci{
12378c2ecf20Sopenharmony_ci	struct au1200fb_device *fbdev = info->par;
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	return dma_mmap_attrs(fbdev->dev, vma, fbdev->fb_mem, fbdev->fb_phys,
12408c2ecf20Sopenharmony_ci			fbdev->fb_len, 0);
12418c2ecf20Sopenharmony_ci}
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_cistatic void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
12448c2ecf20Sopenharmony_ci{
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_ci	unsigned int hi1, divider;
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci	/* SCREEN_SIZE: user cannot reset size, must switch panel choice */
12498c2ecf20Sopenharmony_ci
12508c2ecf20Sopenharmony_ci	if (pdata->flags & SCREEN_BACKCOLOR)
12518c2ecf20Sopenharmony_ci		lcd->backcolor = pdata->backcolor;
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_ci	if (pdata->flags & SCREEN_BRIGHTNESS) {
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci		// limit brightness pwm duty to >= 30/1600
12568c2ecf20Sopenharmony_ci		if (pdata->brightness < 30) {
12578c2ecf20Sopenharmony_ci			pdata->brightness = 30;
12588c2ecf20Sopenharmony_ci		}
12598c2ecf20Sopenharmony_ci		divider = (lcd->pwmdiv & 0x3FFFF) + 1;
12608c2ecf20Sopenharmony_ci		hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8);
12618c2ecf20Sopenharmony_ci		lcd->pwmhi &= 0xFFFF;
12628c2ecf20Sopenharmony_ci		lcd->pwmhi |= (hi1 << 16);
12638c2ecf20Sopenharmony_ci	}
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci	if (pdata->flags & SCREEN_COLORKEY)
12668c2ecf20Sopenharmony_ci		lcd->colorkey = pdata->colorkey;
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci	if (pdata->flags & SCREEN_MASK)
12698c2ecf20Sopenharmony_ci		lcd->colorkeymsk = pdata->mask;
12708c2ecf20Sopenharmony_ci	wmb(); /* drain writebuffer */
12718c2ecf20Sopenharmony_ci}
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_cistatic void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
12748c2ecf20Sopenharmony_ci{
12758c2ecf20Sopenharmony_ci	unsigned int hi1, divider;
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ci	pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1;
12788c2ecf20Sopenharmony_ci	pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1;
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci	pdata->backcolor = lcd->backcolor;
12818c2ecf20Sopenharmony_ci	pdata->colorkey = lcd->colorkey;
12828c2ecf20Sopenharmony_ci	pdata->mask = lcd->colorkeymsk;
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_ci	// brightness
12858c2ecf20Sopenharmony_ci	hi1 = (lcd->pwmhi >> 16) + 1;
12868c2ecf20Sopenharmony_ci	divider = (lcd->pwmdiv & 0x3FFFF) + 1;
12878c2ecf20Sopenharmony_ci	pdata->brightness = ((hi1 << 8) / divider) - 1;
12888c2ecf20Sopenharmony_ci	wmb(); /* drain writebuffer */
12898c2ecf20Sopenharmony_ci}
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_cistatic void set_window(unsigned int plane,
12928c2ecf20Sopenharmony_ci	struct au1200_lcd_window_regs_t *pdata)
12938c2ecf20Sopenharmony_ci{
12948c2ecf20Sopenharmony_ci	unsigned int val, bpp;
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_ci	/* Window control register 0 */
12978c2ecf20Sopenharmony_ci	if (pdata->flags & WIN_POSITION) {
12988c2ecf20Sopenharmony_ci		val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX |
12998c2ecf20Sopenharmony_ci				LCD_WINCTRL0_OY);
13008c2ecf20Sopenharmony_ci		val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX);
13018c2ecf20Sopenharmony_ci		val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY);
13028c2ecf20Sopenharmony_ci		lcd->window[plane].winctrl0 = val;
13038c2ecf20Sopenharmony_ci	}
13048c2ecf20Sopenharmony_ci	if (pdata->flags & WIN_ALPHA_COLOR) {
13058c2ecf20Sopenharmony_ci		val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A);
13068c2ecf20Sopenharmony_ci		val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A);
13078c2ecf20Sopenharmony_ci		lcd->window[plane].winctrl0 = val;
13088c2ecf20Sopenharmony_ci	}
13098c2ecf20Sopenharmony_ci	if (pdata->flags & WIN_ALPHA_MODE) {
13108c2ecf20Sopenharmony_ci		val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN);
13118c2ecf20Sopenharmony_ci		val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN);
13128c2ecf20Sopenharmony_ci		lcd->window[plane].winctrl0 = val;
13138c2ecf20Sopenharmony_ci	}
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci	/* Window control register 1 */
13168c2ecf20Sopenharmony_ci	if (pdata->flags & WIN_PRIORITY) {
13178c2ecf20Sopenharmony_ci		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI);
13188c2ecf20Sopenharmony_ci		val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI);
13198c2ecf20Sopenharmony_ci		lcd->window[plane].winctrl1 = val;
13208c2ecf20Sopenharmony_ci	}
13218c2ecf20Sopenharmony_ci	if (pdata->flags & WIN_CHANNEL) {
13228c2ecf20Sopenharmony_ci		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE);
13238c2ecf20Sopenharmony_ci		val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE);
13248c2ecf20Sopenharmony_ci		lcd->window[plane].winctrl1 = val;
13258c2ecf20Sopenharmony_ci	}
13268c2ecf20Sopenharmony_ci	if (pdata->flags & WIN_BUFFER_FORMAT) {
13278c2ecf20Sopenharmony_ci		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM);
13288c2ecf20Sopenharmony_ci		val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM);
13298c2ecf20Sopenharmony_ci		lcd->window[plane].winctrl1 = val;
13308c2ecf20Sopenharmony_ci	}
13318c2ecf20Sopenharmony_ci	if (pdata->flags & WIN_COLOR_ORDER) {
13328c2ecf20Sopenharmony_ci		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO);
13338c2ecf20Sopenharmony_ci		val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO);
13348c2ecf20Sopenharmony_ci		lcd->window[plane].winctrl1 = val;
13358c2ecf20Sopenharmony_ci	}
13368c2ecf20Sopenharmony_ci	if (pdata->flags & WIN_PIXEL_ORDER) {
13378c2ecf20Sopenharmony_ci		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO);
13388c2ecf20Sopenharmony_ci		val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO);
13398c2ecf20Sopenharmony_ci		lcd->window[plane].winctrl1 = val;
13408c2ecf20Sopenharmony_ci	}
13418c2ecf20Sopenharmony_ci	if (pdata->flags & WIN_SIZE) {
13428c2ecf20Sopenharmony_ci		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX |
13438c2ecf20Sopenharmony_ci				LCD_WINCTRL1_SZY);
13448c2ecf20Sopenharmony_ci		val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX);
13458c2ecf20Sopenharmony_ci		val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY);
13468c2ecf20Sopenharmony_ci		lcd->window[plane].winctrl1 = val;
13478c2ecf20Sopenharmony_ci		/* program buffer line width */
13488c2ecf20Sopenharmony_ci		bpp = winbpp(val) / 8;
13498c2ecf20Sopenharmony_ci		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX);
13508c2ecf20Sopenharmony_ci		val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX);
13518c2ecf20Sopenharmony_ci		lcd->window[plane].winctrl2 = val;
13528c2ecf20Sopenharmony_ci	}
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci	/* Window control register 2 */
13558c2ecf20Sopenharmony_ci	if (pdata->flags & WIN_COLORKEY_MODE) {
13568c2ecf20Sopenharmony_ci		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE);
13578c2ecf20Sopenharmony_ci		val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE);
13588c2ecf20Sopenharmony_ci		lcd->window[plane].winctrl2 = val;
13598c2ecf20Sopenharmony_ci	}
13608c2ecf20Sopenharmony_ci	if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) {
13618c2ecf20Sopenharmony_ci		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM);
13628c2ecf20Sopenharmony_ci		val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM);
13638c2ecf20Sopenharmony_ci		lcd->window[plane].winctrl2 = val;
13648c2ecf20Sopenharmony_ci	}
13658c2ecf20Sopenharmony_ci	if (pdata->flags & WIN_RAM_ARRAY_MODE) {
13668c2ecf20Sopenharmony_ci		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM);
13678c2ecf20Sopenharmony_ci		val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM);
13688c2ecf20Sopenharmony_ci		lcd->window[plane].winctrl2 = val;
13698c2ecf20Sopenharmony_ci	}
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	/* Buffer line width programmed with WIN_SIZE */
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci	if (pdata->flags & WIN_BUFFER_SCALE) {
13748c2ecf20Sopenharmony_ci		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX |
13758c2ecf20Sopenharmony_ci				LCD_WINCTRL2_SCY);
13768c2ecf20Sopenharmony_ci		val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX);
13778c2ecf20Sopenharmony_ci		val |= ((pdata->ysize) & LCD_WINCTRL2_SCY);
13788c2ecf20Sopenharmony_ci		lcd->window[plane].winctrl2 = val;
13798c2ecf20Sopenharmony_ci	}
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci	if (pdata->flags & WIN_ENABLE) {
13828c2ecf20Sopenharmony_ci		val = lcd->winenable;
13838c2ecf20Sopenharmony_ci		val &= ~(1<<plane);
13848c2ecf20Sopenharmony_ci		val |= (pdata->enable & 1) << plane;
13858c2ecf20Sopenharmony_ci		lcd->winenable = val;
13868c2ecf20Sopenharmony_ci	}
13878c2ecf20Sopenharmony_ci	wmb(); /* drain writebuffer */
13888c2ecf20Sopenharmony_ci}
13898c2ecf20Sopenharmony_ci
13908c2ecf20Sopenharmony_cistatic void get_window(unsigned int plane,
13918c2ecf20Sopenharmony_ci	struct au1200_lcd_window_regs_t *pdata)
13928c2ecf20Sopenharmony_ci{
13938c2ecf20Sopenharmony_ci	/* Window control register 0 */
13948c2ecf20Sopenharmony_ci	pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21;
13958c2ecf20Sopenharmony_ci	pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10;
13968c2ecf20Sopenharmony_ci	pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2;
13978c2ecf20Sopenharmony_ci	pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1;
13988c2ecf20Sopenharmony_ci
13998c2ecf20Sopenharmony_ci	/* Window control register 1 */
14008c2ecf20Sopenharmony_ci	pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30;
14018c2ecf20Sopenharmony_ci	pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29;
14028c2ecf20Sopenharmony_ci	pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25;
14038c2ecf20Sopenharmony_ci	pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24;
14048c2ecf20Sopenharmony_ci	pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22;
14058c2ecf20Sopenharmony_ci	pdata->xsize = ((lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11) + 1;
14068c2ecf20Sopenharmony_ci	pdata->ysize = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZY) + 1;
14078c2ecf20Sopenharmony_ci
14088c2ecf20Sopenharmony_ci	/* Window control register 2 */
14098c2ecf20Sopenharmony_ci	pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24;
14108c2ecf20Sopenharmony_ci	pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23;
14118c2ecf20Sopenharmony_ci	pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21;
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ci	pdata->enable = (lcd->winenable >> plane) & 1;
14148c2ecf20Sopenharmony_ci	wmb(); /* drain writebuffer */
14158c2ecf20Sopenharmony_ci}
14168c2ecf20Sopenharmony_ci
14178c2ecf20Sopenharmony_cistatic int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
14188c2ecf20Sopenharmony_ci                          unsigned long arg)
14198c2ecf20Sopenharmony_ci{
14208c2ecf20Sopenharmony_ci	struct au1200fb_device *fbdev = info->par;
14218c2ecf20Sopenharmony_ci	int plane;
14228c2ecf20Sopenharmony_ci	int val;
14238c2ecf20Sopenharmony_ci
14248c2ecf20Sopenharmony_ci	plane = fbinfo2index(info);
14258c2ecf20Sopenharmony_ci	print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane);
14268c2ecf20Sopenharmony_ci
14278c2ecf20Sopenharmony_ci	if (cmd == AU1200_LCD_FB_IOCTL) {
14288c2ecf20Sopenharmony_ci		struct au1200_lcd_iodata_t iodata;
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci		if (copy_from_user(&iodata, (void __user *) arg, sizeof(iodata)))
14318c2ecf20Sopenharmony_ci			return -EFAULT;
14328c2ecf20Sopenharmony_ci
14338c2ecf20Sopenharmony_ci		print_dbg("FB IOCTL called\n");
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ci		switch (iodata.subcmd) {
14368c2ecf20Sopenharmony_ci		case AU1200_LCD_SET_SCREEN:
14378c2ecf20Sopenharmony_ci			print_dbg("AU1200_LCD_SET_SCREEN\n");
14388c2ecf20Sopenharmony_ci			set_global(cmd, &iodata.global);
14398c2ecf20Sopenharmony_ci			break;
14408c2ecf20Sopenharmony_ci
14418c2ecf20Sopenharmony_ci		case AU1200_LCD_GET_SCREEN:
14428c2ecf20Sopenharmony_ci			print_dbg("AU1200_LCD_GET_SCREEN\n");
14438c2ecf20Sopenharmony_ci			get_global(cmd, &iodata.global);
14448c2ecf20Sopenharmony_ci			break;
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_ci		case AU1200_LCD_SET_WINDOW:
14478c2ecf20Sopenharmony_ci			print_dbg("AU1200_LCD_SET_WINDOW\n");
14488c2ecf20Sopenharmony_ci			set_window(plane, &iodata.window);
14498c2ecf20Sopenharmony_ci			break;
14508c2ecf20Sopenharmony_ci
14518c2ecf20Sopenharmony_ci		case AU1200_LCD_GET_WINDOW:
14528c2ecf20Sopenharmony_ci			print_dbg("AU1200_LCD_GET_WINDOW\n");
14538c2ecf20Sopenharmony_ci			get_window(plane, &iodata.window);
14548c2ecf20Sopenharmony_ci			break;
14558c2ecf20Sopenharmony_ci
14568c2ecf20Sopenharmony_ci		case AU1200_LCD_SET_PANEL:
14578c2ecf20Sopenharmony_ci			print_dbg("AU1200_LCD_SET_PANEL\n");
14588c2ecf20Sopenharmony_ci			if ((iodata.global.panel_choice >= 0) &&
14598c2ecf20Sopenharmony_ci					(iodata.global.panel_choice <
14608c2ecf20Sopenharmony_ci					 NUM_PANELS))
14618c2ecf20Sopenharmony_ci			{
14628c2ecf20Sopenharmony_ci				struct panel_settings *newpanel;
14638c2ecf20Sopenharmony_ci				panel_index = iodata.global.panel_choice;
14648c2ecf20Sopenharmony_ci				newpanel = &known_lcd_panels[panel_index];
14658c2ecf20Sopenharmony_ci				au1200_setpanel(newpanel, fbdev->pd);
14668c2ecf20Sopenharmony_ci			}
14678c2ecf20Sopenharmony_ci			break;
14688c2ecf20Sopenharmony_ci
14698c2ecf20Sopenharmony_ci		case AU1200_LCD_GET_PANEL:
14708c2ecf20Sopenharmony_ci			print_dbg("AU1200_LCD_GET_PANEL\n");
14718c2ecf20Sopenharmony_ci			iodata.global.panel_choice = panel_index;
14728c2ecf20Sopenharmony_ci			break;
14738c2ecf20Sopenharmony_ci
14748c2ecf20Sopenharmony_ci		default:
14758c2ecf20Sopenharmony_ci			return -EINVAL;
14768c2ecf20Sopenharmony_ci		}
14778c2ecf20Sopenharmony_ci
14788c2ecf20Sopenharmony_ci		val = copy_to_user((void __user *) arg, &iodata, sizeof(iodata));
14798c2ecf20Sopenharmony_ci		if (val) {
14808c2ecf20Sopenharmony_ci			print_dbg("error: could not copy %d bytes\n", val);
14818c2ecf20Sopenharmony_ci			return -EFAULT;
14828c2ecf20Sopenharmony_ci		}
14838c2ecf20Sopenharmony_ci	}
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci	return 0;
14868c2ecf20Sopenharmony_ci}
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_cistatic const struct fb_ops au1200fb_fb_ops = {
14908c2ecf20Sopenharmony_ci	.owner		= THIS_MODULE,
14918c2ecf20Sopenharmony_ci	.fb_check_var	= au1200fb_fb_check_var,
14928c2ecf20Sopenharmony_ci	.fb_set_par	= au1200fb_fb_set_par,
14938c2ecf20Sopenharmony_ci	.fb_setcolreg	= au1200fb_fb_setcolreg,
14948c2ecf20Sopenharmony_ci	.fb_blank	= au1200fb_fb_blank,
14958c2ecf20Sopenharmony_ci	.fb_fillrect	= sys_fillrect,
14968c2ecf20Sopenharmony_ci	.fb_copyarea	= sys_copyarea,
14978c2ecf20Sopenharmony_ci	.fb_imageblit	= sys_imageblit,
14988c2ecf20Sopenharmony_ci	.fb_read	= fb_sys_read,
14998c2ecf20Sopenharmony_ci	.fb_write	= fb_sys_write,
15008c2ecf20Sopenharmony_ci	.fb_sync	= NULL,
15018c2ecf20Sopenharmony_ci	.fb_ioctl	= au1200fb_ioctl,
15028c2ecf20Sopenharmony_ci	.fb_mmap	= au1200fb_fb_mmap,
15038c2ecf20Sopenharmony_ci};
15048c2ecf20Sopenharmony_ci
15058c2ecf20Sopenharmony_ci/*-------------------------------------------------------------------------*/
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_cistatic irqreturn_t au1200fb_handle_irq(int irq, void* dev_id)
15088c2ecf20Sopenharmony_ci{
15098c2ecf20Sopenharmony_ci	/* Nothing to do for now, just clear any pending interrupt */
15108c2ecf20Sopenharmony_ci	lcd->intstatus = lcd->intstatus;
15118c2ecf20Sopenharmony_ci	wmb(); /* drain writebuffer */
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
15148c2ecf20Sopenharmony_ci}
15158c2ecf20Sopenharmony_ci
15168c2ecf20Sopenharmony_ci/*-------------------------------------------------------------------------*/
15178c2ecf20Sopenharmony_ci
15188c2ecf20Sopenharmony_ci/* AU1200 LCD device probe helpers */
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_cistatic int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
15218c2ecf20Sopenharmony_ci{
15228c2ecf20Sopenharmony_ci	struct fb_info *fbi = fbdev->fb_info;
15238c2ecf20Sopenharmony_ci	int bpp, ret;
15248c2ecf20Sopenharmony_ci
15258c2ecf20Sopenharmony_ci	fbi->fbops = &au1200fb_fb_ops;
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_ci	bpp = winbpp(win->w[fbdev->plane].mode_winctrl1);
15288c2ecf20Sopenharmony_ci
15298c2ecf20Sopenharmony_ci	/* Copy monitor specs from panel data */
15308c2ecf20Sopenharmony_ci	/* fixme: we're setting up LCD controller windows, so these dont give a
15318c2ecf20Sopenharmony_ci	damn as to what the monitor specs are (the panel itself does, but that
15328c2ecf20Sopenharmony_ci	isn't done here...so maybe need a generic catchall monitor setting??? */
15338c2ecf20Sopenharmony_ci	memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs));
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_ci	/* We first try the user mode passed in argument. If that failed,
15368c2ecf20Sopenharmony_ci	 * or if no one has been specified, we default to the first mode of the
15378c2ecf20Sopenharmony_ci	 * panel list. Note that after this call, var data will be set */
15388c2ecf20Sopenharmony_ci	if (!fb_find_mode(&fbi->var,
15398c2ecf20Sopenharmony_ci			  fbi,
15408c2ecf20Sopenharmony_ci			  NULL, /* drv_info.opt_mode, */
15418c2ecf20Sopenharmony_ci			  fbi->monspecs.modedb,
15428c2ecf20Sopenharmony_ci			  fbi->monspecs.modedb_len,
15438c2ecf20Sopenharmony_ci			  fbi->monspecs.modedb,
15448c2ecf20Sopenharmony_ci			  bpp)) {
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci		print_err("Cannot find valid mode for panel %s", panel->name);
15478c2ecf20Sopenharmony_ci		return -EFAULT;
15488c2ecf20Sopenharmony_ci	}
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci	fbi->pseudo_palette = kcalloc(16, sizeof(u32), GFP_KERNEL);
15518c2ecf20Sopenharmony_ci	if (!fbi->pseudo_palette)
15528c2ecf20Sopenharmony_ci		return -ENOMEM;
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci	ret = fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0);
15558c2ecf20Sopenharmony_ci	if (ret < 0) {
15568c2ecf20Sopenharmony_ci		print_err("Fail to allocate colormap (%d entries)",
15578c2ecf20Sopenharmony_ci			  AU1200_LCD_NBR_PALETTE_ENTRIES);
15588c2ecf20Sopenharmony_ci		return ret;
15598c2ecf20Sopenharmony_ci	}
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id));
15628c2ecf20Sopenharmony_ci	fbi->fix.smem_start = fbdev->fb_phys;
15638c2ecf20Sopenharmony_ci	fbi->fix.smem_len = fbdev->fb_len;
15648c2ecf20Sopenharmony_ci	fbi->fix.type = FB_TYPE_PACKED_PIXELS;
15658c2ecf20Sopenharmony_ci	fbi->fix.xpanstep = 0;
15668c2ecf20Sopenharmony_ci	fbi->fix.ypanstep = 0;
15678c2ecf20Sopenharmony_ci	fbi->fix.mmio_start = 0;
15688c2ecf20Sopenharmony_ci	fbi->fix.mmio_len = 0;
15698c2ecf20Sopenharmony_ci	fbi->fix.accel = FB_ACCEL_NONE;
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_ci	fbi->screen_base = (char __iomem *) fbdev->fb_mem;
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	au1200fb_update_fbinfo(fbi);
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci	return 0;
15768c2ecf20Sopenharmony_ci}
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci/*-------------------------------------------------------------------------*/
15798c2ecf20Sopenharmony_ci
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_cistatic int au1200fb_setup(struct au1200fb_platdata *pd)
15828c2ecf20Sopenharmony_ci{
15838c2ecf20Sopenharmony_ci	char *options = NULL;
15848c2ecf20Sopenharmony_ci	char *this_opt, *endptr;
15858c2ecf20Sopenharmony_ci	int num_panels = ARRAY_SIZE(known_lcd_panels);
15868c2ecf20Sopenharmony_ci	int panel_idx = -1;
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_ci	fb_get_options(DRIVER_NAME, &options);
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_ci	if (!options)
15918c2ecf20Sopenharmony_ci		goto out;
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_ci	while ((this_opt = strsep(&options, ",")) != NULL) {
15948c2ecf20Sopenharmony_ci		/* Panel option - can be panel name,
15958c2ecf20Sopenharmony_ci		 * "bs" for board-switch, or number/index */
15968c2ecf20Sopenharmony_ci		if (!strncmp(this_opt, "panel:", 6)) {
15978c2ecf20Sopenharmony_ci			int i;
15988c2ecf20Sopenharmony_ci			long int li;
15998c2ecf20Sopenharmony_ci			char *endptr;
16008c2ecf20Sopenharmony_ci			this_opt += 6;
16018c2ecf20Sopenharmony_ci			/* First check for index, which allows
16028c2ecf20Sopenharmony_ci			 * to short circuit this mess */
16038c2ecf20Sopenharmony_ci			li = simple_strtol(this_opt, &endptr, 0);
16048c2ecf20Sopenharmony_ci			if (*endptr == '\0')
16058c2ecf20Sopenharmony_ci				panel_idx = (int)li;
16068c2ecf20Sopenharmony_ci			else if (strcmp(this_opt, "bs") == 0)
16078c2ecf20Sopenharmony_ci				panel_idx = pd->panel_index();
16088c2ecf20Sopenharmony_ci			else {
16098c2ecf20Sopenharmony_ci				for (i = 0; i < num_panels; i++) {
16108c2ecf20Sopenharmony_ci					if (!strcmp(this_opt,
16118c2ecf20Sopenharmony_ci						    known_lcd_panels[i].name)) {
16128c2ecf20Sopenharmony_ci						panel_idx = i;
16138c2ecf20Sopenharmony_ci						break;
16148c2ecf20Sopenharmony_ci					}
16158c2ecf20Sopenharmony_ci				}
16168c2ecf20Sopenharmony_ci			}
16178c2ecf20Sopenharmony_ci			if ((panel_idx < 0) || (panel_idx >= num_panels))
16188c2ecf20Sopenharmony_ci				print_warn("Panel %s not supported!", this_opt);
16198c2ecf20Sopenharmony_ci			else
16208c2ecf20Sopenharmony_ci				panel_index = panel_idx;
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci		} else if (strncmp(this_opt, "nohwcursor", 10) == 0)
16238c2ecf20Sopenharmony_ci			nohwcursor = 1;
16248c2ecf20Sopenharmony_ci		else if (strncmp(this_opt, "devices:", 8) == 0) {
16258c2ecf20Sopenharmony_ci			this_opt += 8;
16268c2ecf20Sopenharmony_ci			device_count = simple_strtol(this_opt, &endptr, 0);
16278c2ecf20Sopenharmony_ci			if ((device_count < 0) ||
16288c2ecf20Sopenharmony_ci			    (device_count > MAX_DEVICE_COUNT))
16298c2ecf20Sopenharmony_ci				device_count = MAX_DEVICE_COUNT;
16308c2ecf20Sopenharmony_ci		} else if (strncmp(this_opt, "wincfg:", 7) == 0) {
16318c2ecf20Sopenharmony_ci			this_opt += 7;
16328c2ecf20Sopenharmony_ci			window_index = simple_strtol(this_opt, &endptr, 0);
16338c2ecf20Sopenharmony_ci			if ((window_index < 0) ||
16348c2ecf20Sopenharmony_ci			    (window_index >= ARRAY_SIZE(windows)))
16358c2ecf20Sopenharmony_ci				window_index = DEFAULT_WINDOW_INDEX;
16368c2ecf20Sopenharmony_ci		} else if (strncmp(this_opt, "off", 3) == 0)
16378c2ecf20Sopenharmony_ci			return 1;
16388c2ecf20Sopenharmony_ci		else
16398c2ecf20Sopenharmony_ci			print_warn("Unsupported option \"%s\"", this_opt);
16408c2ecf20Sopenharmony_ci	}
16418c2ecf20Sopenharmony_ci
16428c2ecf20Sopenharmony_ciout:
16438c2ecf20Sopenharmony_ci	return 0;
16448c2ecf20Sopenharmony_ci}
16458c2ecf20Sopenharmony_ci
16468c2ecf20Sopenharmony_ci/* AU1200 LCD controller device driver */
16478c2ecf20Sopenharmony_cistatic int au1200fb_drv_probe(struct platform_device *dev)
16488c2ecf20Sopenharmony_ci{
16498c2ecf20Sopenharmony_ci	struct au1200fb_device *fbdev;
16508c2ecf20Sopenharmony_ci	struct au1200fb_platdata *pd;
16518c2ecf20Sopenharmony_ci	struct fb_info *fbi = NULL;
16528c2ecf20Sopenharmony_ci	int bpp, plane, ret, irq;
16538c2ecf20Sopenharmony_ci
16548c2ecf20Sopenharmony_ci	print_info("" DRIVER_DESC "");
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_ci	pd = dev->dev.platform_data;
16578c2ecf20Sopenharmony_ci	if (!pd)
16588c2ecf20Sopenharmony_ci		return -ENODEV;
16598c2ecf20Sopenharmony_ci
16608c2ecf20Sopenharmony_ci	/* Setup driver with options */
16618c2ecf20Sopenharmony_ci	if (au1200fb_setup(pd))
16628c2ecf20Sopenharmony_ci		return -ENODEV;
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci	/* Point to the panel selected */
16658c2ecf20Sopenharmony_ci	panel = &known_lcd_panels[panel_index];
16668c2ecf20Sopenharmony_ci	win = &windows[window_index];
16678c2ecf20Sopenharmony_ci
16688c2ecf20Sopenharmony_ci	printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
16698c2ecf20Sopenharmony_ci	printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_ci	for (plane = 0; plane < device_count; ++plane) {
16728c2ecf20Sopenharmony_ci		bpp = winbpp(win->w[plane].mode_winctrl1);
16738c2ecf20Sopenharmony_ci		if (win->w[plane].xres == 0)
16748c2ecf20Sopenharmony_ci			win->w[plane].xres = panel->Xres;
16758c2ecf20Sopenharmony_ci		if (win->w[plane].yres == 0)
16768c2ecf20Sopenharmony_ci			win->w[plane].yres = panel->Yres;
16778c2ecf20Sopenharmony_ci
16788c2ecf20Sopenharmony_ci		fbi = framebuffer_alloc(sizeof(struct au1200fb_device),
16798c2ecf20Sopenharmony_ci					&dev->dev);
16808c2ecf20Sopenharmony_ci		if (!fbi) {
16818c2ecf20Sopenharmony_ci			ret = -ENOMEM;
16828c2ecf20Sopenharmony_ci			goto failed;
16838c2ecf20Sopenharmony_ci		}
16848c2ecf20Sopenharmony_ci
16858c2ecf20Sopenharmony_ci		_au1200fb_infos[plane] = fbi;
16868c2ecf20Sopenharmony_ci		fbdev = fbi->par;
16878c2ecf20Sopenharmony_ci		fbdev->fb_info = fbi;
16888c2ecf20Sopenharmony_ci		fbdev->pd = pd;
16898c2ecf20Sopenharmony_ci		fbdev->dev = &dev->dev;
16908c2ecf20Sopenharmony_ci
16918c2ecf20Sopenharmony_ci		fbdev->plane = plane;
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_ci		/* Allocate the framebuffer to the maximum screen size */
16948c2ecf20Sopenharmony_ci		fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8;
16958c2ecf20Sopenharmony_ci
16968c2ecf20Sopenharmony_ci		fbdev->fb_mem = dmam_alloc_attrs(&dev->dev,
16978c2ecf20Sopenharmony_ci				PAGE_ALIGN(fbdev->fb_len),
16988c2ecf20Sopenharmony_ci				&fbdev->fb_phys, GFP_KERNEL, 0);
16998c2ecf20Sopenharmony_ci		if (!fbdev->fb_mem) {
17008c2ecf20Sopenharmony_ci			print_err("fail to allocate framebuffer (size: %dK))",
17018c2ecf20Sopenharmony_ci				  fbdev->fb_len / 1024);
17028c2ecf20Sopenharmony_ci			ret = -ENOMEM;
17038c2ecf20Sopenharmony_ci			goto failed;
17048c2ecf20Sopenharmony_ci		}
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_ci		print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
17078c2ecf20Sopenharmony_ci		print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
17088c2ecf20Sopenharmony_ci
17098c2ecf20Sopenharmony_ci		/* Init FB data */
17108c2ecf20Sopenharmony_ci		ret = au1200fb_init_fbinfo(fbdev);
17118c2ecf20Sopenharmony_ci		if (ret < 0)
17128c2ecf20Sopenharmony_ci			goto failed;
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_ci		/* Register new framebuffer */
17158c2ecf20Sopenharmony_ci		ret = register_framebuffer(fbi);
17168c2ecf20Sopenharmony_ci		if (ret < 0) {
17178c2ecf20Sopenharmony_ci			print_err("cannot register new framebuffer");
17188c2ecf20Sopenharmony_ci			goto failed;
17198c2ecf20Sopenharmony_ci		}
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_ci		au1200fb_fb_set_par(fbi);
17228c2ecf20Sopenharmony_ci
17238c2ecf20Sopenharmony_ci#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
17248c2ecf20Sopenharmony_ci		if (plane == 0)
17258c2ecf20Sopenharmony_ci			if (fb_prepare_logo(fbi, FB_ROTATE_UR)) {
17268c2ecf20Sopenharmony_ci				/* Start display and show logo on boot */
17278c2ecf20Sopenharmony_ci				fb_set_cmap(&fbi->cmap, fbi);
17288c2ecf20Sopenharmony_ci				fb_show_logo(fbi, FB_ROTATE_UR);
17298c2ecf20Sopenharmony_ci			}
17308c2ecf20Sopenharmony_ci#endif
17318c2ecf20Sopenharmony_ci	}
17328c2ecf20Sopenharmony_ci
17338c2ecf20Sopenharmony_ci	/* Now hook interrupt too */
17348c2ecf20Sopenharmony_ci	irq = platform_get_irq(dev, 0);
17358c2ecf20Sopenharmony_ci	if (irq < 0)
17368c2ecf20Sopenharmony_ci		return irq;
17378c2ecf20Sopenharmony_ci
17388c2ecf20Sopenharmony_ci	ret = request_irq(irq, au1200fb_handle_irq,
17398c2ecf20Sopenharmony_ci			  IRQF_SHARED, "lcd", (void *)dev);
17408c2ecf20Sopenharmony_ci	if (ret) {
17418c2ecf20Sopenharmony_ci		print_err("fail to request interrupt line %d (err: %d)",
17428c2ecf20Sopenharmony_ci			  irq, ret);
17438c2ecf20Sopenharmony_ci		goto failed;
17448c2ecf20Sopenharmony_ci	}
17458c2ecf20Sopenharmony_ci
17468c2ecf20Sopenharmony_ci	platform_set_drvdata(dev, pd);
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ci	/* Kickstart the panel */
17498c2ecf20Sopenharmony_ci	au1200_setpanel(panel, pd);
17508c2ecf20Sopenharmony_ci
17518c2ecf20Sopenharmony_ci	return 0;
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_cifailed:
17548c2ecf20Sopenharmony_ci	for (plane = 0; plane < device_count; ++plane) {
17558c2ecf20Sopenharmony_ci		fbi = _au1200fb_infos[plane];
17568c2ecf20Sopenharmony_ci		if (!fbi)
17578c2ecf20Sopenharmony_ci			break;
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci		/* Clean up all probe data */
17608c2ecf20Sopenharmony_ci		unregister_framebuffer(fbi);
17618c2ecf20Sopenharmony_ci		if (fbi->cmap.len != 0)
17628c2ecf20Sopenharmony_ci			fb_dealloc_cmap(&fbi->cmap);
17638c2ecf20Sopenharmony_ci		kfree(fbi->pseudo_palette);
17648c2ecf20Sopenharmony_ci
17658c2ecf20Sopenharmony_ci		framebuffer_release(fbi);
17668c2ecf20Sopenharmony_ci		_au1200fb_infos[plane] = NULL;
17678c2ecf20Sopenharmony_ci	}
17688c2ecf20Sopenharmony_ci	return ret;
17698c2ecf20Sopenharmony_ci}
17708c2ecf20Sopenharmony_ci
17718c2ecf20Sopenharmony_cistatic int au1200fb_drv_remove(struct platform_device *dev)
17728c2ecf20Sopenharmony_ci{
17738c2ecf20Sopenharmony_ci	struct au1200fb_platdata *pd = platform_get_drvdata(dev);
17748c2ecf20Sopenharmony_ci	struct fb_info *fbi;
17758c2ecf20Sopenharmony_ci	int plane;
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci	/* Turn off the panel */
17788c2ecf20Sopenharmony_ci	au1200_setpanel(NULL, pd);
17798c2ecf20Sopenharmony_ci
17808c2ecf20Sopenharmony_ci	for (plane = 0; plane < device_count; ++plane)	{
17818c2ecf20Sopenharmony_ci		fbi = _au1200fb_infos[plane];
17828c2ecf20Sopenharmony_ci
17838c2ecf20Sopenharmony_ci		/* Clean up all probe data */
17848c2ecf20Sopenharmony_ci		unregister_framebuffer(fbi);
17858c2ecf20Sopenharmony_ci		if (fbi->cmap.len != 0)
17868c2ecf20Sopenharmony_ci			fb_dealloc_cmap(&fbi->cmap);
17878c2ecf20Sopenharmony_ci		kfree(fbi->pseudo_palette);
17888c2ecf20Sopenharmony_ci
17898c2ecf20Sopenharmony_ci		framebuffer_release(fbi);
17908c2ecf20Sopenharmony_ci		_au1200fb_infos[plane] = NULL;
17918c2ecf20Sopenharmony_ci	}
17928c2ecf20Sopenharmony_ci
17938c2ecf20Sopenharmony_ci	free_irq(platform_get_irq(dev, 0), (void *)dev);
17948c2ecf20Sopenharmony_ci
17958c2ecf20Sopenharmony_ci	return 0;
17968c2ecf20Sopenharmony_ci}
17978c2ecf20Sopenharmony_ci
17988c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
17998c2ecf20Sopenharmony_cistatic int au1200fb_drv_suspend(struct device *dev)
18008c2ecf20Sopenharmony_ci{
18018c2ecf20Sopenharmony_ci	struct au1200fb_platdata *pd = dev_get_drvdata(dev);
18028c2ecf20Sopenharmony_ci	au1200_setpanel(NULL, pd);
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci	lcd->outmask = 0;
18058c2ecf20Sopenharmony_ci	wmb(); /* drain writebuffer */
18068c2ecf20Sopenharmony_ci
18078c2ecf20Sopenharmony_ci	return 0;
18088c2ecf20Sopenharmony_ci}
18098c2ecf20Sopenharmony_ci
18108c2ecf20Sopenharmony_cistatic int au1200fb_drv_resume(struct device *dev)
18118c2ecf20Sopenharmony_ci{
18128c2ecf20Sopenharmony_ci	struct au1200fb_platdata *pd = dev_get_drvdata(dev);
18138c2ecf20Sopenharmony_ci	struct fb_info *fbi;
18148c2ecf20Sopenharmony_ci	int i;
18158c2ecf20Sopenharmony_ci
18168c2ecf20Sopenharmony_ci	/* Kickstart the panel */
18178c2ecf20Sopenharmony_ci	au1200_setpanel(panel, pd);
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_ci	for (i = 0; i < device_count; i++) {
18208c2ecf20Sopenharmony_ci		fbi = _au1200fb_infos[i];
18218c2ecf20Sopenharmony_ci		au1200fb_fb_set_par(fbi);
18228c2ecf20Sopenharmony_ci	}
18238c2ecf20Sopenharmony_ci
18248c2ecf20Sopenharmony_ci	return 0;
18258c2ecf20Sopenharmony_ci}
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_cistatic const struct dev_pm_ops au1200fb_pmops = {
18288c2ecf20Sopenharmony_ci	.suspend	= au1200fb_drv_suspend,
18298c2ecf20Sopenharmony_ci	.resume		= au1200fb_drv_resume,
18308c2ecf20Sopenharmony_ci	.freeze		= au1200fb_drv_suspend,
18318c2ecf20Sopenharmony_ci	.thaw		= au1200fb_drv_resume,
18328c2ecf20Sopenharmony_ci};
18338c2ecf20Sopenharmony_ci
18348c2ecf20Sopenharmony_ci#define AU1200FB_PMOPS	(&au1200fb_pmops)
18358c2ecf20Sopenharmony_ci
18368c2ecf20Sopenharmony_ci#else
18378c2ecf20Sopenharmony_ci#define AU1200FB_PMOPS	NULL
18388c2ecf20Sopenharmony_ci#endif /* CONFIG_PM */
18398c2ecf20Sopenharmony_ci
18408c2ecf20Sopenharmony_cistatic struct platform_driver au1200fb_driver = {
18418c2ecf20Sopenharmony_ci	.driver = {
18428c2ecf20Sopenharmony_ci		.name	= "au1200-lcd",
18438c2ecf20Sopenharmony_ci		.pm	= AU1200FB_PMOPS,
18448c2ecf20Sopenharmony_ci	},
18458c2ecf20Sopenharmony_ci	.probe		= au1200fb_drv_probe,
18468c2ecf20Sopenharmony_ci	.remove		= au1200fb_drv_remove,
18478c2ecf20Sopenharmony_ci};
18488c2ecf20Sopenharmony_cimodule_platform_driver(au1200fb_driver);
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC);
18518c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
1852