186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* 286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * Copyright (C) 2008 386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de> 486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * 586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. 686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * 786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * This program is free software; you can redistribute it and/or modify 886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * it under the terms of the GNU General Public License version 2 as 986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * published by the Free Software Foundation. 1086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 1186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 1286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/module.h> 1386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/kernel.h> 1486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/platform_device.h> 1586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/sched.h> 1686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/errno.h> 1786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/string.h> 1886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/interrupt.h> 1986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/slab.h> 2086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/fb.h> 2186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/delay.h> 2286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/init.h> 2386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/ioport.h> 2486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/dma-mapping.h> 2586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/dmaengine.h> 2686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/console.h> 2786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/clk.h> 2886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <linux/mutex.h> 2986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 301b346af2f88a0e19e718a843d39d34e41e5527e1Sascha Hauer#include <mach/dma.h> 3186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <mach/hardware.h> 3286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <mach/ipu.h> 3386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <mach/mx3fb.h> 3486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 3586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <asm/io.h> 3686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#include <asm/uaccess.h> 3786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 386e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define MX3FB_NAME "mx3_sdc_fb" 3986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 406e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define MX3FB_REG_OFFSET 0xB4 4186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 4286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* SDC Registers */ 436e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_COM_CONF (0xB4 - MX3FB_REG_OFFSET) 446e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_GW_CTRL (0xB8 - MX3FB_REG_OFFSET) 456e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_FG_POS (0xBC - MX3FB_REG_OFFSET) 466e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_BG_POS (0xC0 - MX3FB_REG_OFFSET) 476e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_CUR_POS (0xC4 - MX3FB_REG_OFFSET) 486e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_PWM_CTRL (0xC8 - MX3FB_REG_OFFSET) 496e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_CUR_MAP (0xCC - MX3FB_REG_OFFSET) 506e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_HOR_CONF (0xD0 - MX3FB_REG_OFFSET) 516e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_VER_CONF (0xD4 - MX3FB_REG_OFFSET) 526e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_SHARP_CONF_1 (0xD8 - MX3FB_REG_OFFSET) 536e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_SHARP_CONF_2 (0xDC - MX3FB_REG_OFFSET) 5486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 5586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* Register bits */ 566e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_COM_TFT_COLOR 0x00000001UL 576e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_COM_FG_EN 0x00000010UL 586e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_COM_GWSEL 0x00000020UL 596e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_COM_GLB_A 0x00000040UL 606e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_COM_KEY_COLOR_G 0x00000080UL 616e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_COM_BG_EN 0x00000200UL 626e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_COM_SHARP 0x00001000UL 6386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 646e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define SDC_V_SYNC_WIDTH_L 0x00000001UL 6586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 6686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* Display Interface registers */ 676e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP_IF_CONF (0x0124 - MX3FB_REG_OFFSET) 686e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP_SIG_POL (0x0128 - MX3FB_REG_OFFSET) 696e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_SER_DISP1_CONF (0x012C - MX3FB_REG_OFFSET) 706e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_SER_DISP2_CONF (0x0130 - MX3FB_REG_OFFSET) 716e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_HSP_CLK_PER (0x0134 - MX3FB_REG_OFFSET) 726e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP0_TIME_CONF_1 (0x0138 - MX3FB_REG_OFFSET) 736e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP0_TIME_CONF_2 (0x013C - MX3FB_REG_OFFSET) 746e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP0_TIME_CONF_3 (0x0140 - MX3FB_REG_OFFSET) 756e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP1_TIME_CONF_1 (0x0144 - MX3FB_REG_OFFSET) 766e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP1_TIME_CONF_2 (0x0148 - MX3FB_REG_OFFSET) 776e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP1_TIME_CONF_3 (0x014C - MX3FB_REG_OFFSET) 786e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP2_TIME_CONF_1 (0x0150 - MX3FB_REG_OFFSET) 796e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP2_TIME_CONF_2 (0x0154 - MX3FB_REG_OFFSET) 806e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP2_TIME_CONF_3 (0x0158 - MX3FB_REG_OFFSET) 816e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP3_TIME_CONF (0x015C - MX3FB_REG_OFFSET) 826e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP0_DB0_MAP (0x0160 - MX3FB_REG_OFFSET) 836e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP0_DB1_MAP (0x0164 - MX3FB_REG_OFFSET) 846e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP0_DB2_MAP (0x0168 - MX3FB_REG_OFFSET) 856e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP0_CB0_MAP (0x016C - MX3FB_REG_OFFSET) 866e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP0_CB1_MAP (0x0170 - MX3FB_REG_OFFSET) 876e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP0_CB2_MAP (0x0174 - MX3FB_REG_OFFSET) 886e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP1_DB0_MAP (0x0178 - MX3FB_REG_OFFSET) 896e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP1_DB1_MAP (0x017C - MX3FB_REG_OFFSET) 906e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP1_DB2_MAP (0x0180 - MX3FB_REG_OFFSET) 916e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP1_CB0_MAP (0x0184 - MX3FB_REG_OFFSET) 926e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP1_CB1_MAP (0x0188 - MX3FB_REG_OFFSET) 936e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP1_CB2_MAP (0x018C - MX3FB_REG_OFFSET) 946e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP2_DB0_MAP (0x0190 - MX3FB_REG_OFFSET) 956e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP2_DB1_MAP (0x0194 - MX3FB_REG_OFFSET) 966e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP2_DB2_MAP (0x0198 - MX3FB_REG_OFFSET) 976e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP2_CB0_MAP (0x019C - MX3FB_REG_OFFSET) 986e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP2_CB1_MAP (0x01A0 - MX3FB_REG_OFFSET) 996e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP2_CB2_MAP (0x01A4 - MX3FB_REG_OFFSET) 1006e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP3_B0_MAP (0x01A8 - MX3FB_REG_OFFSET) 1016e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP3_B1_MAP (0x01AC - MX3FB_REG_OFFSET) 1026e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP3_B2_MAP (0x01B0 - MX3FB_REG_OFFSET) 1036e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP_ACC_CC (0x01B4 - MX3FB_REG_OFFSET) 1046e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP_LLA_CONF (0x01B8 - MX3FB_REG_OFFSET) 1056e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_DISP_LLA_DATA (0x01BC - MX3FB_REG_OFFSET) 10686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 10786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* DI_DISP_SIG_POL bits */ 1086e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_D3_VSYNC_POL_SHIFT 28 1096e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_D3_HSYNC_POL_SHIFT 27 1106e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_D3_DRDY_SHARP_POL_SHIFT 26 1116e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_D3_CLK_POL_SHIFT 25 1126e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_D3_DATA_POL_SHIFT 24 11386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 11486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* DI_DISP_IF_CONF bits */ 1156e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_D3_CLK_IDLE_SHIFT 26 1166e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_D3_CLK_SEL_SHIFT 25 1176e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski#define DI_D3_DATAMSK_SHIFT 24 11886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 11986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskienum ipu_panel { 1206e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski IPU_PANEL_SHARP_TFT, 1216e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski IPU_PANEL_TFT, 12286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski}; 12386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 12486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistruct ipu_di_signal_cfg { 1256e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned datamask_en:1; 1266e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned clksel_en:1; 1276e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned clkidle_en:1; 1286e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned data_pol:1; /* true = inverted */ 1296e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned clk_pol:1; /* true = rising edge */ 1306e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned enable_pol:1; 1316e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned Hsync_pol:1; /* true = active high */ 1326e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned Vsync_pol:1; 13386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski}; 13486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic const struct fb_videomode mx3fb_modedb[] = { 1366e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski { 1376e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* 240x320 @ 60 Hz */ 1386e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .name = "Sharp-QVGA", 1396e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .refresh = 60, 1406e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .xres = 240, 1416e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .yres = 320, 1426e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .pixclock = 185925, 1436e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .left_margin = 9, 1446e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .right_margin = 16, 1456e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .upper_margin = 7, 1466e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .lower_margin = 9, 1476e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .hsync_len = 1, 1486e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .vsync_len = 1, 1496e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE | 1506e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski FB_SYNC_CLK_INVERT | FB_SYNC_DATA_INVERT | 1516e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski FB_SYNC_CLK_IDLE_EN, 1526e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .vmode = FB_VMODE_NONINTERLACED, 1536e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .flag = 0, 1546e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski }, { 1556e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* 240x33 @ 60 Hz */ 1566e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .name = "Sharp-CLI", 1576e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .refresh = 60, 1586e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .xres = 240, 1596e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .yres = 33, 1606e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .pixclock = 185925, 1616e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .left_margin = 9, 1626e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .right_margin = 16, 1636e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .upper_margin = 7, 1646e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .lower_margin = 9 + 287, 1656e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .hsync_len = 1, 1666e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .vsync_len = 1, 1676e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE | 1686e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski FB_SYNC_CLK_INVERT | FB_SYNC_DATA_INVERT | 1696e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski FB_SYNC_CLK_IDLE_EN, 1706e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .vmode = FB_VMODE_NONINTERLACED, 1716e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .flag = 0, 1726e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski }, { 1736e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* 640x480 @ 60 Hz */ 1746e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .name = "NEC-VGA", 1756e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .refresh = 60, 1766e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .xres = 640, 1776e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .yres = 480, 1786e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .pixclock = 38255, 1796e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .left_margin = 144, 1806e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .right_margin = 0, 1816e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .upper_margin = 34, 1826e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .lower_margin = 40, 1836e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .hsync_len = 1, 1846e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .vsync_len = 1, 1856e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH, 1866e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .vmode = FB_VMODE_NONINTERLACED, 1876e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .flag = 0, 1886e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski }, { 1896e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* NTSC TV output */ 1906e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .name = "TV-NTSC", 1916e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .refresh = 60, 1926e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .xres = 640, 1936e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .yres = 480, 1946e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .pixclock = 37538, 1956e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .left_margin = 38, 1966e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .right_margin = 858 - 640 - 38 - 3, 1976e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .upper_margin = 36, 1986e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .lower_margin = 518 - 480 - 36 - 1, 1996e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .hsync_len = 3, 2006e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .vsync_len = 1, 2016e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .sync = 0, 2026e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .vmode = FB_VMODE_NONINTERLACED, 2036e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .flag = 0, 2046e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski }, { 2056e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* PAL TV output */ 2066e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .name = "TV-PAL", 2076e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .refresh = 50, 2086e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .xres = 640, 2096e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .yres = 480, 2106e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .pixclock = 37538, 2116e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .left_margin = 38, 2126e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .right_margin = 960 - 640 - 38 - 32, 2136e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .upper_margin = 32, 2146e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .lower_margin = 555 - 480 - 32 - 3, 2156e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .hsync_len = 32, 2166e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .vsync_len = 3, 2176e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .sync = 0, 2186e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .vmode = FB_VMODE_NONINTERLACED, 2196e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .flag = 0, 2206e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski }, { 2216e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* TV output VGA mode, 640x480 @ 65 Hz */ 2226e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .name = "TV-VGA", 2236e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .refresh = 60, 2246e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .xres = 640, 2256e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .yres = 480, 2266e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .pixclock = 40574, 2276e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .left_margin = 35, 2286e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .right_margin = 45, 2296e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .upper_margin = 9, 2306e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .lower_margin = 1, 2316e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .hsync_len = 46, 2326e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .vsync_len = 5, 2336e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .sync = 0, 2346e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .vmode = FB_VMODE_NONINTERLACED, 2356e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .flag = 0, 2366e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski }, 23786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski}; 23886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 23986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistruct mx3fb_data { 2406e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct fb_info *fbi; 2416e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski int backlight_level; 2426e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski void __iomem *reg_base; 2436e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski spinlock_t lock; 2446e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct device *dev; 2456e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 2466e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint32_t h_start_width; 2476e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint32_t v_start_width; 248f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer enum disp_data_mapping disp_data_fmt; 24986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski}; 25086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 25186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistruct dma_chan_request { 2526e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_data *mx3fb; 2536e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski enum ipu_channel id; 25486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski}; 25586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 25686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* MX3 specific framebuffer information. */ 25786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistruct mx3fb_info { 2586e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski int blank; 2596e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski enum ipu_channel ipu_ch; 2606e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint32_t cur_ipu_buf; 26186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 2626e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski u32 pseudo_palette[16]; 26386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 2646e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct completion flip_cmpl; 2656e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mutex mutex; /* Protects fb-ops */ 2666e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_data *mx3fb; 2676e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct idmac_channel *idmac_channel; 2686e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct dma_async_tx_descriptor *txd; 2696e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dma_cookie_t cookie; 2706e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct scatterlist sg[2]; 27186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 2726e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski u32 sync; /* preserve var->sync flags */ 27386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski}; 27486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 27586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic void mx3fb_dma_done(void *); 27686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 27786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* Used fb-mode and bpp. Can be set on kernel command line, therefore file-static. */ 27886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic const char *fb_mode; 27986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic unsigned long default_bpp = 16; 28086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 28186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic u32 mx3fb_read_reg(struct mx3fb_data *mx3fb, unsigned long reg) 28286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 2836e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return __raw_readl(mx3fb->reg_base + reg); 28486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 28586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 28686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic void mx3fb_write_reg(struct mx3fb_data *mx3fb, u32 value, unsigned long reg) 28786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 2886e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski __raw_writel(value, mx3fb->reg_base + reg); 28986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 29086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 291f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauerstruct di_mapping { 292f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer uint32_t b0, b1, b2; 293f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer}; 294f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer 295f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauerstatic const struct di_mapping di_mappings[] = { 296f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer [IPU_DISP_DATA_MAPPING_RGB666] = { 0x0005000f, 0x000b000f, 0x0011000f }, 297f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer [IPU_DISP_DATA_MAPPING_RGB565] = { 0x0004003f, 0x000a000f, 0x000f003f }, 298f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer [IPU_DISP_DATA_MAPPING_RGB888] = { 0x00070000, 0x000f0000, 0x00170000 }, 29986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski}; 30086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 30186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic void sdc_fb_init(struct mx3fb_info *fbi) 30286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 3036e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_data *mx3fb = fbi->mx3fb; 3046e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint32_t reg; 30586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 3066e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF); 30786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 3086e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, reg | SDC_COM_BG_EN, SDC_COM_CONF); 30986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 31086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 31186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* Returns enabled flag before uninit */ 31286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic uint32_t sdc_fb_uninit(struct mx3fb_info *fbi) 31386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 3146e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_data *mx3fb = fbi->mx3fb; 3156e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint32_t reg; 31686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 3176e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF); 31886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 3196e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, reg & ~SDC_COM_BG_EN, SDC_COM_CONF); 32086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 3216e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return reg & SDC_COM_BG_EN; 32286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 32386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 32486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic void sdc_enable_channel(struct mx3fb_info *mx3_fbi) 32586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 3266e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; 3276e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct idmac_channel *ichan = mx3_fbi->idmac_channel; 3286e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct dma_chan *dma_chan = &ichan->dma_chan; 3296e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned long flags; 3306e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dma_cookie_t cookie; 3316e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 332b3cb53721890879d7bde31f5f9eefd4edf41ab64Alberto Panizzo if (mx3_fbi->txd) 333b3cb53721890879d7bde31f5f9eefd4edf41ab64Alberto Panizzo dev_dbg(mx3fb->dev, "mx3fbi %p, desc %p, sg %p\n", mx3_fbi, 334b3cb53721890879d7bde31f5f9eefd4edf41ab64Alberto Panizzo to_tx_desc(mx3_fbi->txd), to_tx_desc(mx3_fbi->txd)->sg); 335b3cb53721890879d7bde31f5f9eefd4edf41ab64Alberto Panizzo else 336b3cb53721890879d7bde31f5f9eefd4edf41ab64Alberto Panizzo dev_dbg(mx3fb->dev, "mx3fbi %p, txd = NULL\n", mx3_fbi); 3376e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 3386e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* This enables the channel */ 3396e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (mx3_fbi->cookie < 0) { 3406e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->txd = dma_chan->device->device_prep_slave_sg(dma_chan, 3411003cab8276cd34d9deab8ca9d148ee59f7728a7Vinod Koul &mx3_fbi->sg[0], 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); 3426e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!mx3_fbi->txd) { 3436e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_err(mx3fb->dev, "Cannot allocate descriptor on %d\n", 3446e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dma_chan->chan_id); 3456e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return; 3466e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 3476e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 3486e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->txd->callback_param = mx3_fbi->txd; 3496e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->txd->callback = mx3fb_dma_done; 3506e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 3516e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski cookie = mx3_fbi->txd->tx_submit(mx3_fbi->txd); 3526e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(mx3fb->dev, "%d: Submit %p #%d [%c]\n", __LINE__, 3536e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->txd, cookie, list_empty(&ichan->queue) ? '-' : '+'); 3546e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } else { 3556e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!mx3_fbi->txd || !mx3_fbi->txd->tx_submit) { 3566e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_err(mx3fb->dev, "Cannot enable channel %d\n", 3576e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dma_chan->chan_id); 3586e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return; 3596e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 3606e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 3616e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* Just re-activate the same buffer */ 3626e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dma_async_issue_pending(dma_chan); 3636e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski cookie = mx3_fbi->cookie; 3646e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(mx3fb->dev, "%d: Re-submit %p #%d [%c]\n", __LINE__, 3656e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->txd, cookie, list_empty(&ichan->queue) ? '-' : '+'); 3666e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 3676e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 3686e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (cookie >= 0) { 3696e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski spin_lock_irqsave(&mx3fb->lock, flags); 3706e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_fb_init(mx3_fbi); 3716e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->cookie = cookie; 3726e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski spin_unlock_irqrestore(&mx3fb->lock, flags); 3736e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 3746e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 3756e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* 3766e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * Attention! Without this msleep the channel keeps generating 3776e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * interrupts. Next sdc_set_brightness() is going to be called 3786e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * from mx3fb_blank(). 3796e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski */ 3806e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski msleep(2); 38186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 38286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 38386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic void sdc_disable_channel(struct mx3fb_info *mx3_fbi) 38486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 3856e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; 3866e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint32_t enabled; 3876e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned long flags; 38886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 3898b53b7fb57e1ce3441b1a32f8374874b53c4bc31Wolfram Stering if (mx3_fbi->txd == NULL) 3908b53b7fb57e1ce3441b1a32f8374874b53c4bc31Wolfram Stering return; 3918b53b7fb57e1ce3441b1a32f8374874b53c4bc31Wolfram Stering 3926e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski spin_lock_irqsave(&mx3fb->lock, flags); 39386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 3946e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski enabled = sdc_fb_uninit(mx3_fbi); 39586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 3966e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski spin_unlock_irqrestore(&mx3fb->lock, flags); 39786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 398c3635c78e500a52c9fcd55de381a72928d9e054dLinus Walleij mx3_fbi->txd->chan->device->device_control(mx3_fbi->txd->chan, 399058276303dbc4ed089c1f7dad0871810b1f5ddf1Linus Walleij DMA_TERMINATE_ALL, 0); 4006e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->txd = NULL; 4016e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->cookie = -EINVAL; 40286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 40386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 40486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/** 40586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * sdc_set_window_pos() - set window position of the respective plane. 4066e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @mx3fb: mx3fb context. 4076e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @channel: IPU DMAC channel ID. 4086e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @x_pos: X coordinate relative to the top left corner to place window at. 4096e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @y_pos: Y coordinate relative to the top left corner to place window at. 4106e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @return: 0 on success or negative error code on failure. 41186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 41286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel, 4136e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski int16_t x_pos, int16_t y_pos) 41486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 4156e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (channel != IDMAC_SDC_0) 4166e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return -EINVAL; 41786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 418d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski x_pos += mx3fb->h_start_width; 419d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski y_pos += mx3fb->v_start_width; 420d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski 4216e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, (x_pos << 16) | y_pos, SDC_BG_POS); 4226e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 42386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 42486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 42586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/** 42686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * sdc_init_panel() - initialize a synchronous LCD panel. 4276e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @mx3fb: mx3fb context. 4286e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @panel: panel type. 4296e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @pixel_clk: desired pixel clock frequency in Hz. 4306e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @width: width of panel in pixels. 4316e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @height: height of panel in pixels. 4326e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @h_start_width: number of pixel clocks between the HSYNC signal pulse 4336e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * and the start of valid data. 4346e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @h_sync_width: width of the HSYNC signal in units of pixel clocks. 4356e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @h_end_width: number of pixel clocks between the end of valid data 4366e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * and the HSYNC signal for next line. 4376e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @v_start_width: number of lines between the VSYNC signal pulse and the 4386e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * start of valid data. 4396e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @v_sync_width: width of the VSYNC signal in units of lines 4406e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @v_end_width: number of lines between the end of valid data and the 4416e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * VSYNC signal for next frame. 4426e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @sig: bitfield of signal polarities for LCD interface. 4436e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @return: 0 on success or negative error code on failure. 44486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 44586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel, 4466e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint32_t pixel_clk, 4476e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint16_t width, uint16_t height, 4486e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint16_t h_start_width, uint16_t h_sync_width, 4496e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint16_t h_end_width, uint16_t v_start_width, 4506e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint16_t v_sync_width, uint16_t v_end_width, 4516e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct ipu_di_signal_cfg sig) 45286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 4536e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned long lock_flags; 4546e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint32_t reg; 4556e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint32_t old_conf; 4566e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint32_t div; 4576e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct clk *ipu_clk; 458f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer const struct di_mapping *map; 45986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 4606e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(mx3fb->dev, "panel size = %d x %d", width, height); 46186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 4626e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (v_sync_width == 0 || h_sync_width == 0) 4636e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return -EINVAL; 46486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 4656e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* Init panel size and blanking periods */ 4666e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski reg = ((uint32_t) (h_sync_width - 1) << 26) | 4676e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski ((uint32_t) (width + h_start_width + h_end_width - 1) << 16); 4686e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, reg, SDC_HOR_CONF); 46986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 47086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#ifdef DEBUG 4716e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski printk(KERN_CONT " hor_conf %x,", reg); 47286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#endif 47386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 4746e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski reg = ((uint32_t) (v_sync_width - 1) << 26) | SDC_V_SYNC_WIDTH_L | 4756e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski ((uint32_t) (height + v_start_width + v_end_width - 1) << 16); 4766e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, reg, SDC_VER_CONF); 47786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 47886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#ifdef DEBUG 4796e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski printk(KERN_CONT " ver_conf %x\n", reg); 48086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#endif 48186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 4826e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb->h_start_width = h_start_width; 4836e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb->v_start_width = v_start_width; 4846e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 4856e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski switch (panel) { 4866e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case IPU_PANEL_SHARP_TFT: 4876e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, 0x00FD0102L, SDC_SHARP_CONF_1); 4886e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, 0x00F500F4L, SDC_SHARP_CONF_2); 4896e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, SDC_COM_SHARP | SDC_COM_TFT_COLOR, SDC_COM_CONF); 4906e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski break; 4916e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case IPU_PANEL_TFT: 4926e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, SDC_COM_TFT_COLOR, SDC_COM_CONF); 4936e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski break; 4946e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski default: 4956e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return -EINVAL; 4966e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 4976e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 4986e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* Init clocking */ 4996e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 5006e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* 5016e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * Calculate divider: fractional part is 4 bits so simply multiple by 5026e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * 2^4 to get fractional part, as long as we stay under ~250MHz and on 5036e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * i.MX31 it (HSP_CLK) is <= 178MHz. Currently 128.267MHz 5046e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski */ 5053879f5d6f03b66626af014cbb6071ad4d79b1c42Russell King ipu_clk = clk_get(mx3fb->dev, NULL); 506d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski if (!IS_ERR(ipu_clk)) { 507d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski div = clk_get_rate(ipu_clk) * 16 / pixel_clk; 508d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski clk_put(ipu_clk); 509d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski } else { 510d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski div = 0; 511d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski } 5126e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 5136e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (div < 0x40) { /* Divider less than 4 */ 5146e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(mx3fb->dev, 5156e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski "InitPanel() - Pixel clock divider less than 4\n"); 5166e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski div = 0x40; 5176e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 5186e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 519d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski dev_dbg(mx3fb->dev, "pixel clk = %u, divider %u.%u\n", 520d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski pixel_clk, div >> 4, (div & 7) * 125); 521d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski 5226e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski spin_lock_irqsave(&mx3fb->lock, lock_flags); 5236e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 5246e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* 5256e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * DISP3_IF_CLK_DOWN_WR is half the divider value and 2 fraction bits 5266e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * fewer. Subtract 1 extra from DISP3_IF_CLK_DOWN_WR based on timing 5276e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * debug. DISP3_IF_CLK_UP_WR is 0 5286e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski */ 5296e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, (((div / 8) - 1) << 22) | div, DI_DISP3_TIME_CONF); 5306e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 5316e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* DI settings */ 5326e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski old_conf = mx3fb_read_reg(mx3fb, DI_DISP_IF_CONF) & 0x78FFFFFF; 5336e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski old_conf |= sig.datamask_en << DI_D3_DATAMSK_SHIFT | 534d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski sig.clksel_en << DI_D3_CLK_SEL_SHIFT | 535d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski sig.clkidle_en << DI_D3_CLK_IDLE_SHIFT; 5366e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, old_conf, DI_DISP_IF_CONF); 5376e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 5386e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski old_conf = mx3fb_read_reg(mx3fb, DI_DISP_SIG_POL) & 0xE0FFFFFF; 5396e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski old_conf |= sig.data_pol << DI_D3_DATA_POL_SHIFT | 540d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski sig.clk_pol << DI_D3_CLK_POL_SHIFT | 541d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski sig.enable_pol << DI_D3_DRDY_SHARP_POL_SHIFT | 542d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski sig.Hsync_pol << DI_D3_HSYNC_POL_SHIFT | 543d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski sig.Vsync_pol << DI_D3_VSYNC_POL_SHIFT; 5446e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, old_conf, DI_DISP_SIG_POL); 5456e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 546f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer map = &di_mappings[mx3fb->disp_data_fmt]; 547f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer mx3fb_write_reg(mx3fb, map->b0, DI_DISP3_B0_MAP); 548f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer mx3fb_write_reg(mx3fb, map->b1, DI_DISP3_B1_MAP); 549f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer mx3fb_write_reg(mx3fb, map->b2, DI_DISP3_B2_MAP); 5506e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 5516e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski spin_unlock_irqrestore(&mx3fb->lock, lock_flags); 5526e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 5536e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(mx3fb->dev, "DI_DISP_IF_CONF = 0x%08X\n", 5546e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_read_reg(mx3fb, DI_DISP_IF_CONF)); 5556e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(mx3fb->dev, "DI_DISP_SIG_POL = 0x%08X\n", 5566e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_read_reg(mx3fb, DI_DISP_SIG_POL)); 5576e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(mx3fb->dev, "DI_DISP3_TIME_CONF = 0x%08X\n", 5586e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_read_reg(mx3fb, DI_DISP3_TIME_CONF)); 5596e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 5606e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 56186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 56286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 56386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/** 56486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * sdc_set_color_key() - set the transparent color key for SDC graphic plane. 5656e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @mx3fb: mx3fb context. 5666e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @channel: IPU DMAC channel ID. 5676e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @enable: boolean to enable or disable color keyl. 5686e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @color_key: 24-bit RGB color to use as transparent color key. 5696e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @return: 0 on success or negative error code on failure. 57086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 57186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int sdc_set_color_key(struct mx3fb_data *mx3fb, enum ipu_channel channel, 5726e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski bool enable, uint32_t color_key) 57386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 5746e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint32_t reg, sdc_conf; 5756e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned long lock_flags; 57686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 5776e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski spin_lock_irqsave(&mx3fb->lock, lock_flags); 57886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 5796e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_conf = mx3fb_read_reg(mx3fb, SDC_COM_CONF); 5806e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (channel == IDMAC_SDC_0) 5816e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_conf &= ~SDC_COM_GWSEL; 5826e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski else 5836e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_conf |= SDC_COM_GWSEL; 58486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 5856e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (enable) { 5866e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski reg = mx3fb_read_reg(mx3fb, SDC_GW_CTRL) & 0xFF000000L; 5876e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, reg | (color_key & 0x00FFFFFFL), 5886e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski SDC_GW_CTRL); 58986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 5906e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_conf |= SDC_COM_KEY_COLOR_G; 5916e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } else { 5926e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_conf &= ~SDC_COM_KEY_COLOR_G; 5936e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 5946e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, sdc_conf, SDC_COM_CONF); 59586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 5966e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski spin_unlock_irqrestore(&mx3fb->lock, lock_flags); 59786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 5986e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 59986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 60086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 60186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/** 60286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * sdc_set_global_alpha() - set global alpha blending modes. 6036e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @mx3fb: mx3fb context. 6046e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @enable: boolean to enable or disable global alpha blending. If disabled, 6056e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * per pixel blending is used. 6066e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @alpha: global alpha value. 6076e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @return: 0 on success or negative error code on failure. 60886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 60986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int sdc_set_global_alpha(struct mx3fb_data *mx3fb, bool enable, uint8_t alpha) 61086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 6116e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint32_t reg; 6126e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned long lock_flags; 61386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 6146e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski spin_lock_irqsave(&mx3fb->lock, lock_flags); 61586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 6166e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (enable) { 6176e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski reg = mx3fb_read_reg(mx3fb, SDC_GW_CTRL) & 0x00FFFFFFL; 6186e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, reg | ((uint32_t) alpha << 24), SDC_GW_CTRL); 61986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 6206e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF); 6216e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, reg | SDC_COM_GLB_A, SDC_COM_CONF); 6226e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } else { 6236e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF); 6246e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, reg & ~SDC_COM_GLB_A, SDC_COM_CONF); 6256e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 62686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 6276e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski spin_unlock_irqrestore(&mx3fb->lock, lock_flags); 62886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 6296e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 63086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 63186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 63286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value) 63386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 634b3cb53721890879d7bde31f5f9eefd4edf41ab64Alberto Panizzo dev_dbg(mx3fb->dev, "%s: value = %d\n", __func__, value); 6356e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* This might be board-specific */ 6366e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, 0x03000000UL | value << 16, SDC_PWM_CTRL); 6376e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return; 63886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 63986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 64086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic uint32_t bpp_to_pixfmt(int bpp) 64186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 6426e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski uint32_t pixfmt = 0; 6436e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski switch (bpp) { 6446e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case 24: 6456e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski pixfmt = IPU_PIX_FMT_BGR24; 6466e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski break; 6476e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case 32: 6486e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski pixfmt = IPU_PIX_FMT_BGR32; 6496e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski break; 6506e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case 16: 6516e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski pixfmt = IPU_PIX_FMT_RGB565; 6526e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski break; 6536e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 6546e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return pixfmt; 65586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 65686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 65786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int mx3fb_blank(int blank, struct fb_info *fbi); 65820de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetskistatic int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len, 65920de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski bool lock); 66086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int mx3fb_unmap_video_memory(struct fb_info *fbi); 66186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 66286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/** 66386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * mx3fb_set_fix() - set fixed framebuffer parameters from variable settings. 6646e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @info: framebuffer information pointer 6656e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @return: 0 on success or negative error code on failure. 66686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 66786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int mx3fb_set_fix(struct fb_info *fbi) 66886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 6696e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct fb_fix_screeninfo *fix = &fbi->fix; 6706e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct fb_var_screeninfo *var = &fbi->var; 67186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 6726e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski strncpy(fix->id, "DISP3 BG", 8); 67386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 6746e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; 67586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 6766e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fix->type = FB_TYPE_PACKED_PIXELS; 6776e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fix->accel = FB_ACCEL_NONE; 6786e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fix->visual = FB_VISUAL_TRUECOLOR; 6796e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fix->xpanstep = 1; 6806e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fix->ypanstep = 1; 68186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 6826e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 68386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 68486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 68586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic void mx3fb_dma_done(void *arg) 68686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 6876e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct idmac_tx_desc *tx_desc = to_tx_desc(arg); 6886e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct dma_chan *chan = tx_desc->txd.chan; 6896e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct idmac_channel *ichannel = to_idmac_chan(chan); 6906e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_data *mx3fb = ichannel->client; 6916e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_info *mx3_fbi = mx3fb->fbi->par; 69286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 6936e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(mx3fb->dev, "irq %d callback\n", ichannel->eof_irq); 69486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 6956e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* We only need one interrupt, it will be re-enabled as needed */ 696c8a4fb472c5101ec52f94b1e1277b8fde4b823cfGuennadi Liakhovetski disable_irq_nosync(ichannel->eof_irq); 69786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 6986e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski complete(&mx3_fbi->flip_cmpl); 69986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 70086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 70120de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetskistatic int __set_par(struct fb_info *fbi, bool lock) 70286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 7036e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski u32 mem_len; 7046e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct ipu_di_signal_cfg sig_cfg; 7056e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski enum ipu_panel mode = IPU_PANEL_TFT; 7066e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_info *mx3_fbi = fbi->par; 7076e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; 7086e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct idmac_channel *ichan = mx3_fbi->idmac_channel; 7096e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct idmac_video_param *video = &ichan->params.video; 7106e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct scatterlist *sg = mx3_fbi->sg; 7116e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 7126e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* Total cleanup */ 7136e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (mx3_fbi->txd) 7146e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_disable_channel(mx3_fbi); 7156e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 7166e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_set_fix(fbi); 7176e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 7186e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mem_len = fbi->var.yres_virtual * fbi->fix.line_length; 7196e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (mem_len > fbi->fix.smem_len) { 7206e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (fbi->fix.smem_start) 7216e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_unmap_video_memory(fbi); 7226e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 72320de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski if (mx3fb_map_video_memory(fbi, mem_len, lock) < 0) 7246e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return -ENOMEM; 7256e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 7266e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 7276e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sg_init_table(&sg[0], 1); 7286e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sg_init_table(&sg[1], 1); 7296e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 730d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski sg_dma_address(&sg[0]) = fbi->fix.smem_start; 7316e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sg_set_page(&sg[0], virt_to_page(fbi->screen_base), 7326e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->fix.smem_len, 7336e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski offset_in_page(fbi->screen_base)); 7346e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 7356e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (mx3_fbi->ipu_ch == IDMAC_SDC_0) { 7366e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski memset(&sig_cfg, 0, sizeof(sig_cfg)); 7376e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT) 7386e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sig_cfg.Hsync_pol = true; 7396e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) 7406e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sig_cfg.Vsync_pol = true; 7416e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (fbi->var.sync & FB_SYNC_CLK_INVERT) 7426e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sig_cfg.clk_pol = true; 7436e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (fbi->var.sync & FB_SYNC_DATA_INVERT) 7446e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sig_cfg.data_pol = true; 7456e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (fbi->var.sync & FB_SYNC_OE_ACT_HIGH) 7466e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sig_cfg.enable_pol = true; 7476e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN) 7486e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sig_cfg.clkidle_en = true; 7496e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (fbi->var.sync & FB_SYNC_CLK_SEL_EN) 7506e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sig_cfg.clksel_en = true; 7516e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (fbi->var.sync & FB_SYNC_SHARP_MODE) 7526e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mode = IPU_PANEL_SHARP_TFT; 7536e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 7546e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(fbi->device, "pixclock = %ul Hz\n", 7556e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski (u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL)); 7566e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 7576e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (sdc_init_panel(mx3fb, mode, 7586e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski (PICOS2KHZ(fbi->var.pixclock)) * 1000UL, 7596e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.xres, fbi->var.yres, 7606e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.left_margin, 7616e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.hsync_len, 7626e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.right_margin + 7636e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.hsync_len, 7646e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.upper_margin, 7656e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.vsync_len, 7666e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.lower_margin + 7676e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.vsync_len, sig_cfg) != 0) { 7686e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_err(fbi->device, 7696e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski "mx3fb: Error initializing panel.\n"); 7706e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return -EINVAL; 7716e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 7726e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 7736e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 7746e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_set_window_pos(mx3fb, mx3_fbi->ipu_ch, 0, 0); 7756e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 7766e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->cur_ipu_buf = 0; 7776e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 7786e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski video->out_pixel_fmt = bpp_to_pixfmt(fbi->var.bits_per_pixel); 7796e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski video->out_width = fbi->var.xres; 7806e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski video->out_height = fbi->var.yres; 7816e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski video->out_stride = fbi->var.xres_virtual; 7826e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 7836e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (mx3_fbi->blank == FB_BLANK_UNBLANK) 7846e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_enable_channel(mx3_fbi); 7856e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 78620de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski return 0; 78720de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski} 78820de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski 78920de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski/** 79020de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski * mx3fb_set_par() - set framebuffer parameters and change the operating mode. 79120de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski * @fbi: framebuffer information pointer. 79220de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski * @return: 0 on success or negative error code on failure. 79320de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski */ 79420de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetskistatic int mx3fb_set_par(struct fb_info *fbi) 79520de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski{ 79620de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski struct mx3fb_info *mx3_fbi = fbi->par; 79720de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; 79820de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski struct idmac_channel *ichan = mx3_fbi->idmac_channel; 79920de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski int ret; 80020de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski 80120de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+'); 80220de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski 80320de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski mutex_lock(&mx3_fbi->mutex); 80420de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski 80520de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski ret = __set_par(fbi, true); 80620de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski 8076e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mutex_unlock(&mx3_fbi->mutex); 8086e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 80920de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski return ret; 81086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 81186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 81286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/** 81386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * mx3fb_check_var() - check and adjust framebuffer variable parameters. 8146e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @var: framebuffer variable parameters 8156e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @fbi: framebuffer information pointer 81686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 81786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int mx3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) 81886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 8196e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_info *mx3_fbi = fbi->par; 8206e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski u32 vtotal; 8216e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski u32 htotal; 8226e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8236e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(fbi->device, "%s\n", __func__); 8246e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8256e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (var->xres_virtual < var->xres) 8266e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->xres_virtual = var->xres; 8276e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (var->yres_virtual < var->yres) 8286e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->yres_virtual = var->yres; 8296e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8306e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) && 8316e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski (var->bits_per_pixel != 16)) 8326e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->bits_per_pixel = default_bpp; 8336e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8346e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski switch (var->bits_per_pixel) { 8356e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case 16: 8366e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->red.length = 5; 8376e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->red.offset = 11; 8386e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->red.msb_right = 0; 8396e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8406e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->green.length = 6; 8416e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->green.offset = 5; 8426e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->green.msb_right = 0; 8436e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8446e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->blue.length = 5; 8456e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->blue.offset = 0; 8466e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->blue.msb_right = 0; 8476e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8486e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->transp.length = 0; 8496e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->transp.offset = 0; 8506e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->transp.msb_right = 0; 8516e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski break; 8526e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case 24: 8536e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->red.length = 8; 8546e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->red.offset = 16; 8556e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->red.msb_right = 0; 8566e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8576e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->green.length = 8; 8586e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->green.offset = 8; 8596e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->green.msb_right = 0; 8606e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8616e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->blue.length = 8; 8626e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->blue.offset = 0; 8636e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->blue.msb_right = 0; 8646e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8656e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->transp.length = 0; 8666e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->transp.offset = 0; 8676e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->transp.msb_right = 0; 8686e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski break; 8696e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case 32: 8706e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->red.length = 8; 8716e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->red.offset = 16; 8726e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->red.msb_right = 0; 8736e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8746e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->green.length = 8; 8756e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->green.offset = 8; 8766e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->green.msb_right = 0; 8776e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8786e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->blue.length = 8; 8796e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->blue.offset = 0; 8806e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->blue.msb_right = 0; 8816e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8826e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->transp.length = 8; 8836e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->transp.offset = 24; 8846e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->transp.msb_right = 0; 8856e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski break; 8866e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 8876e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8886e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (var->pixclock < 1000) { 8896e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski htotal = var->xres + var->right_margin + var->hsync_len + 8906e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->left_margin; 8916e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski vtotal = var->yres + var->lower_margin + var->vsync_len + 8926e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->upper_margin; 8936e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->pixclock = (vtotal * htotal * 6UL) / 100UL; 8946e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->pixclock = KHZ2PICOS(var->pixclock); 8956e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(fbi->device, "pixclock set for 60Hz refresh = %u ps\n", 8966e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->pixclock); 8976e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 8986e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 8996e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->height = -1; 9006e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->width = -1; 9016e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->grayscale = 0; 9026e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 9036e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* Preserve sync flags */ 9046e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski var->sync |= mx3_fbi->sync; 9056e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->sync |= var->sync; 9066e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 9076e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 90886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 90986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 91086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic u32 chan_to_field(unsigned int chan, struct fb_bitfield *bf) 91186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 9126e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski chan &= 0xffff; 9136e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski chan >>= 16 - bf->length; 9146e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return chan << bf->offset; 91586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 91686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 91786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int mx3fb_setcolreg(unsigned int regno, unsigned int red, 9186e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned int green, unsigned int blue, 9196e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned int trans, struct fb_info *fbi) 92086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 9216e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_info *mx3_fbi = fbi->par; 9226e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski u32 val; 9236e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski int ret = 1; 9246e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 925d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski dev_dbg(fbi->device, "%s, regno = %u\n", __func__, regno); 9266e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 9276e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mutex_lock(&mx3_fbi->mutex); 9286e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* 9296e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * If greyscale is true, then we convert the RGB value 9306e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * to greyscale no matter what visual we are using. 9316e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski */ 9326e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (fbi->var.grayscale) 9336e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski red = green = blue = (19595 * red + 38470 * green + 9346e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 7471 * blue) >> 16; 9356e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski switch (fbi->fix.visual) { 9366e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case FB_VISUAL_TRUECOLOR: 9376e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* 9386e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * 16-bit True Colour. We encode the RGB value 9396e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * according to the RGB bitfield information. 9406e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski */ 9416e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (regno < 16) { 9426e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski u32 *pal = fbi->pseudo_palette; 9436e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 9446e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski val = chan_to_field(red, &fbi->var.red); 9456e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski val |= chan_to_field(green, &fbi->var.green); 9466e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski val |= chan_to_field(blue, &fbi->var.blue); 9476e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 9486e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski pal[regno] = val; 9496e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 9506e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski ret = 0; 9516e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 9526e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski break; 9536e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 9546e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case FB_VISUAL_STATIC_PSEUDOCOLOR: 9556e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case FB_VISUAL_PSEUDOCOLOR: 9566e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski break; 9576e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 9586e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mutex_unlock(&mx3_fbi->mutex); 9596e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 9606e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return ret; 96186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 96286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 96320de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetskistatic void __blank(int blank, struct fb_info *fbi) 96486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 9656e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_info *mx3_fbi = fbi->par; 9666e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; 9678b53b7fb57e1ce3441b1a32f8374874b53c4bc31Wolfram Stering int was_blank = mx3_fbi->blank; 9686e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 9696e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->blank = blank; 9706e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 9718b53b7fb57e1ce3441b1a32f8374874b53c4bc31Wolfram Stering /* Attention! 9728b53b7fb57e1ce3441b1a32f8374874b53c4bc31Wolfram Stering * Do not call sdc_disable_channel() for a channel that is disabled 9738b53b7fb57e1ce3441b1a32f8374874b53c4bc31Wolfram Stering * already! This will result in a kernel NULL pointer dereference 9748b53b7fb57e1ce3441b1a32f8374874b53c4bc31Wolfram Stering * (mx3_fbi->txd is NULL). Hide the fact, that all blank modes are 9758b53b7fb57e1ce3441b1a32f8374874b53c4bc31Wolfram Stering * handled equally by this driver. 9768b53b7fb57e1ce3441b1a32f8374874b53c4bc31Wolfram Stering */ 9778b53b7fb57e1ce3441b1a32f8374874b53c4bc31Wolfram Stering if (blank > FB_BLANK_UNBLANK && was_blank > FB_BLANK_UNBLANK) 9788b53b7fb57e1ce3441b1a32f8374874b53c4bc31Wolfram Stering return; 9798b53b7fb57e1ce3441b1a32f8374874b53c4bc31Wolfram Stering 9806e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski switch (blank) { 9816e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case FB_BLANK_POWERDOWN: 9826e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case FB_BLANK_VSYNC_SUSPEND: 9836e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case FB_BLANK_HSYNC_SUSPEND: 9846e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case FB_BLANK_NORMAL: 9856e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_set_brightness(mx3fb, 0); 986d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski memset((char *)fbi->screen_base, 0, fbi->fix.smem_len); 987d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski /* Give LCD time to update - enough for 50 and 60 Hz */ 988d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski msleep(25); 989d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski sdc_disable_channel(mx3_fbi); 9906e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski break; 9916e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski case FB_BLANK_UNBLANK: 9926e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_enable_channel(mx3_fbi); 9936e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_set_brightness(mx3fb, mx3fb->backlight_level); 9946e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski break; 9956e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 99620de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski} 99720de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski 99820de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski/** 99920de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski * mx3fb_blank() - blank the display. 100020de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski */ 100120de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetskistatic int mx3fb_blank(int blank, struct fb_info *fbi) 100220de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski{ 100320de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski struct mx3fb_info *mx3_fbi = fbi->par; 100420de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski 100520de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski dev_dbg(fbi->device, "%s, blank = %d, base %p, len %u\n", __func__, 100620de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski blank, fbi->screen_base, fbi->fix.smem_len); 100720de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski 100820de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski if (mx3_fbi->blank == blank) 100920de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski return 0; 101020de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski 101120de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski mutex_lock(&mx3_fbi->mutex); 101220de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski __blank(blank, fbi); 10136e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mutex_unlock(&mx3_fbi->mutex); 10146e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 10156e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 101686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 101786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 101886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/** 101986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * mx3fb_pan_display() - pan or wrap the display 10206e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @var: variable screen buffer information. 10216e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @info: framebuffer information pointer. 102286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * 102386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * We look only at xoffset, yoffset and the FB_VMODE_YWRAP flag 102486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 102586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int mx3fb_pan_display(struct fb_var_screeninfo *var, 10266e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct fb_info *fbi) 102786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 10286e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_info *mx3_fbi = fbi->par; 10296e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski u32 y_bottom; 10306e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned long base; 10316e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski off_t offset; 10326e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dma_cookie_t cookie; 10336e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct scatterlist *sg = mx3_fbi->sg; 10346e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct dma_chan *dma_chan = &mx3_fbi->idmac_channel->dma_chan; 10356e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct dma_async_tx_descriptor *txd; 10366e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski int ret; 10376e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 10386e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(fbi->device, "%s [%c]\n", __func__, 10396e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski list_empty(&mx3_fbi->idmac_channel->queue) ? '-' : '+'); 10406e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 10416e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (var->xoffset > 0) { 10426e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(fbi->device, "x panning not supported\n"); 10436e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return -EINVAL; 10446e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 10456e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 10466e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (fbi->var.xoffset == var->xoffset && 10476e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.yoffset == var->yoffset) 10486e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; /* No change, do nothing */ 10496e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 10506e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski y_bottom = var->yoffset; 10516e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 10526e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!(var->vmode & FB_VMODE_YWRAP)) 10539f1b3ebbce04dc61986a1b3b41b0f1b1a77a5cc4Laurent Pinchart y_bottom += fbi->var.yres; 10546e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 10556e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (y_bottom > fbi->var.yres_virtual) 10566e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return -EINVAL; 10576e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 10586e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mutex_lock(&mx3_fbi->mutex); 10596e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 10609f1b3ebbce04dc61986a1b3b41b0f1b1a77a5cc4Laurent Pinchart offset = var->yoffset * fbi->fix.line_length 10619f1b3ebbce04dc61986a1b3b41b0f1b1a77a5cc4Laurent Pinchart + var->xoffset * (fbi->var.bits_per_pixel / 8); 10626e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski base = fbi->fix.smem_start + offset; 10636e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 10646e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n", 10656e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->cur_ipu_buf, base); 10666e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 10676e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* 10686e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * We enable the End of Frame interrupt, which will free a tx-descriptor, 10696e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * which we will need for the next device_prep_slave_sg(). The 10706e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * IRQ-handler will disable the IRQ again. 10716e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski */ 10726e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski init_completion(&mx3_fbi->flip_cmpl); 10736e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski enable_irq(mx3_fbi->idmac_channel->eof_irq); 10746e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 10756e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski ret = wait_for_completion_timeout(&mx3_fbi->flip_cmpl, HZ / 10); 10766e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (ret <= 0) { 10776e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mutex_unlock(&mx3_fbi->mutex); 10786e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_info(fbi->device, "Panning failed due to %s\n", ret < 0 ? 10796e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski "user interrupt" : "timeout"); 1080d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski disable_irq(mx3_fbi->idmac_channel->eof_irq); 10816e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return ret ? : -ETIMEDOUT; 10826e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 10836e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 10846e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->cur_ipu_buf = !mx3_fbi->cur_ipu_buf; 10856e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 10866e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sg_dma_address(&sg[mx3_fbi->cur_ipu_buf]) = base; 10876e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sg_set_page(&sg[mx3_fbi->cur_ipu_buf], 10886e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski virt_to_page(fbi->screen_base + offset), fbi->fix.smem_len, 10896e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski offset_in_page(fbi->screen_base + offset)); 10906e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 1091d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski if (mx3_fbi->txd) 1092d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski async_tx_ack(mx3_fbi->txd); 1093d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetski 10946e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg + 10951003cab8276cd34d9deab8ca9d148ee59f7728a7Vinod Koul mx3_fbi->cur_ipu_buf, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); 10966e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!txd) { 10976e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_err(fbi->device, 10986e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski "Error preparing a DMA transaction descriptor.\n"); 10996e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mutex_unlock(&mx3_fbi->mutex); 11006e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return -EIO; 11016e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 11026e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 11036e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski txd->callback_param = txd; 11046e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski txd->callback = mx3fb_dma_done; 11056e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 11066e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* 11076e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * Emulate original mx3fb behaviour: each new call to idmac_tx_submit() 11086e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * should switch to another buffer 11096e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski */ 11106e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski cookie = txd->tx_submit(txd); 11116e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(fbi->device, "%d: Submit %p #%d\n", __LINE__, txd, cookie); 11126e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (cookie < 0) { 11136e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_err(fbi->device, 11146e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski "Error updating SDC buf %d to address=0x%08lX\n", 11156e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->cur_ipu_buf, base); 11166e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mutex_unlock(&mx3_fbi->mutex); 11176e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return -EIO; 11186e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 11196e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 11206e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3_fbi->txd = txd; 11216e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 11226e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.xoffset = var->xoffset; 11236e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.yoffset = var->yoffset; 11246e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 11256e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (var->vmode & FB_VMODE_YWRAP) 11266e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.vmode |= FB_VMODE_YWRAP; 11276e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski else 11286e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.vmode &= ~FB_VMODE_YWRAP; 11296e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 11306e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mutex_unlock(&mx3_fbi->mutex); 11316e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 11326e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(fbi->device, "Update complete\n"); 11336e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 11346e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 113586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 113686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 113786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* 113886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * This structure contains the pointers to the control functions that are 113986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * invoked by the core framebuffer driver to perform operations like 114086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * blitting, rectangle filling, copy regions and cursor definition. 114186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 114286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic struct fb_ops mx3fb_ops = { 11436e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .owner = THIS_MODULE, 11446e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .fb_set_par = mx3fb_set_par, 11456e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .fb_check_var = mx3fb_check_var, 11466e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .fb_setcolreg = mx3fb_setcolreg, 11476e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .fb_pan_display = mx3fb_pan_display, 11486e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .fb_fillrect = cfb_fillrect, 11496e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .fb_copyarea = cfb_copyarea, 11506e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .fb_imageblit = cfb_imageblit, 11516e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .fb_blank = mx3fb_blank, 115286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski}; 115386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 115486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#ifdef CONFIG_PM 115586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* 115686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * Power management hooks. Note that we won't be called from IRQ context, 115786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * unlike the blank functions above, so we may sleep. 115886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 115986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 116086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* 116186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * Suspends the framebuffer and blanks the screen. Power management support 116286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 116386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int mx3fb_suspend(struct platform_device *pdev, pm_message_t state) 116486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 1165b09de4209d179c92ab880d911e72a892d053ff01Sascha Hauer struct mx3fb_data *mx3fb = platform_get_drvdata(pdev); 1166b09de4209d179c92ab880d911e72a892d053ff01Sascha Hauer struct mx3fb_info *mx3_fbi = mx3fb->fbi->par; 116786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 1168ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 1169b09de4209d179c92ab880d911e72a892d053ff01Sascha Hauer fb_set_suspend(mx3fb->fbi, 1); 1170ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 117186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 11726e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (mx3_fbi->blank == FB_BLANK_UNBLANK) { 11736e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_disable_channel(mx3_fbi); 11746e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_set_brightness(mx3fb, 0); 117586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 11766e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 11776e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 117886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 117986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 118086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* 118186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * Resumes the framebuffer and unblanks the screen. Power management support 118286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 118386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int mx3fb_resume(struct platform_device *pdev) 118486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 1185b09de4209d179c92ab880d911e72a892d053ff01Sascha Hauer struct mx3fb_data *mx3fb = platform_get_drvdata(pdev); 1186b09de4209d179c92ab880d911e72a892d053ff01Sascha Hauer struct mx3fb_info *mx3_fbi = mx3fb->fbi->par; 118786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 11886e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (mx3_fbi->blank == FB_BLANK_UNBLANK) { 11896e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_enable_channel(mx3_fbi); 1190b09de4209d179c92ab880d911e72a892d053ff01Sascha Hauer sdc_set_brightness(mx3fb, mx3fb->backlight_level); 11916e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 119286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 1193ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 1194b09de4209d179c92ab880d911e72a892d053ff01Sascha Hauer fb_set_suspend(mx3fb->fbi, 0); 1195ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 119686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 11976e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 119886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 119986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#else 120086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#define mx3fb_suspend NULL 120186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#define mx3fb_resume NULL 120286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#endif 120386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 120486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* 120586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * Main framebuffer functions 120686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 120786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 120886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/** 120986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer. 12106e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @fbi: framebuffer information pointer 1211537a1bf059fa312355696fa6db80726e655e7f17Krzysztof Helt * @mem_len: length of mapped memory 121220de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski * @lock: do not lock during initialisation 12136e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @return: Error code indicating success or failure 121486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * 121586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * This buffer is remapped into a non-cached, non-buffered, memory region to 121686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * allow palette and pixel writes to occur without flushing the cache. Once this 121786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * area is remapped, all virtual memory access to the video memory should occur 121886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * at the new region. 121986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 122020de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetskistatic int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len, 122120de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski bool lock) 122286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 12236e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski int retval = 0; 12246e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dma_addr_t addr; 122586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 12266e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->screen_base = dma_alloc_writecombine(fbi->device, 1227537a1bf059fa312355696fa6db80726e655e7f17Krzysztof Helt mem_len, 12286e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski &addr, GFP_DMA); 122986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 12306e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!fbi->screen_base) { 12316e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n", 1232537a1bf059fa312355696fa6db80726e655e7f17Krzysztof Helt mem_len); 12336e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski retval = -EBUSY; 12346e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski goto err0; 12356e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 123686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 123720de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski if (lock) 123820de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski mutex_lock(&fbi->mm_lock); 12396e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->fix.smem_start = addr; 1240537a1bf059fa312355696fa6db80726e655e7f17Krzysztof Helt fbi->fix.smem_len = mem_len; 124120de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski if (lock) 124220de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski mutex_unlock(&fbi->mm_lock); 124386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 12446e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n", 12456e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski (uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len); 124686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 12476e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->screen_size = fbi->fix.smem_len; 124886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 12496e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* Clear the screen */ 12506e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski memset((char *)fbi->screen_base, 0, fbi->fix.smem_len); 125186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 12526e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 125386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 125486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskierr0: 12556e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->fix.smem_len = 0; 12566e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->fix.smem_start = 0; 12576e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->screen_base = NULL; 12586e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return retval; 125986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 126086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 126186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/** 126286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * mx3fb_unmap_video_memory() - de-allocate frame buffer memory. 12636e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @fbi: framebuffer information pointer 12646e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @return: error code indicating success or failure 126586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 126686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int mx3fb_unmap_video_memory(struct fb_info *fbi) 126786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 12686e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dma_free_writecombine(fbi->device, fbi->fix.smem_len, 12696e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->screen_base, fbi->fix.smem_start); 127086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 12716e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->screen_base = 0; 1272537a1bf059fa312355696fa6db80726e655e7f17Krzysztof Helt mutex_lock(&fbi->mm_lock); 12736e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->fix.smem_start = 0; 12746e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->fix.smem_len = 0; 1275537a1bf059fa312355696fa6db80726e655e7f17Krzysztof Helt mutex_unlock(&fbi->mm_lock); 12766e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 127786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 127886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 127986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/** 128086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * mx3fb_init_fbinfo() - initialize framebuffer information object. 12816e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * @return: initialized framebuffer structure. 128286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 128386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic struct fb_info *mx3fb_init_fbinfo(struct device *dev, struct fb_ops *ops) 128486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 12856e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct fb_info *fbi; 12866e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_info *mx3fbi; 12876e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski int ret; 128886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 12896e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* Allocate sufficient memory for the fb structure */ 12906e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi = framebuffer_alloc(sizeof(struct mx3fb_info), dev); 12916e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!fbi) 12926e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return NULL; 129386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 12946e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fbi = fbi->par; 12956e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fbi->cookie = -EINVAL; 12966e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fbi->cur_ipu_buf = 0; 129786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 12986e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.activate = FB_ACTIVATE_NOW; 129986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13006e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->fbops = ops; 13016e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->flags = FBINFO_FLAG_DEFAULT; 13026e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->pseudo_palette = mx3fbi->pseudo_palette; 130386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13046e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mutex_init(&mx3fbi->mutex); 130586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13066e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* Allocate colormap */ 13076e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski ret = fb_alloc_cmap(&fbi->cmap, 16, 0); 13086e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (ret < 0) { 13096e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski framebuffer_release(fbi); 13106e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return NULL; 13116e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 131286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13136e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return fbi; 131486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 131586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 131686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan) 131786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 13186e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct device *dev = mx3fb->dev; 13196e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_platform_data *mx3fb_pdata = dev->platform_data; 13206e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski const char *name = mx3fb_pdata->name; 13216e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unsigned int irq; 13226e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct fb_info *fbi; 13236e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_info *mx3fbi; 13246e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski const struct fb_videomode *mode; 13256e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski int ret, num_modes; 132686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 1327f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer if (mx3fb_pdata->disp_data_fmt >= ARRAY_SIZE(di_mappings)) { 1328f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer dev_err(dev, "Illegal display data format %d\n", 1329f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer mx3fb_pdata->disp_data_fmt); 1330f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer return -EINVAL; 1331f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer } 1332f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer 13336e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski ichan->client = mx3fb; 13346e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski irq = ichan->eof_irq; 133586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13366e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (ichan->dma_chan.chan_id != IDMAC_SDC_0) 13376e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return -EINVAL; 133886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13396e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi = mx3fb_init_fbinfo(dev, &mx3fb_ops); 13406e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!fbi) 13416e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return -ENOMEM; 134286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13436e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!fb_mode) 13446e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fb_mode = name; 134586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13466e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!fb_mode) { 13476e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski ret = -EINVAL; 13486e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski goto emode; 13496e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 135086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13516e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (mx3fb_pdata->mode && mx3fb_pdata->num_modes) { 13526e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mode = mx3fb_pdata->mode; 13536e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski num_modes = mx3fb_pdata->num_modes; 13546e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } else { 13556e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mode = mx3fb_modedb; 13566e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski num_modes = ARRAY_SIZE(mx3fb_modedb); 13576e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 135886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13596e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!fb_find_mode(&fbi->var, fbi, fb_mode, mode, 13606e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski num_modes, NULL, default_bpp)) { 13616e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski ret = -EBUSY; 13626e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski goto emode; 13636e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 136486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13656e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fb_videomode_to_modelist(mode, num_modes, &fbi->modelist); 136686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13676e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* Default Y virtual size is 2x panel size */ 13686e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fbi->var.yres_virtual = fbi->var.yres * 2; 136986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13706e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb->fbi = fbi; 137186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13726e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* set Display Interface clock period */ 13736e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_write_reg(mx3fb, 0x00100010L, DI_HSP_CLK_PER); 13746e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* Might need to trigger HSP clock change - see 44.3.3.8.5 */ 137586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13766e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_set_brightness(mx3fb, 255); 13776e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_set_global_alpha(mx3fb, true, 0xFF); 13786e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_set_color_key(mx3fb, IDMAC_SDC_0, false, 0); 137986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13806e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fbi = fbi->par; 13816e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fbi->idmac_channel = ichan; 13826e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fbi->ipu_ch = ichan->dma_chan.chan_id; 13836e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fbi->mx3fb = mx3fb; 13846e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fbi->blank = FB_BLANK_NORMAL; 138586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 1386f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer mx3fb->disp_data_fmt = mx3fb_pdata->disp_data_fmt; 1387f910fb8fcd1c97788f2291c8646597bcd87ee061Sascha Hauer 13886e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski init_completion(&mx3fbi->flip_cmpl); 13896e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski disable_irq(ichan->eof_irq); 13906e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq); 139120de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski ret = __set_par(fbi, false); 139220de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski if (ret < 0) 139320de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski goto esetpar; 139420de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski 139520de03dae54e10271ffd308654dfb4a117f4789dGuennadi Liakhovetski __blank(FB_BLANK_UNBLANK, fbi); 139686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13972eec8c318b9bbfe9e0f2a889b4ad3f4b4e5ba429Sascha Hauer dev_info(dev, "registered, using mode %s\n", fb_mode); 139886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 13996e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski ret = register_framebuffer(fbi); 14006e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (ret < 0) 14016e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski goto erfb; 140286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 14036e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 140486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 140586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskierfb: 140686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskiesetpar: 140786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskiemode: 14086e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fb_dealloc_cmap(&fbi->cmap); 14096e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski framebuffer_release(fbi); 141086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 14116e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return ret; 141286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 141386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 141486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic bool chan_filter(struct dma_chan *chan, void *arg) 141586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 14166e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct dma_chan_request *rq = arg; 14176e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct device *dev; 14186e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_platform_data *mx3fb_pdata; 141986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 14201b346af2f88a0e19e718a843d39d34e41e5527e1Sascha Hauer if (!imx_dma_is_ipu(chan)) 14211b346af2f88a0e19e718a843d39d34e41e5527e1Sascha Hauer return false; 14221b346af2f88a0e19e718a843d39d34e41e5527e1Sascha Hauer 14236e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!rq) 14246e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return false; 142586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 14266e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev = rq->mx3fb->dev; 14276e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_pdata = dev->platform_data; 142886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 14296e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return rq->id == chan->chan_id && 14306e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_pdata->dma_dev == chan->device->dev; 143186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 143286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 143386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic void release_fbi(struct fb_info *fbi) 143486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 14356e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb_unmap_video_memory(fbi); 143686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 14376e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fb_dealloc_cmap(&fbi->cmap); 143886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 14396e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski unregister_framebuffer(fbi); 14406e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski framebuffer_release(fbi); 144186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 144286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 144386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int mx3fb_probe(struct platform_device *pdev) 144486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 14456e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct device *dev = &pdev->dev; 14466e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski int ret; 14476e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct resource *sdc_reg; 14486e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_data *mx3fb; 14496e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dma_cap_mask_t mask; 14506e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct dma_chan *chan; 14516e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct dma_chan_request rq; 14526e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 14536e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* 14546e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * Display Interface (DI) and Synchronous Display Controller (SDC) 14556e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * registers 14566e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski */ 14576e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski sdc_reg = platform_get_resource(pdev, IORESOURCE_MEM, 0); 14586e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!sdc_reg) 14596e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return -EINVAL; 14606e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 14616e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb = kzalloc(sizeof(*mx3fb), GFP_KERNEL); 14626e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!mx3fb) 14636e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return -ENOMEM; 14646e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 14656e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski spin_lock_init(&mx3fb->lock); 14666e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 14676e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb->reg_base = ioremap(sdc_reg->start, resource_size(sdc_reg)); 14686e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!mx3fb->reg_base) { 14696e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski ret = -ENOMEM; 14706e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski goto eremap; 14716e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 14726e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 14733b80ffdef001ac7ff53bdcb80ad2baadb5953f91Joe Perches pr_debug("Remapped %pR at %p\n", sdc_reg, mx3fb->reg_base); 14746e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 14756e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski /* IDMAC interface */ 14766e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dmaengine_get(); 14776e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 14786e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski mx3fb->dev = dev; 14796e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski platform_set_drvdata(pdev, mx3fb); 14806e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 14816e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski rq.mx3fb = mx3fb; 14826e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 14836e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dma_cap_zero(mask); 14846e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dma_cap_set(DMA_SLAVE, mask); 14856e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dma_cap_set(DMA_PRIVATE, mask); 14866e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski rq.id = IDMAC_SDC_0; 14876e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski chan = dma_request_channel(mask, chan_filter, &rq); 14886e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!chan) { 14896e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski ret = -EBUSY; 14906e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski goto ersdc0; 14916e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 14926e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 1493b3cb53721890879d7bde31f5f9eefd4edf41ab64Alberto Panizzo mx3fb->backlight_level = 255; 1494b3cb53721890879d7bde31f5f9eefd4edf41ab64Alberto Panizzo 14956e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski ret = init_fb_chan(mx3fb, to_idmac_chan(chan)); 14966e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (ret < 0) 14976e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski goto eisdc0; 14986e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 14996e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 150086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 150186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskieisdc0: 15026e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dma_release_channel(chan); 150386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskiersdc0: 15046e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dmaengine_put(); 15056e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski iounmap(mx3fb->reg_base); 150686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskieremap: 15076e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski kfree(mx3fb); 15086e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dev_err(dev, "mx3fb: failed to register fb\n"); 15096e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return ret; 151086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 151186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 151286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int mx3fb_remove(struct platform_device *dev) 151386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 15146e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_data *mx3fb = platform_get_drvdata(dev); 15156e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct fb_info *fbi = mx3fb->fbi; 15166e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct mx3fb_info *mx3_fbi = fbi->par; 15176e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski struct dma_chan *chan; 151886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 15196e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski chan = &mx3_fbi->idmac_channel->dma_chan; 15206e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski release_fbi(fbi); 152186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 15226e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dma_release_channel(chan); 15236e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski dmaengine_put(); 152486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 15256e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski iounmap(mx3fb->reg_base); 15266e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski kfree(mx3fb); 15276e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 152886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 152986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 153086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic struct platform_driver mx3fb_driver = { 15316e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .driver = { 15326e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .name = MX3FB_NAME, 15336e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski }, 15346e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .probe = mx3fb_probe, 15356e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .remove = mx3fb_remove, 15366e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .suspend = mx3fb_suspend, 15376e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski .resume = mx3fb_resume, 153886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski}; 153986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 154086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski/* 154186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * Parse user specified options (`video=mx3fb:') 154286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski * example: 15436e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski * video=mx3fb:bpp=16 154486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski */ 1545d88ca815b5b3534ed2dae123ba0bf366861f850cGuennadi Liakhovetskistatic int __init mx3fb_setup(void) 154686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 154786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#ifndef MODULE 15486e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski char *opt, *options = NULL; 15496e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 15506e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (fb_get_options("mx3fb", &options)) 15516e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return -ENODEV; 15526e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 15536e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!options || !*options) 15546e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 15556e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski 15566e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski while ((opt = strsep(&options, ",")) != NULL) { 15576e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!*opt) 15586e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski continue; 15596e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (!strncmp(opt, "bpp=", 4)) 15606e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski default_bpp = simple_strtoul(opt + 4, NULL, 0); 15616e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski else 15626e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski fb_mode = opt; 15636e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski } 156486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski#endif 156586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 15666e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return 0; 156786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 156886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 156986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic int __init mx3fb_init(void) 157086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 15716e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski int ret = mx3fb_setup(); 157286528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 15736e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski if (ret < 0) 15746e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return ret; 157586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 15766e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski ret = platform_driver_register(&mx3fb_driver); 15776e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski return ret; 157886528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 157986528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 158086528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskistatic void __exit mx3fb_exit(void) 158186528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski{ 15826e1588cbd88590273300403648aef70e6bdaf5afGuennadi Liakhovetski platform_driver_unregister(&mx3fb_driver); 158386528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski} 158486528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 158586528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskimodule_init(mx3fb_init); 158686528da229a448577a8401a17c295883640d336cGuennadi Liakhovetskimodule_exit(mx3fb_exit); 158786528da229a448577a8401a17c295883640d336cGuennadi Liakhovetski 158886528da229a448577a8401a17c295883640d336cGuennadi LiakhovetskiMODULE_AUTHOR("Freescale Semiconductor, Inc."); 158986528da229a448577a8401a17c295883640d336cGuennadi LiakhovetskiMODULE_DESCRIPTION("MX3 framebuffer driver"); 159086528da229a448577a8401a17c295883640d336cGuennadi LiakhovetskiMODULE_ALIAS("platform:" MX3FB_NAME); 159186528da229a448577a8401a17c295883640d336cGuennadi LiakhovetskiMODULE_LICENSE("GPL v2"); 1592