Commit 56023db1 authored by Imre Deak's avatar Imre Deak Committed by Tony Lindgren

FB: OMAP: Add support for framebuffer

Adds support for OMAP framebuffer.
Signed-off-by: default avatarImre Deak <imre.deak@nokia.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 49067b23
...@@ -1468,6 +1468,48 @@ config FB_S1D13XXX ...@@ -1468,6 +1468,48 @@ config FB_S1D13XXX
working with S1D13806). Product specs at working with S1D13806). Product specs at
<http://www.erd.epson.com/vdc/html/legacy_13xxx.htm> <http://www.erd.epson.com/vdc/html/legacy_13xxx.htm>
config FB_OMAP
tristate "OMAP frame buffer support (EXPERIMENTAL)"
depends on FB && ARCH_OMAP1
select FB_SOFT_CURSOR
help
This is the new frame buffer device driver with 2D acceleration
for OMAP boards.
config FB_OMAP_INTERNAL_LCDC
bool "OMAP internal LCD controller support"
depends on FB_OMAP
default y
help
Say Y here, if you want to have support for the internal OMAP
LCD controller. If unsure, say Y.
config FB_OMAP_EXTERNAL_LCDC
bool "OMAP external LCD controller support"
depends on FB_OMAP
help
Say Y here, if you want to have support for boards with an
external LCD controller connected to the SoSSI interface.
config FB_OMAP_MANUAL_UPDATE
bool "Default to manual update mode"
depends on FB_OMAP_EXTERNAL_LCDC
help
Say Y here, if your user-space applications are capable of
notifying the frame buffer driver when a change has occured in
the frame buffer content and thus a reload of the image data is
required. If unsure, say N.
config FB_OMAP_DMA_TUNE
bool "Set DMA SDRAM access priority high"
depends on FB_OMAP
help
On systems in which video memory is in system memory
(SDRAM) this will speed up graphics DMA operations.
If you have such a system and want to use rotation
answer yes. Answer no if you have a dedicated video
memory, or don't use any of the accelerated features.
config FB_VIRTUAL config FB_VIRTUAL
tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
depends on FB depends on FB
......
...@@ -96,6 +96,7 @@ obj-$(CONFIG_FB_IMX) += imxfb.o ...@@ -96,6 +96,7 @@ obj-$(CONFIG_FB_IMX) += imxfb.o
obj-$(CONFIG_FB_VESA) += vesafb.o obj-$(CONFIG_FB_VESA) += vesafb.o
obj-$(CONFIG_FB_VGA16) += vga16fb.o vgastate.o obj-$(CONFIG_FB_VGA16) += vga16fb.o vgastate.o
obj-$(CONFIG_FB_OF) += offb.o obj-$(CONFIG_FB_OF) += offb.o
obj-$(CONFIG_FB_OMAP) += omap/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
# the test framebuffer is last # the test framebuffer is last
obj-$(CONFIG_FB_VIRTUAL) += vfb.o obj-$(CONFIG_FB_VIRTUAL) += vfb.o
#
# Makefile for the new OMAP framebuffer device driver
#
obj-$(CONFIG_FB_OMAP) += omapfb.o
objs-yy := omapfb_main.o
objs-y$(CONFIG_FB_OMAP_INTERNAL_LCDC) += omap_lcdc.o
objs-y$(CONFIG_FB_OMAP_EXTERNAL_LCDC) += sossi.o
objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_H3) += lcd_h3.o
objs-y$(CONFIG_MACH_OMAP_H2) += lcd_h2.o
objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o
objs-$(CONFIG_ARCH_OMAP1510)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
objs-$(CONFIG_ARCH_OMAP730)$(CONFIG_MACH_OMAP_PERSEUS2) += lcd_p2.o
omapfb-objs := $(objs-yy)
/*
* File: drivers/video/omap_new/debug.c
*
* Debug support for the omapfb driver
*
* Copyright (C) 2004 Nokia Corporation
* Author: Imre Deak <imre.deak@nokia.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __OMAPFB_DEBUG_H
#define __OMAPFB_DEBUG_H
#ifdef OMAPFB_DBG
#define DBG_BUF_SIZE 2048
#define MAX_DBG_INDENT_LEVEL 5
#define DBG_INDENT_SIZE 3
#define MAX_DBG_MESSAGES 0
static int dbg_indent;
static int dbg_cnt;
static char dbg_buf[DBG_BUF_SIZE];
static spinlock_t dbg_spinlock = SPIN_LOCK_UNLOCKED;
static inline void dbg_print(int level, const char *fmt, ...)
{
if (level <= OMAPFB_DBG) {
if (!MAX_DBG_MESSAGES || dbg_cnt < MAX_DBG_MESSAGES) {
va_list args;
int ind = dbg_indent;
unsigned long flags;
spin_lock_irqsave(&dbg_spinlock, flags);
dbg_cnt++;
if (ind > MAX_DBG_INDENT_LEVEL)
ind = MAX_DBG_INDENT_LEVEL;
printk("%*s", ind * DBG_INDENT_SIZE, "");
va_start(args, fmt);
vsnprintf(dbg_buf, sizeof(dbg_buf), fmt, args);
printk(dbg_buf);
va_end(args);
spin_unlock_irqrestore(&dbg_spinlock, flags);
}
}
}
#define DBGPRINT dbg_print
#define DBGENTER(level) do { \
dbg_print(level, "%s: Enter\n", __FUNCTION__); \
dbg_indent++; \
} while (0)
#define DBGLEAVE(level) do { \
dbg_indent--; \
dbg_print(level, "%s: Leave\n", __FUNCTION__); \
} while (0)
static inline void dump_dma_regs(int lch)
{
#define _R(x) __REG16(OMAP_DMA_##x(lch))
dbg_print(4, "\nCSDP :%#06x CCR :%#06x CSSA_U :%#06x "
"\nCDSA_L:%#06x CDSA_U :%#06x CEN :%#06x "
"\nCFN :%#06x CSFI :%#06x CSEI :%#06x "
"\nCSAC :%#06x CICR :%#06x CSR :%04x "
"\nCSSA_L:%#06x CDAC :%#06x CDEI :%#06x "
"\nCDFI :%#06x COLOR_L :%#06x COLOR_U :%#06x "
"\nCCR2 :%#06x CLNK_CTRL:%#06x LCH_CTRL:%#06x\n",
_R(CSDP), _R(CCR), _R(CSSA_U),
_R(CDSA_L), _R(CDSA_U), _R(CEN),
_R(CFN), _R(CSFI), _R(CSEI),
_R(CSAC), _R(CICR), 0, /* _R(CSR), */
_R(CSSA_L), _R(CDAC), _R(CDEI),
_R(CDFI), _R(COLOR_L), _R(COLOR_U),
_R(CCR2), _R(CLNK_CTRL), _R(LCH_CTRL));
#undef _R
}
#define DUMP_DMA_REGS(lch) dump_dma_regs(lch)
#else /* OMAPFB_DBG */
#define DBGPRINT(level, format, ...)
#define DBGENTER(level)
#define DBGLEAVE(level)
#define DUMP_DMA_REGS(lch)
#endif /* OMAPFB_DBG */
#endif /* __OMAPFB_DEBUG_H */
/*
* File: drivers/video/omap_new/lcd-h2.c
*
* LCD panel support for the TI OMAP H2 board
*
* Copyright (C) 2004 Nokia Corporation
* Author: Imre Deak <imre.deak@nokia.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <asm/arch/mux.h>
#include "omapfb.h"
// #define OMAPFB_DBG 1
#include "debug.h"
#include "../drivers/ssi/omap-uwire.h"
#define TSC2101_UWIRE_CS 1
static int tsc2101_write_reg(int page, int reg, u16 data)
{
u16 cmd;
int r;
DBGENTER(1);
cmd = ((page & 3) << 11) | ((reg & 0x3f) << 5);
if (omap_uwire_data_transfer(TSC2101_UWIRE_CS, cmd, 16, 0, NULL, 1))
r = -1;
else
r = omap_uwire_data_transfer(TSC2101_UWIRE_CS, data, 16, 0, NULL, 0);
DBGLEAVE(1);
return r;
}
static int h2_panel_init(struct lcd_panel *panel)
{
unsigned long uwire_flags;
DBGENTER(1);
/* Configure N15 pin to be uWire CS1 */
omap_cfg_reg(N15_1610_UWIRE_CS1);
uwire_flags = UWIRE_READ_RISING_EDGE | UWIRE_WRITE_RISING_EDGE;
uwire_flags |= UWIRE_FREQ_DIV_8;
omap_uwire_configure_mode(TSC2101_UWIRE_CS, uwire_flags);
DBGLEAVE(1);
return 0;
}
static void h2_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static int h2_panel_enable(struct lcd_panel *panel)
{
int r;
DBGENTER(1);
/* Assert LCD_EN, BKLIGHT_EN pins on LCD panel
* page2, GPIO config reg, GPIO(0,1) to out and asserted
*/
r = tsc2101_write_reg(2, 0x23, 0xCC00) ? -1 : 0;
DBGLEAVE(1);
return r;
}
static void h2_panel_disable(struct lcd_panel *panel)
{
DBGENTER(1);
/* Deassert LCD_EN and BKLIGHT_EN pins on LCD panel
* page2, GPIO config reg, GPIO(0,1) to out and deasserted
*/
if (tsc2101_write_reg(2, 0x23, 0x8800))
PRNERR("failed to disable LCD panel\n");
DBGLEAVE(1);
}
static unsigned long h2_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
static struct lcdc_video_mode mode240x320 = {
.x_res = 240,
.y_res = 320,
.pixel_clock = 12500,
.bpp = 16,
.hsw = 12,
.hfp = 14,
.hbp = 72 - 12,
.vsw = 1,
.vfp = 1,
.vbp = 0,
.pcd = 12,
};
struct lcd_panel h2_panel = {
.name = "h2",
.config = LCD_PANEL_TFT,
.video_mode = &mode240x320,
.init = h2_panel_init,
.cleanup = h2_panel_cleanup,
.enable = h2_panel_enable,
.disable = h2_panel_disable,
.get_caps= h2_panel_get_caps,
};
/*
* File: drivers/video/omap_new/lcd-h3.c
*
* LCD panel support for the TI OMAP H3 board
*
* Copyright (C) 2004 Nokia Corporation
* Author: Imre Deak <imre.deak@nokia.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <asm/arch/gpio.h>
#include <asm/arch/tps65010.h>
#include "omapfb.h"
// #define OMAPFB_DBG 1
#include "debug.h"
static int h3_panel_init(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
return 0;
}
static void h3_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static int h3_panel_enable(struct lcd_panel *panel)
{
int r = 0;
DBGENTER(1);
/* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
r = tps65010_set_gpio_out_value(GPIO1, HIGH);
if (!r)
r = tps65010_set_gpio_out_value(GPIO2, HIGH);
if (r)
PRNERR("Unable to turn on LCD panel\n");
DBGLEAVE(1);
return r;
}
static void h3_panel_disable(struct lcd_panel *panel)
{
int r = 0;
DBGENTER(1);
/* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
r = tps65010_set_gpio_out_value(GPIO1, LOW);
if (!r)
tps65010_set_gpio_out_value(GPIO2, LOW);
if (r)
PRNERR("Unable to turn off LCD panel\n");
DBGLEAVE(1);
}
static unsigned long h3_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
static struct lcdc_video_mode mode240x320 = {
.x_res = 240,
.y_res = 320,
.pixel_clock = 12500,
.bpp = 16,
.hsw = 12,
.hfp = 14,
.hbp = 72 - 12,
.vsw = 1,
.vfp = 1,
.vbp = 0,
.pcd = 4,
};
struct lcd_panel h3_panel = {
.name = "h3",
.config = LCD_PANEL_TFT,
.video_mode = &mode240x320,
.init = h3_panel_init,
.cleanup = h3_panel_cleanup,
.enable = h3_panel_enable,
.disable = h3_panel_disable,
.get_caps= h3_panel_get_caps,
};
/*
* File: drivers/video/omap_new/lcd-inn1510.c
*
* LCD panel support for the TI OMAP1510 Innovator board
*
* Copyright (C) 2004 Nokia Corporation
* Author: Imre Deak <imre.deak@nokia.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <asm/io.h>
#include <asm/arch/fpga.h>
#include "omapfb.h"
// #define OMAPFB_DBG 1
#include "debug.h"
static int innovator1510_panel_init(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
return 0;
}
static void innovator1510_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static int innovator1510_panel_enable(struct lcd_panel *panel)
{
DBGENTER(1);
fpga_write(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
DBGLEAVE(1);
return 0;
}
static void innovator1510_panel_disable(struct lcd_panel *panel)
{
DBGENTER(1);
fpga_write(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
DBGLEAVE(1);
}
static unsigned long innovator1510_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
static struct lcdc_video_mode mode240x320 = {
.x_res = 240,
.y_res = 320,
.pixel_clock = 12500,
.bpp = 16,
.hsw = 40,
.hfp = 40,
.hbp = 72,
.vsw = 1,
.vfp = 1,
.vbp = 0,
.pcd = 12,
};
struct lcd_panel innovator1510_panel = {
.name = "inn1510",
.config = LCD_PANEL_TFT,
.video_mode = &mode240x320,
.init = innovator1510_panel_init,
.cleanup = innovator1510_panel_cleanup,
.enable = innovator1510_panel_enable,
.disable = innovator1510_panel_disable,
.get_caps= innovator1510_panel_get_caps,
};
/*
* File: drivers/video/omap_new/lcd-inn1610.c
*
* LCD panel support for the TI OMAP1610 Innovator board
*
* Copyright (C) 2004 Nokia Corporation
* Author: Imre Deak <imre.deak@nokia.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <asm/arch/gpio.h>
#include "omapfb.h"
// #define OMAPFB_DBG 1
#include "debug.h"
static int innovator1610_panel_init(struct lcd_panel *panel)
{
int r = 0;
DBGENTER(1);
if (omap_request_gpio(14)) {
PRNERR("can't request GPIO 14\n");
r = -1;
goto exit;
}
if (omap_request_gpio(15)) {
PRNERR("can't request GPIO 15\n");
omap_free_gpio(14);
r = -1;
goto exit;
}
/* configure GPIO(14, 15) as outputs */
omap_set_gpio_direction(14, 0);
omap_set_gpio_direction(15, 0);
exit:
DBGLEAVE(1);
return r;
}
static void innovator1610_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
omap_free_gpio(15);
omap_free_gpio(14);
DBGLEAVE(1);
}
static int innovator1610_panel_enable(struct lcd_panel *panel)
{
DBGENTER(1);
/* set GPIO14 and GPIO15 high */
omap_set_gpio_dataout(14, 1);
omap_set_gpio_dataout(15, 1);
DBGLEAVE(1);
return 0;
}
static void innovator1610_panel_disable(struct lcd_panel *panel)
{
DBGENTER(1);
/* set GPIO13, GPIO14 and GPIO15 low */
omap_set_gpio_dataout(14, 0);
omap_set_gpio_dataout(15, 0);
DBGLEAVE(1);
}
static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
static struct lcdc_video_mode mode320x240 = {
.x_res = 320,
.y_res = 240,
.pixel_clock = 12500,
.bpp = 16,
.hsw = 40,
.hfp = 40,
.hbp = 72,
.vsw = 1,
.vfp = 1,
.vbp = 0,
.pcd = 12,
};
struct lcd_panel innovator1610_panel = {
.name = "inn1610",
.config = LCD_PANEL_TFT,
.video_mode = &mode320x240,
.init = innovator1610_panel_init,
.cleanup = innovator1610_panel_cleanup,
.enable = innovator1610_panel_enable,
.disable = innovator1610_panel_disable,
.get_caps= innovator1610_panel_get_caps,
};
/*
* File: drivers/video/omap_new/lcd-osk.c
*
* LCD panel support for the TI OMAP OSK board
*
* Copyright (C) 2004 Nokia Corporation
* Author: Imre Deak <imre.deak@nokia.com>
* Adapted for OSK by <dirk.behme@de.bosch.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include "omapfb.h"
// #define OMAPFB_DBG 1
#include "debug.h"
static int osk_panel_init(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
return 0;
}
static void osk_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static int osk_panel_enable(struct lcd_panel *panel)
{
DBGENTER(1);
/* configure PWL pin */
omap_cfg_reg(PWL);
/* Enable PWL unit */
omap_writeb(0x01, OMAP16XX_PWL_CLK_ENABLE);
/* Set PWL level */
omap_writeb(0xFF, OMAP16XX_PWL_ENABLE);
/* configure GPIO2 as output */
omap_set_gpio_direction(2, 0);
/* set GPIO2 high */
omap_set_gpio_dataout(2, 1);
DBGLEAVE(1);
return 0;
}
static void osk_panel_disable(struct lcd_panel *panel)
{
DBGENTER(1);
/* Set PWL level to zero */
omap_writeb(0x00, OMAP16XX_PWL_ENABLE);
/* Disable PWL unit */
omap_writeb(0x00, OMAP16XX_PWL_CLK_ENABLE);
/* set GPIO2 low */
omap_set_gpio_dataout(2, 0);
DBGLEAVE(1);
}
static unsigned long osk_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
static struct lcdc_video_mode mode240x320 = {
.x_res = 240,
.y_res = 320,
.pixel_clock = 12500,
.bpp = 16,
.hsw = 40,
.hfp = 40,
.hbp = 72,
.vsw = 1,
.vfp = 1,
.vbp = 0,
.pcd = 12,
};
struct lcd_panel osk_panel = {
.name = "osk",
.config = LCD_PANEL_TFT,
.video_mode = &mode240x320,
.init = osk_panel_init,
.cleanup = osk_panel_cleanup,
.enable = osk_panel_enable,
.disable = osk_panel_disable,
.get_caps= osk_panel_get_caps,
};
/*
* File: drivers/video/omap_new/lcd-p2.c
*
* LCD panel support for the TI OMAP P2 board
*
* Authors:
* jekyll <jekyll@mail.jekyll.idv.tw>
* B Jp <lastjp_fr@yahoo.fr>
* Brian Swetland <swetland@android.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <asm/arch/mux.h>
#include <asm/arch/gpio.h>
#include "omapfb.h"
/*
* File: epson-md-tft.h
*
* This file contains definitions for Epsons MD-TF LCD Module
*
* Copyright (C) 2004 MPC-Data Limited (http://www.mpc-data.co.uk)
* Author: Dave Peverley <dpeverley at mpc-data.co.uk>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Please report all bugs and problems to the author.
*
*/
/* LCD uWire commands & params
* All values from Epson
*/
#define LCD_DISON 0xAF
#define LCD_DISOFF 0xAE
#define LCD_DISNOR 0xA6
#define LCD_DISINV 0xA7
#define LCD_DISCTL 0xCA
#define LCD_GCP64 0xCB
#define LCD_GCP16 0xCC
#define LCD_GSSET 0xCD
#define LCD_SLPIN 0x95
#define LCD_SLPOUT 0x94
#define LCD_SD_PSET 0x75
#define LCD_MD_PSET 0x76
#define LCD_SD_CSET 0x15
#define LCD_MD_CSET 0x16
#define LCD_DATCTL 0xBC
#define LCD_RAMWR 0x5C
#define LCD_RAMRD 0x5D
#define LCD_PTLIN 0xA8
#define LCD_PTLOUT 0xA9
#define LCD_ASCSET 0xAA
#define LCD_SCSTART 0xAB
#define LCD_VOLCTL 0xC6
#define LCD_NOP 0x25
#define LCD_OSCISEL 0x7
#define LCD_3500KSET 0xD1
#define LCD_3500KEND 0xD2
#define LCD_14MSET 0xD3
#define LCD_14MEND 0xD4
#define INIT_3500KSET 0x45
#define INIT_14MSET 0x4B
#define INIT_DATCTL 0x08 /* 6.6.6 bits for D-Sample */
#define INIT_OSCISEL 0x05
#define INIT_VOLCTL 0x77 /* Nominel "volume" */
#define INIT_VOLCTL_Ton 0x98 /* Activate power-IC timer */
#define INIT_GSSET 0x00
const unsigned short INIT_DISCTL[11] =
{
0xDE, 0x01, 0x64, 0x00, 0x1B, 0xF4, 0x00, 0xDC, 0x00, 0x02, 0x00
};
const unsigned short INIT_GCP64[126] =
{
0x3B,0x00,0x42,0x00,0x4A,0x00,0x51,0x00,
0x58,0x00,0x5F,0x00,0x66,0x00,0x6E,0x00,
0x75,0x00,0x7C,0x00,0x83,0x00,0x8A,0x00,
0x92,0x00,0x99,0x00,0xA0,0x00,0xA7,0x00,
0xAE,0x00,0xB6,0x00,0xBD,0x00,0xC4,0x00,
0xCB,0x00,0xD2,0x00,0xDA,0x00,0xE1,0x00,
0xE8,0x00,0xEF,0x00,0xF6,0x00,0xFE,0x00,
0x05,0x01,0x0C,0x01,0x13,0x01,0x1A,0x01,
0x22,0x01,0x29,0x01,0x30,0x01,0x37,0x01,
0x3E,0x01,0x46,0x01,0x4D,0x01,0x54,0x01,
0x5B,0x01,0x62,0x01,0x6A,0x01,0x71,0x01,
0x78,0x01,0x7F,0x01,0x86,0x01,0x8E,0x01,
0x95,0x01,0x9C,0x01,0xA3,0x01,0xAA,0x01,
0xB2,0x01,0xB9,0x01,0xC0,0x01,0xC7,0x01,
0xCE,0x01,0xD6,0x01,0xDD,0x01,0xE4,0x01,
0xEB,0x01,0xF2,0x01,0xFA,0x01
};
const unsigned short INIT_GCP16[15] =
{
0x1A,0x31,0x48,0x54,0x5F,0x67,0x70,0x76,0x7C,0x80,0x83,0x84,0x85,0x87,0x96
};
const unsigned short INIT_MD_PSET[4] = { 0, 0, 219, 0 };
const unsigned short INIT_MD_CSET[4] = { 2, 0, 177, 0 };
const unsigned short INIT_SD_PSET[4] = { 0x00, 0x01, 0x00, 0x01 };
const unsigned short INIT_SD_CSET[4] = { 0x00, 0x02, 0x00, 0x02 };
const unsigned short INIT_ASCSET[7] = { 0x00, 0x00, 0xDB, 0x00, 0xDC, 0x00, 0x01 };
const unsigned short INIT_SCSTART[2] = { 0x00, 0x00 };
/* ----- end of epson_md_tft.h ----- */
#include "debug.h"
#include "../drivers/ssi/omap-uwire.h"
#define LCD_UWIRE_CS 0
static int p2_panel_init(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
return 0;
}
static void p2_panel_cleanup(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static int p2_panel_enable(struct lcd_panel *panel)
{
int i;
unsigned long value;
DBGENTER(1);
/* thwack the reset line */
omap_set_gpio_direction(19, 0);
omap_set_gpio_dataout(19, 0);
mdelay(2);
omap_set_gpio_dataout(19, 1);
/* bits 31:28 -> 0 LCD_PXL_15 .. 12 */
value = omap_readl(OMAP730_IO_CONF_3) & 0x0FFFFFFF;
omap_writel(value, OMAP730_IO_CONF_3);
/* bits 19:0 -> 0 LCD_VSYNC, AC, PXL_0, PCLK, HSYNC,
** PXL_9..1, PXL_10, PXL_11
*/
value = omap_readl(OMAP730_IO_CONF_4) & 0xFFF00000;
omap_writel(value, OMAP730_IO_CONF_4);
omap_uwire_configure_mode(0,16);
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DISOFF, 9, 0,NULL,1);
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_SLPIN, 9, 0,NULL,1);
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DISNOR, 9, 0,NULL,1);
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_GSSET, 9, 0,NULL,1);
omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_GSSET | 0x100), 9, 0,NULL,1);
/* DISCTL */
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DISCTL, 9, 0,NULL,1);
for (i = 0; i < (sizeof(INIT_DISCTL)/sizeof(unsigned short)); i++)
omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_DISCTL[i] | 0x100), 9, 0,NULL,1);
/* GCP64 */
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_GCP64, 9, 0,NULL,1);
for (i = 0; i < (sizeof(INIT_GCP64)/sizeof(unsigned short)); i++)
omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_GCP64[i] | 0x100), 9, 0,NULL,1);
/* GCP16 */
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_GCP16, 9, 0,NULL,1);
for (i = 0; i < (sizeof(INIT_GCP16)/sizeof(unsigned short)); i++)
omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_GCP16[i] | 0x100), 9, 0,NULL,1);
/* MD_CSET */
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_MD_CSET, 9, 0,NULL,1);
for (i = 0; i < (sizeof(INIT_MD_CSET)/sizeof(unsigned short)); i++)
omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_MD_CSET[i] | 0x100), 9, 0,NULL,1);
/* MD_PSET */
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_MD_PSET, 9, 0,NULL,1);
for (i = 0; i < (sizeof(INIT_MD_PSET)/sizeof(unsigned short)); i++)
omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_MD_PSET[i] | 0x100), 9, 0,NULL,1);
/* SD_CSET */
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_SD_CSET, 9, 0,NULL,1);
for (i = 0; i < (sizeof(INIT_SD_CSET)/sizeof(unsigned short)); i++)
omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_SD_CSET[i] | 0x100), 9, 0,NULL,1);
/* SD_PSET */
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_SD_PSET, 9, 0,NULL,1);
for (i = 0; i < (sizeof(INIT_SD_PSET)/sizeof(unsigned short)); i++)
omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_SD_PSET[i] | 0x100), 9, 0,NULL,1);
/* DATCTL */
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DATCTL, 9, 0,NULL,1);
omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_DATCTL | 0x100), 9, 0,NULL,1);
/* OSSISEL = d'5 */
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_OSCISEL, 9, 0,NULL,1);
omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_OSCISEL | 0x100), 9, 0,NULL,1);
/* 14MSET = d'74 */
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_14MSET, 9, 0,NULL,1);
omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_14MSET | 0x100), 9, 0,NULL,1);
/* 14MEND */
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_14MEND, 9, 0,NULL,1);
/* 3500KSET = d'69 */
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_3500KSET, 9, 0,NULL,1);
omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_3500KSET | 0x100), 9, 0,NULL,1);
/* 3500KEND */
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_3500KEND, 9, 0,NULL,1);
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_SLPOUT, 9, 0,NULL,1);
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_VOLCTL, 9, 0,NULL,1);
omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_VOLCTL_Ton | 0x100), 9, 0,NULL,1);
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_VOLCTL, 9, 0,NULL,1);
omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_VOLCTL | 0x100), 9, 0,NULL,1);
omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DISON, 9, 0,NULL,1);
/* enable backlight */
omap_set_gpio_direction(134, 0);
omap_set_gpio_dataout(134, 1);
DBGLEAVE(1);
return 0;
}
static void p2_panel_disable(struct lcd_panel *panel)
{
DBGENTER(1);
DBGLEAVE(1);
}
static unsigned long p2_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
static struct lcdc_video_mode mode176x220 = {
.x_res = 176,
.y_res = 220,
.pixel_clock = 12500,
.bpp = 16,
.hsw = 5,
.hfp = 1,
.hbp = 1,
.vsw = 2,
.vfp = 12,
.vbp = 1,
.pcd = 4,
.flags = OMAP_LCDC_INV_PIX_CLOCK,
};
struct lcd_panel p2_panel = {
.name = "p2",
.config = LCD_PANEL_TFT,
.video_mode = &mode176x220,
.init = p2_panel_init,
.cleanup = p2_panel_cleanup,
.enable = p2_panel_enable,
.disable = p2_panel_disable,
.get_caps= p2_panel_get_caps,
};
This diff is collapsed.
/*
* File: drivers/video/omap_new/omapfb.c
*
* Framebuffer driver for TI OMAP boards
*
* Copyright (C) 2004 Nokia Corporation
* Author: Imre Deak <imre.deak@nokia.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __OMAPFB_H
#define __OMAPFB_H
/* IOCTL commands. */
#define OMAP_IOW(num, dtype) _IOW('O', num, dtype)
#define OMAP_IOR(num, dtype) _IOR('O', num, dtype)
#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype)
#define OMAP_IO(num) _IO('O', num)
#define OMAPFB_FILLRECT OMAP_IOW(0, struct fb_fillrect)
#define OMAPFB_COPYAREA OMAP_IOW(1, struct fb_copyarea)
#define OMAPFB_IMAGEBLIT OMAP_IOW(2, struct fb_image)
#define OMAPFB_TRANSPARENT_BLIT OMAP_IOW(30, struct fb_image)
#define OMAPFB_MIRROR OMAP_IOW(31, int)
#define OMAPFB_SCALE OMAP_IOW(32, struct fb_scale)
#define OMAPFB_SELECT_VIS_FRAME OMAP_IOW(33, int)
#define OMAPFB_SELECT_SRC_FRAME OMAP_IOW(34, int)
#define OMAPFB_SELECT_DST_FRAME OMAP_IOW(35, int)
#define OMAPFB_GET_FRAME_OFFSET OMAP_IOWR(36, struct fb_frame_offset)
#define OMAPFB_SYNC_GFX OMAP_IO(37)
#define OMAPFB_VSYNC OMAP_IO(38)
#define OMAPFB_LATE_ACTIVATE OMAP_IO(39)
#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, enum fb_update_mode)
#define OMAPFB_UPDATE_WINDOW OMAP_IOW(41, struct fb_update_window)
#define OMAPFB_GET_CAPS OMAP_IOR(42, unsigned long)
#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, enum fb_update_mode)
#define OMAPFB_GET_GFX_STATUS OMAP_IOR(44, unsigned long)
#define FBCAPS_GENERIC_MASK 0x00000fff
#define FBCAPS_LCDC_MASK 0x00fff000
#define FBCAPS_PANEL_MASK 0xff000000
#define FBCAPS_MANUAL_UPDATE 0x00001000
#define FBCAPS_SET_BACKLIGHT 0x01000000
enum omapfb_gfx_status {
OMAPFB_GFX_STATUS_OK = 0,
OMAPFB_GFX_STATUS_CHANGED
};
#define OMAPFB_UPDATE_FAILED 0x01
#define OMAPFB_FILLRECT_FAILED 0x02
#define OMAPFB_COPYAREA_FAILED 0x04
#define OMAPFB_IMGBLIT_FAILED 0x08
struct fb_copyarea_ext {
__u32 dx;
__u32 dy;
__u32 width;
__u32 height;
__u32 sx;
__u32 sy;
__u32 trans_color;
__u32 rev_dir;
};
struct fb_scale {
unsigned int xscale, yscale;
};
struct fb_frame_offset {
unsigned int idx;
unsigned long offset;
};
struct fb_update_window {
unsigned int x, y;
unsigned int width, height;
};
enum fb_update_mode {
FB_UPDATE_DISABLED = 0,
FB_AUTO_UPDATE,
FB_MANUAL_UPDATE
};
#ifdef __KERNEL__
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
#define OMAPFB_DEVICE "omapfb"
#define OMAPFB_DRIVER "omapfb"
#define PRNERR(fmt, args...) printk(KERN_ERR OMAPFB_DRIVER ": " fmt, ## args)
#define GFX_FIFO_SIZE 2
#define LCD_PANEL_TFT 0x01
#define OMAP_LCDC_INV_VSYNC 0x01
#define OMAP_LCDC_INV_HSYNC 0x02
#define OMAP_LCDC_INV_PIX_CLOCK 0x04
#define OMAP_LCDC_INV_OUTPUT_EN 0x08
#define OMAP_LCDC_HSVS_RISING_EDGE 0x10
#define OMAP_LCDC_HSVS_OPPOSITE 0x20
struct lcdc_video_mode {
u16 x_res, y_res;
u32 pixel_clock; /* In kHz */
int bpp;
u8 hsw; /* Horizontal synchronization pulse width */
u8 hfp; /* Horizontal front porch */
u8 hbp; /* Horizontal back porch */
u8 vsw; /* Vertical synchronization pulse width */
u8 vfp; /* Vertical front porch */
u8 vbp; /* Vertical back porch */
u8 acb; /* ac-bias pin frequency */
u8 pcd; /* Pixel clock divider (this will change) */
u8 flags;
};
struct lcd_panel {
const char *name;
int config;
int signals;
struct lcdc_video_mode *video_mode;
int (*init) (struct lcd_panel *panel);
void (*cleanup) (struct lcd_panel *panel);
int (*enable) (struct lcd_panel *panel);
void (*disable) (struct lcd_panel *panel);
unsigned long (*get_caps)(struct lcd_panel *panel);
int (*set_bklight_level)(struct lcd_panel *panel,
unsigned int level);
unsigned int (*get_bklight_level)(struct lcd_panel *panel);
unsigned int (*get_bklight_max) (struct lcd_panel *panel);
};
struct omapfb_device;
struct lcd_ctrl {
const char *name;
void *data;
int (*init) (struct omapfb_device *fbdev);
void (*cleanup) (struct omapfb_device *fbdev);
void (*get_mem_layout) (struct omapfb_device *fbdev,
unsigned long *size,
unsigned long *fb_org);
unsigned long (*get_caps) (struct omapfb_device *fbdev);
int (*set_update_mode)(struct omapfb_device *fbdev,
enum fb_update_mode mode);
enum fb_update_mode (*get_update_mode)(struct omapfb_device *fbdev);
int (*update_window) (struct omapfb_device *fbdev,
struct fb_update_window *win);
void (*suspend) (struct omapfb_device *fbdev);
void (*resume) (struct omapfb_device *fbdev);
void (*change_mode) (struct omapfb_device *fbdev);
};
enum omapfb_state {
OMAPFB_DISABLED = 0,
OMAPFB_SUSPENDED= 99,
OMAPFB_ACTIVE = 100
};
struct gfx_lchannel {
int lch_num;
struct gfx_lchannel *next, *prev;
};
struct gfx_dma {
spinlock_t spinlock;
struct completion sync_complete; /* Signalled when the
fifo gets empty */
volatile int done; /* Indicates the
end of a DMA chain
transfer */
struct gfx_lchannel fifo[GFX_FIFO_SIZE];
struct gfx_lchannel *f_head, *f_tail; /* Process and insert
points on the
fifo */
struct gfx_lchannel *f_chain_end; /* Points to the new
chain end */
struct semaphore f_free; /* # of free lch-s */
int f_run; /* # of active lch-s */
int f_wait; /* # of lch-s
waiting */
struct tasklet_struct dequeue_tasklet; /* Processes new DMA
chain transfers on
the fifo */
};
#define OMAPFB_RQUEUE_SIZE 20
struct omapfb_fillrect_params
{
struct fb_info *fbi;
struct fb_fillrect rect;
};
struct omapfb_copyarea_params
{
struct fb_info *fbi;
struct fb_copyarea_ext area;
};
struct omapfb_update_window_params
{
struct fb_info *fbi;
struct fb_update_window win;
};
struct omapfb_imageblit_params
{
struct fb_info *fbi;
struct fb_image image;
int flags;
};
union req_params
{
/* All possible requests are to be listed here */
struct omapfb_fillrect_params fillrect;
struct omapfb_copyarea_params copyarea;
struct omapfb_update_window_params update_window;
struct omapfb_imageblit_params imageblit;
};
struct omapfb_request
{
struct list_head entry;
int (*function)(void *par);
union req_params par;
};
struct omapfb_rqueue
{
spinlock_t lock;
struct list_head free_list;
struct list_head pending_list;
struct completion rqueue_empty;
struct semaphore free_sema;
struct omapfb_request req_pool[OMAPFB_RQUEUE_SIZE];
struct work_struct work;
unsigned long status;
};
struct omapfb_device {
int state;
int ext_lcdc; /* Using external
LCD controller */
void *lcddma_base; /* MPU virtual
address */
dma_addr_t lcddma_handle; /* Bus physical
address */
unsigned long lcddma_mem_size;
unsigned long palette_org; /* Palette offset into
lcddma_base/handle */
unsigned long frame0_org, frame1_org; /* Frame offsets for
back and front
frame buffers into
lcddma_base/handle */
unsigned long vis_frame_org; /* Offset of visible
frame buffer.
= frame0/1_org */
unsigned long src_frame_org; /* Offset of source
frame for drawing
operations.
= frame0/1_org */
unsigned long dst_frame_org; /* Offset of dest
frame for drawing
operations.
= frame0/1_org */
unsigned long view_org; /* View offset into
lcddma_base/handle+
vis_frame_org.
Used for panning */
unsigned long palette_size;
int xscale, yscale, mirror; /* transformations.
rotate is stored in
fb_info->var */
u32 pseudo_palette[17];
struct gfx_dma gfx; /* Accelerator */
struct omapfb_rqueue rqueue;
struct lcd_panel *panel; /* LCD panel */
struct lcd_ctrl *ctrl; /* LCD controller */
struct fb_info *fb_info; /* Linux fbdev
framework data */
struct device *dev;
};
extern struct lcd_panel h3_panel;
extern struct lcd_panel h2_panel;
extern struct lcd_panel p2_panel;
extern struct lcd_panel osk_panel;
extern struct lcd_panel innovator1610_panel;
extern struct lcd_panel innovator1510_panel;
extern struct lcd_ctrl omapfb_lcdc_ctrl;
#endif /* __KERNEL__ */
#endif /* __OMAPFB_H */
This diff is collapsed.
/*
* File: drivers/video/omap_new/omapfb_main.c
*
* Special optimiSed Screen Interface driver for TI OMAP boards
*
* Copyright (C) 2004 Nokia Corporation
* Author: Juha Yrjl <juha.yrjola@nokia.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <asm/io.h>
#include "sossi.h"
#define OMAP_SOSSI_BASE 0xfffbac00
#define SOSSI_ID_REG 0x00
#define SOSSI_INIT1_REG 0x04
#define SOSSI_INIT2_REG 0x08
#define SOSSI_INIT3_REG 0x0c
#define SOSSI_FIFO_REG 0x10
#define SOSSI_REOTABLE_REG 0x14
#define SOSSI_TEARING_REG 0x18
#define SOSSI_INIT1B_REG 0x1c
#define SOSSI_FIFOB_REG 0x20
#define DMA_GSCR 0xfffedc04
#define DMA_LCD_CCR 0xfffee3c2
#define DMA_LCD_CTRL 0xfffee3c4
#define DMA_LCD_LCH_CTRL 0xfffee3ea
static int sossi_base = IO_ADDRESS(OMAP_SOSSI_BASE);
static inline u32 sossi_read_reg(int reg)
{
return readl(sossi_base + reg);
}
static inline u16 sossi_read_reg16(int reg)
{
return readw(sossi_base + reg);
}
static inline u8 sossi_read_reg8(int reg)
{
return readb(sossi_base + reg);
}
static inline void sossi_write_reg(int reg, u32 value)
{
writel(value, sossi_base + reg);
}
static inline void sossi_write_reg16(int reg, u16 value)
{
writew(value, sossi_base + reg);
}
static inline void sossi_write_reg8(int reg, u8 value)
{
writeb(value, sossi_base + reg);
}
static void sossi_set_bits(int reg, u32 bits)
{
sossi_write_reg(reg, sossi_read_reg(reg) | bits);
}
static void sossi_clear_bits(int reg, u32 bits)
{
sossi_write_reg(reg, sossi_read_reg(reg) & ~bits);
}
#if 1
void sossi_dump(void)
{
printk(" INIT1: 0x%08x\n", sossi_read_reg(SOSSI_INIT1_REG));
printk(" INIT2: 0x%08x\n", sossi_read_reg(SOSSI_INIT2_REG));
printk(" INIT3: 0x%08x\n", sossi_read_reg(SOSSI_INIT3_REG));
printk(" TEARING: 0x%08x\n", sossi_read_reg(SOSSI_TEARING_REG));
printk(" INIT1B: 0x%08x\n", sossi_read_reg(SOSSI_INIT1B_REG));
}
#endif
static void sossi_dma_init(void)
{
/* OMAP3.1 mapping disable */
omap_writel(omap_readl(DMA_GSCR) | (1 << 3), DMA_GSCR);
/* Logical channel type to b0100 */
omap_writew(omap_readw(DMA_LCD_LCH_CTRL) | (1 << 2), DMA_LCD_LCH_CTRL);
/* LCD_DMA dest port to 1 */
omap_writew(omap_readw(DMA_LCD_CTRL) | (1 << 8), DMA_LCD_CTRL);
/* LCD_CCR OMAP31 comp mode */
omap_writew(omap_readw(DMA_LCD_CCR) | (1 << 10), DMA_LCD_CCR);
}
#define MOD_CONF_CTRL_1 0xfffe1110
#define CONF_SOSSI_RESET_R (1 << 23)
#define CONF_MOD_SOSSI_CLK_EN_R (1 << 16)
int sossi_init(void)
{
u32 l, k;
/* Reset and enable the SoSSI module */
l = omap_readl(MOD_CONF_CTRL_1);
l |= CONF_SOSSI_RESET_R;
omap_writel(l, MOD_CONF_CTRL_1);
l &= ~CONF_SOSSI_RESET_R;
omap_writel(l, MOD_CONF_CTRL_1);
l |= CONF_MOD_SOSSI_CLK_EN_R;
/* FIXME: Hardcode divide ratio 3 */
l |= 2 << 17;
omap_writel(l, MOD_CONF_CTRL_1);
omap_writel(omap_readl(ARM_IDLECT2) | (1 << 11), ARM_IDLECT2);
omap_writel(omap_readl(ARM_IDLECT1) | (1 << 6), ARM_IDLECT1);
sossi_dma_init();
l = sossi_read_reg(SOSSI_INIT2_REG);
/* Enable and reset the SoSSI block */
l |= (1 << 0) | (1 << 1);
sossi_write_reg(SOSSI_INIT2_REG, l);
/* Take SoSSI out of reset */
l &= ~(1 << 1);
sossi_write_reg(SOSSI_INIT2_REG, l);
sossi_write_reg(SOSSI_ID_REG, 0);
l = sossi_read_reg(SOSSI_ID_REG);
k = sossi_read_reg(SOSSI_ID_REG);
if (l != 0x55555555 || k != 0xaaaaaaaa) {
printk(KERN_ERR "Invalid SoSSI sync pattern: %08x, %08x\n", l, k);
return -ENODEV;
}
l = sossi_read_reg(SOSSI_ID_REG); /* Component code */
l = sossi_read_reg(SOSSI_ID_REG);
printk(KERN_INFO "SoSSI rev. %d.%d initialized\n", l >> 16, l & 0xffff);
l = sossi_read_reg(SOSSI_INIT1_REG);
l |= (1 << 19); /* DMA_MODE */
l &= ~(1 << 31); /* REORDERING */
sossi_write_reg(SOSSI_INIT1_REG, l);
return 0;
}
static void set_timings(int tw0, int tw1)
{
u32 l;
l = sossi_read_reg(SOSSI_INIT1_REG);
l &= ~((0x0f << 20) | (0x3f << 24));
l |= ((tw0 & 0x0f) << 20) | ((tw1 & 0x3f) << 24);
sossi_write_reg(SOSSI_INIT1_REG, l);
}
static struct sossi {
int bus_pick_width;
} sossi;
void sossi_set_xfer_params(int tw0, int tw1, int bus_pick_count, int bus_pick_width)
{
u32 l;
set_timings(tw0, tw1);
sossi.bus_pick_width = bus_pick_width;
l = ((bus_pick_count - 1) << 5) | ((bus_pick_width - 1) & 0x1f);
sossi_write_reg(SOSSI_INIT3_REG, l);
}
void sossi_start_transfer(void)
{
/* WE */
sossi_clear_bits(SOSSI_INIT2_REG, 1 << 4);
/* CS active low */
sossi_clear_bits(SOSSI_INIT1_REG, 1 << 30);
/* FIXME: locking? */
}
void sossi_stop_transfer(void)
{
/* WE */
sossi_set_bits(SOSSI_INIT2_REG, 1 << 4);
/* CS active low */
sossi_set_bits(SOSSI_INIT1_REG, 1 << 30);
/* FIXME: locking? */
}
static void send_data(const void *data, unsigned int len)
{
while (len >= 4) {
sossi_write_reg(SOSSI_FIFO_REG, *(const u32 *) data);
len -= 4;
data += 4;
}
while (len >= 2) {
sossi_write_reg16(SOSSI_FIFO_REG, *(const u16 *) data);
len -= 2;
data += 2;
}
while (len) {
sossi_write_reg8(SOSSI_FIFO_REG, *(const u8 *) data);
len--;
data++;
}
}
static void set_cycles(unsigned int len)
{
int nr_cycles = len / (sossi.bus_pick_width / 8);
sossi_clear_bits(SOSSI_INIT1_REG, 0x3ffff);
sossi_set_bits(SOSSI_INIT1_REG, (nr_cycles - 1) & 0x3ffff);
}
void sossi_send_cmd(const void *data, unsigned int len)
{
sossi_clear_bits(SOSSI_INIT1_REG, 1 << 18);
set_cycles(len);
send_data(data, len);
}
void sossi_send_data(const void *data, unsigned int len)
{
sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
set_cycles(len);
send_data(data, len);
}
void sossi_prepare_dma_transfer(unsigned int count)
{
sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
set_cycles(count);
}
void sossi_send_data_const32(u32 data, unsigned int count)
{
sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
set_cycles(count * 4);
while (count > 0) {
sossi_write_reg(SOSSI_FIFO_REG, data);
count--;
}
}
void sossi_set_tearing(int mode, int hs_counter, int detect_limit,
int vs_counter, int vs_detect_limit, int flags)
{
u32 l = 0;
l |= vs_counter << 30;
if (flags & SOSSI_FLAG_HS_INVERTED)
l |= 1 << 29;
if (flags & SOSSI_FLAG_VS_INVERTED)
l |= 1 << 28;
l |= mode << 26;
l |= hs_counter << 15;
l |= vs_detect_limit << 3;
l |= detect_limit;
sossi_write_reg(SOSSI_TEARING_REG, l);
}
void sossi_read_data(void *data, unsigned int len)
{
/* Before reading we must check if some writings are going on */
while (!(sossi_read_reg(SOSSI_INIT2_REG) & (1 << 3)));
sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
set_cycles(len);
while (len >= 4) {
*(u32 *) data = sossi_read_reg(SOSSI_FIFO_REG);
len -= 4;
data += 4;
}
while (len >= 2) {
*(u16 *) data = sossi_read_reg16(SOSSI_FIFO_REG);
len -= 2;
data += 2;
}
while (len) {
*(u8 *) data = sossi_read_reg8(SOSSI_FIFO_REG);
len--;
data++;
}
}
#ifndef DRIVERS_VIDEO_OMAP_SOSSI_H
#define DRIVERS_VIDEO_OMAP_SOSSI_H
#define SOSSI_FLAG_HS_INVERTED 0x01
#define SOSSI_FLAG_VS_INVERTED 0x02
extern int sossi_init(void);
extern void sossi_set_xfer_params(int tw0, int tw1, int bus_pick_count, int bus_pick_width);
extern void sossi_start_transfer(void);
extern void sossi_stop_transfer(void);
extern void sossi_send_cmd(const void *data, unsigned int len);
extern void sossi_send_data(const void *data, unsigned int len);
extern void sossi_send_data_const32(u32 data, unsigned int count);
extern void sossi_prepare_dma_transfer(unsigned int count);
extern void sossi_read_data(void *data, unsigned int len);
extern void sossi_set_tearing(int mode, int hs_counter, int detect_limit,
int vs_counter, int vs_detect_limit, int flags);
#endif
...@@ -107,6 +107,7 @@ ...@@ -107,6 +107,7 @@
#define FB_ACCEL_NV_20 44 /* nVidia Arch 20 */ #define FB_ACCEL_NV_20 44 /* nVidia Arch 20 */
#define FB_ACCEL_NV_30 45 /* nVidia Arch 30 */ #define FB_ACCEL_NV_30 45 /* nVidia Arch 30 */
#define FB_ACCEL_NV_40 46 /* nVidia Arch 40 */ #define FB_ACCEL_NV_40 46 /* nVidia Arch 40 */
#define FB_ACCEL_OMAP1610 47 /* TI OMAP16xx */
#define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */ #define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */
#define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */ #define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */
#define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */ #define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment