1f95ec3c6SRalf Baechle /* 2f95ec3c6SRalf Baechle * BRIEF MODULE DESCRIPTION 3f95ec3c6SRalf Baechle * Au1200 LCD Driver. 4f95ec3c6SRalf Baechle * 5f95ec3c6SRalf Baechle * Copyright 2004-2005 AMD 6f95ec3c6SRalf Baechle * Author: AMD 7f95ec3c6SRalf Baechle * 8f95ec3c6SRalf Baechle * Based on: 9f95ec3c6SRalf Baechle * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device 10f95ec3c6SRalf Baechle * Created 28 Dec 1997 by Geert Uytterhoeven 11f95ec3c6SRalf Baechle * 12f95ec3c6SRalf Baechle * This program is free software; you can redistribute it and/or modify it 13f95ec3c6SRalf Baechle * under the terms of the GNU General Public License as published by the 14f95ec3c6SRalf Baechle * Free Software Foundation; either version 2 of the License, or (at your 15f95ec3c6SRalf Baechle * option) any later version. 16f95ec3c6SRalf Baechle * 17f95ec3c6SRalf Baechle * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 18f95ec3c6SRalf Baechle * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19f95ec3c6SRalf Baechle * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 20f95ec3c6SRalf Baechle * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21f95ec3c6SRalf Baechle * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22f95ec3c6SRalf Baechle * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 23f95ec3c6SRalf Baechle * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24f95ec3c6SRalf Baechle * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25f95ec3c6SRalf Baechle * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26f95ec3c6SRalf Baechle * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27f95ec3c6SRalf Baechle * 28f95ec3c6SRalf Baechle * You should have received a copy of the GNU General Public License along 29f95ec3c6SRalf Baechle * with this program; if not, write to the Free Software Foundation, Inc., 30f95ec3c6SRalf Baechle * 675 Mass Ave, Cambridge, MA 02139, USA. 31f95ec3c6SRalf Baechle */ 32f95ec3c6SRalf Baechle 33ecc2ea3bSManuel Lauss #include <linux/clk.h> 34f95ec3c6SRalf Baechle #include <linux/module.h> 35f95ec3c6SRalf Baechle #include <linux/platform_device.h> 36f95ec3c6SRalf Baechle #include <linux/kernel.h> 37f95ec3c6SRalf Baechle #include <linux/errno.h> 38f95ec3c6SRalf Baechle #include <linux/string.h> 39f95ec3c6SRalf Baechle #include <linux/mm.h> 40f95ec3c6SRalf Baechle #include <linux/fb.h> 41f95ec3c6SRalf Baechle #include <linux/init.h> 42f95ec3c6SRalf Baechle #include <linux/interrupt.h> 43f95ec3c6SRalf Baechle #include <linux/ctype.h> 44f95ec3c6SRalf Baechle #include <linux/dma-mapping.h> 455a0e3ad6STejun Heo #include <linux/slab.h> 4629abfbd9SAl Viro #include <linux/uaccess.h> 47f95ec3c6SRalf Baechle 48f95ec3c6SRalf Baechle #include <asm/mach-au1x00/au1000.h> 49a9b71a8fSManuel Lauss #include <asm/mach-au1x00/au1200fb.h> /* platform_data */ 50f95ec3c6SRalf Baechle #include "au1200fb.h" 51f95ec3c6SRalf Baechle 52f95ec3c6SRalf Baechle #define DRIVER_NAME "au1200fb" 53f95ec3c6SRalf Baechle #define DRIVER_DESC "LCD controller driver for AU1200 processors" 54f95ec3c6SRalf Baechle 55f49446ebSManuel Lauss #define DEBUG 0 56f95ec3c6SRalf Baechle 57f95ec3c6SRalf Baechle #define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) 58f95ec3c6SRalf Baechle #define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) 59f95ec3c6SRalf Baechle #define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) 60f95ec3c6SRalf Baechle 61f95ec3c6SRalf Baechle #if DEBUG 62f95ec3c6SRalf Baechle #define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg) 63f95ec3c6SRalf Baechle #else 64f95ec3c6SRalf Baechle #define print_dbg(f, arg...) do {} while (0) 65f95ec3c6SRalf Baechle #endif 66f95ec3c6SRalf Baechle 67f95ec3c6SRalf Baechle 68f95ec3c6SRalf Baechle #define AU1200_LCD_FB_IOCTL 0x46FF 69f95ec3c6SRalf Baechle 70f95ec3c6SRalf Baechle #define AU1200_LCD_SET_SCREEN 1 71f95ec3c6SRalf Baechle #define AU1200_LCD_GET_SCREEN 2 72f95ec3c6SRalf Baechle #define AU1200_LCD_SET_WINDOW 3 73f95ec3c6SRalf Baechle #define AU1200_LCD_GET_WINDOW 4 74f95ec3c6SRalf Baechle #define AU1200_LCD_SET_PANEL 5 75f95ec3c6SRalf Baechle #define AU1200_LCD_GET_PANEL 6 76f95ec3c6SRalf Baechle 77f95ec3c6SRalf Baechle #define SCREEN_SIZE (1<< 1) 78f95ec3c6SRalf Baechle #define SCREEN_BACKCOLOR (1<< 2) 79f95ec3c6SRalf Baechle #define SCREEN_BRIGHTNESS (1<< 3) 80f95ec3c6SRalf Baechle #define SCREEN_COLORKEY (1<< 4) 81f95ec3c6SRalf Baechle #define SCREEN_MASK (1<< 5) 82f95ec3c6SRalf Baechle 83f95ec3c6SRalf Baechle struct au1200_lcd_global_regs_t { 84f95ec3c6SRalf Baechle unsigned int flags; 85f95ec3c6SRalf Baechle unsigned int xsize; 86f95ec3c6SRalf Baechle unsigned int ysize; 87f95ec3c6SRalf Baechle unsigned int backcolor; 88f95ec3c6SRalf Baechle unsigned int brightness; 89f95ec3c6SRalf Baechle unsigned int colorkey; 90f95ec3c6SRalf Baechle unsigned int mask; 91f95ec3c6SRalf Baechle unsigned int panel_choice; 92f95ec3c6SRalf Baechle char panel_desc[80]; 93f95ec3c6SRalf Baechle 94f95ec3c6SRalf Baechle }; 95f95ec3c6SRalf Baechle 96f95ec3c6SRalf Baechle #define WIN_POSITION (1<< 0) 97f95ec3c6SRalf Baechle #define WIN_ALPHA_COLOR (1<< 1) 98f95ec3c6SRalf Baechle #define WIN_ALPHA_MODE (1<< 2) 99f95ec3c6SRalf Baechle #define WIN_PRIORITY (1<< 3) 100f95ec3c6SRalf Baechle #define WIN_CHANNEL (1<< 4) 101f95ec3c6SRalf Baechle #define WIN_BUFFER_FORMAT (1<< 5) 102f95ec3c6SRalf Baechle #define WIN_COLOR_ORDER (1<< 6) 103f95ec3c6SRalf Baechle #define WIN_PIXEL_ORDER (1<< 7) 104f95ec3c6SRalf Baechle #define WIN_SIZE (1<< 8) 105f95ec3c6SRalf Baechle #define WIN_COLORKEY_MODE (1<< 9) 106f95ec3c6SRalf Baechle #define WIN_DOUBLE_BUFFER_MODE (1<< 10) 107f95ec3c6SRalf Baechle #define WIN_RAM_ARRAY_MODE (1<< 11) 108f95ec3c6SRalf Baechle #define WIN_BUFFER_SCALE (1<< 12) 109f95ec3c6SRalf Baechle #define WIN_ENABLE (1<< 13) 110f95ec3c6SRalf Baechle 111f95ec3c6SRalf Baechle struct au1200_lcd_window_regs_t { 112f95ec3c6SRalf Baechle unsigned int flags; 113f95ec3c6SRalf Baechle unsigned int xpos; 114f95ec3c6SRalf Baechle unsigned int ypos; 115f95ec3c6SRalf Baechle unsigned int alpha_color; 116f95ec3c6SRalf Baechle unsigned int alpha_mode; 117f95ec3c6SRalf Baechle unsigned int priority; 118f95ec3c6SRalf Baechle unsigned int channel; 119f95ec3c6SRalf Baechle unsigned int buffer_format; 120f95ec3c6SRalf Baechle unsigned int color_order; 121f95ec3c6SRalf Baechle unsigned int pixel_order; 122f95ec3c6SRalf Baechle unsigned int xsize; 123f95ec3c6SRalf Baechle unsigned int ysize; 124f95ec3c6SRalf Baechle unsigned int colorkey_mode; 125f95ec3c6SRalf Baechle unsigned int double_buffer_mode; 126f95ec3c6SRalf Baechle unsigned int ram_array_mode; 127f95ec3c6SRalf Baechle unsigned int xscale; 128f95ec3c6SRalf Baechle unsigned int yscale; 129f95ec3c6SRalf Baechle unsigned int enable; 130f95ec3c6SRalf Baechle }; 131f95ec3c6SRalf Baechle 132f95ec3c6SRalf Baechle 133f95ec3c6SRalf Baechle struct au1200_lcd_iodata_t { 134f95ec3c6SRalf Baechle unsigned int subcmd; 135f95ec3c6SRalf Baechle struct au1200_lcd_global_regs_t global; 136f95ec3c6SRalf Baechle struct au1200_lcd_window_regs_t window; 137f95ec3c6SRalf Baechle }; 138f95ec3c6SRalf Baechle 139f95ec3c6SRalf Baechle #if defined(__BIG_ENDIAN) 140f95ec3c6SRalf Baechle #define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11 141f95ec3c6SRalf Baechle #else 142f95ec3c6SRalf Baechle #define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00 143f95ec3c6SRalf Baechle #endif 144f95ec3c6SRalf Baechle #define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565 145f95ec3c6SRalf Baechle 146f95ec3c6SRalf Baechle /* Private, per-framebuffer management information (independent of the panel itself) */ 147f95ec3c6SRalf Baechle struct au1200fb_device { 148c329f606SManuel Lauss struct fb_info *fb_info; /* FB driver info record */ 149a9b71a8fSManuel Lauss struct au1200fb_platdata *pd; 150e0b29902SChristoph Hellwig struct device *dev; 151f95ec3c6SRalf Baechle 152f95ec3c6SRalf Baechle int plane; 153f95ec3c6SRalf Baechle unsigned char* fb_mem; /* FrameBuffer memory map */ 154f95ec3c6SRalf Baechle unsigned int fb_len; 155f95ec3c6SRalf Baechle dma_addr_t fb_phys; 156f95ec3c6SRalf Baechle }; 157f95ec3c6SRalf Baechle 158f95ec3c6SRalf Baechle /********************************************************************/ 159f95ec3c6SRalf Baechle 160f95ec3c6SRalf Baechle /* LCD controller restrictions */ 161f95ec3c6SRalf Baechle #define AU1200_LCD_MAX_XRES 1280 162f95ec3c6SRalf Baechle #define AU1200_LCD_MAX_YRES 1024 163f95ec3c6SRalf Baechle #define AU1200_LCD_MAX_BPP 32 164f95ec3c6SRalf Baechle #define AU1200_LCD_MAX_CLK 96000000 /* fixme: this needs to go away ? */ 165f95ec3c6SRalf Baechle #define AU1200_LCD_NBR_PALETTE_ENTRIES 256 166f95ec3c6SRalf Baechle 167f95ec3c6SRalf Baechle /* Default number of visible screen buffer to allocate */ 168f95ec3c6SRalf Baechle #define AU1200FB_NBR_VIDEO_BUFFERS 1 169f95ec3c6SRalf Baechle 1708be90b07SManuel Lauss /* Default maximum number of fb devices to create */ 1718be90b07SManuel Lauss #define MAX_DEVICE_COUNT 4 1728be90b07SManuel Lauss 1738be90b07SManuel Lauss /* Default window configuration entry to use (see windows[]) */ 1748be90b07SManuel Lauss #define DEFAULT_WINDOW_INDEX 2 1758be90b07SManuel Lauss 176f95ec3c6SRalf Baechle /********************************************************************/ 177f95ec3c6SRalf Baechle 1788be90b07SManuel Lauss static struct fb_info *_au1200fb_infos[MAX_DEVICE_COUNT]; 179f95ec3c6SRalf Baechle static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; 1808be90b07SManuel Lauss static int device_count = MAX_DEVICE_COUNT; 1818be90b07SManuel Lauss static int window_index = DEFAULT_WINDOW_INDEX; /* default is zero */ 182f95ec3c6SRalf Baechle static int panel_index = 2; /* default is zero */ 183f95ec3c6SRalf Baechle static struct window_settings *win; 184f95ec3c6SRalf Baechle static struct panel_settings *panel; 185f95ec3c6SRalf Baechle static int noblanking = 1; 186f95ec3c6SRalf Baechle static int nohwcursor = 0; 187f95ec3c6SRalf Baechle 188f95ec3c6SRalf Baechle struct window_settings { 189f95ec3c6SRalf Baechle unsigned char name[64]; 190f95ec3c6SRalf Baechle uint32 mode_backcolor; 191f95ec3c6SRalf Baechle uint32 mode_colorkey; 192f95ec3c6SRalf Baechle uint32 mode_colorkeymsk; 193f95ec3c6SRalf Baechle struct { 194f95ec3c6SRalf Baechle int xres; 195f95ec3c6SRalf Baechle int yres; 196f95ec3c6SRalf Baechle int xpos; 197f95ec3c6SRalf Baechle int ypos; 198f95ec3c6SRalf Baechle uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */ 199f95ec3c6SRalf Baechle uint32 mode_winenable; 200f95ec3c6SRalf Baechle } w[4]; 201f95ec3c6SRalf Baechle }; 202f95ec3c6SRalf Baechle 203f95ec3c6SRalf Baechle #if defined(__BIG_ENDIAN) 204f95ec3c6SRalf Baechle #define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00 205f95ec3c6SRalf Baechle #else 206f95ec3c6SRalf Baechle #define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01 207f95ec3c6SRalf Baechle #endif 208f95ec3c6SRalf Baechle 209f95ec3c6SRalf Baechle /* 210f95ec3c6SRalf Baechle * Default window configurations 211f95ec3c6SRalf Baechle */ 212f95ec3c6SRalf Baechle static struct window_settings windows[] = { 213f95ec3c6SRalf Baechle { /* Index 0 */ 214f95ec3c6SRalf Baechle "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", 215f95ec3c6SRalf Baechle /* mode_backcolor */ 0x006600ff, 216f95ec3c6SRalf Baechle /* mode_colorkey,msk*/ 0, 0, 217f95ec3c6SRalf Baechle { 218f95ec3c6SRalf Baechle { 219f95ec3c6SRalf Baechle /* xres, yres, xpos, ypos */ 0, 0, 0, 0, 220f95ec3c6SRalf Baechle /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | 221f95ec3c6SRalf Baechle LCD_WINCTRL1_PO_16BPP, 222f95ec3c6SRalf Baechle /* mode_winenable*/ LCD_WINENABLE_WEN0, 223f95ec3c6SRalf Baechle }, 224f95ec3c6SRalf Baechle { 225f95ec3c6SRalf Baechle /* xres, yres, xpos, ypos */ 100, 100, 100, 100, 226f95ec3c6SRalf Baechle /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | 227f95ec3c6SRalf Baechle LCD_WINCTRL1_PO_16BPP | 228f95ec3c6SRalf Baechle LCD_WINCTRL1_PIPE, 229f95ec3c6SRalf Baechle /* mode_winenable*/ LCD_WINENABLE_WEN1, 230f95ec3c6SRalf Baechle }, 231f95ec3c6SRalf Baechle { 232f95ec3c6SRalf Baechle /* xres, yres, xpos, ypos */ 0, 0, 0, 0, 233f95ec3c6SRalf Baechle /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | 234f95ec3c6SRalf Baechle LCD_WINCTRL1_PO_16BPP, 235f95ec3c6SRalf Baechle /* mode_winenable*/ 0, 236f95ec3c6SRalf Baechle }, 237f95ec3c6SRalf Baechle { 238f95ec3c6SRalf Baechle /* xres, yres, xpos, ypos */ 0, 0, 0, 0, 239f95ec3c6SRalf Baechle /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | 240f95ec3c6SRalf Baechle LCD_WINCTRL1_PO_16BPP | 241f95ec3c6SRalf Baechle LCD_WINCTRL1_PIPE, 242f95ec3c6SRalf Baechle /* mode_winenable*/ 0, 243f95ec3c6SRalf Baechle }, 244f95ec3c6SRalf Baechle }, 245f95ec3c6SRalf Baechle }, 246f95ec3c6SRalf Baechle 247f95ec3c6SRalf Baechle { /* Index 1 */ 248f95ec3c6SRalf Baechle "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", 249f95ec3c6SRalf Baechle /* mode_backcolor */ 0x006600ff, 250f95ec3c6SRalf Baechle /* mode_colorkey,msk*/ 0, 0, 251f95ec3c6SRalf Baechle { 252f95ec3c6SRalf Baechle { 253f95ec3c6SRalf Baechle /* xres, yres, xpos, ypos */ 320, 240, 5, 5, 254f95ec3c6SRalf Baechle /* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP | 255f95ec3c6SRalf Baechle LCD_WINCTRL1_PO_00, 256f95ec3c6SRalf Baechle /* mode_winenable*/ LCD_WINENABLE_WEN0, 257f95ec3c6SRalf Baechle }, 258f95ec3c6SRalf Baechle { 259f95ec3c6SRalf Baechle /* xres, yres, xpos, ypos */ 0, 0, 0, 0, 260f95ec3c6SRalf Baechle /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 261f95ec3c6SRalf Baechle | LCD_WINCTRL1_PO_16BPP, 262f95ec3c6SRalf Baechle /* mode_winenable*/ 0, 263f95ec3c6SRalf Baechle }, 264f95ec3c6SRalf Baechle { 265f95ec3c6SRalf Baechle /* xres, yres, xpos, ypos */ 100, 100, 0, 0, 266f95ec3c6SRalf Baechle /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | 267f95ec3c6SRalf Baechle LCD_WINCTRL1_PO_16BPP | 268f95ec3c6SRalf Baechle LCD_WINCTRL1_PIPE, 269f95ec3c6SRalf Baechle /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/, 270f95ec3c6SRalf Baechle }, 271f95ec3c6SRalf Baechle { 272f95ec3c6SRalf Baechle /* xres, yres, xpos, ypos */ 200, 25, 0, 0, 273f95ec3c6SRalf Baechle /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | 274f95ec3c6SRalf Baechle LCD_WINCTRL1_PO_16BPP | 275f95ec3c6SRalf Baechle LCD_WINCTRL1_PIPE, 276f95ec3c6SRalf Baechle /* mode_winenable*/ 0, 277f95ec3c6SRalf Baechle }, 278f95ec3c6SRalf Baechle }, 279f95ec3c6SRalf Baechle }, 280f95ec3c6SRalf Baechle { /* Index 2 */ 281f95ec3c6SRalf Baechle "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", 282f95ec3c6SRalf Baechle /* mode_backcolor */ 0x006600ff, 283f95ec3c6SRalf Baechle /* mode_colorkey,msk*/ 0, 0, 284f95ec3c6SRalf Baechle { 285f95ec3c6SRalf Baechle { 286f95ec3c6SRalf Baechle /* xres, yres, xpos, ypos */ 0, 0, 0, 0, 287f95ec3c6SRalf Baechle /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | 288f95ec3c6SRalf Baechle LCD_WINCTRL1_PO_16BPP, 289f95ec3c6SRalf Baechle /* mode_winenable*/ LCD_WINENABLE_WEN0, 290f95ec3c6SRalf Baechle }, 291f95ec3c6SRalf Baechle { 292f95ec3c6SRalf Baechle /* xres, yres, xpos, ypos */ 0, 0, 0, 0, 293f95ec3c6SRalf Baechle /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | 294f95ec3c6SRalf Baechle LCD_WINCTRL1_PO_16BPP, 295f95ec3c6SRalf Baechle /* mode_winenable*/ 0, 296f95ec3c6SRalf Baechle }, 297f95ec3c6SRalf Baechle { 298f95ec3c6SRalf Baechle /* xres, yres, xpos, ypos */ 0, 0, 0, 0, 299f95ec3c6SRalf Baechle /* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP | 300f95ec3c6SRalf Baechle LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE, 301f95ec3c6SRalf Baechle /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/, 302f95ec3c6SRalf Baechle }, 303f95ec3c6SRalf Baechle { 304f95ec3c6SRalf Baechle /* xres, yres, xpos, ypos */ 0, 0, 0, 0, 305f95ec3c6SRalf Baechle /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | 306f95ec3c6SRalf Baechle LCD_WINCTRL1_PO_16BPP | 307f95ec3c6SRalf Baechle LCD_WINCTRL1_PIPE, 308f95ec3c6SRalf Baechle /* mode_winenable*/ 0, 309f95ec3c6SRalf Baechle }, 310f95ec3c6SRalf Baechle }, 311f95ec3c6SRalf Baechle }, 312f95ec3c6SRalf Baechle /* Need VGA 640 @ 24bpp, @ 32bpp */ 313f95ec3c6SRalf Baechle /* Need VGA 800 @ 24bpp, @ 32bpp */ 314f95ec3c6SRalf Baechle /* Need VGA 1024 @ 24bpp, @ 32bpp */ 315f95ec3c6SRalf Baechle }; 316f95ec3c6SRalf Baechle 317f95ec3c6SRalf Baechle /* 318f95ec3c6SRalf Baechle * Controller configurations for various panels. 319f95ec3c6SRalf Baechle */ 320f95ec3c6SRalf Baechle 321f95ec3c6SRalf Baechle struct panel_settings 322f95ec3c6SRalf Baechle { 323f95ec3c6SRalf Baechle const char name[25]; /* Full name <vendor>_<model> */ 324f95ec3c6SRalf Baechle 325f95ec3c6SRalf Baechle struct fb_monspecs monspecs; /* FB monitor specs */ 326f95ec3c6SRalf Baechle 327f95ec3c6SRalf Baechle /* panel timings */ 328f95ec3c6SRalf Baechle uint32 mode_screen; 329f95ec3c6SRalf Baechle uint32 mode_horztiming; 330f95ec3c6SRalf Baechle uint32 mode_verttiming; 331f95ec3c6SRalf Baechle uint32 mode_clkcontrol; 332f95ec3c6SRalf Baechle uint32 mode_pwmdiv; 333f95ec3c6SRalf Baechle uint32 mode_pwmhi; 334f95ec3c6SRalf Baechle uint32 mode_outmask; 335f95ec3c6SRalf Baechle uint32 mode_fifoctrl; 336f95ec3c6SRalf Baechle uint32 mode_backlight; 337ecc2ea3bSManuel Lauss uint32 lcdclk; 338f95ec3c6SRalf Baechle #define Xres min_xres 339f95ec3c6SRalf Baechle #define Yres min_yres 340f95ec3c6SRalf Baechle u32 min_xres; /* Minimum horizontal resolution */ 341f95ec3c6SRalf Baechle u32 max_xres; /* Maximum horizontal resolution */ 342f95ec3c6SRalf Baechle u32 min_yres; /* Minimum vertical resolution */ 343f95ec3c6SRalf Baechle u32 max_yres; /* Maximum vertical resolution */ 344f95ec3c6SRalf Baechle }; 345f95ec3c6SRalf Baechle 346f95ec3c6SRalf Baechle /********************************************************************/ 347f95ec3c6SRalf Baechle /* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is */ 348f95ec3c6SRalf Baechle 349f95ec3c6SRalf Baechle /* List of panels known to work with the AU1200 LCD controller. 350f95ec3c6SRalf Baechle * To add a new panel, enter the same specifications as the 351f95ec3c6SRalf Baechle * Generic_TFT one, and MAKE SURE that it doesn't conflicts 352f95ec3c6SRalf Baechle * with the controller restrictions. Restrictions are: 353f95ec3c6SRalf Baechle * 354f95ec3c6SRalf Baechle * STN color panels: max_bpp <= 12 355f95ec3c6SRalf Baechle * STN mono panels: max_bpp <= 4 356f95ec3c6SRalf Baechle * TFT panels: max_bpp <= 16 357f95ec3c6SRalf Baechle * max_xres <= 800 358f95ec3c6SRalf Baechle * max_yres <= 600 359f95ec3c6SRalf Baechle */ 360f95ec3c6SRalf Baechle static struct panel_settings known_lcd_panels[] = 361f95ec3c6SRalf Baechle { 362f95ec3c6SRalf Baechle [0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */ 363f95ec3c6SRalf Baechle .name = "QVGA_320x240", 364f95ec3c6SRalf Baechle .monspecs = { 365f95ec3c6SRalf Baechle .modedb = NULL, 366f95ec3c6SRalf Baechle .modedb_len = 0, 367f95ec3c6SRalf Baechle .hfmin = 30000, 368f95ec3c6SRalf Baechle .hfmax = 70000, 369f95ec3c6SRalf Baechle .vfmin = 60, 370f95ec3c6SRalf Baechle .vfmax = 60, 371f95ec3c6SRalf Baechle .dclkmin = 6000000, 372f95ec3c6SRalf Baechle .dclkmax = 28000000, 373f95ec3c6SRalf Baechle .input = FB_DISP_RGB, 374f95ec3c6SRalf Baechle }, 375f95ec3c6SRalf Baechle .mode_screen = LCD_SCREEN_SX_N(320) | 376f95ec3c6SRalf Baechle LCD_SCREEN_SY_N(240), 377f95ec3c6SRalf Baechle .mode_horztiming = 0x00c4623b, 378f95ec3c6SRalf Baechle .mode_verttiming = 0x00502814, 379f95ec3c6SRalf Baechle .mode_clkcontrol = 0x00020002, /* /4=24Mhz */ 380f95ec3c6SRalf Baechle .mode_pwmdiv = 0x00000000, 381f95ec3c6SRalf Baechle .mode_pwmhi = 0x00000000, 382f95ec3c6SRalf Baechle .mode_outmask = 0x00FFFFFF, 383f95ec3c6SRalf Baechle .mode_fifoctrl = 0x2f2f2f2f, 384f95ec3c6SRalf Baechle .mode_backlight = 0x00000000, 385ecc2ea3bSManuel Lauss .lcdclk = 96, 386f95ec3c6SRalf Baechle 320, 320, 387f95ec3c6SRalf Baechle 240, 240, 388f95ec3c6SRalf Baechle }, 389f95ec3c6SRalf Baechle 390f95ec3c6SRalf Baechle [1] = { /* VGA 640x480 H:30.3kHz V:58Hz */ 391f95ec3c6SRalf Baechle .name = "VGA_640x480", 392f95ec3c6SRalf Baechle .monspecs = { 393f95ec3c6SRalf Baechle .modedb = NULL, 394f95ec3c6SRalf Baechle .modedb_len = 0, 395f95ec3c6SRalf Baechle .hfmin = 30000, 396f95ec3c6SRalf Baechle .hfmax = 70000, 397f95ec3c6SRalf Baechle .vfmin = 60, 398f95ec3c6SRalf Baechle .vfmax = 60, 399f95ec3c6SRalf Baechle .dclkmin = 6000000, 400f95ec3c6SRalf Baechle .dclkmax = 28000000, 401f95ec3c6SRalf Baechle .input = FB_DISP_RGB, 402f95ec3c6SRalf Baechle }, 403f95ec3c6SRalf Baechle .mode_screen = 0x13f9df80, 404f95ec3c6SRalf Baechle .mode_horztiming = 0x003c5859, 405f95ec3c6SRalf Baechle .mode_verttiming = 0x00741201, 406f95ec3c6SRalf Baechle .mode_clkcontrol = 0x00020001, /* /4=24Mhz */ 407f95ec3c6SRalf Baechle .mode_pwmdiv = 0x00000000, 408f95ec3c6SRalf Baechle .mode_pwmhi = 0x00000000, 409f95ec3c6SRalf Baechle .mode_outmask = 0x00FFFFFF, 410f95ec3c6SRalf Baechle .mode_fifoctrl = 0x2f2f2f2f, 411f95ec3c6SRalf Baechle .mode_backlight = 0x00000000, 412ecc2ea3bSManuel Lauss .lcdclk = 96, 413f95ec3c6SRalf Baechle 640, 480, 414f95ec3c6SRalf Baechle 640, 480, 415f95ec3c6SRalf Baechle }, 416f95ec3c6SRalf Baechle 417f95ec3c6SRalf Baechle [2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */ 418f95ec3c6SRalf Baechle .name = "SVGA_800x600", 419f95ec3c6SRalf Baechle .monspecs = { 420f95ec3c6SRalf Baechle .modedb = NULL, 421f95ec3c6SRalf Baechle .modedb_len = 0, 422f95ec3c6SRalf Baechle .hfmin = 30000, 423f95ec3c6SRalf Baechle .hfmax = 70000, 424f95ec3c6SRalf Baechle .vfmin = 60, 425f95ec3c6SRalf Baechle .vfmax = 60, 426f95ec3c6SRalf Baechle .dclkmin = 6000000, 427f95ec3c6SRalf Baechle .dclkmax = 28000000, 428f95ec3c6SRalf Baechle .input = FB_DISP_RGB, 429f95ec3c6SRalf Baechle }, 430f95ec3c6SRalf Baechle .mode_screen = 0x18fa5780, 431f95ec3c6SRalf Baechle .mode_horztiming = 0x00dc7e77, 432f95ec3c6SRalf Baechle .mode_verttiming = 0x00584805, 433f95ec3c6SRalf Baechle .mode_clkcontrol = 0x00020000, /* /2=48Mhz */ 434f95ec3c6SRalf Baechle .mode_pwmdiv = 0x00000000, 435f95ec3c6SRalf Baechle .mode_pwmhi = 0x00000000, 436f95ec3c6SRalf Baechle .mode_outmask = 0x00FFFFFF, 437f95ec3c6SRalf Baechle .mode_fifoctrl = 0x2f2f2f2f, 438f95ec3c6SRalf Baechle .mode_backlight = 0x00000000, 439ecc2ea3bSManuel Lauss .lcdclk = 96, 440f95ec3c6SRalf Baechle 800, 800, 441f95ec3c6SRalf Baechle 600, 600, 442f95ec3c6SRalf Baechle }, 443f95ec3c6SRalf Baechle 444f95ec3c6SRalf Baechle [3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */ 445f95ec3c6SRalf Baechle .name = "XVGA_1024x768", 446f95ec3c6SRalf Baechle .monspecs = { 447f95ec3c6SRalf Baechle .modedb = NULL, 448f95ec3c6SRalf Baechle .modedb_len = 0, 449f95ec3c6SRalf Baechle .hfmin = 30000, 450f95ec3c6SRalf Baechle .hfmax = 70000, 451f95ec3c6SRalf Baechle .vfmin = 60, 452f95ec3c6SRalf Baechle .vfmax = 60, 453f95ec3c6SRalf Baechle .dclkmin = 6000000, 454f95ec3c6SRalf Baechle .dclkmax = 28000000, 455f95ec3c6SRalf Baechle .input = FB_DISP_RGB, 456f95ec3c6SRalf Baechle }, 457f95ec3c6SRalf Baechle .mode_screen = 0x1ffaff80, 458f95ec3c6SRalf Baechle .mode_horztiming = 0x007d0e57, 459f95ec3c6SRalf Baechle .mode_verttiming = 0x00740a01, 460f95ec3c6SRalf Baechle .mode_clkcontrol = 0x000A0000, /* /1 */ 461f95ec3c6SRalf Baechle .mode_pwmdiv = 0x00000000, 462f95ec3c6SRalf Baechle .mode_pwmhi = 0x00000000, 463f95ec3c6SRalf Baechle .mode_outmask = 0x00FFFFFF, 464f95ec3c6SRalf Baechle .mode_fifoctrl = 0x2f2f2f2f, 465f95ec3c6SRalf Baechle .mode_backlight = 0x00000000, 466ecc2ea3bSManuel Lauss .lcdclk = 72, 467f95ec3c6SRalf Baechle 1024, 1024, 468f95ec3c6SRalf Baechle 768, 768, 469f95ec3c6SRalf Baechle }, 470f95ec3c6SRalf Baechle 471f95ec3c6SRalf Baechle [4] = { /* XVGA XVGA 1280x1024 H:68.5kHz V:65Hz */ 472f95ec3c6SRalf Baechle .name = "XVGA_1280x1024", 473f95ec3c6SRalf Baechle .monspecs = { 474f95ec3c6SRalf Baechle .modedb = NULL, 475f95ec3c6SRalf Baechle .modedb_len = 0, 476f95ec3c6SRalf Baechle .hfmin = 30000, 477f95ec3c6SRalf Baechle .hfmax = 70000, 478f95ec3c6SRalf Baechle .vfmin = 60, 479f95ec3c6SRalf Baechle .vfmax = 60, 480f95ec3c6SRalf Baechle .dclkmin = 6000000, 481f95ec3c6SRalf Baechle .dclkmax = 28000000, 482f95ec3c6SRalf Baechle .input = FB_DISP_RGB, 483f95ec3c6SRalf Baechle }, 484f95ec3c6SRalf Baechle .mode_screen = 0x27fbff80, 485f95ec3c6SRalf Baechle .mode_horztiming = 0x00cdb2c7, 486f95ec3c6SRalf Baechle .mode_verttiming = 0x00600002, 487f95ec3c6SRalf Baechle .mode_clkcontrol = 0x000A0000, /* /1 */ 488f95ec3c6SRalf Baechle .mode_pwmdiv = 0x00000000, 489f95ec3c6SRalf Baechle .mode_pwmhi = 0x00000000, 490f95ec3c6SRalf Baechle .mode_outmask = 0x00FFFFFF, 491f95ec3c6SRalf Baechle .mode_fifoctrl = 0x2f2f2f2f, 492f95ec3c6SRalf Baechle .mode_backlight = 0x00000000, 493ecc2ea3bSManuel Lauss .lcdclk = 120, 494f95ec3c6SRalf Baechle 1280, 1280, 495f95ec3c6SRalf Baechle 1024, 1024, 496f95ec3c6SRalf Baechle }, 497f95ec3c6SRalf Baechle 498f95ec3c6SRalf Baechle [5] = { /* Samsung 1024x768 TFT */ 499f95ec3c6SRalf Baechle .name = "Samsung_1024x768_TFT", 500f95ec3c6SRalf Baechle .monspecs = { 501f95ec3c6SRalf Baechle .modedb = NULL, 502f95ec3c6SRalf Baechle .modedb_len = 0, 503f95ec3c6SRalf Baechle .hfmin = 30000, 504f95ec3c6SRalf Baechle .hfmax = 70000, 505f95ec3c6SRalf Baechle .vfmin = 60, 506f95ec3c6SRalf Baechle .vfmax = 60, 507f95ec3c6SRalf Baechle .dclkmin = 6000000, 508f95ec3c6SRalf Baechle .dclkmax = 28000000, 509f95ec3c6SRalf Baechle .input = FB_DISP_RGB, 510f95ec3c6SRalf Baechle }, 511f95ec3c6SRalf Baechle .mode_screen = 0x1ffaff80, 512f95ec3c6SRalf Baechle .mode_horztiming = 0x018cc677, 513f95ec3c6SRalf Baechle .mode_verttiming = 0x00241217, 514f95ec3c6SRalf Baechle .mode_clkcontrol = 0x00000000, /* SCB 0x1 /4=24Mhz */ 515f95ec3c6SRalf Baechle .mode_pwmdiv = 0x8000063f, /* SCB 0x0 */ 516f95ec3c6SRalf Baechle .mode_pwmhi = 0x03400000, /* SCB 0x0 */ 517f95ec3c6SRalf Baechle .mode_outmask = 0x00FFFFFF, 518f95ec3c6SRalf Baechle .mode_fifoctrl = 0x2f2f2f2f, 519f95ec3c6SRalf Baechle .mode_backlight = 0x00000000, 520ecc2ea3bSManuel Lauss .lcdclk = 96, 521f95ec3c6SRalf Baechle 1024, 1024, 522f95ec3c6SRalf Baechle 768, 768, 523f95ec3c6SRalf Baechle }, 524f95ec3c6SRalf Baechle 525f95ec3c6SRalf Baechle [6] = { /* Toshiba 640x480 TFT */ 526f95ec3c6SRalf Baechle .name = "Toshiba_640x480_TFT", 527f95ec3c6SRalf Baechle .monspecs = { 528f95ec3c6SRalf Baechle .modedb = NULL, 529f95ec3c6SRalf Baechle .modedb_len = 0, 530f95ec3c6SRalf Baechle .hfmin = 30000, 531f95ec3c6SRalf Baechle .hfmax = 70000, 532f95ec3c6SRalf Baechle .vfmin = 60, 533f95ec3c6SRalf Baechle .vfmax = 60, 534f95ec3c6SRalf Baechle .dclkmin = 6000000, 535f95ec3c6SRalf Baechle .dclkmax = 28000000, 536f95ec3c6SRalf Baechle .input = FB_DISP_RGB, 537f95ec3c6SRalf Baechle }, 538f95ec3c6SRalf Baechle .mode_screen = LCD_SCREEN_SX_N(640) | 539f95ec3c6SRalf Baechle LCD_SCREEN_SY_N(480), 540f95ec3c6SRalf Baechle .mode_horztiming = LCD_HORZTIMING_HPW_N(96) | 541f95ec3c6SRalf Baechle LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51), 542f95ec3c6SRalf Baechle .mode_verttiming = LCD_VERTTIMING_VPW_N(2) | 543f95ec3c6SRalf Baechle LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32), 544f95ec3c6SRalf Baechle .mode_clkcontrol = 0x00000000, /* /4=24Mhz */ 545f95ec3c6SRalf Baechle .mode_pwmdiv = 0x8000063f, 546f95ec3c6SRalf Baechle .mode_pwmhi = 0x03400000, 547f95ec3c6SRalf Baechle .mode_outmask = 0x00fcfcfc, 548f95ec3c6SRalf Baechle .mode_fifoctrl = 0x2f2f2f2f, 549f95ec3c6SRalf Baechle .mode_backlight = 0x00000000, 550ecc2ea3bSManuel Lauss .lcdclk = 96, 551f95ec3c6SRalf Baechle 640, 480, 552f95ec3c6SRalf Baechle 640, 480, 553f95ec3c6SRalf Baechle }, 554f95ec3c6SRalf Baechle 555f95ec3c6SRalf Baechle [7] = { /* Sharp 320x240 TFT */ 556f95ec3c6SRalf Baechle .name = "Sharp_320x240_TFT", 557f95ec3c6SRalf Baechle .monspecs = { 558f95ec3c6SRalf Baechle .modedb = NULL, 559f95ec3c6SRalf Baechle .modedb_len = 0, 560f95ec3c6SRalf Baechle .hfmin = 12500, 561f95ec3c6SRalf Baechle .hfmax = 20000, 562f95ec3c6SRalf Baechle .vfmin = 38, 563f95ec3c6SRalf Baechle .vfmax = 81, 564f95ec3c6SRalf Baechle .dclkmin = 4500000, 565f95ec3c6SRalf Baechle .dclkmax = 6800000, 566f95ec3c6SRalf Baechle .input = FB_DISP_RGB, 567f95ec3c6SRalf Baechle }, 568f95ec3c6SRalf Baechle .mode_screen = LCD_SCREEN_SX_N(320) | 569f95ec3c6SRalf Baechle LCD_SCREEN_SY_N(240), 570f95ec3c6SRalf Baechle .mode_horztiming = LCD_HORZTIMING_HPW_N(60) | 571f95ec3c6SRalf Baechle LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2), 572f95ec3c6SRalf Baechle .mode_verttiming = LCD_VERTTIMING_VPW_N(2) | 573f95ec3c6SRalf Baechle LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5), 574f95ec3c6SRalf Baechle .mode_clkcontrol = LCD_CLKCONTROL_PCD_N(7), /*16=6Mhz*/ 575f95ec3c6SRalf Baechle .mode_pwmdiv = 0x8000063f, 576f95ec3c6SRalf Baechle .mode_pwmhi = 0x03400000, 577f95ec3c6SRalf Baechle .mode_outmask = 0x00fcfcfc, 578f95ec3c6SRalf Baechle .mode_fifoctrl = 0x2f2f2f2f, 579f95ec3c6SRalf Baechle .mode_backlight = 0x00000000, 580ecc2ea3bSManuel Lauss .lcdclk = 96, /* 96MHz AUXPLL */ 581f95ec3c6SRalf Baechle 320, 320, 582f95ec3c6SRalf Baechle 240, 240, 583f95ec3c6SRalf Baechle }, 584f95ec3c6SRalf Baechle 585f95ec3c6SRalf Baechle [8] = { /* Toppoly TD070WGCB2 7" 856x480 TFT */ 586f95ec3c6SRalf Baechle .name = "Toppoly_TD070WGCB2", 587f95ec3c6SRalf Baechle .monspecs = { 588f95ec3c6SRalf Baechle .modedb = NULL, 589f95ec3c6SRalf Baechle .modedb_len = 0, 590f95ec3c6SRalf Baechle .hfmin = 30000, 591f95ec3c6SRalf Baechle .hfmax = 70000, 592f95ec3c6SRalf Baechle .vfmin = 60, 593f95ec3c6SRalf Baechle .vfmax = 60, 594f95ec3c6SRalf Baechle .dclkmin = 6000000, 595f95ec3c6SRalf Baechle .dclkmax = 28000000, 596f95ec3c6SRalf Baechle .input = FB_DISP_RGB, 597f95ec3c6SRalf Baechle }, 598f95ec3c6SRalf Baechle .mode_screen = LCD_SCREEN_SX_N(856) | 599f95ec3c6SRalf Baechle LCD_SCREEN_SY_N(480), 600f95ec3c6SRalf Baechle .mode_horztiming = LCD_HORZTIMING_HND2_N(43) | 601f95ec3c6SRalf Baechle LCD_HORZTIMING_HND1_N(43) | LCD_HORZTIMING_HPW_N(114), 602f95ec3c6SRalf Baechle .mode_verttiming = LCD_VERTTIMING_VND2_N(20) | 603f95ec3c6SRalf Baechle LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4), 604f95ec3c6SRalf Baechle .mode_clkcontrol = 0x00020001, /* /4=24Mhz */ 605f95ec3c6SRalf Baechle .mode_pwmdiv = 0x8000063f, 606f95ec3c6SRalf Baechle .mode_pwmhi = 0x03400000, 607f95ec3c6SRalf Baechle .mode_outmask = 0x00fcfcfc, 608f95ec3c6SRalf Baechle .mode_fifoctrl = 0x2f2f2f2f, 609f95ec3c6SRalf Baechle .mode_backlight = 0x00000000, 610ecc2ea3bSManuel Lauss .lcdclk = 96, 611f95ec3c6SRalf Baechle 856, 856, 612f95ec3c6SRalf Baechle 480, 480, 613f95ec3c6SRalf Baechle }, 61464cd04d0SManuel Lauss [9] = { 61564cd04d0SManuel Lauss .name = "DB1300_800x480", 61664cd04d0SManuel Lauss .monspecs = { 61764cd04d0SManuel Lauss .modedb = NULL, 61864cd04d0SManuel Lauss .modedb_len = 0, 61964cd04d0SManuel Lauss .hfmin = 30000, 62064cd04d0SManuel Lauss .hfmax = 70000, 62164cd04d0SManuel Lauss .vfmin = 60, 62264cd04d0SManuel Lauss .vfmax = 60, 62364cd04d0SManuel Lauss .dclkmin = 6000000, 62464cd04d0SManuel Lauss .dclkmax = 28000000, 62564cd04d0SManuel Lauss .input = FB_DISP_RGB, 62664cd04d0SManuel Lauss }, 62764cd04d0SManuel Lauss .mode_screen = LCD_SCREEN_SX_N(800) | 62864cd04d0SManuel Lauss LCD_SCREEN_SY_N(480), 62964cd04d0SManuel Lauss .mode_horztiming = LCD_HORZTIMING_HPW_N(5) | 63064cd04d0SManuel Lauss LCD_HORZTIMING_HND1_N(16) | 63164cd04d0SManuel Lauss LCD_HORZTIMING_HND2_N(8), 63264cd04d0SManuel Lauss .mode_verttiming = LCD_VERTTIMING_VPW_N(4) | 63364cd04d0SManuel Lauss LCD_VERTTIMING_VND1_N(8) | 63464cd04d0SManuel Lauss LCD_VERTTIMING_VND2_N(5), 63564cd04d0SManuel Lauss .mode_clkcontrol = LCD_CLKCONTROL_PCD_N(1) | 63664cd04d0SManuel Lauss LCD_CLKCONTROL_IV | 63764cd04d0SManuel Lauss LCD_CLKCONTROL_IH, 63864cd04d0SManuel Lauss .mode_pwmdiv = 0x00000000, 63964cd04d0SManuel Lauss .mode_pwmhi = 0x00000000, 64064cd04d0SManuel Lauss .mode_outmask = 0x00FFFFFF, 64164cd04d0SManuel Lauss .mode_fifoctrl = 0x2f2f2f2f, 64264cd04d0SManuel Lauss .mode_backlight = 0x00000000, 643ecc2ea3bSManuel Lauss .lcdclk = 96, 64464cd04d0SManuel Lauss 800, 800, 64564cd04d0SManuel Lauss 480, 480, 64664cd04d0SManuel Lauss }, 647f95ec3c6SRalf Baechle }; 648f95ec3c6SRalf Baechle 649f95ec3c6SRalf Baechle #define NUM_PANELS (ARRAY_SIZE(known_lcd_panels)) 650f95ec3c6SRalf Baechle 651f95ec3c6SRalf Baechle /********************************************************************/ 652f95ec3c6SRalf Baechle 653f95ec3c6SRalf Baechle static int winbpp (unsigned int winctrl1) 654f95ec3c6SRalf Baechle { 655f95ec3c6SRalf Baechle int bits = 0; 656f95ec3c6SRalf Baechle 657f95ec3c6SRalf Baechle /* how many bits are needed for each pixel format */ 658f95ec3c6SRalf Baechle switch (winctrl1 & LCD_WINCTRL1_FRM) { 659f95ec3c6SRalf Baechle case LCD_WINCTRL1_FRM_1BPP: 660f95ec3c6SRalf Baechle bits = 1; 661f95ec3c6SRalf Baechle break; 662f95ec3c6SRalf Baechle case LCD_WINCTRL1_FRM_2BPP: 663f95ec3c6SRalf Baechle bits = 2; 664f95ec3c6SRalf Baechle break; 665f95ec3c6SRalf Baechle case LCD_WINCTRL1_FRM_4BPP: 666f95ec3c6SRalf Baechle bits = 4; 667f95ec3c6SRalf Baechle break; 668f95ec3c6SRalf Baechle case LCD_WINCTRL1_FRM_8BPP: 669f95ec3c6SRalf Baechle bits = 8; 670f95ec3c6SRalf Baechle break; 671f95ec3c6SRalf Baechle case LCD_WINCTRL1_FRM_12BPP: 672f95ec3c6SRalf Baechle case LCD_WINCTRL1_FRM_16BPP655: 673f95ec3c6SRalf Baechle case LCD_WINCTRL1_FRM_16BPP565: 674f95ec3c6SRalf Baechle case LCD_WINCTRL1_FRM_16BPP556: 675f95ec3c6SRalf Baechle case LCD_WINCTRL1_FRM_16BPPI1555: 676f95ec3c6SRalf Baechle case LCD_WINCTRL1_FRM_16BPPI5551: 677f95ec3c6SRalf Baechle case LCD_WINCTRL1_FRM_16BPPA1555: 678f95ec3c6SRalf Baechle case LCD_WINCTRL1_FRM_16BPPA5551: 679f95ec3c6SRalf Baechle bits = 16; 680f95ec3c6SRalf Baechle break; 681f95ec3c6SRalf Baechle case LCD_WINCTRL1_FRM_24BPP: 682f95ec3c6SRalf Baechle case LCD_WINCTRL1_FRM_32BPP: 683f95ec3c6SRalf Baechle bits = 32; 684f95ec3c6SRalf Baechle break; 685f95ec3c6SRalf Baechle } 686f95ec3c6SRalf Baechle 687f95ec3c6SRalf Baechle return bits; 688f95ec3c6SRalf Baechle } 689f95ec3c6SRalf Baechle 690f95ec3c6SRalf Baechle static int fbinfo2index (struct fb_info *fb_info) 691f95ec3c6SRalf Baechle { 692f95ec3c6SRalf Baechle int i; 693f95ec3c6SRalf Baechle 6948be90b07SManuel Lauss for (i = 0; i < device_count; ++i) { 695c329f606SManuel Lauss if (fb_info == _au1200fb_infos[i]) 696f95ec3c6SRalf Baechle return i; 697f95ec3c6SRalf Baechle } 698f95ec3c6SRalf Baechle printk("au1200fb: ERROR: fbinfo2index failed!\n"); 699f95ec3c6SRalf Baechle return -1; 700f95ec3c6SRalf Baechle } 701f95ec3c6SRalf Baechle 702f95ec3c6SRalf Baechle static int au1200_setlocation (struct au1200fb_device *fbdev, int plane, 703f95ec3c6SRalf Baechle int xpos, int ypos) 704f95ec3c6SRalf Baechle { 705f95ec3c6SRalf Baechle uint32 winctrl0, winctrl1, winenable, fb_offset = 0; 706f95ec3c6SRalf Baechle int xsz, ysz; 707f95ec3c6SRalf Baechle 708f95ec3c6SRalf Baechle /* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */ 709f95ec3c6SRalf Baechle 710f95ec3c6SRalf Baechle winctrl0 = lcd->window[plane].winctrl0; 711f95ec3c6SRalf Baechle winctrl1 = lcd->window[plane].winctrl1; 712f95ec3c6SRalf Baechle winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN); 713f95ec3c6SRalf Baechle winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY); 714f95ec3c6SRalf Baechle 715f95ec3c6SRalf Baechle /* Check for off-screen adjustments */ 716f95ec3c6SRalf Baechle xsz = win->w[plane].xres; 717f95ec3c6SRalf Baechle ysz = win->w[plane].yres; 718f95ec3c6SRalf Baechle if ((xpos + win->w[plane].xres) > panel->Xres) { 719f95ec3c6SRalf Baechle /* Off-screen to the right */ 720f95ec3c6SRalf Baechle xsz = panel->Xres - xpos; /* off by 1 ??? */ 721f95ec3c6SRalf Baechle /*printk("off screen right\n");*/ 722f95ec3c6SRalf Baechle } 723f95ec3c6SRalf Baechle 724f95ec3c6SRalf Baechle if ((ypos + win->w[plane].yres) > panel->Yres) { 725f95ec3c6SRalf Baechle /* Off-screen to the bottom */ 726f95ec3c6SRalf Baechle ysz = panel->Yres - ypos; /* off by 1 ??? */ 727f95ec3c6SRalf Baechle /*printk("off screen bottom\n");*/ 728f95ec3c6SRalf Baechle } 729f95ec3c6SRalf Baechle 730f95ec3c6SRalf Baechle if (xpos < 0) { 731f95ec3c6SRalf Baechle /* Off-screen to the left */ 732f95ec3c6SRalf Baechle xsz = win->w[plane].xres + xpos; 733f95ec3c6SRalf Baechle fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8); 734f95ec3c6SRalf Baechle xpos = 0; 735f95ec3c6SRalf Baechle /*printk("off screen left\n");*/ 736f95ec3c6SRalf Baechle } 737f95ec3c6SRalf Baechle 738f95ec3c6SRalf Baechle if (ypos < 0) { 739f95ec3c6SRalf Baechle /* Off-screen to the top */ 740f95ec3c6SRalf Baechle ysz = win->w[plane].yres + ypos; 741f95ec3c6SRalf Baechle /* fixme: fb_offset += ((0-ypos)*fb_pars[plane].line_length); */ 742f95ec3c6SRalf Baechle ypos = 0; 743f95ec3c6SRalf Baechle /*printk("off screen top\n");*/ 744f95ec3c6SRalf Baechle } 745f95ec3c6SRalf Baechle 746f95ec3c6SRalf Baechle /* record settings */ 747f95ec3c6SRalf Baechle win->w[plane].xpos = xpos; 748f95ec3c6SRalf Baechle win->w[plane].ypos = ypos; 749f95ec3c6SRalf Baechle 750f95ec3c6SRalf Baechle xsz -= 1; 751f95ec3c6SRalf Baechle ysz -= 1; 752f95ec3c6SRalf Baechle winctrl0 |= (xpos << 21); 753f95ec3c6SRalf Baechle winctrl0 |= (ypos << 10); 754f95ec3c6SRalf Baechle winctrl1 |= (xsz << 11); 755f95ec3c6SRalf Baechle winctrl1 |= (ysz << 0); 756f95ec3c6SRalf Baechle 757f95ec3c6SRalf Baechle /* Disable the window while making changes, then restore WINEN */ 758f95ec3c6SRalf Baechle winenable = lcd->winenable & (1 << plane); 7592f73bfbeSManuel Lauss wmb(); /* drain writebuffer */ 760f95ec3c6SRalf Baechle lcd->winenable &= ~(1 << plane); 761f95ec3c6SRalf Baechle lcd->window[plane].winctrl0 = winctrl0; 762f95ec3c6SRalf Baechle lcd->window[plane].winctrl1 = winctrl1; 763f95ec3c6SRalf Baechle lcd->window[plane].winbuf0 = 764f95ec3c6SRalf Baechle lcd->window[plane].winbuf1 = fbdev->fb_phys; 765f95ec3c6SRalf Baechle lcd->window[plane].winbufctrl = 0; /* select winbuf0 */ 766f95ec3c6SRalf Baechle lcd->winenable |= winenable; 7672f73bfbeSManuel Lauss wmb(); /* drain writebuffer */ 768f95ec3c6SRalf Baechle 769f95ec3c6SRalf Baechle return 0; 770f95ec3c6SRalf Baechle } 771f95ec3c6SRalf Baechle 772a9b71a8fSManuel Lauss static void au1200_setpanel(struct panel_settings *newpanel, 773a9b71a8fSManuel Lauss struct au1200fb_platdata *pd) 774f95ec3c6SRalf Baechle { 775f95ec3c6SRalf Baechle /* 776f95ec3c6SRalf Baechle * Perform global setup/init of LCD controller 777f95ec3c6SRalf Baechle */ 778f95ec3c6SRalf Baechle uint32 winenable; 779f95ec3c6SRalf Baechle 780f95ec3c6SRalf Baechle /* Make sure all windows disabled */ 781f95ec3c6SRalf Baechle winenable = lcd->winenable; 782f95ec3c6SRalf Baechle lcd->winenable = 0; 7832f73bfbeSManuel Lauss wmb(); /* drain writebuffer */ 784f95ec3c6SRalf Baechle /* 785f95ec3c6SRalf Baechle * Ensure everything is disabled before reconfiguring 786f95ec3c6SRalf Baechle */ 787f95ec3c6SRalf Baechle if (lcd->screen & LCD_SCREEN_SEN) { 788f95ec3c6SRalf Baechle /* Wait for vertical sync period */ 789f95ec3c6SRalf Baechle lcd->intstatus = LCD_INT_SS; 7902f73bfbeSManuel Lauss while ((lcd->intstatus & LCD_INT_SS) == 0) 7912f73bfbeSManuel Lauss ; 792f95ec3c6SRalf Baechle 793f95ec3c6SRalf Baechle lcd->screen &= ~LCD_SCREEN_SEN; /*disable the controller*/ 794f95ec3c6SRalf Baechle 795f95ec3c6SRalf Baechle do { 796f95ec3c6SRalf Baechle lcd->intstatus = lcd->intstatus; /*clear interrupts*/ 7972f73bfbeSManuel Lauss wmb(); /* drain writebuffer */ 798f95ec3c6SRalf Baechle /*wait for controller to shut down*/ 799f95ec3c6SRalf Baechle } while ((lcd->intstatus & LCD_INT_SD) == 0); 800f95ec3c6SRalf Baechle 801f95ec3c6SRalf Baechle /* Call shutdown of current panel (if up) */ 802f95ec3c6SRalf Baechle /* this must occur last, because if an external clock is driving 803f95ec3c6SRalf Baechle the controller, the clock cannot be turned off before first 804f95ec3c6SRalf Baechle shutting down the controller. 805f95ec3c6SRalf Baechle */ 806a9b71a8fSManuel Lauss if (pd->panel_shutdown) 807a9b71a8fSManuel Lauss pd->panel_shutdown(); 808f95ec3c6SRalf Baechle } 809f95ec3c6SRalf Baechle 810f95ec3c6SRalf Baechle /* Newpanel == NULL indicates a shutdown operation only */ 811f95ec3c6SRalf Baechle if (newpanel == NULL) 812f95ec3c6SRalf Baechle return; 813f95ec3c6SRalf Baechle 814f95ec3c6SRalf Baechle panel = newpanel; 815f95ec3c6SRalf Baechle 816f95ec3c6SRalf Baechle printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres); 817f95ec3c6SRalf Baechle 818f95ec3c6SRalf Baechle /* 819f95ec3c6SRalf Baechle * Setup clocking if internal LCD clock source (assumes sys_auxpll valid) 820f95ec3c6SRalf Baechle */ 821f95ec3c6SRalf Baechle if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT)) 822f95ec3c6SRalf Baechle { 823ecc2ea3bSManuel Lauss struct clk *c = clk_get(NULL, "lcd_intclk"); 824ecc2ea3bSManuel Lauss long r, pc = panel->lcdclk * 1000000; 825ecc2ea3bSManuel Lauss 826ecc2ea3bSManuel Lauss if (!IS_ERR(c)) { 827ecc2ea3bSManuel Lauss r = clk_round_rate(c, pc); 828ecc2ea3bSManuel Lauss if ((pc - r) < (pc / 10)) { /* 10% slack */ 829ecc2ea3bSManuel Lauss clk_set_rate(c, r); 830ecc2ea3bSManuel Lauss clk_prepare_enable(c); 831ecc2ea3bSManuel Lauss } 832ecc2ea3bSManuel Lauss clk_put(c); 833ecc2ea3bSManuel Lauss } 834f95ec3c6SRalf Baechle } 835f95ec3c6SRalf Baechle 836f95ec3c6SRalf Baechle /* 837f95ec3c6SRalf Baechle * Configure panel timings 838f95ec3c6SRalf Baechle */ 839f95ec3c6SRalf Baechle lcd->screen = panel->mode_screen; 840f95ec3c6SRalf Baechle lcd->horztiming = panel->mode_horztiming; 841f95ec3c6SRalf Baechle lcd->verttiming = panel->mode_verttiming; 842f95ec3c6SRalf Baechle lcd->clkcontrol = panel->mode_clkcontrol; 843f95ec3c6SRalf Baechle lcd->pwmdiv = panel->mode_pwmdiv; 844f95ec3c6SRalf Baechle lcd->pwmhi = panel->mode_pwmhi; 845f95ec3c6SRalf Baechle lcd->outmask = panel->mode_outmask; 846f95ec3c6SRalf Baechle lcd->fifoctrl = panel->mode_fifoctrl; 8472f73bfbeSManuel Lauss wmb(); /* drain writebuffer */ 848f95ec3c6SRalf Baechle 849f95ec3c6SRalf Baechle /* fixme: Check window settings to make sure still valid 850f95ec3c6SRalf Baechle * for new geometry */ 851f95ec3c6SRalf Baechle #if 0 852f95ec3c6SRalf Baechle au1200_setlocation(fbdev, 0, win->w[0].xpos, win->w[0].ypos); 853f95ec3c6SRalf Baechle au1200_setlocation(fbdev, 1, win->w[1].xpos, win->w[1].ypos); 854f95ec3c6SRalf Baechle au1200_setlocation(fbdev, 2, win->w[2].xpos, win->w[2].ypos); 855f95ec3c6SRalf Baechle au1200_setlocation(fbdev, 3, win->w[3].xpos, win->w[3].ypos); 856f95ec3c6SRalf Baechle #endif 857f95ec3c6SRalf Baechle lcd->winenable = winenable; 858f95ec3c6SRalf Baechle 859f95ec3c6SRalf Baechle /* 860f95ec3c6SRalf Baechle * Re-enable screen now that it is configured 861f95ec3c6SRalf Baechle */ 862f95ec3c6SRalf Baechle lcd->screen |= LCD_SCREEN_SEN; 8632f73bfbeSManuel Lauss wmb(); /* drain writebuffer */ 864f95ec3c6SRalf Baechle 865f95ec3c6SRalf Baechle /* Call init of panel */ 866a9b71a8fSManuel Lauss if (pd->panel_init) 867a9b71a8fSManuel Lauss pd->panel_init(); 868f95ec3c6SRalf Baechle 869f95ec3c6SRalf Baechle /* FIX!!!! not appropriate on panel change!!! Global setup/init */ 870f95ec3c6SRalf Baechle lcd->intenable = 0; 871f95ec3c6SRalf Baechle lcd->intstatus = ~0; 872f95ec3c6SRalf Baechle lcd->backcolor = win->mode_backcolor; 873f95ec3c6SRalf Baechle 874f95ec3c6SRalf Baechle /* Setup Color Key - FIX!!! */ 875f95ec3c6SRalf Baechle lcd->colorkey = win->mode_colorkey; 876f95ec3c6SRalf Baechle lcd->colorkeymsk = win->mode_colorkeymsk; 877f95ec3c6SRalf Baechle 878f95ec3c6SRalf Baechle /* Setup HWCursor - FIX!!! Need to support this eventually */ 879f95ec3c6SRalf Baechle lcd->hwc.cursorctrl = 0; 880f95ec3c6SRalf Baechle lcd->hwc.cursorpos = 0; 881f95ec3c6SRalf Baechle lcd->hwc.cursorcolor0 = 0; 882f95ec3c6SRalf Baechle lcd->hwc.cursorcolor1 = 0; 883f95ec3c6SRalf Baechle lcd->hwc.cursorcolor2 = 0; 884f95ec3c6SRalf Baechle lcd->hwc.cursorcolor3 = 0; 885f95ec3c6SRalf Baechle 886f95ec3c6SRalf Baechle 887f95ec3c6SRalf Baechle #if 0 888f95ec3c6SRalf Baechle #define D(X) printk("%25s: %08X\n", #X, X) 889f95ec3c6SRalf Baechle D(lcd->screen); 890f95ec3c6SRalf Baechle D(lcd->horztiming); 891f95ec3c6SRalf Baechle D(lcd->verttiming); 892f95ec3c6SRalf Baechle D(lcd->clkcontrol); 893f95ec3c6SRalf Baechle D(lcd->pwmdiv); 894f95ec3c6SRalf Baechle D(lcd->pwmhi); 895f95ec3c6SRalf Baechle D(lcd->outmask); 896f95ec3c6SRalf Baechle D(lcd->fifoctrl); 897f95ec3c6SRalf Baechle D(lcd->window[0].winctrl0); 898f95ec3c6SRalf Baechle D(lcd->window[0].winctrl1); 899f95ec3c6SRalf Baechle D(lcd->window[0].winctrl2); 900f95ec3c6SRalf Baechle D(lcd->window[0].winbuf0); 901f95ec3c6SRalf Baechle D(lcd->window[0].winbuf1); 902f95ec3c6SRalf Baechle D(lcd->window[0].winbufctrl); 903f95ec3c6SRalf Baechle D(lcd->window[1].winctrl0); 904f95ec3c6SRalf Baechle D(lcd->window[1].winctrl1); 905f95ec3c6SRalf Baechle D(lcd->window[1].winctrl2); 906f95ec3c6SRalf Baechle D(lcd->window[1].winbuf0); 907f95ec3c6SRalf Baechle D(lcd->window[1].winbuf1); 908f95ec3c6SRalf Baechle D(lcd->window[1].winbufctrl); 909f95ec3c6SRalf Baechle D(lcd->window[2].winctrl0); 910f95ec3c6SRalf Baechle D(lcd->window[2].winctrl1); 911f95ec3c6SRalf Baechle D(lcd->window[2].winctrl2); 912f95ec3c6SRalf Baechle D(lcd->window[2].winbuf0); 913f95ec3c6SRalf Baechle D(lcd->window[2].winbuf1); 914f95ec3c6SRalf Baechle D(lcd->window[2].winbufctrl); 915f95ec3c6SRalf Baechle D(lcd->window[3].winctrl0); 916f95ec3c6SRalf Baechle D(lcd->window[3].winctrl1); 917f95ec3c6SRalf Baechle D(lcd->window[3].winctrl2); 918f95ec3c6SRalf Baechle D(lcd->window[3].winbuf0); 919f95ec3c6SRalf Baechle D(lcd->window[3].winbuf1); 920f95ec3c6SRalf Baechle D(lcd->window[3].winbufctrl); 921f95ec3c6SRalf Baechle D(lcd->winenable); 922f95ec3c6SRalf Baechle D(lcd->intenable); 923f95ec3c6SRalf Baechle D(lcd->intstatus); 924f95ec3c6SRalf Baechle D(lcd->backcolor); 925f95ec3c6SRalf Baechle D(lcd->winenable); 926f95ec3c6SRalf Baechle D(lcd->colorkey); 927f95ec3c6SRalf Baechle D(lcd->colorkeymsk); 928f95ec3c6SRalf Baechle D(lcd->hwc.cursorctrl); 929f95ec3c6SRalf Baechle D(lcd->hwc.cursorpos); 930f95ec3c6SRalf Baechle D(lcd->hwc.cursorcolor0); 931f95ec3c6SRalf Baechle D(lcd->hwc.cursorcolor1); 932f95ec3c6SRalf Baechle D(lcd->hwc.cursorcolor2); 933f95ec3c6SRalf Baechle D(lcd->hwc.cursorcolor3); 934f95ec3c6SRalf Baechle #endif 935f95ec3c6SRalf Baechle } 936f95ec3c6SRalf Baechle 937f95ec3c6SRalf Baechle static void au1200_setmode(struct au1200fb_device *fbdev) 938f95ec3c6SRalf Baechle { 939f95ec3c6SRalf Baechle int plane = fbdev->plane; 940f95ec3c6SRalf Baechle /* Window/plane setup */ 941f95ec3c6SRalf Baechle lcd->window[plane].winctrl1 = ( 0 942f95ec3c6SRalf Baechle | LCD_WINCTRL1_PRI_N(plane) 943f95ec3c6SRalf Baechle | win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */ 944f95ec3c6SRalf Baechle ) ; 945f95ec3c6SRalf Baechle 946f95ec3c6SRalf Baechle au1200_setlocation(fbdev, plane, win->w[plane].xpos, win->w[plane].ypos); 947f95ec3c6SRalf Baechle 948f95ec3c6SRalf Baechle lcd->window[plane].winctrl2 = ( 0 949f95ec3c6SRalf Baechle | LCD_WINCTRL2_CKMODE_00 950f95ec3c6SRalf Baechle | LCD_WINCTRL2_DBM 951c329f606SManuel Lauss | LCD_WINCTRL2_BX_N(fbdev->fb_info->fix.line_length) 952f95ec3c6SRalf Baechle | LCD_WINCTRL2_SCX_1 953f95ec3c6SRalf Baechle | LCD_WINCTRL2_SCY_1 954f95ec3c6SRalf Baechle ) ; 955f95ec3c6SRalf Baechle lcd->winenable |= win->w[plane].mode_winenable; 9562f73bfbeSManuel Lauss wmb(); /* drain writebuffer */ 957f95ec3c6SRalf Baechle } 958f95ec3c6SRalf Baechle 959f95ec3c6SRalf Baechle 960f95ec3c6SRalf Baechle /* Inline helpers */ 961f95ec3c6SRalf Baechle 962f95ec3c6SRalf Baechle /*#define panel_is_dual(panel) ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/ 963f95ec3c6SRalf Baechle /*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/ 964f95ec3c6SRalf Baechle 965f95ec3c6SRalf Baechle #define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN) 966f95ec3c6SRalf Baechle 967f95ec3c6SRalf Baechle /* Bitfields format supported by the controller. */ 968f95ec3c6SRalf Baechle static struct fb_bitfield rgb_bitfields[][4] = { 969f95ec3c6SRalf Baechle /* Red, Green, Blue, Transp */ 970f95ec3c6SRalf Baechle [LCD_WINCTRL1_FRM_16BPP655 >> 25] = 971f95ec3c6SRalf Baechle { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, 972f95ec3c6SRalf Baechle 973f95ec3c6SRalf Baechle [LCD_WINCTRL1_FRM_16BPP565 >> 25] = 974f95ec3c6SRalf Baechle { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, 975f95ec3c6SRalf Baechle 976f95ec3c6SRalf Baechle [LCD_WINCTRL1_FRM_16BPP556 >> 25] = 977f95ec3c6SRalf Baechle { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } }, 978f95ec3c6SRalf Baechle 979f95ec3c6SRalf Baechle [LCD_WINCTRL1_FRM_16BPPI1555 >> 25] = 980f95ec3c6SRalf Baechle { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, 981f95ec3c6SRalf Baechle 982f95ec3c6SRalf Baechle [LCD_WINCTRL1_FRM_16BPPI5551 >> 25] = 983f95ec3c6SRalf Baechle { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } }, 984f95ec3c6SRalf Baechle 985f95ec3c6SRalf Baechle [LCD_WINCTRL1_FRM_16BPPA1555 >> 25] = 986f95ec3c6SRalf Baechle { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } }, 987f95ec3c6SRalf Baechle 988f95ec3c6SRalf Baechle [LCD_WINCTRL1_FRM_16BPPA5551 >> 25] = 989f95ec3c6SRalf Baechle { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } }, 990f95ec3c6SRalf Baechle 991f95ec3c6SRalf Baechle [LCD_WINCTRL1_FRM_24BPP >> 25] = 992f95ec3c6SRalf Baechle { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } }, 993f95ec3c6SRalf Baechle 994f95ec3c6SRalf Baechle [LCD_WINCTRL1_FRM_32BPP >> 25] = 995f95ec3c6SRalf Baechle { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } }, 996f95ec3c6SRalf Baechle }; 997f95ec3c6SRalf Baechle 998f95ec3c6SRalf Baechle /*-------------------------------------------------------------------------*/ 999f95ec3c6SRalf Baechle 1000f95ec3c6SRalf Baechle /* Helpers */ 1001f95ec3c6SRalf Baechle 1002f95ec3c6SRalf Baechle static void au1200fb_update_fbinfo(struct fb_info *fbi) 1003f95ec3c6SRalf Baechle { 1004f95ec3c6SRalf Baechle /* FIX!!!! This also needs to take the window pixel format into account!!! */ 1005f95ec3c6SRalf Baechle 1006f95ec3c6SRalf Baechle /* Update var-dependent FB info */ 1007f95ec3c6SRalf Baechle if (panel_is_color(panel)) { 1008f95ec3c6SRalf Baechle if (fbi->var.bits_per_pixel <= 8) { 1009f95ec3c6SRalf Baechle /* palettized */ 1010f95ec3c6SRalf Baechle fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR; 1011f95ec3c6SRalf Baechle fbi->fix.line_length = fbi->var.xres_virtual / 1012f95ec3c6SRalf Baechle (8/fbi->var.bits_per_pixel); 1013f95ec3c6SRalf Baechle } else { 1014f95ec3c6SRalf Baechle /* non-palettized */ 1015f95ec3c6SRalf Baechle fbi->fix.visual = FB_VISUAL_TRUECOLOR; 1016f95ec3c6SRalf Baechle fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8); 1017f95ec3c6SRalf Baechle } 1018f95ec3c6SRalf Baechle } else { 1019f95ec3c6SRalf Baechle /* mono FIX!!! mono 8 and 4 bits */ 1020f95ec3c6SRalf Baechle fbi->fix.visual = FB_VISUAL_MONO10; 1021f95ec3c6SRalf Baechle fbi->fix.line_length = fbi->var.xres_virtual / 8; 1022f95ec3c6SRalf Baechle } 1023f95ec3c6SRalf Baechle 1024f95ec3c6SRalf Baechle fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual; 1025f95ec3c6SRalf Baechle print_dbg("line length: %d\n", fbi->fix.line_length); 1026f95ec3c6SRalf Baechle print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel); 1027f95ec3c6SRalf Baechle } 1028f95ec3c6SRalf Baechle 1029f95ec3c6SRalf Baechle /*-------------------------------------------------------------------------*/ 1030f95ec3c6SRalf Baechle 1031f95ec3c6SRalf Baechle /* AU1200 framebuffer driver */ 1032f95ec3c6SRalf Baechle 1033f95ec3c6SRalf Baechle /* fb_check_var 1034f95ec3c6SRalf Baechle * Validate var settings with hardware restrictions and modify it if necessary 1035f95ec3c6SRalf Baechle */ 1036f95ec3c6SRalf Baechle static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, 1037f95ec3c6SRalf Baechle struct fb_info *fbi) 1038f95ec3c6SRalf Baechle { 1039c329f606SManuel Lauss struct au1200fb_device *fbdev = fbi->par; 1040f95ec3c6SRalf Baechle u32 pixclock; 1041f95ec3c6SRalf Baechle int screen_size, plane; 1042f95ec3c6SRalf Baechle 104344a3b36bSWei Chen if (!var->pixclock) 104444a3b36bSWei Chen return -EINVAL; 104544a3b36bSWei Chen 1046f95ec3c6SRalf Baechle plane = fbdev->plane; 1047f95ec3c6SRalf Baechle 1048f95ec3c6SRalf Baechle /* Make sure that the mode respect all LCD controller and 1049f95ec3c6SRalf Baechle * panel restrictions. */ 1050f95ec3c6SRalf Baechle var->xres = win->w[plane].xres; 1051f95ec3c6SRalf Baechle var->yres = win->w[plane].yres; 1052f95ec3c6SRalf Baechle 1053f95ec3c6SRalf Baechle /* No need for virtual resolution support */ 1054f95ec3c6SRalf Baechle var->xres_virtual = var->xres; 1055f95ec3c6SRalf Baechle var->yres_virtual = var->yres; 1056f95ec3c6SRalf Baechle 1057f95ec3c6SRalf Baechle var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1); 1058f95ec3c6SRalf Baechle 1059f95ec3c6SRalf Baechle screen_size = var->xres_virtual * var->yres_virtual; 1060f95ec3c6SRalf Baechle if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8); 1061f95ec3c6SRalf Baechle else screen_size /= (8/var->bits_per_pixel); 1062f95ec3c6SRalf Baechle 1063f95ec3c6SRalf Baechle if (fbdev->fb_len < screen_size) 1064f95ec3c6SRalf Baechle return -EINVAL; /* Virtual screen is to big, abort */ 1065f95ec3c6SRalf Baechle 1066f95ec3c6SRalf Baechle /* FIX!!!! what are the implicaitons of ignoring this for windows ??? */ 1067f95ec3c6SRalf Baechle /* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel 1068f95ec3c6SRalf Baechle * clock can only be obtain by dividing this value by an even integer. 1069f95ec3c6SRalf Baechle * Fallback to a slower pixel clock if necessary. */ 1070f95ec3c6SRalf Baechle pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin); 1071732eacc0SHagen Paul Pfeifer pixclock = min3(pixclock, fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2); 1072f95ec3c6SRalf Baechle 1073f95ec3c6SRalf Baechle if (AU1200_LCD_MAX_CLK % pixclock) { 1074f95ec3c6SRalf Baechle int diff = AU1200_LCD_MAX_CLK % pixclock; 1075f95ec3c6SRalf Baechle pixclock -= diff; 1076f95ec3c6SRalf Baechle } 1077f95ec3c6SRalf Baechle 1078f95ec3c6SRalf Baechle var->pixclock = KHZ2PICOS(pixclock/1000); 1079f95ec3c6SRalf Baechle #if 0 1080f95ec3c6SRalf Baechle if (!panel_is_active(panel)) { 1081f95ec3c6SRalf Baechle int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1; 1082f95ec3c6SRalf Baechle 1083f95ec3c6SRalf Baechle if (!panel_is_color(panel) 1084f95ec3c6SRalf Baechle && (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) { 1085f95ec3c6SRalf Baechle /* STN 8bit mono panel support is up to 6MHz pixclock */ 1086f95ec3c6SRalf Baechle var->pixclock = KHZ2PICOS(6000); 1087f95ec3c6SRalf Baechle } else if (!pcd) { 1088f95ec3c6SRalf Baechle /* Other STN panel support is up to 12MHz */ 1089f95ec3c6SRalf Baechle var->pixclock = KHZ2PICOS(12000); 1090f95ec3c6SRalf Baechle } 1091f95ec3c6SRalf Baechle } 1092f95ec3c6SRalf Baechle #endif 1093f95ec3c6SRalf Baechle /* Set bitfield accordingly */ 1094f95ec3c6SRalf Baechle switch (var->bits_per_pixel) { 1095f95ec3c6SRalf Baechle case 16: 1096f95ec3c6SRalf Baechle { 1097f95ec3c6SRalf Baechle /* 16bpp True color. 1098f95ec3c6SRalf Baechle * These must be set to MATCH WINCTRL[FORM] */ 1099f95ec3c6SRalf Baechle int idx; 1100f95ec3c6SRalf Baechle idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; 1101f95ec3c6SRalf Baechle var->red = rgb_bitfields[idx][0]; 1102f95ec3c6SRalf Baechle var->green = rgb_bitfields[idx][1]; 1103f95ec3c6SRalf Baechle var->blue = rgb_bitfields[idx][2]; 1104f95ec3c6SRalf Baechle var->transp = rgb_bitfields[idx][3]; 1105f95ec3c6SRalf Baechle break; 1106f95ec3c6SRalf Baechle } 1107f95ec3c6SRalf Baechle 1108f95ec3c6SRalf Baechle case 32: 1109f95ec3c6SRalf Baechle { 1110f95ec3c6SRalf Baechle /* 32bpp True color. 1111f95ec3c6SRalf Baechle * These must be set to MATCH WINCTRL[FORM] */ 1112f95ec3c6SRalf Baechle int idx; 1113f95ec3c6SRalf Baechle idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; 1114f95ec3c6SRalf Baechle var->red = rgb_bitfields[idx][0]; 1115f95ec3c6SRalf Baechle var->green = rgb_bitfields[idx][1]; 1116f95ec3c6SRalf Baechle var->blue = rgb_bitfields[idx][2]; 1117f95ec3c6SRalf Baechle var->transp = rgb_bitfields[idx][3]; 1118f95ec3c6SRalf Baechle break; 1119f95ec3c6SRalf Baechle } 1120f95ec3c6SRalf Baechle default: 1121f95ec3c6SRalf Baechle print_dbg("Unsupported depth %dbpp", var->bits_per_pixel); 1122f95ec3c6SRalf Baechle return -EINVAL; 1123f95ec3c6SRalf Baechle } 1124f95ec3c6SRalf Baechle 1125f95ec3c6SRalf Baechle return 0; 1126f95ec3c6SRalf Baechle } 1127f95ec3c6SRalf Baechle 1128f95ec3c6SRalf Baechle /* fb_set_par 1129f95ec3c6SRalf Baechle * Set hardware with var settings. This will enable the controller with a 1130f95ec3c6SRalf Baechle * specific mode, normally validated with the fb_check_var method 1131f95ec3c6SRalf Baechle */ 1132f95ec3c6SRalf Baechle static int au1200fb_fb_set_par(struct fb_info *fbi) 1133f95ec3c6SRalf Baechle { 1134c329f606SManuel Lauss struct au1200fb_device *fbdev = fbi->par; 1135f95ec3c6SRalf Baechle 1136f95ec3c6SRalf Baechle au1200fb_update_fbinfo(fbi); 1137f95ec3c6SRalf Baechle au1200_setmode(fbdev); 1138f95ec3c6SRalf Baechle 1139f95ec3c6SRalf Baechle return 0; 1140f95ec3c6SRalf Baechle } 1141f95ec3c6SRalf Baechle 1142f95ec3c6SRalf Baechle /* fb_setcolreg 1143f95ec3c6SRalf Baechle * Set color in LCD palette. 1144f95ec3c6SRalf Baechle */ 1145f95ec3c6SRalf Baechle static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, 1146f95ec3c6SRalf Baechle unsigned blue, unsigned transp, struct fb_info *fbi) 1147f95ec3c6SRalf Baechle { 1148f95ec3c6SRalf Baechle volatile u32 *palette = lcd->palette; 1149f95ec3c6SRalf Baechle u32 value; 1150f95ec3c6SRalf Baechle 1151f95ec3c6SRalf Baechle if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1)) 1152f95ec3c6SRalf Baechle return -EINVAL; 1153f95ec3c6SRalf Baechle 1154f95ec3c6SRalf Baechle if (fbi->var.grayscale) { 1155f95ec3c6SRalf Baechle /* Convert color to grayscale */ 1156f95ec3c6SRalf Baechle red = green = blue = 1157f95ec3c6SRalf Baechle (19595 * red + 38470 * green + 7471 * blue) >> 16; 1158f95ec3c6SRalf Baechle } 1159f95ec3c6SRalf Baechle 1160f95ec3c6SRalf Baechle if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) { 1161f95ec3c6SRalf Baechle /* Place color in the pseudopalette */ 1162f95ec3c6SRalf Baechle if (regno > 16) 1163f95ec3c6SRalf Baechle return -EINVAL; 1164f95ec3c6SRalf Baechle 1165f95ec3c6SRalf Baechle palette = (u32*) fbi->pseudo_palette; 1166f95ec3c6SRalf Baechle 1167f95ec3c6SRalf Baechle red >>= (16 - fbi->var.red.length); 1168f95ec3c6SRalf Baechle green >>= (16 - fbi->var.green.length); 1169f95ec3c6SRalf Baechle blue >>= (16 - fbi->var.blue.length); 1170f95ec3c6SRalf Baechle 1171f95ec3c6SRalf Baechle value = (red << fbi->var.red.offset) | 1172f95ec3c6SRalf Baechle (green << fbi->var.green.offset)| 1173f95ec3c6SRalf Baechle (blue << fbi->var.blue.offset); 1174f95ec3c6SRalf Baechle value &= 0xFFFF; 1175f95ec3c6SRalf Baechle 1176f95ec3c6SRalf Baechle } else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) { 1177f95ec3c6SRalf Baechle /* COLOR TFT PALLETTIZED (use RGB 565) */ 1178f95ec3c6SRalf Baechle value = (red & 0xF800)|((green >> 5) & 1179f95ec3c6SRalf Baechle 0x07E0)|((blue >> 11) & 0x001F); 1180f95ec3c6SRalf Baechle value &= 0xFFFF; 1181f95ec3c6SRalf Baechle 1182f95ec3c6SRalf Baechle } else if (0 /*panel_is_color(fbdev->panel)*/) { 1183f95ec3c6SRalf Baechle /* COLOR STN MODE */ 1184f95ec3c6SRalf Baechle value = 0x1234; 1185f95ec3c6SRalf Baechle value &= 0xFFF; 1186f95ec3c6SRalf Baechle } else { 1187f95ec3c6SRalf Baechle /* MONOCHROME MODE */ 1188f95ec3c6SRalf Baechle value = (green >> 12) & 0x000F; 1189f95ec3c6SRalf Baechle value &= 0xF; 1190f95ec3c6SRalf Baechle } 1191f95ec3c6SRalf Baechle 1192f95ec3c6SRalf Baechle palette[regno] = value; 1193f95ec3c6SRalf Baechle 1194f95ec3c6SRalf Baechle return 0; 1195f95ec3c6SRalf Baechle } 1196f95ec3c6SRalf Baechle 1197f95ec3c6SRalf Baechle /* fb_blank 1198f95ec3c6SRalf Baechle * Blank the screen. Depending on the mode, the screen will be 1199f95ec3c6SRalf Baechle * activated with the backlight color, or desactivated 1200f95ec3c6SRalf Baechle */ 1201f95ec3c6SRalf Baechle static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi) 1202f95ec3c6SRalf Baechle { 1203a9b71a8fSManuel Lauss struct au1200fb_device *fbdev = fbi->par; 1204a9b71a8fSManuel Lauss 1205f95ec3c6SRalf Baechle /* Short-circuit screen blanking */ 1206f95ec3c6SRalf Baechle if (noblanking) 1207f95ec3c6SRalf Baechle return 0; 1208f95ec3c6SRalf Baechle 1209f95ec3c6SRalf Baechle switch (blank_mode) { 1210f95ec3c6SRalf Baechle 1211f95ec3c6SRalf Baechle case FB_BLANK_UNBLANK: 1212f95ec3c6SRalf Baechle case FB_BLANK_NORMAL: 1213f95ec3c6SRalf Baechle /* printk("turn on panel\n"); */ 1214a9b71a8fSManuel Lauss au1200_setpanel(panel, fbdev->pd); 1215f95ec3c6SRalf Baechle break; 1216f95ec3c6SRalf Baechle case FB_BLANK_VSYNC_SUSPEND: 1217f95ec3c6SRalf Baechle case FB_BLANK_HSYNC_SUSPEND: 1218f95ec3c6SRalf Baechle case FB_BLANK_POWERDOWN: 1219f95ec3c6SRalf Baechle /* printk("turn off panel\n"); */ 1220a9b71a8fSManuel Lauss au1200_setpanel(NULL, fbdev->pd); 1221f95ec3c6SRalf Baechle break; 1222f95ec3c6SRalf Baechle default: 1223f95ec3c6SRalf Baechle break; 1224f95ec3c6SRalf Baechle 1225f95ec3c6SRalf Baechle } 1226f95ec3c6SRalf Baechle 1227f95ec3c6SRalf Baechle /* FB_BLANK_NORMAL is a soft blank */ 1228f95ec3c6SRalf Baechle return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0; 1229f95ec3c6SRalf Baechle } 1230f95ec3c6SRalf Baechle 1231f95ec3c6SRalf Baechle /* fb_mmap 1232f95ec3c6SRalf Baechle * Map video memory in user space. We don't use the generic fb_mmap 1233f95ec3c6SRalf Baechle * method mainly to allow the use of the TLB streaming flag (CCA=6) 1234f95ec3c6SRalf Baechle */ 1235f95ec3c6SRalf Baechle static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) 1236f95ec3c6SRalf Baechle { 1237c329f606SManuel Lauss struct au1200fb_device *fbdev = info->par; 1238f95ec3c6SRalf Baechle 1239212efde8SCai Huoqing return dma_mmap_coherent(fbdev->dev, vma, 1240212efde8SCai Huoqing fbdev->fb_mem, fbdev->fb_phys, fbdev->fb_len); 1241f95ec3c6SRalf Baechle } 1242f95ec3c6SRalf Baechle 1243f95ec3c6SRalf Baechle static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) 1244f95ec3c6SRalf Baechle { 1245f95ec3c6SRalf Baechle 1246f95ec3c6SRalf Baechle unsigned int hi1, divider; 1247f95ec3c6SRalf Baechle 1248f95ec3c6SRalf Baechle /* SCREEN_SIZE: user cannot reset size, must switch panel choice */ 1249f95ec3c6SRalf Baechle 1250f95ec3c6SRalf Baechle if (pdata->flags & SCREEN_BACKCOLOR) 1251f95ec3c6SRalf Baechle lcd->backcolor = pdata->backcolor; 1252f95ec3c6SRalf Baechle 1253f95ec3c6SRalf Baechle if (pdata->flags & SCREEN_BRIGHTNESS) { 1254f95ec3c6SRalf Baechle 1255f95ec3c6SRalf Baechle // limit brightness pwm duty to >= 30/1600 1256f95ec3c6SRalf Baechle if (pdata->brightness < 30) { 1257f95ec3c6SRalf Baechle pdata->brightness = 30; 1258f95ec3c6SRalf Baechle } 1259f95ec3c6SRalf Baechle divider = (lcd->pwmdiv & 0x3FFFF) + 1; 1260f95ec3c6SRalf Baechle hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8); 1261f95ec3c6SRalf Baechle lcd->pwmhi &= 0xFFFF; 1262f95ec3c6SRalf Baechle lcd->pwmhi |= (hi1 << 16); 1263f95ec3c6SRalf Baechle } 1264f95ec3c6SRalf Baechle 1265f95ec3c6SRalf Baechle if (pdata->flags & SCREEN_COLORKEY) 1266f95ec3c6SRalf Baechle lcd->colorkey = pdata->colorkey; 1267f95ec3c6SRalf Baechle 1268f95ec3c6SRalf Baechle if (pdata->flags & SCREEN_MASK) 1269f95ec3c6SRalf Baechle lcd->colorkeymsk = pdata->mask; 12702f73bfbeSManuel Lauss wmb(); /* drain writebuffer */ 1271f95ec3c6SRalf Baechle } 1272f95ec3c6SRalf Baechle 1273f95ec3c6SRalf Baechle static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) 1274f95ec3c6SRalf Baechle { 1275f95ec3c6SRalf Baechle unsigned int hi1, divider; 1276f95ec3c6SRalf Baechle 1277f95ec3c6SRalf Baechle pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1; 1278f95ec3c6SRalf Baechle pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1; 1279f95ec3c6SRalf Baechle 1280f95ec3c6SRalf Baechle pdata->backcolor = lcd->backcolor; 1281f95ec3c6SRalf Baechle pdata->colorkey = lcd->colorkey; 1282f95ec3c6SRalf Baechle pdata->mask = lcd->colorkeymsk; 1283f95ec3c6SRalf Baechle 1284f95ec3c6SRalf Baechle // brightness 1285f95ec3c6SRalf Baechle hi1 = (lcd->pwmhi >> 16) + 1; 1286f95ec3c6SRalf Baechle divider = (lcd->pwmdiv & 0x3FFFF) + 1; 1287f95ec3c6SRalf Baechle pdata->brightness = ((hi1 << 8) / divider) - 1; 12882f73bfbeSManuel Lauss wmb(); /* drain writebuffer */ 1289f95ec3c6SRalf Baechle } 1290f95ec3c6SRalf Baechle 1291f95ec3c6SRalf Baechle static void set_window(unsigned int plane, 1292f95ec3c6SRalf Baechle struct au1200_lcd_window_regs_t *pdata) 1293f95ec3c6SRalf Baechle { 1294f95ec3c6SRalf Baechle unsigned int val, bpp; 1295f95ec3c6SRalf Baechle 1296f95ec3c6SRalf Baechle /* Window control register 0 */ 1297f95ec3c6SRalf Baechle if (pdata->flags & WIN_POSITION) { 1298f95ec3c6SRalf Baechle val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX | 1299f95ec3c6SRalf Baechle LCD_WINCTRL0_OY); 1300f95ec3c6SRalf Baechle val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX); 1301f95ec3c6SRalf Baechle val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY); 1302f95ec3c6SRalf Baechle lcd->window[plane].winctrl0 = val; 1303f95ec3c6SRalf Baechle } 1304f95ec3c6SRalf Baechle if (pdata->flags & WIN_ALPHA_COLOR) { 1305f95ec3c6SRalf Baechle val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A); 1306f95ec3c6SRalf Baechle val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A); 1307f95ec3c6SRalf Baechle lcd->window[plane].winctrl0 = val; 1308f95ec3c6SRalf Baechle } 1309f95ec3c6SRalf Baechle if (pdata->flags & WIN_ALPHA_MODE) { 1310f95ec3c6SRalf Baechle val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN); 1311f95ec3c6SRalf Baechle val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN); 1312f95ec3c6SRalf Baechle lcd->window[plane].winctrl0 = val; 1313f95ec3c6SRalf Baechle } 1314f95ec3c6SRalf Baechle 1315f95ec3c6SRalf Baechle /* Window control register 1 */ 1316f95ec3c6SRalf Baechle if (pdata->flags & WIN_PRIORITY) { 1317f95ec3c6SRalf Baechle val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI); 1318f95ec3c6SRalf Baechle val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI); 1319f95ec3c6SRalf Baechle lcd->window[plane].winctrl1 = val; 1320f95ec3c6SRalf Baechle } 1321f95ec3c6SRalf Baechle if (pdata->flags & WIN_CHANNEL) { 1322f95ec3c6SRalf Baechle val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE); 1323f95ec3c6SRalf Baechle val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE); 1324f95ec3c6SRalf Baechle lcd->window[plane].winctrl1 = val; 1325f95ec3c6SRalf Baechle } 1326f95ec3c6SRalf Baechle if (pdata->flags & WIN_BUFFER_FORMAT) { 1327f95ec3c6SRalf Baechle val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM); 1328f95ec3c6SRalf Baechle val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM); 1329f95ec3c6SRalf Baechle lcd->window[plane].winctrl1 = val; 1330f95ec3c6SRalf Baechle } 1331f95ec3c6SRalf Baechle if (pdata->flags & WIN_COLOR_ORDER) { 1332f95ec3c6SRalf Baechle val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO); 1333f95ec3c6SRalf Baechle val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO); 1334f95ec3c6SRalf Baechle lcd->window[plane].winctrl1 = val; 1335f95ec3c6SRalf Baechle } 1336f95ec3c6SRalf Baechle if (pdata->flags & WIN_PIXEL_ORDER) { 1337f95ec3c6SRalf Baechle val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO); 1338f95ec3c6SRalf Baechle val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO); 1339f95ec3c6SRalf Baechle lcd->window[plane].winctrl1 = val; 1340f95ec3c6SRalf Baechle } 1341f95ec3c6SRalf Baechle if (pdata->flags & WIN_SIZE) { 1342f95ec3c6SRalf Baechle val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX | 1343f95ec3c6SRalf Baechle LCD_WINCTRL1_SZY); 1344f95ec3c6SRalf Baechle val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX); 1345f95ec3c6SRalf Baechle val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY); 1346f95ec3c6SRalf Baechle lcd->window[plane].winctrl1 = val; 1347f95ec3c6SRalf Baechle /* program buffer line width */ 1348f95ec3c6SRalf Baechle bpp = winbpp(val) / 8; 1349f95ec3c6SRalf Baechle val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX); 1350f95ec3c6SRalf Baechle val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX); 1351f95ec3c6SRalf Baechle lcd->window[plane].winctrl2 = val; 1352f95ec3c6SRalf Baechle } 1353f95ec3c6SRalf Baechle 1354f95ec3c6SRalf Baechle /* Window control register 2 */ 1355f95ec3c6SRalf Baechle if (pdata->flags & WIN_COLORKEY_MODE) { 1356f95ec3c6SRalf Baechle val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE); 1357f95ec3c6SRalf Baechle val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE); 1358f95ec3c6SRalf Baechle lcd->window[plane].winctrl2 = val; 1359f95ec3c6SRalf Baechle } 1360f95ec3c6SRalf Baechle if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) { 1361f95ec3c6SRalf Baechle val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM); 1362f95ec3c6SRalf Baechle val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM); 1363f95ec3c6SRalf Baechle lcd->window[plane].winctrl2 = val; 1364f95ec3c6SRalf Baechle } 1365f95ec3c6SRalf Baechle if (pdata->flags & WIN_RAM_ARRAY_MODE) { 1366f95ec3c6SRalf Baechle val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM); 1367f95ec3c6SRalf Baechle val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM); 1368f95ec3c6SRalf Baechle lcd->window[plane].winctrl2 = val; 1369f95ec3c6SRalf Baechle } 1370f95ec3c6SRalf Baechle 1371f95ec3c6SRalf Baechle /* Buffer line width programmed with WIN_SIZE */ 1372f95ec3c6SRalf Baechle 1373f95ec3c6SRalf Baechle if (pdata->flags & WIN_BUFFER_SCALE) { 1374f95ec3c6SRalf Baechle val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX | 1375f95ec3c6SRalf Baechle LCD_WINCTRL2_SCY); 1376f95ec3c6SRalf Baechle val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX); 1377f95ec3c6SRalf Baechle val |= ((pdata->ysize) & LCD_WINCTRL2_SCY); 1378f95ec3c6SRalf Baechle lcd->window[plane].winctrl2 = val; 1379f95ec3c6SRalf Baechle } 1380f95ec3c6SRalf Baechle 1381f95ec3c6SRalf Baechle if (pdata->flags & WIN_ENABLE) { 1382f95ec3c6SRalf Baechle val = lcd->winenable; 1383f95ec3c6SRalf Baechle val &= ~(1<<plane); 1384f95ec3c6SRalf Baechle val |= (pdata->enable & 1) << plane; 1385f95ec3c6SRalf Baechle lcd->winenable = val; 1386f95ec3c6SRalf Baechle } 13872f73bfbeSManuel Lauss wmb(); /* drain writebuffer */ 1388f95ec3c6SRalf Baechle } 1389f95ec3c6SRalf Baechle 1390f95ec3c6SRalf Baechle static void get_window(unsigned int plane, 1391f95ec3c6SRalf Baechle struct au1200_lcd_window_regs_t *pdata) 1392f95ec3c6SRalf Baechle { 1393f95ec3c6SRalf Baechle /* Window control register 0 */ 1394f95ec3c6SRalf Baechle pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21; 1395f95ec3c6SRalf Baechle pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10; 1396f95ec3c6SRalf Baechle pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2; 1397f95ec3c6SRalf Baechle pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1; 1398f95ec3c6SRalf Baechle 1399f95ec3c6SRalf Baechle /* Window control register 1 */ 1400f95ec3c6SRalf Baechle pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30; 1401f95ec3c6SRalf Baechle pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29; 1402f95ec3c6SRalf Baechle pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25; 1403f95ec3c6SRalf Baechle pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24; 1404f95ec3c6SRalf Baechle pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22; 1405f95ec3c6SRalf Baechle pdata->xsize = ((lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11) + 1; 1406f95ec3c6SRalf Baechle pdata->ysize = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZY) + 1; 1407f95ec3c6SRalf Baechle 1408f95ec3c6SRalf Baechle /* Window control register 2 */ 1409f95ec3c6SRalf Baechle pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24; 1410f95ec3c6SRalf Baechle pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23; 1411f95ec3c6SRalf Baechle pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21; 1412f95ec3c6SRalf Baechle 1413f95ec3c6SRalf Baechle pdata->enable = (lcd->winenable >> plane) & 1; 14142f73bfbeSManuel Lauss wmb(); /* drain writebuffer */ 1415f95ec3c6SRalf Baechle } 1416f95ec3c6SRalf Baechle 1417f95ec3c6SRalf Baechle static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd, 1418f95ec3c6SRalf Baechle unsigned long arg) 1419f95ec3c6SRalf Baechle { 1420a9b71a8fSManuel Lauss struct au1200fb_device *fbdev = info->par; 1421f95ec3c6SRalf Baechle int plane; 1422f95ec3c6SRalf Baechle int val; 1423f95ec3c6SRalf Baechle 1424f95ec3c6SRalf Baechle plane = fbinfo2index(info); 1425f95ec3c6SRalf Baechle print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); 1426f95ec3c6SRalf Baechle 1427f95ec3c6SRalf Baechle if (cmd == AU1200_LCD_FB_IOCTL) { 1428f95ec3c6SRalf Baechle struct au1200_lcd_iodata_t iodata; 1429f95ec3c6SRalf Baechle 1430f95ec3c6SRalf Baechle if (copy_from_user(&iodata, (void __user *) arg, sizeof(iodata))) 1431f95ec3c6SRalf Baechle return -EFAULT; 1432f95ec3c6SRalf Baechle 1433f95ec3c6SRalf Baechle print_dbg("FB IOCTL called\n"); 1434f95ec3c6SRalf Baechle 1435f95ec3c6SRalf Baechle switch (iodata.subcmd) { 1436f95ec3c6SRalf Baechle case AU1200_LCD_SET_SCREEN: 1437f95ec3c6SRalf Baechle print_dbg("AU1200_LCD_SET_SCREEN\n"); 1438f95ec3c6SRalf Baechle set_global(cmd, &iodata.global); 1439f95ec3c6SRalf Baechle break; 1440f95ec3c6SRalf Baechle 1441f95ec3c6SRalf Baechle case AU1200_LCD_GET_SCREEN: 1442f95ec3c6SRalf Baechle print_dbg("AU1200_LCD_GET_SCREEN\n"); 1443f95ec3c6SRalf Baechle get_global(cmd, &iodata.global); 1444f95ec3c6SRalf Baechle break; 1445f95ec3c6SRalf Baechle 1446f95ec3c6SRalf Baechle case AU1200_LCD_SET_WINDOW: 1447f95ec3c6SRalf Baechle print_dbg("AU1200_LCD_SET_WINDOW\n"); 1448f95ec3c6SRalf Baechle set_window(plane, &iodata.window); 1449f95ec3c6SRalf Baechle break; 1450f95ec3c6SRalf Baechle 1451f95ec3c6SRalf Baechle case AU1200_LCD_GET_WINDOW: 1452f95ec3c6SRalf Baechle print_dbg("AU1200_LCD_GET_WINDOW\n"); 1453f95ec3c6SRalf Baechle get_window(plane, &iodata.window); 1454f95ec3c6SRalf Baechle break; 1455f95ec3c6SRalf Baechle 1456f95ec3c6SRalf Baechle case AU1200_LCD_SET_PANEL: 1457f95ec3c6SRalf Baechle print_dbg("AU1200_LCD_SET_PANEL\n"); 1458f95ec3c6SRalf Baechle if ((iodata.global.panel_choice >= 0) && 1459f95ec3c6SRalf Baechle (iodata.global.panel_choice < 1460f95ec3c6SRalf Baechle NUM_PANELS)) 1461f95ec3c6SRalf Baechle { 1462f95ec3c6SRalf Baechle struct panel_settings *newpanel; 1463f95ec3c6SRalf Baechle panel_index = iodata.global.panel_choice; 1464f95ec3c6SRalf Baechle newpanel = &known_lcd_panels[panel_index]; 1465a9b71a8fSManuel Lauss au1200_setpanel(newpanel, fbdev->pd); 1466f95ec3c6SRalf Baechle } 1467f95ec3c6SRalf Baechle break; 1468f95ec3c6SRalf Baechle 1469f95ec3c6SRalf Baechle case AU1200_LCD_GET_PANEL: 1470f95ec3c6SRalf Baechle print_dbg("AU1200_LCD_GET_PANEL\n"); 1471f95ec3c6SRalf Baechle iodata.global.panel_choice = panel_index; 1472f95ec3c6SRalf Baechle break; 1473f95ec3c6SRalf Baechle 1474f95ec3c6SRalf Baechle default: 1475f95ec3c6SRalf Baechle return -EINVAL; 1476f95ec3c6SRalf Baechle } 1477f95ec3c6SRalf Baechle 1478f95ec3c6SRalf Baechle val = copy_to_user((void __user *) arg, &iodata, sizeof(iodata)); 1479f95ec3c6SRalf Baechle if (val) { 1480f95ec3c6SRalf Baechle print_dbg("error: could not copy %d bytes\n", val); 1481f95ec3c6SRalf Baechle return -EFAULT; 1482f95ec3c6SRalf Baechle } 1483f95ec3c6SRalf Baechle } 1484f95ec3c6SRalf Baechle 1485f95ec3c6SRalf Baechle return 0; 1486f95ec3c6SRalf Baechle } 1487f95ec3c6SRalf Baechle 1488f95ec3c6SRalf Baechle 14898a48ac33SJani Nikula static const struct fb_ops au1200fb_fb_ops = { 1490f95ec3c6SRalf Baechle .owner = THIS_MODULE, 1491f95ec3c6SRalf Baechle .fb_check_var = au1200fb_fb_check_var, 1492f95ec3c6SRalf Baechle .fb_set_par = au1200fb_fb_set_par, 1493f95ec3c6SRalf Baechle .fb_setcolreg = au1200fb_fb_setcolreg, 1494f95ec3c6SRalf Baechle .fb_blank = au1200fb_fb_blank, 14954ee58461SManuel Lauss .fb_fillrect = sys_fillrect, 14964ee58461SManuel Lauss .fb_copyarea = sys_copyarea, 14974ee58461SManuel Lauss .fb_imageblit = sys_imageblit, 14984ee58461SManuel Lauss .fb_read = fb_sys_read, 14994ee58461SManuel Lauss .fb_write = fb_sys_write, 1500f95ec3c6SRalf Baechle .fb_sync = NULL, 1501f95ec3c6SRalf Baechle .fb_ioctl = au1200fb_ioctl, 1502f95ec3c6SRalf Baechle .fb_mmap = au1200fb_fb_mmap, 1503f95ec3c6SRalf Baechle }; 1504f95ec3c6SRalf Baechle 1505f95ec3c6SRalf Baechle /*-------------------------------------------------------------------------*/ 1506f95ec3c6SRalf Baechle 15077d12e780SDavid Howells static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id) 1508f95ec3c6SRalf Baechle { 1509f95ec3c6SRalf Baechle /* Nothing to do for now, just clear any pending interrupt */ 1510f95ec3c6SRalf Baechle lcd->intstatus = lcd->intstatus; 15112f73bfbeSManuel Lauss wmb(); /* drain writebuffer */ 1512f95ec3c6SRalf Baechle 1513f95ec3c6SRalf Baechle return IRQ_HANDLED; 1514f95ec3c6SRalf Baechle } 1515f95ec3c6SRalf Baechle 1516f95ec3c6SRalf Baechle /*-------------------------------------------------------------------------*/ 1517f95ec3c6SRalf Baechle 1518f95ec3c6SRalf Baechle /* AU1200 LCD device probe helpers */ 1519f95ec3c6SRalf Baechle 1520f95ec3c6SRalf Baechle static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) 1521f95ec3c6SRalf Baechle { 1522c329f606SManuel Lauss struct fb_info *fbi = fbdev->fb_info; 152306208656SChristophe JAILLET int bpp, ret; 1524f95ec3c6SRalf Baechle 1525f95ec3c6SRalf Baechle fbi->fbops = &au1200fb_fb_ops; 1526f95ec3c6SRalf Baechle 1527f95ec3c6SRalf Baechle bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); 1528f95ec3c6SRalf Baechle 1529f95ec3c6SRalf Baechle /* Copy monitor specs from panel data */ 1530f95ec3c6SRalf Baechle /* fixme: we're setting up LCD controller windows, so these dont give a 1531f95ec3c6SRalf Baechle damn as to what the monitor specs are (the panel itself does, but that 153225985edcSLucas De Marchi isn't done here...so maybe need a generic catchall monitor setting??? */ 1533f95ec3c6SRalf Baechle memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs)); 1534f95ec3c6SRalf Baechle 1535f95ec3c6SRalf Baechle /* We first try the user mode passed in argument. If that failed, 1536f95ec3c6SRalf Baechle * or if no one has been specified, we default to the first mode of the 1537f95ec3c6SRalf Baechle * panel list. Note that after this call, var data will be set */ 1538f95ec3c6SRalf Baechle if (!fb_find_mode(&fbi->var, 1539f95ec3c6SRalf Baechle fbi, 1540f95ec3c6SRalf Baechle NULL, /* drv_info.opt_mode, */ 1541f95ec3c6SRalf Baechle fbi->monspecs.modedb, 1542f95ec3c6SRalf Baechle fbi->monspecs.modedb_len, 1543f95ec3c6SRalf Baechle fbi->monspecs.modedb, 1544f95ec3c6SRalf Baechle bpp)) { 1545f95ec3c6SRalf Baechle 1546f95ec3c6SRalf Baechle print_err("Cannot find valid mode for panel %s", panel->name); 1547f95ec3c6SRalf Baechle return -EFAULT; 1548f95ec3c6SRalf Baechle } 1549f95ec3c6SRalf Baechle 1550dd00cc48SYoann Padioleau fbi->pseudo_palette = kcalloc(16, sizeof(u32), GFP_KERNEL); 1551ab798b90SChristophe JAILLET if (!fbi->pseudo_palette) 1552f95ec3c6SRalf Baechle return -ENOMEM; 1553f95ec3c6SRalf Baechle 155406208656SChristophe JAILLET ret = fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0); 155506208656SChristophe JAILLET if (ret < 0) { 1556f95ec3c6SRalf Baechle print_err("Fail to allocate colormap (%d entries)", 1557f95ec3c6SRalf Baechle AU1200_LCD_NBR_PALETTE_ENTRIES); 155806208656SChristophe JAILLET return ret; 1559f95ec3c6SRalf Baechle } 1560f95ec3c6SRalf Baechle 1561f95ec3c6SRalf Baechle strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id)); 1562f95ec3c6SRalf Baechle fbi->fix.smem_start = fbdev->fb_phys; 1563f95ec3c6SRalf Baechle fbi->fix.smem_len = fbdev->fb_len; 1564f95ec3c6SRalf Baechle fbi->fix.type = FB_TYPE_PACKED_PIXELS; 1565f95ec3c6SRalf Baechle fbi->fix.xpanstep = 0; 1566f95ec3c6SRalf Baechle fbi->fix.ypanstep = 0; 1567f95ec3c6SRalf Baechle fbi->fix.mmio_start = 0; 1568f95ec3c6SRalf Baechle fbi->fix.mmio_len = 0; 1569f95ec3c6SRalf Baechle fbi->fix.accel = FB_ACCEL_NONE; 1570f95ec3c6SRalf Baechle 1571f5eccc49SThomas Zimmermann fbi->screen_buffer = fbdev->fb_mem; 1572f95ec3c6SRalf Baechle 1573f95ec3c6SRalf Baechle au1200fb_update_fbinfo(fbi); 1574f95ec3c6SRalf Baechle 1575f95ec3c6SRalf Baechle return 0; 1576f95ec3c6SRalf Baechle } 1577f95ec3c6SRalf Baechle 1578f95ec3c6SRalf Baechle /*-------------------------------------------------------------------------*/ 1579f95ec3c6SRalf Baechle 1580f95ec3c6SRalf Baechle 1581a9b71a8fSManuel Lauss static int au1200fb_setup(struct au1200fb_platdata *pd) 1582a9b71a8fSManuel Lauss { 1583a9b71a8fSManuel Lauss char *options = NULL; 1584a9b71a8fSManuel Lauss char *this_opt, *endptr; 1585a9b71a8fSManuel Lauss int num_panels = ARRAY_SIZE(known_lcd_panels); 1586a9b71a8fSManuel Lauss int panel_idx = -1; 1587a9b71a8fSManuel Lauss 1588a9b71a8fSManuel Lauss fb_get_options(DRIVER_NAME, &options); 1589a9b71a8fSManuel Lauss 1590a9b71a8fSManuel Lauss if (!options) 1591a9b71a8fSManuel Lauss goto out; 1592a9b71a8fSManuel Lauss 1593a9b71a8fSManuel Lauss while ((this_opt = strsep(&options, ",")) != NULL) { 1594a9b71a8fSManuel Lauss /* Panel option - can be panel name, 1595a9b71a8fSManuel Lauss * "bs" for board-switch, or number/index */ 1596a9b71a8fSManuel Lauss if (!strncmp(this_opt, "panel:", 6)) { 1597a9b71a8fSManuel Lauss int i; 1598a9b71a8fSManuel Lauss long int li; 1599a9b71a8fSManuel Lauss char *endptr; 1600a9b71a8fSManuel Lauss this_opt += 6; 1601a9b71a8fSManuel Lauss /* First check for index, which allows 1602a9b71a8fSManuel Lauss * to short circuit this mess */ 1603a9b71a8fSManuel Lauss li = simple_strtol(this_opt, &endptr, 0); 1604a9b71a8fSManuel Lauss if (*endptr == '\0') 1605a9b71a8fSManuel Lauss panel_idx = (int)li; 1606a9b71a8fSManuel Lauss else if (strcmp(this_opt, "bs") == 0) 1607a9b71a8fSManuel Lauss panel_idx = pd->panel_index(); 1608a9b71a8fSManuel Lauss else { 1609a9b71a8fSManuel Lauss for (i = 0; i < num_panels; i++) { 1610a9b71a8fSManuel Lauss if (!strcmp(this_opt, 1611a9b71a8fSManuel Lauss known_lcd_panels[i].name)) { 1612a9b71a8fSManuel Lauss panel_idx = i; 1613a9b71a8fSManuel Lauss break; 1614a9b71a8fSManuel Lauss } 1615a9b71a8fSManuel Lauss } 1616a9b71a8fSManuel Lauss } 1617a9b71a8fSManuel Lauss if ((panel_idx < 0) || (panel_idx >= num_panels)) 1618a9b71a8fSManuel Lauss print_warn("Panel %s not supported!", this_opt); 1619a9b71a8fSManuel Lauss else 1620a9b71a8fSManuel Lauss panel_index = panel_idx; 1621a9b71a8fSManuel Lauss 1622a9b71a8fSManuel Lauss } else if (strncmp(this_opt, "nohwcursor", 10) == 0) 1623a9b71a8fSManuel Lauss nohwcursor = 1; 1624a9b71a8fSManuel Lauss else if (strncmp(this_opt, "devices:", 8) == 0) { 1625a9b71a8fSManuel Lauss this_opt += 8; 1626a9b71a8fSManuel Lauss device_count = simple_strtol(this_opt, &endptr, 0); 1627a9b71a8fSManuel Lauss if ((device_count < 0) || 1628a9b71a8fSManuel Lauss (device_count > MAX_DEVICE_COUNT)) 1629a9b71a8fSManuel Lauss device_count = MAX_DEVICE_COUNT; 1630a9b71a8fSManuel Lauss } else if (strncmp(this_opt, "wincfg:", 7) == 0) { 1631a9b71a8fSManuel Lauss this_opt += 7; 1632a9b71a8fSManuel Lauss window_index = simple_strtol(this_opt, &endptr, 0); 1633a9b71a8fSManuel Lauss if ((window_index < 0) || 1634a9b71a8fSManuel Lauss (window_index >= ARRAY_SIZE(windows))) 1635a9b71a8fSManuel Lauss window_index = DEFAULT_WINDOW_INDEX; 1636a9b71a8fSManuel Lauss } else if (strncmp(this_opt, "off", 3) == 0) 1637a9b71a8fSManuel Lauss return 1; 1638a9b71a8fSManuel Lauss else 1639a9b71a8fSManuel Lauss print_warn("Unsupported option \"%s\"", this_opt); 1640a9b71a8fSManuel Lauss } 1641a9b71a8fSManuel Lauss 1642a9b71a8fSManuel Lauss out: 1643a9b71a8fSManuel Lauss return 0; 1644a9b71a8fSManuel Lauss } 1645a9b71a8fSManuel Lauss 1646a9b71a8fSManuel Lauss /* AU1200 LCD controller device driver */ 164748c68c4fSGreg Kroah-Hartman static int au1200fb_drv_probe(struct platform_device *dev) 1648f95ec3c6SRalf Baechle { 1649f95ec3c6SRalf Baechle struct au1200fb_device *fbdev; 1650a9b71a8fSManuel Lauss struct au1200fb_platdata *pd; 1651c329f606SManuel Lauss struct fb_info *fbi = NULL; 16521630d85aSManuel Lauss int bpp, plane, ret, irq; 1653f95ec3c6SRalf Baechle 1654a9b71a8fSManuel Lauss print_info("" DRIVER_DESC ""); 1655a9b71a8fSManuel Lauss 1656a9b71a8fSManuel Lauss pd = dev->dev.platform_data; 1657a9b71a8fSManuel Lauss if (!pd) 1658a9b71a8fSManuel Lauss return -ENODEV; 1659a9b71a8fSManuel Lauss 1660a9b71a8fSManuel Lauss /* Setup driver with options */ 1661a9b71a8fSManuel Lauss if (au1200fb_setup(pd)) 1662a9b71a8fSManuel Lauss return -ENODEV; 1663a9b71a8fSManuel Lauss 1664a9b71a8fSManuel Lauss /* Point to the panel selected */ 1665a9b71a8fSManuel Lauss panel = &known_lcd_panels[panel_index]; 1666a9b71a8fSManuel Lauss win = &windows[window_index]; 1667a9b71a8fSManuel Lauss 1668a9b71a8fSManuel Lauss printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); 1669a9b71a8fSManuel Lauss printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); 1670a9b71a8fSManuel Lauss 16718be90b07SManuel Lauss for (plane = 0; plane < device_count; ++plane) { 1672f95ec3c6SRalf Baechle bpp = winbpp(win->w[plane].mode_winctrl1); 1673f95ec3c6SRalf Baechle if (win->w[plane].xres == 0) 1674f95ec3c6SRalf Baechle win->w[plane].xres = panel->Xres; 1675f95ec3c6SRalf Baechle if (win->w[plane].yres == 0) 1676f95ec3c6SRalf Baechle win->w[plane].yres = panel->Yres; 1677f95ec3c6SRalf Baechle 1678c329f606SManuel Lauss fbi = framebuffer_alloc(sizeof(struct au1200fb_device), 1679c329f606SManuel Lauss &dev->dev); 16808cae353eSChristophe JAILLET if (!fbi) { 16818cae353eSChristophe JAILLET ret = -ENOMEM; 1682c329f606SManuel Lauss goto failed; 16838cae353eSChristophe JAILLET } 1684c329f606SManuel Lauss 1685c329f606SManuel Lauss _au1200fb_infos[plane] = fbi; 1686c329f606SManuel Lauss fbdev = fbi->par; 1687c329f606SManuel Lauss fbdev->fb_info = fbi; 1688a9b71a8fSManuel Lauss fbdev->pd = pd; 1689e0b29902SChristoph Hellwig fbdev->dev = &dev->dev; 1690c329f606SManuel Lauss 1691f95ec3c6SRalf Baechle fbdev->plane = plane; 1692f95ec3c6SRalf Baechle 1693f95ec3c6SRalf Baechle /* Allocate the framebuffer to the maximum screen size */ 1694f95ec3c6SRalf Baechle fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8; 1695f95ec3c6SRalf Baechle 169663d36c95SChristoph Hellwig fbdev->fb_mem = dmam_alloc_attrs(&dev->dev, 1697f95ec3c6SRalf Baechle PAGE_ALIGN(fbdev->fb_len), 16985ae01cbaSChristoph Hellwig &fbdev->fb_phys, GFP_KERNEL, 0); 1699f95ec3c6SRalf Baechle if (!fbdev->fb_mem) { 17003879490fSColin Ian King print_err("fail to allocate framebuffer (size: %dK))", 1701f95ec3c6SRalf Baechle fbdev->fb_len / 1024); 1702451f1306SChristophe JAILLET ret = -ENOMEM; 1703451f1306SChristophe JAILLET goto failed; 1704f95ec3c6SRalf Baechle } 1705f95ec3c6SRalf Baechle 1706f95ec3c6SRalf Baechle print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); 1707f95ec3c6SRalf Baechle print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); 1708f95ec3c6SRalf Baechle 1709f95ec3c6SRalf Baechle /* Init FB data */ 1710ab798b90SChristophe JAILLET ret = au1200fb_init_fbinfo(fbdev); 1711ab798b90SChristophe JAILLET if (ret < 0) 1712f95ec3c6SRalf Baechle goto failed; 1713f95ec3c6SRalf Baechle 1714f95ec3c6SRalf Baechle /* Register new framebuffer */ 1715c329f606SManuel Lauss ret = register_framebuffer(fbi); 1716c329f606SManuel Lauss if (ret < 0) { 1717f95ec3c6SRalf Baechle print_err("cannot register new framebuffer"); 1718f95ec3c6SRalf Baechle goto failed; 1719f95ec3c6SRalf Baechle } 1720f95ec3c6SRalf Baechle 1721c329f606SManuel Lauss au1200fb_fb_set_par(fbi); 1722f95ec3c6SRalf Baechle 1723f95ec3c6SRalf Baechle #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) 1724f95ec3c6SRalf Baechle if (plane == 0) 1725c329f606SManuel Lauss if (fb_prepare_logo(fbi, FB_ROTATE_UR)) { 1726f95ec3c6SRalf Baechle /* Start display and show logo on boot */ 1727c329f606SManuel Lauss fb_set_cmap(&fbi->cmap, fbi); 1728c329f606SManuel Lauss fb_show_logo(fbi, FB_ROTATE_UR); 1729f95ec3c6SRalf Baechle } 1730f95ec3c6SRalf Baechle #endif 1731f95ec3c6SRalf Baechle } 1732f95ec3c6SRalf Baechle 1733f95ec3c6SRalf Baechle /* Now hook interrupt too */ 17341630d85aSManuel Lauss irq = platform_get_irq(dev, 0); 17351630d85aSManuel Lauss ret = request_irq(irq, au1200fb_handle_irq, 1736f8798ccbSYong Zhang IRQF_SHARED, "lcd", (void *)dev); 17371630d85aSManuel Lauss if (ret) { 1738f95ec3c6SRalf Baechle print_err("fail to request interrupt line %d (err: %d)", 17391630d85aSManuel Lauss irq, ret); 1740f95ec3c6SRalf Baechle goto failed; 1741f95ec3c6SRalf Baechle } 1742f95ec3c6SRalf Baechle 1743a9b71a8fSManuel Lauss platform_set_drvdata(dev, pd); 1744a9b71a8fSManuel Lauss 1745a9b71a8fSManuel Lauss /* Kickstart the panel */ 1746a9b71a8fSManuel Lauss au1200_setpanel(panel, pd); 1747a9b71a8fSManuel Lauss 1748f95ec3c6SRalf Baechle return 0; 1749f95ec3c6SRalf Baechle 1750f95ec3c6SRalf Baechle failed: 17516bbbb680SChristophe JAILLET for (plane = 0; plane < device_count; ++plane) { 17526bbbb680SChristophe JAILLET fbi = _au1200fb_infos[plane]; 17536bbbb680SChristophe JAILLET if (!fbi) 17546bbbb680SChristophe JAILLET break; 17556bbbb680SChristophe JAILLET 17566bbbb680SChristophe JAILLET /* Clean up all probe data */ 17576bbbb680SChristophe JAILLET unregister_framebuffer(fbi); 1758c329f606SManuel Lauss if (fbi->cmap.len != 0) 1759c329f606SManuel Lauss fb_dealloc_cmap(&fbi->cmap); 1760c329f606SManuel Lauss kfree(fbi->pseudo_palette); 17616bbbb680SChristophe JAILLET 17626bbbb680SChristophe JAILLET framebuffer_release(fbi); 17636bbbb680SChristophe JAILLET _au1200fb_infos[plane] = NULL; 1764c329f606SManuel Lauss } 1765f95ec3c6SRalf Baechle return ret; 1766f95ec3c6SRalf Baechle } 1767f95ec3c6SRalf Baechle 176848c68c4fSGreg Kroah-Hartman static int au1200fb_drv_remove(struct platform_device *dev) 1769f95ec3c6SRalf Baechle { 1770a9b71a8fSManuel Lauss struct au1200fb_platdata *pd = platform_get_drvdata(dev); 1771c329f606SManuel Lauss struct fb_info *fbi; 1772f95ec3c6SRalf Baechle int plane; 1773f95ec3c6SRalf Baechle 1774f95ec3c6SRalf Baechle /* Turn off the panel */ 1775a9b71a8fSManuel Lauss au1200_setpanel(NULL, pd); 1776f95ec3c6SRalf Baechle 17778be90b07SManuel Lauss for (plane = 0; plane < device_count; ++plane) { 1778c329f606SManuel Lauss fbi = _au1200fb_infos[plane]; 1779f95ec3c6SRalf Baechle 1780f95ec3c6SRalf Baechle /* Clean up all probe data */ 1781c329f606SManuel Lauss unregister_framebuffer(fbi); 1782c329f606SManuel Lauss if (fbi->cmap.len != 0) 1783c329f606SManuel Lauss fb_dealloc_cmap(&fbi->cmap); 1784c329f606SManuel Lauss kfree(fbi->pseudo_palette); 1785c329f606SManuel Lauss 1786c329f606SManuel Lauss framebuffer_release(fbi); 1787c329f606SManuel Lauss _au1200fb_infos[plane] = NULL; 1788f95ec3c6SRalf Baechle } 1789f95ec3c6SRalf Baechle 17901630d85aSManuel Lauss free_irq(platform_get_irq(dev, 0), (void *)dev); 1791f95ec3c6SRalf Baechle 1792f95ec3c6SRalf Baechle return 0; 1793f95ec3c6SRalf Baechle } 1794f95ec3c6SRalf Baechle 1795f95ec3c6SRalf Baechle #ifdef CONFIG_PM 179698707fccSManuel Lauss static int au1200fb_drv_suspend(struct device *dev) 1797f95ec3c6SRalf Baechle { 1798a9b71a8fSManuel Lauss struct au1200fb_platdata *pd = dev_get_drvdata(dev); 1799a9b71a8fSManuel Lauss au1200_setpanel(NULL, pd); 180098707fccSManuel Lauss 180198707fccSManuel Lauss lcd->outmask = 0; 18022f73bfbeSManuel Lauss wmb(); /* drain writebuffer */ 180398707fccSManuel Lauss 1804f95ec3c6SRalf Baechle return 0; 1805f95ec3c6SRalf Baechle } 1806f95ec3c6SRalf Baechle 180798707fccSManuel Lauss static int au1200fb_drv_resume(struct device *dev) 1808f95ec3c6SRalf Baechle { 1809a9b71a8fSManuel Lauss struct au1200fb_platdata *pd = dev_get_drvdata(dev); 181098707fccSManuel Lauss struct fb_info *fbi; 181198707fccSManuel Lauss int i; 181298707fccSManuel Lauss 181398707fccSManuel Lauss /* Kickstart the panel */ 1814a9b71a8fSManuel Lauss au1200_setpanel(panel, pd); 181598707fccSManuel Lauss 18168be90b07SManuel Lauss for (i = 0; i < device_count; i++) { 181798707fccSManuel Lauss fbi = _au1200fb_infos[i]; 181898707fccSManuel Lauss au1200fb_fb_set_par(fbi); 181998707fccSManuel Lauss } 182098707fccSManuel Lauss 1821f95ec3c6SRalf Baechle return 0; 1822f95ec3c6SRalf Baechle } 182398707fccSManuel Lauss 182498707fccSManuel Lauss static const struct dev_pm_ops au1200fb_pmops = { 182598707fccSManuel Lauss .suspend = au1200fb_drv_suspend, 182698707fccSManuel Lauss .resume = au1200fb_drv_resume, 182798707fccSManuel Lauss .freeze = au1200fb_drv_suspend, 182898707fccSManuel Lauss .thaw = au1200fb_drv_resume, 182998707fccSManuel Lauss }; 183098707fccSManuel Lauss 183198707fccSManuel Lauss #define AU1200FB_PMOPS (&au1200fb_pmops) 183298707fccSManuel Lauss 183398707fccSManuel Lauss #else 183498707fccSManuel Lauss #define AU1200FB_PMOPS NULL 1835f95ec3c6SRalf Baechle #endif /* CONFIG_PM */ 1836f95ec3c6SRalf Baechle 18377a192ec3SMing Lei static struct platform_driver au1200fb_driver = { 18387a192ec3SMing Lei .driver = { 1839f95ec3c6SRalf Baechle .name = "au1200-lcd", 184098707fccSManuel Lauss .pm = AU1200FB_PMOPS, 18417a192ec3SMing Lei }, 1842f95ec3c6SRalf Baechle .probe = au1200fb_drv_probe, 184348c68c4fSGreg Kroah-Hartman .remove = au1200fb_drv_remove, 1844f95ec3c6SRalf Baechle }; 1845d07b3191SHanjun Guo module_platform_driver(au1200fb_driver); 1846f95ec3c6SRalf Baechle 1847f95ec3c6SRalf Baechle MODULE_DESCRIPTION(DRIVER_DESC); 1848f95ec3c6SRalf Baechle MODULE_LICENSE("GPL"); 1849