提交 aa2cf420 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of git://gitorious.org/linux-omap-dss2/linux

* 'for-linus' of git://gitorious.org/linux-omap-dss2/linux:
  MAINTAINERS: Add OMAP2/3 DSS and OMAPFB maintainer
  OMAP: SDP: Enable DSS2 for OMAP3 SDP board
  OMAP: DSS2: Taal DSI command mode panel driver
  OMAP: DSS2: Add generic and Sharp panel drivers
  OMAP: DSS2: omapfb driver
  OMAP: DSS2: DSI driver
  OMAP: DSS2: SDI driver
  OMAP: DSS2: RFBI driver
  OMAP: DSS2: Video encoder driver
  OMAP: DSS2: DPI driver
  OMAP: DSS2: DISPC
  OMAP: DSS2: Add more core files
  OMAP: DSS2: Display Subsystem Driver core
  OMAP: DSS2: Documentation for DSS2
  OMAP: Add support for VRFB rotation engine
  OMAP: Add VRAM manager
  OMAP: OMAPFB: add omapdss device
  OMAP: OMAPFB: split omapfb.h
  OMAP2: Add funcs for writing SMS_ROT_* registers
OMAP2/3 Display Subsystem
-------------------------
This is an almost total rewrite of the OMAP FB driver in drivers/video/omap
(let's call it DSS1). The main differences between DSS1 and DSS2 are DSI,
TV-out and multiple display support, but there are lots of small improvements
also.
The DSS2 driver (omapdss module) is in arch/arm/plat-omap/dss/, and the FB,
panel and controller drivers are in drivers/video/omap2/. DSS1 and DSS2 live
currently side by side, you can choose which one to use.
Features
--------
Working and tested features include:
- MIPI DPI (parallel) output
- MIPI DSI output in command mode
- MIPI DBI (RFBI) output
- SDI output
- TV output
- All pieces can be compiled as a module or inside kernel
- Use DISPC to update any of the outputs
- Use CPU to update RFBI or DSI output
- OMAP DISPC planes
- RGB16, RGB24 packed, RGB24 unpacked
- YUV2, UYVY
- Scaling
- Adjusting DSS FCK to find a good pixel clock
- Use DSI DPLL to create DSS FCK
Tested boards include:
- OMAP3 SDP board
- Beagle board
- N810
omapdss driver
--------------
The DSS driver does not itself have any support for Linux framebuffer, V4L or
such like the current ones, but it has an internal kernel API that upper level
drivers can use.
The DSS driver models OMAP's overlays, overlay managers and displays in a
flexible way to enable non-common multi-display configuration. In addition to
modelling the hardware overlays, omapdss supports virtual overlays and overlay
managers. These can be used when updating a display with CPU or system DMA.
Panel and controller drivers
----------------------------
The drivers implement panel or controller specific functionality and are not
usually visible to users except through omapfb driver. They register
themselves to the DSS driver.
omapfb driver
-------------
The omapfb driver implements arbitrary number of standard linux framebuffers.
These framebuffers can be routed flexibly to any overlays, thus allowing very
dynamic display architecture.
The driver exports some omapfb specific ioctls, which are compatible with the
ioctls in the old driver.
The rest of the non standard features are exported via sysfs. Whether the final
implementation will use sysfs, or ioctls, is still open.
V4L2 drivers
------------
V4L2 is being implemented in TI.
From omapdss point of view the V4L2 drivers should be similar to framebuffer
driver.
Architecture
--------------------
Some clarification what the different components do:
- Framebuffer is a memory area inside OMAP's SRAM/SDRAM that contains the
pixel data for the image. Framebuffer has width and height and color
depth.
- Overlay defines where the pixels are read from and where they go on the
screen. The overlay may be smaller than framebuffer, thus displaying only
part of the framebuffer. The position of the overlay may be changed if
the overlay is smaller than the display.
- Overlay manager combines the overlays in to one image and feeds them to
display.
- Display is the actual physical display device.
A framebuffer can be connected to multiple overlays to show the same pixel data
on all of the overlays. Note that in this case the overlay input sizes must be
the same, but, in case of video overlays, the output size can be different. Any
framebuffer can be connected to any overlay.
An overlay can be connected to one overlay manager. Also DISPC overlays can be
connected only to DISPC overlay managers, and virtual overlays can be only
connected to virtual overlays.
An overlay manager can be connected to one display. There are certain
restrictions which kinds of displays an overlay manager can be connected:
- DISPC TV overlay manager can be only connected to TV display.
- Virtual overlay managers can only be connected to DBI or DSI displays.
- DISPC LCD overlay manager can be connected to all displays, except TV
display.
Sysfs
-----
The sysfs interface is mainly used for testing. I don't think sysfs
interface is the best for this in the final version, but I don't quite know
what would be the best interfaces for these things.
The sysfs interface is divided to two parts: DSS and FB.
/sys/class/graphics/fb? directory:
mirror 0=off, 1=on
rotate Rotation 0-3 for 0, 90, 180, 270 degrees
rotate_type 0 = DMA rotation, 1 = VRFB rotation
overlays List of overlay numbers to which framebuffer pixels go
phys_addr Physical address of the framebuffer
virt_addr Virtual address of the framebuffer
size Size of the framebuffer
/sys/devices/platform/omapdss/overlay? directory:
enabled 0=off, 1=on
input_size width,height (ie. the framebuffer size)
manager Destination overlay manager name
name
output_size width,height
position x,y
screen_width width
global_alpha global alpha 0-255 0=transparent 255=opaque
/sys/devices/platform/omapdss/manager? directory:
display Destination display
name
alpha_blending_enabled 0=off, 1=on
trans_key_enabled 0=off, 1=on
trans_key_type gfx-destination, video-source
trans_key_value transparency color key (RGB24)
default_color default background color (RGB24)
/sys/devices/platform/omapdss/display? directory:
ctrl_name Controller name
mirror 0=off, 1=on
update_mode 0=off, 1=auto, 2=manual
enabled 0=off, 1=on
name
rotate Rotation 0-3 for 0, 90, 180, 270 degrees
timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw)
When writing, two special timings are accepted for tv-out:
"pal" and "ntsc"
panel_name
tear_elim Tearing elimination 0=off, 1=on
There are also some debugfs files at <debugfs>/omapdss/ which show information
about clocks and registers.
Examples
--------
The following definitions have been made for the examples below:
ovl0=/sys/devices/platform/omapdss/overlay0
ovl1=/sys/devices/platform/omapdss/overlay1
ovl2=/sys/devices/platform/omapdss/overlay2
mgr0=/sys/devices/platform/omapdss/manager0
mgr1=/sys/devices/platform/omapdss/manager1
lcd=/sys/devices/platform/omapdss/display0
dvi=/sys/devices/platform/omapdss/display1
tv=/sys/devices/platform/omapdss/display2
fb0=/sys/class/graphics/fb0
fb1=/sys/class/graphics/fb1
fb2=/sys/class/graphics/fb2
Default setup on OMAP3 SDP
--------------------------
Here's the default setup on OMAP3 SDP board. All planes go to LCD. DVI
and TV-out are not in use. The columns from left to right are:
framebuffers, overlays, overlay managers, displays. Framebuffers are
handled by omapfb, and the rest by the DSS.
FB0 --- GFX -\ DVI
FB1 --- VID1 --+- LCD ---- LCD
FB2 --- VID2 -/ TV ----- TV
Example: Switch from LCD to DVI
----------------------
w=`cat $dvi/timings | cut -d "," -f 2 | cut -d "/" -f 1`
h=`cat $dvi/timings | cut -d "," -f 3 | cut -d "/" -f 1`
echo "0" > $lcd/enabled
echo "" > $mgr0/display
fbset -fb /dev/fb0 -xres $w -yres $h -vxres $w -vyres $h
# at this point you have to switch the dvi/lcd dip-switch from the omap board
echo "dvi" > $mgr0/display
echo "1" > $dvi/enabled
After this the configuration looks like:
FB0 --- GFX -\ -- DVI
FB1 --- VID1 --+- LCD -/ LCD
FB2 --- VID2 -/ TV ----- TV
Example: Clone GFX overlay to LCD and TV
-------------------------------
w=`cat $tv/timings | cut -d "," -f 2 | cut -d "/" -f 1`
h=`cat $tv/timings | cut -d "," -f 3 | cut -d "/" -f 1`
echo "0" > $ovl0/enabled
echo "0" > $ovl1/enabled
echo "" > $fb1/overlays
echo "0,1" > $fb0/overlays
echo "$w,$h" > $ovl1/output_size
echo "tv" > $ovl1/manager
echo "1" > $ovl0/enabled
echo "1" > $ovl1/enabled
echo "1" > $tv/enabled
After this the configuration looks like (only relevant parts shown):
FB0 +-- GFX ---- LCD ---- LCD
\- VID1 ---- TV ---- TV
Misc notes
----------
OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator.
Using DSI DPLL to generate pixel clock it is possible produce the pixel clock
of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI.
Rotation and mirroring currently only supports RGB565 and RGB8888 modes. VRFB
does not support mirroring.
VRFB rotation requires much more memory than non-rotated framebuffer, so you
probably need to increase your vram setting before using VRFB rotation. Also,
many applications may not work with VRFB if they do not pay attention to all
framebuffer parameters.
Kernel boot arguments
---------------------
vram=<size>
- Amount of total VRAM to preallocate. For example, "10M". omapfb
allocates memory for framebuffers from VRAM.
omapfb.mode=<display>:<mode>[,...]
- Default video mode for specified displays. For example,
"dvi:800x400MR-24@60". See drivers/video/modedb.c.
There are also two special modes: "pal" and "ntsc" that
can be used to tv out.
omapfb.vram=<fbnum>:<size>[@<physaddr>][,...]
- VRAM allocated for a framebuffer. Normally omapfb allocates vram
depending on the display size. With this you can manually allocate
more or define the physical address of each framebuffer. For example,
"1:4M" to allocate 4M for fb1.
omapfb.debug=<y|n>
- Enable debug printing. You have to have OMAPFB debug support enabled
in kernel config.
omapfb.test=<y|n>
- Draw test pattern to framebuffer whenever framebuffer settings change.
You need to have OMAPFB debug support enabled in kernel config.
omapfb.vrfb=<y|n>
- Use VRFB rotation for all framebuffers.
omapfb.rotate=<angle>
- Default rotation applied to all framebuffers.
0 - 0 degree rotation
1 - 90 degree rotation
2 - 180 degree rotation
3 - 270 degree rotation
omapfb.mirror=<y|n>
- Default mirror for all framebuffers. Only works with DMA rotation.
omapdss.def_disp=<display>
- Name of default display, to which all overlays will be connected.
Common examples are "lcd" or "tv".
omapdss.debug=<y|n>
- Enable debug printing. You have to have DSS debug support enabled in
kernel config.
TODO
----
DSS locking
Error checking
- Lots of checks are missing or implemented just as BUG()
System DMA update for DSI
- Can be used for RGB16 and RGB24P modes. Probably not for RGB24U (how
to skip the empty byte?)
OMAP1 support
- Not sure if needed
......@@ -3903,6 +3903,23 @@ L: linux-omap@vger.kernel.org
S: Maintained
F: drivers/video/omap/
OMAP DISPLAY SUBSYSTEM SUPPORT (DSS2)
M: Tomi Valkeinen <tomi.valkeinen@nokia.com>
L: linux-omap@vger.kernel.org
L: linux-fbdev@vger.kernel.org (moderated for non-subscribers)
S: Maintained
F: drivers/video/omap2/dss/
F: drivers/video/omap2/vrfb.c
F: drivers/video/omap2/vram.c
F: Documentation/arm/OMAP/DSS
OMAP FRAMEBUFFER SUPPORT (FOR DSS2)
M: Tomi Valkeinen <tomi.valkeinen@nokia.com>
L: linux-omap@vger.kernel.org
L: linux-fbdev@vger.kernel.org (moderated for non-subscribers)
S: Maintained
F: drivers/video/omap2/omapfb/
OMAP MMC SUPPORT
M: Jarkko Lavinen <jarkko.lavinen@nokia.com>
L: linux-omap@vger.kernel.org
......
......@@ -963,10 +963,32 @@ CONFIG_FB_CFB_IMAGEBLIT=y
#
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
CONFIG_FB_OMAP=y
# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
# CONFIG_FB_BROADSHEET is not set
# CONFIG_FB_OMAP_LCD_VGA is not set
# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2
CONFIG_OMAP2_VRAM=y
CONFIG_OMAP2_VRFB=y
CONFIG_OMAP2_DSS=y
CONFIG_OMAP2_VRAM_SIZE=4
CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
# CONFIG_OMAP2_DSS_RFBI is not set
CONFIG_OMAP2_DSS_VENC=y
# CONFIG_OMAP2_DSS_SDI is not set
# CONFIG_OMAP2_DSS_DSI is not set
# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
CONFIG_FB_OMAP2=y
CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
CONFIG_FB_OMAP2_NUM_FBS=3
#
# OMAP2/3 Display Device Drivers
#
CONFIG_PANEL_GENERIC=y
CONFIG_PANEL_SHARP_LS037V7DW01=y
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
......
......@@ -14,6 +14,7 @@
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/clk.h>
#include <linux/omapfb.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
......@@ -32,7 +33,6 @@
#include <plat/keypad.h>
#include <plat/common.h>
#include <plat/dsp_common.h>
#include <plat/omapfb.h>
#include <plat/hwa742.h>
#include <plat/lcd_mipid.h>
#include <plat/mmc.h>
......
......@@ -37,6 +37,7 @@
#include <plat/common.h>
#include <plat/dma.h>
#include <plat/gpmc.h>
#include <plat/display.h>
#include <plat/control.h>
#include <plat/gpmc-smc91x.h>
......@@ -152,31 +153,152 @@ static struct spi_board_info sdp3430_spi_board_info[] __initdata = {
},
};
static struct platform_device sdp3430_lcd_device = {
.name = "sdp2430_lcd",
.id = -1,
#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8
#define SDP3430_LCD_PANEL_ENABLE_GPIO 5
static unsigned backlight_gpio;
static unsigned enable_gpio;
static int lcd_enabled;
static int dvi_enabled;
static void __init sdp3430_display_init(void)
{
int r;
enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO;
backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO;
r = gpio_request(enable_gpio, "LCD reset");
if (r) {
printk(KERN_ERR "failed to get LCD reset GPIO\n");
goto err0;
}
r = gpio_request(backlight_gpio, "LCD Backlight");
if (r) {
printk(KERN_ERR "failed to get LCD backlight GPIO\n");
goto err1;
}
gpio_direction_output(enable_gpio, 0);
gpio_direction_output(backlight_gpio, 0);
return;
err1:
gpio_free(enable_gpio);
err0:
return;
}
static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev)
{
if (dvi_enabled) {
printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
return -EINVAL;
}
gpio_direction_output(enable_gpio, 1);
gpio_direction_output(backlight_gpio, 1);
lcd_enabled = 1;
return 0;
}
static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev)
{
lcd_enabled = 0;
gpio_direction_output(enable_gpio, 0);
gpio_direction_output(backlight_gpio, 0);
}
static int sdp3430_panel_enable_dvi(struct omap_dss_device *dssdev)
{
if (lcd_enabled) {
printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
return -EINVAL;
}
dvi_enabled = 1;
return 0;
}
static void sdp3430_panel_disable_dvi(struct omap_dss_device *dssdev)
{
dvi_enabled = 0;
}
static int sdp3430_panel_enable_tv(struct omap_dss_device *dssdev)
{
return 0;
}
static void sdp3430_panel_disable_tv(struct omap_dss_device *dssdev)
{
}
static struct omap_dss_device sdp3430_lcd_device = {
.name = "lcd",
.driver_name = "sharp_ls_panel",
.type = OMAP_DISPLAY_TYPE_DPI,
.phy.dpi.data_lines = 16,
.platform_enable = sdp3430_panel_enable_lcd,
.platform_disable = sdp3430_panel_disable_lcd,
};
static struct regulator_consumer_supply sdp3430_vdac_supply = {
.supply = "vdac",
.dev = &sdp3430_lcd_device.dev,
static struct omap_dss_device sdp3430_dvi_device = {
.name = "dvi",
.driver_name = "generic_panel",
.type = OMAP_DISPLAY_TYPE_DPI,
.phy.dpi.data_lines = 24,
.platform_enable = sdp3430_panel_enable_dvi,
.platform_disable = sdp3430_panel_disable_dvi,
};
static struct regulator_consumer_supply sdp3430_vdvi_supply = {
.supply = "vdvi",
.dev = &sdp3430_lcd_device.dev,
static struct omap_dss_device sdp3430_tv_device = {
.name = "tv",
.driver_name = "venc",
.type = OMAP_DISPLAY_TYPE_VENC,
.phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
.platform_enable = sdp3430_panel_enable_tv,
.platform_disable = sdp3430_panel_disable_tv,
};
static struct platform_device *sdp3430_devices[] __initdata = {
static struct omap_dss_device *sdp3430_dss_devices[] = {
&sdp3430_lcd_device,
&sdp3430_dvi_device,
&sdp3430_tv_device,
};
static struct omap_lcd_config sdp3430_lcd_config __initdata = {
.ctrl_name = "internal",
static struct omap_dss_board_info sdp3430_dss_data = {
.num_devices = ARRAY_SIZE(sdp3430_dss_devices),
.devices = sdp3430_dss_devices,
.default_device = &sdp3430_lcd_device,
};
static struct platform_device sdp3430_dss_device = {
.name = "omapdss",
.id = -1,
.dev = {
.platform_data = &sdp3430_dss_data,
},
};
static struct regulator_consumer_supply sdp3430_vdda_dac_supply = {
.supply = "vdda_dac",
.dev = &sdp3430_dss_device.dev,
};
static struct platform_device *sdp3430_devices[] __initdata = {
&sdp3430_dss_device,
};
static struct omap_board_config_kernel sdp3430_config[] __initdata = {
{ OMAP_TAG_LCD, &sdp3430_lcd_config },
};
static void __init omap_3430sdp_init_irq(void)
......@@ -392,22 +514,34 @@ static struct regulator_init_data sdp3430_vdac = {
| REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = 1,
.consumer_supplies = &sdp3430_vdac_supply,
.consumer_supplies = &sdp3430_vdda_dac_supply,
};
/* VPLL2 for digital video outputs */
static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = {
{
.supply = "vdvi",
.dev = &sdp3430_lcd_device.dev,
},
{
.supply = "vdds_dsi",
.dev = &sdp3430_dss_device.dev,
}
};
static struct regulator_init_data sdp3430_vpll2 = {
.constraints = {
.name = "VDVI",
.min_uV = 1800000,
.max_uV = 1800000,
.apply_uV = true,
.valid_modes_mask = REGULATOR_MODE_NORMAL
| REGULATOR_MODE_STANDBY,
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = 1,
.consumer_supplies = &sdp3430_vdvi_supply,
.num_consumer_supplies = ARRAY_SIZE(sdp3430_vpll2_supplies),
.consumer_supplies = sdp3430_vpll2_supplies,
};
static struct twl4030_codec_audio_data sdp3430_audio = {
......@@ -521,6 +655,7 @@ static void __init omap_3430sdp_init(void)
omap_serial_init();
usb_musb_init();
board_smc91x_init();
sdp3430_display_init();
enable_board_wakeup_source();
usb_ehci_init(&ehci_pdata);
}
......
......@@ -116,10 +116,10 @@ static struct omap_clk omap24xx_clks[] = {
CLK(NULL, "mdm_ick", &mdm_ick, CK_243X),
CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X),
/* DSS domain clocks */
CLK("omapfb", "ick", &dss_ick, CK_243X | CK_242X),
CLK("omapfb", "dss1_fck", &dss1_fck, CK_243X | CK_242X),
CLK("omapfb", "dss2_fck", &dss2_fck, CK_243X | CK_242X),
CLK("omapfb", "tv_fck", &dss_54m_fck, CK_243X | CK_242X),
CLK("omapdss", "ick", &dss_ick, CK_243X | CK_242X),
CLK("omapdss", "dss1_fck", &dss1_fck, CK_243X | CK_242X),
CLK("omapdss", "dss2_fck", &dss2_fck, CK_243X | CK_242X),
CLK("omapdss", "tv_fck", &dss_54m_fck, CK_243X | CK_242X),
/* L3 domain clocks */
CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X | CK_242X),
CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X | CK_242X),
......
......@@ -236,13 +236,13 @@ static struct omap_clk omap34xx_clks[] = {
CLK("omap_rng", "ick", &rng_ick, CK_343X),
CLK(NULL, "sha11_ick", &sha11_ick, CK_343X),
CLK(NULL, "des1_ick", &des1_ick, CK_343X),
CLK("omapfb", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
CLK("omapfb", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2),
CLK("omapfb", "tv_fck", &dss_tv_fck, CK_343X),
CLK("omapfb", "video_fck", &dss_96m_fck, CK_343X),
CLK("omapfb", "dss2_fck", &dss2_alwon_fck, CK_343X),
CLK("omapfb", "ick", &dss_ick_3430es1, CK_3430ES1),
CLK("omapfb", "ick", &dss_ick_3430es2, CK_3430ES2),
CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2),
CLK("omapdss", "tv_fck", &dss_tv_fck, CK_343X),
CLK("omapdss", "video_fck", &dss_96m_fck, CK_343X),
CLK("omapdss", "dss2_fck", &dss2_alwon_fck, CK_343X),
CLK("omapdss", "ick", &dss_ick_3430es1, CK_3430ES1),
CLK("omapdss", "ick", &dss_ick_3430es2, CK_3430ES2),
CLK(NULL, "cam_mclk", &cam_mclk, CK_343X),
CLK(NULL, "cam_ick", &cam_ick, CK_343X),
CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_343X),
......
......@@ -22,17 +22,18 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/omapfb.h>
#include <asm/tlb.h>
#include <asm/mach/map.h>
#include <plat/mux.h>
#include <plat/omapfb.h>
#include <plat/sram.h>
#include <plat/sdrc.h>
#include <plat/gpmc.h>
#include <plat/serial.h>
#include <plat/vram.h>
#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdev is ready */
#include "clock.h"
......@@ -264,6 +265,7 @@ void __init omap2_map_common_io(void)
omap2_check_revision();
omap_sram_init();
omapfb_reserve_sdram();
omap_vram_reserve_sdram();
}
/*
......
......@@ -160,3 +160,19 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
sdrc_write_reg(l, SDRC_POWER);
omap2_sms_save_context();
}
void omap2_sms_write_rot_control(u32 val, unsigned ctx)
{
sms_write_reg(val, SMS_ROT_CONTROL(ctx));
}
void omap2_sms_write_rot_size(u32 val, unsigned ctx)
{
sms_write_reg(val, SMS_ROT_SIZE(ctx));
}
void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
{
sms_write_reg(val, SMS_ROT_PHYSICAL_BA(ctx));
}
......@@ -28,13 +28,13 @@
#include <linux/platform_device.h>
#include <linux/bootmem.h>
#include <linux/io.h>
#include <linux/omapfb.h>
#include <mach/hardware.h>
#include <asm/mach/map.h>
#include <plat/board.h>
#include <plat/sram.h>
#include <plat/omapfb.h>
#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
......@@ -55,6 +55,10 @@ static struct platform_device omap_fb_device = {
.num_resources = 0,
};
void omapfb_set_platform_data(struct omapfb_platform_data *data)
{
}
static inline int ranges_overlap(unsigned long start1, unsigned long size1,
unsigned long start2, unsigned long size2)
{
......@@ -327,7 +331,33 @@ static inline int omap_init_fb(void)
arch_initcall(omap_init_fb);
#else
#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
static u64 omap_fb_dma_mask = ~(u32)0;
static struct omapfb_platform_data omapfb_config;
static struct platform_device omap_fb_device = {
.name = "omapfb",
.id = -1,
.dev = {
.dma_mask = &omap_fb_dma_mask,
.coherent_dma_mask = ~(u32)0,
.platform_data = &omapfb_config,
},
.num_resources = 0,
};
void omapfb_set_platform_data(struct omapfb_platform_data *data)
{
omapfb_config = *data;
}
static inline int omap_init_fb(void)
{
return platform_device_register(&omap_fb_device);
}
arch_initcall(omap_init_fb);
void omapfb_reserve_sdram(void) {}
unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
......@@ -339,5 +369,20 @@ unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
return 0;
}
#else
void omapfb_set_platform_data(struct omapfb_platform_data *data)
{
}
void omapfb_reserve_sdram(void) {}
unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
unsigned long sram_vstart,
unsigned long sram_size,
unsigned long start_avail,
unsigned long size_avail)
{
return 0;
}
#endif
/*
* linux/include/asm-arm/arch-omap/display.h
*
* Copyright (C) 2008 Nokia Corporation
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ASM_ARCH_OMAP_DISPLAY_H
#define __ASM_ARCH_OMAP_DISPLAY_H
#include <linux/list.h>
#include <linux/kobject.h>
#include <linux/device.h>
#include <asm/atomic.h>
#define DISPC_IRQ_FRAMEDONE (1 << 0)
#define DISPC_IRQ_VSYNC (1 << 1)
#define DISPC_IRQ_EVSYNC_EVEN (1 << 2)
#define DISPC_IRQ_EVSYNC_ODD (1 << 3)
#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4)
#define DISPC_IRQ_PROG_LINE_NUM (1 << 5)
#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6)
#define DISPC_IRQ_GFX_END_WIN (1 << 7)
#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8)
#define DISPC_IRQ_OCP_ERR (1 << 9)
#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10)
#define DISPC_IRQ_VID1_END_WIN (1 << 11)
#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12)
#define DISPC_IRQ_VID2_END_WIN (1 << 13)
#define DISPC_IRQ_SYNC_LOST (1 << 14)
#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15)
#define DISPC_IRQ_WAKEUP (1 << 16)
struct omap_dss_device;
struct omap_overlay_manager;
enum omap_display_type {
OMAP_DISPLAY_TYPE_NONE = 0,
OMAP_DISPLAY_TYPE_DPI = 1 << 0,
OMAP_DISPLAY_TYPE_DBI = 1 << 1,
OMAP_DISPLAY_TYPE_SDI = 1 << 2,
OMAP_DISPLAY_TYPE_DSI = 1 << 3,
OMAP_DISPLAY_TYPE_VENC = 1 << 4,
};
enum omap_plane {
OMAP_DSS_GFX = 0,
OMAP_DSS_VIDEO1 = 1,
OMAP_DSS_VIDEO2 = 2
};
enum omap_channel {
OMAP_DSS_CHANNEL_LCD = 0,
OMAP_DSS_CHANNEL_DIGIT = 1,
};
enum omap_color_mode {
OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */
OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */
OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */
OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */
OMAP_DSS_COLOR_RGB12U = 1 << 4, /* RGB12, 16-bit container */
OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16 */
OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16 */
OMAP_DSS_COLOR_RGB24U = 1 << 7, /* RGB24, 32-bit container */
OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24, 24-bit container */
OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */
OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */
OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */
OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */
OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */
OMAP_DSS_COLOR_GFX_OMAP2 =
OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P,
OMAP_DSS_COLOR_VID_OMAP2 =
OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
OMAP_DSS_COLOR_UYVY,
OMAP_DSS_COLOR_GFX_OMAP3 =
OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
OMAP_DSS_COLOR_VID1_OMAP3 =
OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P |
OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
OMAP_DSS_COLOR_VID2_OMAP3 =
OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
OMAP_DSS_COLOR_UYVY | OMAP_DSS_COLOR_ARGB32 |
OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
};
enum omap_lcd_display_type {
OMAP_DSS_LCD_DISPLAY_STN,
OMAP_DSS_LCD_DISPLAY_TFT,
};
enum omap_dss_load_mode {
OMAP_DSS_LOAD_CLUT_AND_FRAME = 0,
OMAP_DSS_LOAD_CLUT_ONLY = 1,
OMAP_DSS_LOAD_FRAME_ONLY = 2,
OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3,
};
enum omap_dss_trans_key_type {
OMAP_DSS_COLOR_KEY_GFX_DST = 0,
OMAP_DSS_COLOR_KEY_VID_SRC = 1,
};
enum omap_rfbi_te_mode {
OMAP_DSS_RFBI_TE_MODE_1 = 1,
OMAP_DSS_RFBI_TE_MODE_2 = 2,
};
enum omap_panel_config {
OMAP_DSS_LCD_IVS = 1<<0,
OMAP_DSS_LCD_IHS = 1<<1,
OMAP_DSS_LCD_IPC = 1<<2,
OMAP_DSS_LCD_IEO = 1<<3,
OMAP_DSS_LCD_RF = 1<<4,
OMAP_DSS_LCD_ONOFF = 1<<5,
OMAP_DSS_LCD_TFT = 1<<20,
};
enum omap_dss_venc_type {
OMAP_DSS_VENC_TYPE_COMPOSITE,
OMAP_DSS_VENC_TYPE_SVIDEO,
};
enum omap_display_caps {
OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0,
OMAP_DSS_DISPLAY_CAP_TEAR_ELIM = 1 << 1,
};
enum omap_dss_update_mode {
OMAP_DSS_UPDATE_DISABLED = 0,
OMAP_DSS_UPDATE_AUTO,
OMAP_DSS_UPDATE_MANUAL,
};
enum omap_dss_display_state {
OMAP_DSS_DISPLAY_DISABLED = 0,
OMAP_DSS_DISPLAY_ACTIVE,
OMAP_DSS_DISPLAY_SUSPENDED,
};
/* XXX perhaps this should be removed */
enum omap_dss_overlay_managers {
OMAP_DSS_OVL_MGR_LCD,
OMAP_DSS_OVL_MGR_TV,
};
enum omap_dss_rotation_type {
OMAP_DSS_ROT_DMA = 0,
OMAP_DSS_ROT_VRFB = 1,
};
/* clockwise rotation angle */
enum omap_dss_rotation_angle {
OMAP_DSS_ROT_0 = 0,
OMAP_DSS_ROT_90 = 1,
OMAP_DSS_ROT_180 = 2,
OMAP_DSS_ROT_270 = 3,
};
enum omap_overlay_caps {
OMAP_DSS_OVL_CAP_SCALE = 1 << 0,
OMAP_DSS_OVL_CAP_DISPC = 1 << 1,
};
enum omap_overlay_manager_caps {
OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0,
};
/* RFBI */
struct rfbi_timings {
int cs_on_time;
int cs_off_time;
int we_on_time;
int we_off_time;
int re_on_time;
int re_off_time;
int we_cycle_time;
int re_cycle_time;
int cs_pulse_width;
int access_time;
int clk_div;
u32 tim[5]; /* set by rfbi_convert_timings() */
int converted;
};
void omap_rfbi_write_command(const void *buf, u32 len);
void omap_rfbi_read_data(void *buf, u32 len);
void omap_rfbi_write_data(const void *buf, u32 len);
void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
u16 x, u16 y,
u16 w, u16 h);
int omap_rfbi_enable_te(bool enable, unsigned line);
int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
unsigned hs_pulse_time, unsigned vs_pulse_time,
int hs_pol_inv, int vs_pol_inv, int extif_div);
/* DSI */
void dsi_bus_lock(void);
void dsi_bus_unlock(void);
int dsi_vc_dcs_write(int channel, u8 *data, int len);
int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len);
int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
int dsi_vc_set_max_rx_packet_size(int channel, u16 len);
int dsi_vc_send_null(int channel);
int dsi_vc_send_bta_sync(int channel);
/* Board specific data */
struct omap_dss_board_info {
int (*get_last_off_on_transaction_id)(struct device *dev);
int num_devices;
struct omap_dss_device **devices;
struct omap_dss_device *default_device;
};
struct omap_video_timings {
/* Unit: pixels */
u16 x_res;
/* Unit: pixels */
u16 y_res;
/* Unit: KHz */
u32 pixel_clock;
/* Unit: pixel clocks */
u16 hsw; /* Horizontal synchronization pulse width */
/* Unit: pixel clocks */
u16 hfp; /* Horizontal front porch */
/* Unit: pixel clocks */
u16 hbp; /* Horizontal back porch */
/* Unit: line clocks */
u16 vsw; /* Vertical synchronization pulse width */
/* Unit: line clocks */
u16 vfp; /* Vertical front porch */
/* Unit: line clocks */
u16 vbp; /* Vertical back porch */
};
#ifdef CONFIG_OMAP2_DSS_VENC
/* Hardcoded timings for tv modes. Venc only uses these to
* identify the mode, and does not actually use the configs
* itself. However, the configs should be something that
* a normal monitor can also show */
const extern struct omap_video_timings omap_dss_pal_timings;
const extern struct omap_video_timings omap_dss_ntsc_timings;
#endif
struct omap_overlay_info {
bool enabled;
u32 paddr;
void __iomem *vaddr;
u16 screen_width;
u16 width;
u16 height;
enum omap_color_mode color_mode;
u8 rotation;
enum omap_dss_rotation_type rotation_type;
bool mirror;
u16 pos_x;
u16 pos_y;
u16 out_width; /* if 0, out_width == width */
u16 out_height; /* if 0, out_height == height */
u8 global_alpha;
};
struct omap_overlay {
struct kobject kobj;
struct list_head list;
/* static fields */
const char *name;
int id;
enum omap_color_mode supported_modes;
enum omap_overlay_caps caps;
/* dynamic fields */
struct omap_overlay_manager *manager;
struct omap_overlay_info info;
/* if true, info has been changed, but not applied() yet */
bool info_dirty;
int (*set_manager)(struct omap_overlay *ovl,
struct omap_overlay_manager *mgr);
int (*unset_manager)(struct omap_overlay *ovl);
int (*set_overlay_info)(struct omap_overlay *ovl,
struct omap_overlay_info *info);
void (*get_overlay_info)(struct omap_overlay *ovl,
struct omap_overlay_info *info);
int (*wait_for_go)(struct omap_overlay *ovl);
};
struct omap_overlay_manager_info {
u32 default_color;
enum omap_dss_trans_key_type trans_key_type;
u32 trans_key;
bool trans_enabled;
bool alpha_enabled;
};
struct omap_overlay_manager {
struct kobject kobj;
struct list_head list;
/* static fields */
const char *name;
int id;
enum omap_overlay_manager_caps caps;
int num_overlays;
struct omap_overlay **overlays;
enum omap_display_type supported_displays;
/* dynamic fields */
struct omap_dss_device *device;
struct omap_overlay_manager_info info;
bool device_changed;
/* if true, info has been changed but not applied() yet */
bool info_dirty;
int (*set_device)(struct omap_overlay_manager *mgr,
struct omap_dss_device *dssdev);
int (*unset_device)(struct omap_overlay_manager *mgr);
int (*set_manager_info)(struct omap_overlay_manager *mgr,
struct omap_overlay_manager_info *info);
void (*get_manager_info)(struct omap_overlay_manager *mgr,
struct omap_overlay_manager_info *info);
int (*apply)(struct omap_overlay_manager *mgr);
int (*wait_for_go)(struct omap_overlay_manager *mgr);
};
struct omap_dss_device {
struct device dev;
enum omap_display_type type;
union {
struct {
u8 data_lines;
} dpi;
struct {
u8 channel;
u8 data_lines;
} rfbi;
struct {
u8 datapairs;
} sdi;
struct {
u8 clk_lane;
u8 clk_pol;
u8 data1_lane;
u8 data1_pol;
u8 data2_lane;
u8 data2_pol;
struct {
u16 regn;
u16 regm;
u16 regm3;
u16 regm4;
u16 lp_clk_div;
u16 lck_div;
u16 pck_div;
} div;
bool ext_te;
u8 ext_te_gpio;
} dsi;
struct {
enum omap_dss_venc_type type;
bool invert_polarity;
} venc;
} phy;
struct {
struct omap_video_timings timings;
int acbi; /* ac-bias pin transitions per interrupt */
/* Unit: line clocks */
int acb; /* ac-bias pin frequency */
enum omap_panel_config config;
u8 recommended_bpp;
struct omap_dss_device *ctrl;
} panel;
struct {
u8 pixel_size;
struct rfbi_timings rfbi_timings;
struct omap_dss_device *panel;
} ctrl;
int reset_gpio;
int max_backlight_level;
const char *name;
/* used to match device to driver */
const char *driver_name;
void *data;
struct omap_dss_driver *driver;
/* helper variable for driver suspend/resume */
bool activate_after_resume;
enum omap_display_caps caps;
struct omap_overlay_manager *manager;
enum omap_dss_display_state state;
int (*enable)(struct omap_dss_device *dssdev);
void (*disable)(struct omap_dss_device *dssdev);
int (*suspend)(struct omap_dss_device *dssdev);
int (*resume)(struct omap_dss_device *dssdev);
void (*get_resolution)(struct omap_dss_device *dssdev,
u16 *xres, u16 *yres);
int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
int (*check_timings)(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
void (*set_timings)(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
void (*get_timings)(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
int (*update)(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h);
int (*sync)(struct omap_dss_device *dssdev);
int (*wait_vsync)(struct omap_dss_device *dssdev);
int (*set_update_mode)(struct omap_dss_device *dssdev,
enum omap_dss_update_mode);
enum omap_dss_update_mode (*get_update_mode)
(struct omap_dss_device *dssdev);
int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
int (*get_te)(struct omap_dss_device *dssdev);
u8 (*get_rotate)(struct omap_dss_device *dssdev);
int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
bool (*get_mirror)(struct omap_dss_device *dssdev);
int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
int (*run_test)(struct omap_dss_device *dssdev, int test);
int (*memory_read)(struct omap_dss_device *dssdev,
void *buf, size_t size,
u16 x, u16 y, u16 w, u16 h);
int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
u32 (*get_wss)(struct omap_dss_device *dssdev);
/* platform specific */
int (*platform_enable)(struct omap_dss_device *dssdev);
void (*platform_disable)(struct omap_dss_device *dssdev);
int (*set_backlight)(struct omap_dss_device *dssdev, int level);
int (*get_backlight)(struct omap_dss_device *dssdev);
};
struct omap_dss_driver {
struct device_driver driver;
int (*probe)(struct omap_dss_device *);
void (*remove)(struct omap_dss_device *);
int (*enable)(struct omap_dss_device *display);
void (*disable)(struct omap_dss_device *display);
int (*suspend)(struct omap_dss_device *display);
int (*resume)(struct omap_dss_device *display);
int (*run_test)(struct omap_dss_device *display, int test);
void (*setup_update)(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h);
int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
int (*wait_for_te)(struct omap_dss_device *dssdev);
u8 (*get_rotate)(struct omap_dss_device *dssdev);
int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
bool (*get_mirror)(struct omap_dss_device *dssdev);
int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
int (*memory_read)(struct omap_dss_device *dssdev,
void *buf, size_t size,
u16 x, u16 y, u16 w, u16 h);
};
int omap_dss_register_driver(struct omap_dss_driver *);
void omap_dss_unregister_driver(struct omap_dss_driver *);
int omap_dss_register_device(struct omap_dss_device *);
void omap_dss_unregister_device(struct omap_dss_device *);
void omap_dss_get_device(struct omap_dss_device *dssdev);
void omap_dss_put_device(struct omap_dss_device *dssdev);
#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL)
struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
struct omap_dss_device *omap_dss_find_device(void *data,
int (*match)(struct omap_dss_device *dssdev, void *data));
int omap_dss_start_device(struct omap_dss_device *dssdev);
void omap_dss_stop_device(struct omap_dss_device *dssdev);
int omap_dss_get_num_overlay_managers(void);
struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
int omap_dss_get_num_overlays(void);
struct omap_overlay *omap_dss_get_overlay(int num);
typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout);
int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
unsigned long timeout);
#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
#endif
......@@ -94,7 +94,10 @@
/* SMS register offsets - read/write with sms_{read,write}_reg() */
#define SMS_SYSCONFIG 0x010
#define SMS_SYSCONFIG 0x010
#define SMS_ROT_CONTROL(context) (0x180 + 0x10 * context)
#define SMS_ROT_SIZE(context) (0x184 + 0x10 * context)
#define SMS_ROT_PHYSICAL_BA(context) (0x188 + 0x10 * context)
/* REVISIT: fill in other SMS registers here */
......@@ -129,6 +132,10 @@ int omap2_sdrc_get_params(unsigned long r,
void omap2_sms_save_context(void);
void omap2_sms_restore_context(void);
void omap2_sms_write_rot_control(u32 val, unsigned ctx);
void omap2_sms_write_rot_size(u32 val, unsigned ctx);
void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx);
#ifdef CONFIG_ARCH_OMAP2
struct memory_timings {
......
/*
* VRAM manager for OMAP
*
* Copyright (C) 2009 Nokia Corporation
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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 __OMAP_VRAM_H__
#define __OMAP_VRAM_H__
#include <linux/types.h>
#define OMAP_VRAM_MEMTYPE_SDRAM 0
#define OMAP_VRAM_MEMTYPE_SRAM 1
#define OMAP_VRAM_MEMTYPE_MAX 1
extern int omap_vram_add_region(unsigned long paddr, size_t size);
extern int omap_vram_free(unsigned long paddr, size_t size);
extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr);
extern int omap_vram_reserve(unsigned long paddr, size_t size);
extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram,
unsigned long *largest_free_block);
#ifdef CONFIG_OMAP2_VRAM
extern void omap_vram_set_sdram_vram(u32 size, u32 start);
extern void omap_vram_set_sram_vram(u32 size, u32 start);
extern void omap_vram_reserve_sdram(void);
extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart,
unsigned long sram_vstart,
unsigned long sram_size,
unsigned long pstart_avail,
unsigned long size_avail);
#else
static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { }
static inline void omap_vram_set_sram_vram(u32 size, u32 start) { }
static inline void omap_vram_reserve_sdram(void) { }
static inline unsigned long omap_vram_reserve_sram(unsigned long sram_pstart,
unsigned long sram_vstart,
unsigned long sram_size,
unsigned long pstart_avail,
unsigned long size_avail)
{
return 0;
}
#endif
#endif
/*
* VRFB Rotation Engine
*
* Copyright (C) 2009 Nokia Corporation
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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 __OMAP_VRFB_H__
#define __OMAP_VRFB_H__
#define OMAP_VRFB_LINE_LEN 2048
struct vrfb {
u8 context;
void __iomem *vaddr[4];
unsigned long paddr[4];
u16 xres;
u16 yres;
u16 xoffset;
u16 yoffset;
u8 bytespp;
bool yuv_mode;
};
extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
u8 bytespp);
extern u32 omap_vrfb_min_phys_size(u16 width, u16 height, u8 bytespp);
extern u16 omap_vrfb_max_height(u32 phys_size, u16 width, u8 bytespp);
extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
u16 width, u16 height,
unsigned bytespp, bool yuv_mode);
extern int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot);
extern void omap_vrfb_restore_context(void);
#endif /* __VRFB_H */
......@@ -28,6 +28,7 @@
#include <plat/sram.h>
#include <plat/board.h>
#include <plat/cpu.h>
#include <plat/vram.h>
#include <plat/control.h>
......@@ -185,6 +186,13 @@ void __init omap_detect_sram(void)
omap_sram_start + SRAM_BOOTLOADER_SZ,
omap_sram_size - SRAM_BOOTLOADER_SZ);
omap_sram_size -= reserved;
reserved = omap_vram_reserve_sram(omap_sram_start, omap_sram_base,
omap_sram_size,
omap_sram_start + SRAM_BOOTLOADER_SZ,
omap_sram_size - SRAM_BOOTLOADER_SZ);
omap_sram_size -= reserved;
omap_sram_ceil = omap_sram_base + omap_sram_size;
}
......
......@@ -2165,6 +2165,7 @@ config FB_BROADSHEET
a bridge adapter.
source "drivers/video/omap/Kconfig"
source "drivers/video/omap2/Kconfig"
source "drivers/video/backlight/Kconfig"
source "drivers/video/display/Kconfig"
......
......@@ -124,6 +124,7 @@ obj-$(CONFIG_FB_SM501) += sm501fb.o
obj-$(CONFIG_FB_XILINX) += xilinxfb.o
obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
obj-$(CONFIG_FB_OMAP) += omap/
obj-y += omap2/
obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
obj-$(CONFIG_FB_CARMINE) += carminefb.o
obj-$(CONFIG_FB_MB862XX) += mb862xx/
......
config FB_OMAP
tristate "OMAP frame buffer support (EXPERIMENTAL)"
depends on FB && ARCH_OMAP
depends on FB && ARCH_OMAP && (OMAP2_DSS = "n")
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
......@@ -72,7 +73,7 @@ config FB_OMAP_LCD_MIPID
config FB_OMAP_BOOTLOADER_INIT
bool "Check bootloader initialization"
depends on FB_OMAP
depends on FB_OMAP || FB_OMAP2
help
Say Y here if you want to enable checking if the bootloader has
already initialized the display controller. In this case the
......
......@@ -27,9 +27,9 @@
#include <linux/clk.h>
#include <plat/dma.h>
#include <plat/omapfb.h>
#include <plat/blizzard.h>
#include "omapfb.h"
#include "dispc.h"
#define MODULE_NAME "blizzard"
......
......@@ -24,11 +24,12 @@
#include <linux/vmalloc.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <plat/sram.h>
#include <plat/omapfb.h>
#include <plat/board.h>
#include "omapfb.h"
#include "dispc.h"
#define MODULE_NAME "dispc"
......@@ -188,6 +189,11 @@ static struct {
struct omapfb_color_key color_key;
} dispc;
static struct platform_device omapdss_device = {
.name = "omapdss",
.id = -1,
};
static void enable_lcd_clocks(int enable);
static void inline dispc_write_reg(int idx, u32 val)
......@@ -914,20 +920,20 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
static int get_dss_clocks(void)
{
dispc.dss_ick = clk_get(dispc.fbdev->dev, "ick");
dispc.dss_ick = clk_get(&omapdss_device.dev, "ick");
if (IS_ERR(dispc.dss_ick)) {
dev_err(dispc.fbdev->dev, "can't get ick\n");
return PTR_ERR(dispc.dss_ick);
}
dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck");
dispc.dss1_fck = clk_get(&omapdss_device.dev, "dss1_fck");
if (IS_ERR(dispc.dss1_fck)) {
dev_err(dispc.fbdev->dev, "can't get dss1_fck\n");
clk_put(dispc.dss_ick);
return PTR_ERR(dispc.dss1_fck);
}
dispc.dss_54m_fck = clk_get(dispc.fbdev->dev, "tv_fck");
dispc.dss_54m_fck = clk_get(&omapdss_device.dev, "tv_fck");
if (IS_ERR(dispc.dss_54m_fck)) {
dev_err(dispc.fbdev->dev, "can't get tv_fck\n");
clk_put(dispc.dss_ick);
......@@ -1379,6 +1385,12 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
int skip_init = 0;
int i;
r = platform_device_register(&omapdss_device);
if (r) {
dev_err(fbdev->dev, "can't register omapdss device\n");
return r;
}
memset(&dispc, 0, sizeof(dispc));
dispc.base = ioremap(DISPC_BASE, SZ_1K);
......@@ -1522,6 +1534,7 @@ static void omap_dispc_cleanup(void)
free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
put_dss_clocks();
iounmap(dispc.base);
platform_device_unregister(&omapdss_device);
}
const struct lcd_ctrl omap2_int_ctrl = {
......
......@@ -25,10 +25,11 @@
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <plat/dma.h>
#include <plat/omapfb.h>
#include <plat/hwa742.h>
#include "omapfb.h"
#define HWA742_REV_CODE_REG 0x0
#define HWA742_CONFIG_REG 0x2
......
......@@ -28,9 +28,10 @@
#include <linux/i2c/twl4030.h>
#include <plat/mux.h>
#include <plat/omapfb.h>
#include <asm/mach-types.h>
#include "omapfb.h"
#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91
#define SDP2430_LCD_PANEL_ENABLE_GPIO 154
#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24
......
......@@ -27,7 +27,8 @@
#include <plat/board-ams-delta.h>
#include <mach/hardware.h>
#include <plat/omapfb.h>
#include "omapfb.h"
#define AMS_DELTA_DEFAULT_CONTRAST 112
......
......@@ -26,7 +26,8 @@
#include <mach/gpio.h>
#include <plat/mux.h>
#include <plat/omapfb.h>
#include "omapfb.h"
/* #define USE_35INCH_LCD 1 */
......
......@@ -24,7 +24,7 @@
#include <linux/i2c/tps65010.h>
#include <mach/gpio.h>
#include <plat/omapfb.h>
#include "omapfb.h"
#define MODULE_NAME "omapfb-lcd_h3"
......
......@@ -22,7 +22,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <plat/omapfb.h>
#include "omapfb.h"
static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
{
......
......@@ -29,7 +29,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <plat/omapfb.h>
#include "omapfb.h"
static int htcherald_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
......
......@@ -24,7 +24,7 @@
#include <linux/io.h>
#include <plat/fpga.h>
#include <plat/omapfb.h>
#include "omapfb.h"
static int innovator1510_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
......
......@@ -23,7 +23,7 @@
#include <linux/platform_device.h>
#include <mach/gpio.h>
#include <plat/omapfb.h>
#include "omapfb.h"
#define MODULE_NAME "omapfb-lcd_h3"
......
......@@ -28,9 +28,10 @@
#include <mach/gpio.h>
#include <plat/mux.h>
#include <plat/omapfb.h>
#include <asm/mach-types.h>
#include "omapfb.h"
#define LCD_PANEL_BACKLIGHT_GPIO (15 + OMAP_MAX_GPIO_LINES)
#define LCD_PANEL_ENABLE_GPIO (7 + OMAP_MAX_GPIO_LINES)
......
......@@ -23,9 +23,10 @@
#include <linux/workqueue.h>
#include <linux/spi/spi.h>
#include <plat/omapfb.h>
#include <plat/lcd_mipid.h>
#include "omapfb.h"
#define MIPID_MODULE_NAME "lcd_mipid"
#define MIPID_CMD_READ_DISP_ID 0x04
......
......@@ -27,9 +27,10 @@
#include <linux/i2c/twl4030.h>
#include <plat/mux.h>
#include <plat/omapfb.h>
#include <asm/mach-types.h>
#include "omapfb.h"
#define LCD_PANEL_ENABLE_GPIO 154
#define LCD_PANEL_LR 128
#define LCD_PANEL_UD 129
......
......@@ -26,9 +26,11 @@
#include <linux/i2c/twl4030.h>
#include <plat/mux.h>
#include <plat/omapfb.h>
#include <plat/mux.h>
#include <asm/mach-types.h>
#include "omapfb.h"
#define LCD_PANEL_ENABLE_GPIO 170
static int omap3beagle_panel_init(struct lcd_panel *panel,
......
......@@ -26,9 +26,10 @@
#include <linux/i2c/twl4030.h>
#include <plat/mux.h>
#include <plat/omapfb.h>
#include <asm/mach-types.h>
#include "omapfb.h"
#define LCD_PANEL_ENABLE_GPIO 153
#define LCD_PANEL_LR 2
#define LCD_PANEL_UD 3
......
......@@ -25,7 +25,7 @@
#include <mach/gpio.h>
#include <plat/mux.h>
#include <plat/omapfb.h>
#include "omapfb.h"
static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
{
......
......@@ -25,9 +25,10 @@
#include <mach/gpio.h>
#include <plat/mux.h>
#include <plat/omapfb.h>
#include <asm/mach-types.h>
#include "omapfb.h"
#define LCD_ENABLE 144
static int overo_panel_init(struct lcd_panel *panel,
......
......@@ -24,7 +24,7 @@
#include <linux/io.h>
#include <plat/fpga.h>
#include <plat/omapfb.h>
#include "omapfb.h"
static int palmte_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
......
......@@ -30,7 +30,7 @@ GPIO13 - screen blanking
#include <linux/io.h>
#include <mach/gpio.h>
#include <plat/omapfb.h>
#include "omapfb.h"
static int palmtt_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
......
......@@ -24,7 +24,7 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <plat/omapfb.h>
#include "omapfb.h"
static int palmz71_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
......
......@@ -30,10 +30,11 @@
#include <linux/clk.h>
#include <plat/dma.h>
#include <plat/omapfb.h>
#include <asm/mach-types.h>
#include "omapfb.h"
#include "lcdc.h"
#define MODULE_NAME "lcdc"
......
/*
* File: arch/arm/plat-omap/include/mach/omapfb.h
* File: drivers/video/omap/omapfb.h
*
* Framebuffer driver for TI OMAP boards
*
......@@ -24,151 +24,12 @@
#ifndef __OMAPFB_H
#define __OMAPFB_H
#include <asm/ioctl.h>
#include <asm/types.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_MIRROR OMAP_IOW(31, int)
#define OMAPFB_SYNC_GFX OMAP_IO(37)
#define OMAPFB_VSYNC OMAP_IO(38)
#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps)
#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
#define OMAPFB_LCD_TEST OMAP_IOW(45, int)
#define OMAPFB_CTRL_TEST OMAP_IOW(46, int)
#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old)
#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key)
#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key)
#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info)
#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info)
#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window)
#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info)
#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info)
#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
#define OMAPFB_CAPS_LCDC_MASK 0x00fff000
#define OMAPFB_CAPS_PANEL_MASK 0xff000000
#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000
#define OMAPFB_CAPS_TEARSYNC 0x00002000
#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000
#define OMAPFB_CAPS_PLANE_SCALE 0x00008000
#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000
#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000
#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000
#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000
#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000
/* Values from DSP must map to lower 16-bits */
#define OMAPFB_FORMAT_MASK 0x00ff
#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100
#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200
#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400
#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800
#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000
#define OMAPFB_EVENT_READY 1
#define OMAPFB_EVENT_DISABLED 2
#define OMAPFB_MEMTYPE_SDRAM 0
#define OMAPFB_MEMTYPE_SRAM 1
#define OMAPFB_MEMTYPE_MAX 1
enum omapfb_color_format {
OMAPFB_COLOR_RGB565 = 0,
OMAPFB_COLOR_YUV422,
OMAPFB_COLOR_YUV420,
OMAPFB_COLOR_CLUT_8BPP,
OMAPFB_COLOR_CLUT_4BPP,
OMAPFB_COLOR_CLUT_2BPP,
OMAPFB_COLOR_CLUT_1BPP,
OMAPFB_COLOR_RGB444,
OMAPFB_COLOR_YUY422,
};
struct omapfb_update_window {
__u32 x, y;
__u32 width, height;
__u32 format;
__u32 out_x, out_y;
__u32 out_width, out_height;
__u32 reserved[8];
};
struct omapfb_update_window_old {
__u32 x, y;
__u32 width, height;
__u32 format;
};
enum omapfb_plane {
OMAPFB_PLANE_GFX = 0,
OMAPFB_PLANE_VID1,
OMAPFB_PLANE_VID2,
};
enum omapfb_channel_out {
OMAPFB_CHANNEL_OUT_LCD = 0,
OMAPFB_CHANNEL_OUT_DIGIT,
};
struct omapfb_plane_info {
__u32 pos_x;
__u32 pos_y;
__u8 enabled;
__u8 channel_out;
__u8 mirror;
__u8 reserved1;
__u32 out_width;
__u32 out_height;
__u32 reserved2[12];
};
struct omapfb_mem_info {
__u32 size;
__u8 type;
__u8 reserved[3];
};
struct omapfb_caps {
__u32 ctrl;
__u32 plane_color;
__u32 wnd_color;
};
enum omapfb_color_key_type {
OMAPFB_COLOR_KEY_DISABLED = 0,
OMAPFB_COLOR_KEY_GFX_DST,
OMAPFB_COLOR_KEY_VID_SRC,
};
struct omapfb_color_key {
__u8 channel_out;
__u32 background;
__u32 trans_key;
__u8 key_type;
};
enum omapfb_update_mode {
OMAPFB_UPDATE_DISABLED = 0,
OMAPFB_AUTO_UPDATE,
OMAPFB_MANUAL_UPDATE
};
#ifdef __KERNEL__
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/mutex.h>
#include <linux/omapfb.h>
#include <plat/board.h>
#define OMAPFB_EVENT_READY 1
#define OMAPFB_EVENT_DISABLED 2
#define OMAP_LCDC_INV_VSYNC 0x0001
#define OMAP_LCDC_INV_HSYNC 0x0002
......@@ -184,12 +45,6 @@ enum omapfb_update_mode {
#define OMAPFB_PLANE_XRES_MIN 8
#define OMAPFB_PLANE_YRES_MIN 8
#ifdef CONFIG_ARCH_OMAP1
#define OMAPFB_PLANE_NUM 1
#else
#define OMAPFB_PLANE_NUM 3
#endif
struct omapfb_device;
struct lcd_panel {
......@@ -256,7 +111,7 @@ struct lcd_ctrl_extif {
void (*read_data) (void *buf, unsigned int len);
void (*write_data) (const void *buf, unsigned int len);
void (*transfer_area) (int width, int height,
void (callback)(void * data), void *data);
void (callback)(void *data), void *data);
int (*setup_tearsync) (unsigned pin_cnt,
unsigned hs_pulse_time, unsigned vs_pulse_time,
int hs_pol_inv, int vs_pol_inv, int div);
......@@ -275,20 +130,6 @@ typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
unsigned long event,
void *fbi);
struct omapfb_mem_region {
u32 paddr;
void __iomem *vaddr;
unsigned long size;
u8 type; /* OMAPFB_PLANE_MEM_* */
unsigned alloc:1; /* allocated by the driver */
unsigned map:1; /* kernel mapped by the driver */
};
struct omapfb_mem_desc {
int region_cnt;
struct omapfb_mem_region region[OMAPFB_PLANE_NUM];
};
struct lcd_ctrl {
const char *name;
void *data;
......@@ -331,9 +172,9 @@ struct lcd_ctrl {
};
enum omapfb_state {
OMAPFB_DISABLED = 0,
OMAPFB_SUSPENDED= 99,
OMAPFB_ACTIVE = 100
OMAPFB_DISABLED = 0,
OMAPFB_SUSPENDED = 99,
OMAPFB_ACTIVE = 100
};
struct omapfb_plane_struct {
......@@ -345,8 +186,8 @@ struct omapfb_plane_struct {
struct omapfb_device {
int state;
int ext_lcdc; /* Using external
LCD controller */
int ext_lcdc; /* Using external
LCD controller */
struct mutex rqueue_mutex;
int palette_size;
......@@ -364,19 +205,12 @@ struct omapfb_device {
struct fb_info *fb_info[OMAPFB_PLANE_NUM];
};
struct omapfb_platform_data {
struct omap_lcd_config lcd;
struct omapfb_mem_desc mem_desc;
void *ctrl_platform_data;
};
#ifdef CONFIG_ARCH_OMAP1
extern struct lcd_ctrl omap1_lcd_ctrl;
#else
extern struct lcd_ctrl omap2_disp_ctrl;
#endif
extern void omapfb_reserve_sdram(void);
extern void omapfb_register_panel(struct lcd_panel *panel);
extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
extern void omapfb_notify_clients(struct omapfb_device *fbdev,
......@@ -390,9 +224,4 @@ extern int omapfb_update_window_async(struct fb_info *fbi,
void (*callback)(void *),
void *callback_data);
/* in arch/arm/plat-omap/fb.c */
extern void omapfb_set_ctrl_platform_data(void *pdata);
#endif /* __KERNEL__ */
#endif /* __OMAPFB_H */
......@@ -29,8 +29,8 @@
#include <linux/uaccess.h>
#include <plat/dma.h>
#include <plat/omapfb.h>
#include "omapfb.h"
#include "lcdc.h"
#include "dispc.h"
......
......@@ -27,8 +27,7 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <plat/omapfb.h>
#include "omapfb.h"
#include "dispc.h"
/* To work around an RFBI transfer rate limitation */
......
......@@ -23,10 +23,11 @@
#include <linux/clk.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <plat/dma.h>
#include <plat/omapfb.h>
#include "omapfb.h"
#include "lcdc.h"
#define MODULE_NAME "omapfb-sossi"
......
config OMAP2_VRAM
bool
config OMAP2_VRFB
bool
source "drivers/video/omap2/dss/Kconfig"
source "drivers/video/omap2/omapfb/Kconfig"
source "drivers/video/omap2/displays/Kconfig"
obj-$(CONFIG_OMAP2_VRAM) += vram.o
obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
obj-y += dss/
obj-y += omapfb/
obj-y += displays/
menu "OMAP2/3 Display Device Drivers"
depends on OMAP2_DSS
config PANEL_GENERIC
tristate "Generic Panel"
help
Generic panel driver.
Used for DVI output for Beagle and OMAP3 SDP.
config PANEL_SHARP_LS037V7DW01
tristate "Sharp LS037V7DW01 LCD Panel"
depends on OMAP2_DSS
help
LCD Panel used in TI's SDP3430 and EVM boards
config PANEL_TAAL
tristate "Taal DSI Panel"
depends on OMAP2_DSS_DSI
help
Taal DSI command mode panel from TPO.
endmenu
obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
/*
* Generic panel support
*
* Copyright (C) 2008 Nokia Corporation
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <plat/display.h>
static struct omap_video_timings generic_panel_timings = {
/* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
.x_res = 640,
.y_res = 480,
.pixel_clock = 23500,
.hfp = 48,
.hsw = 32,
.hbp = 80,
.vfp = 3,
.vsw = 4,
.vbp = 7,
};
static int generic_panel_probe(struct omap_dss_device *dssdev)
{
dssdev->panel.config = OMAP_DSS_LCD_TFT;
dssdev->panel.timings = generic_panel_timings;
return 0;
}
static void generic_panel_remove(struct omap_dss_device *dssdev)
{
}
static int generic_panel_enable(struct omap_dss_device *dssdev)
{
int r = 0;
if (dssdev->platform_enable)
r = dssdev->platform_enable(dssdev);
return r;
}
static void generic_panel_disable(struct omap_dss_device *dssdev)
{
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
}
static int generic_panel_suspend(struct omap_dss_device *dssdev)
{
generic_panel_disable(dssdev);
return 0;
}
static int generic_panel_resume(struct omap_dss_device *dssdev)
{
return generic_panel_enable(dssdev);
}
static struct omap_dss_driver generic_driver = {
.probe = generic_panel_probe,
.remove = generic_panel_remove,
.enable = generic_panel_enable,
.disable = generic_panel_disable,
.suspend = generic_panel_suspend,
.resume = generic_panel_resume,
.driver = {
.name = "generic_panel",
.owner = THIS_MODULE,
},
};
static int __init generic_panel_drv_init(void)
{
return omap_dss_register_driver(&generic_driver);
}
static void __exit generic_panel_drv_exit(void)
{
omap_dss_unregister_driver(&generic_driver);
}
module_init(generic_panel_drv_init);
module_exit(generic_panel_drv_exit);
MODULE_LICENSE("GPL");
/*
* LCD panel driver for Sharp LS037V7DW01
*
* Copyright (C) 2008 Nokia Corporation
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
#include <plat/display.h>
struct sharp_data {
/* XXX This regulator should actually be in SDP board file, not here,
* as it doesn't actually power the LCD, but something else that
* affects the output to LCD (I think. Somebody clarify). It doesn't do
* harm here, as SDP is the only board using this currently */
struct regulator *vdvi_reg;
};
static struct omap_video_timings sharp_ls_timings = {
.x_res = 480,
.y_res = 640,
.pixel_clock = 19200,
.hsw = 2,
.hfp = 1,
.hbp = 28,
.vsw = 1,
.vfp = 1,
.vbp = 1,
};
static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
{
struct sharp_data *sd;
dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
OMAP_DSS_LCD_IHS;
dssdev->panel.acb = 0x28;
dssdev->panel.timings = sharp_ls_timings;
sd = kzalloc(sizeof(*sd), GFP_KERNEL);
if (!sd)
return -ENOMEM;
dev_set_drvdata(&dssdev->dev, sd);
sd->vdvi_reg = regulator_get(&dssdev->dev, "vdvi");
if (IS_ERR(sd->vdvi_reg)) {
kfree(sd);
pr_err("failed to get VDVI regulator\n");
return PTR_ERR(sd->vdvi_reg);
}
return 0;
}
static void sharp_ls_panel_remove(struct omap_dss_device *dssdev)
{
struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
regulator_put(sd->vdvi_reg);
kfree(sd);
}
static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
{
struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
int r = 0;
/* wait couple of vsyncs until enabling the LCD */
msleep(50);
regulator_enable(sd->vdvi_reg);
if (dssdev->platform_enable)
r = dssdev->platform_enable(dssdev);
return r;
}
static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
{
struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
regulator_disable(sd->vdvi_reg);
/* wait at least 5 vsyncs after disabling the LCD */
msleep(100);
}
static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
{
sharp_ls_panel_disable(dssdev);
return 0;
}
static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
{
return sharp_ls_panel_enable(dssdev);
}
static struct omap_dss_driver sharp_ls_driver = {
.probe = sharp_ls_panel_probe,
.remove = sharp_ls_panel_remove,
.enable = sharp_ls_panel_enable,
.disable = sharp_ls_panel_disable,
.suspend = sharp_ls_panel_suspend,
.resume = sharp_ls_panel_resume,
.driver = {
.name = "sharp_ls_panel",
.owner = THIS_MODULE,
},
};
static int __init sharp_ls_panel_drv_init(void)
{
return omap_dss_register_driver(&sharp_ls_driver);
}
static void __exit sharp_ls_panel_drv_exit(void)
{
omap_dss_unregister_driver(&sharp_ls_driver);
}
module_init(sharp_ls_panel_drv_init);
module_exit(sharp_ls_panel_drv_exit);
MODULE_LICENSE("GPL");
此差异已折叠。
menuconfig OMAP2_DSS
tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)"
depends on ARCH_OMAP2 || ARCH_OMAP3
help
OMAP2/3 Display Subsystem support.
if OMAP2_DSS
config OMAP2_VRAM_SIZE
int "VRAM size (MB)"
range 0 32
default 0
help
The amount of SDRAM to reserve at boot time for video RAM use.
This VRAM will be used by omapfb and other drivers that need
large continuous RAM area for video use.
You can also set this with "vram=<bytes>" kernel argument, or
in the board file.
config OMAP2_DSS_DEBUG_SUPPORT
bool "Debug support"
default y
help
This enables debug messages. You need to enable printing
with 'debug' module parameter.
config OMAP2_DSS_RFBI
bool "RFBI support"
default n
help
MIPI DBI, or RFBI (Remote Framebuffer Interface), support.
config OMAP2_DSS_VENC
bool "VENC support"
default y
help
OMAP Video Encoder support.
config OMAP2_DSS_SDI
bool "SDI support"
depends on ARCH_OMAP3
default n
help
SDI (Serial Display Interface) support.
config OMAP2_DSS_DSI
bool "DSI support"
depends on ARCH_OMAP3
default n
help
MIPI DSI support.
config OMAP2_DSS_USE_DSI_PLL
bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
default n
depends on OMAP2_DSS_DSI
help
Use DSI PLL to generate pixel clock. Currently only for DPI output.
DSI PLL can be used to generate higher and more precise pixel clocks.
config OMAP2_DSS_FAKE_VSYNC
bool "Fake VSYNC irq from manual update displays"
default n
help
If this is selected, DSI will generate a fake DISPC VSYNC interrupt
when DSI has sent a frame. This is only needed with DSI or RFBI
displays using manual mode, and you want VSYNC to, for example,
time animation.
config OMAP2_DSS_MIN_FCK_PER_PCK
int "Minimum FCK/PCK ratio (for scaling)"
range 0 32
default 0
help
This can be used to adjust the minimum FCK/PCK ratio.
With this you can make sure that DISPC FCK is at least
n x PCK. Video plane scaling requires higher FCK than
normally.
If this is set to 0, there's no extra constraint on the
DISPC FCK. However, the FCK will at minimum be
2xPCK (if active matrix) or 3xPCK (if passive matrix).
Max FCK is 173MHz, so this doesn't work if your PCK
is very high.
endif
obj-$(CONFIG_OMAP2_DSS) += omapdss.o
omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o
omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
/*
* linux/drivers/video/omap2/dss/core.c
*
* Copyright (C) 2009 Nokia Corporation
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
*
* Some code and ideas taken from drivers/video/omap/ driver
* by Imre Deak.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#define DSS_SUBSYS_NAME "CORE"
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/seq_file.h>
#include <linux/debugfs.h>
#include <linux/io.h>
#include <linux/device.h>
#include <plat/display.h>
#include <plat/clock.h>
#include "dss.h"
static struct {
struct platform_device *pdev;
int ctx_id;
struct clk *dss_ick;
struct clk *dss1_fck;
struct clk *dss2_fck;
struct clk *dss_54m_fck;
struct clk *dss_96m_fck;
unsigned num_clks_enabled;
} core;
static void dss_clk_enable_all_no_ctx(void);
static void dss_clk_disable_all_no_ctx(void);
static void dss_clk_enable_no_ctx(enum dss_clock clks);
static void dss_clk_disable_no_ctx(enum dss_clock clks);
static char *def_disp_name;
module_param_named(def_disp, def_disp_name, charp, 0);
MODULE_PARM_DESC(def_disp_name, "default display name");
#ifdef DEBUG
unsigned int dss_debug;
module_param_named(debug, dss_debug, bool, 0644);
#endif
/* CONTEXT */
static int dss_get_ctx_id(void)
{
struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
int r;
if (!pdata->get_last_off_on_transaction_id)
return 0;
r = pdata->get_last_off_on_transaction_id(&core.pdev->dev);
if (r < 0) {
dev_err(&core.pdev->dev, "getting transaction ID failed, "
"will force context restore\n");
r = -1;
}
return r;
}
int dss_need_ctx_restore(void)
{
int id = dss_get_ctx_id();
if (id < 0 || id != core.ctx_id) {
DSSDBG("ctx id %d -> id %d\n",
core.ctx_id, id);
core.ctx_id = id;
return 1;
} else {
return 0;
}
}
static void save_all_ctx(void)
{
DSSDBG("save context\n");
dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
dss_save_context();
dispc_save_context();
#ifdef CONFIG_OMAP2_DSS_DSI
dsi_save_context();
#endif
dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
}
static void restore_all_ctx(void)
{
DSSDBG("restore context\n");
dss_clk_enable_all_no_ctx();
dss_restore_context();
dispc_restore_context();
#ifdef CONFIG_OMAP2_DSS_DSI
dsi_restore_context();
#endif
dss_clk_disable_all_no_ctx();
}
/* CLOCKS */
static void core_dump_clocks(struct seq_file *s)
{
int i;
struct clk *clocks[5] = {
core.dss_ick,
core.dss1_fck,
core.dss2_fck,
core.dss_54m_fck,
core.dss_96m_fck
};
seq_printf(s, "- CORE -\n");
seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled);
for (i = 0; i < 5; i++) {
if (!clocks[i])
continue;
seq_printf(s, "%-15s\t%lu\t%d\n",
clocks[i]->name,
clk_get_rate(clocks[i]),
clocks[i]->usecount);
}
}
static int dss_get_clock(struct clk **clock, const char *clk_name)
{
struct clk *clk;
clk = clk_get(&core.pdev->dev, clk_name);
if (IS_ERR(clk)) {
DSSERR("can't get clock %s", clk_name);
return PTR_ERR(clk);
}
*clock = clk;
DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
return 0;
}
static int dss_get_clocks(void)
{
int r;
core.dss_ick = NULL;
core.dss1_fck = NULL;
core.dss2_fck = NULL;
core.dss_54m_fck = NULL;
core.dss_96m_fck = NULL;
r = dss_get_clock(&core.dss_ick, "ick");
if (r)
goto err;
r = dss_get_clock(&core.dss1_fck, "dss1_fck");
if (r)
goto err;
r = dss_get_clock(&core.dss2_fck, "dss2_fck");
if (r)
goto err;
r = dss_get_clock(&core.dss_54m_fck, "tv_fck");
if (r)
goto err;
r = dss_get_clock(&core.dss_96m_fck, "video_fck");
if (r)
goto err;
return 0;
err:
if (core.dss_ick)
clk_put(core.dss_ick);
if (core.dss1_fck)
clk_put(core.dss1_fck);
if (core.dss2_fck)
clk_put(core.dss2_fck);
if (core.dss_54m_fck)
clk_put(core.dss_54m_fck);
if (core.dss_96m_fck)
clk_put(core.dss_96m_fck);
return r;
}
static void dss_put_clocks(void)
{
if (core.dss_96m_fck)
clk_put(core.dss_96m_fck);
clk_put(core.dss_54m_fck);
clk_put(core.dss1_fck);
clk_put(core.dss2_fck);
clk_put(core.dss_ick);
}
unsigned long dss_clk_get_rate(enum dss_clock clk)
{
switch (clk) {
case DSS_CLK_ICK:
return clk_get_rate(core.dss_ick);
case DSS_CLK_FCK1:
return clk_get_rate(core.dss1_fck);
case DSS_CLK_FCK2:
return clk_get_rate(core.dss2_fck);
case DSS_CLK_54M:
return clk_get_rate(core.dss_54m_fck);
case DSS_CLK_96M:
return clk_get_rate(core.dss_96m_fck);
}
BUG();
return 0;
}
static unsigned count_clk_bits(enum dss_clock clks)
{
unsigned num_clks = 0;
if (clks & DSS_CLK_ICK)
++num_clks;
if (clks & DSS_CLK_FCK1)
++num_clks;
if (clks & DSS_CLK_FCK2)
++num_clks;
if (clks & DSS_CLK_54M)
++num_clks;
if (clks & DSS_CLK_96M)
++num_clks;
return num_clks;
}
static void dss_clk_enable_no_ctx(enum dss_clock clks)
{
unsigned num_clks = count_clk_bits(clks);
if (clks & DSS_CLK_ICK)
clk_enable(core.dss_ick);
if (clks & DSS_CLK_FCK1)
clk_enable(core.dss1_fck);
if (clks & DSS_CLK_FCK2)
clk_enable(core.dss2_fck);
if (clks & DSS_CLK_54M)
clk_enable(core.dss_54m_fck);
if (clks & DSS_CLK_96M)
clk_enable(core.dss_96m_fck);
core.num_clks_enabled += num_clks;
}
void dss_clk_enable(enum dss_clock clks)
{
dss_clk_enable_no_ctx(clks);
if (cpu_is_omap34xx() && dss_need_ctx_restore())
restore_all_ctx();
}
static void dss_clk_disable_no_ctx(enum dss_clock clks)
{
unsigned num_clks = count_clk_bits(clks);
if (clks & DSS_CLK_ICK)
clk_disable(core.dss_ick);
if (clks & DSS_CLK_FCK1)
clk_disable(core.dss1_fck);
if (clks & DSS_CLK_FCK2)
clk_disable(core.dss2_fck);
if (clks & DSS_CLK_54M)
clk_disable(core.dss_54m_fck);
if (clks & DSS_CLK_96M)
clk_disable(core.dss_96m_fck);
core.num_clks_enabled -= num_clks;
}
void dss_clk_disable(enum dss_clock clks)
{
if (cpu_is_omap34xx()) {
unsigned num_clks = count_clk_bits(clks);
BUG_ON(core.num_clks_enabled < num_clks);
if (core.num_clks_enabled == num_clks)
save_all_ctx();
}
dss_clk_disable_no_ctx(clks);
}
static void dss_clk_enable_all_no_ctx(void)
{
enum dss_clock clks;
clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
if (cpu_is_omap34xx())
clks |= DSS_CLK_96M;
dss_clk_enable_no_ctx(clks);
}
static void dss_clk_disable_all_no_ctx(void)
{
enum dss_clock clks;
clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
if (cpu_is_omap34xx())
clks |= DSS_CLK_96M;
dss_clk_disable_no_ctx(clks);
}
static void dss_clk_disable_all(void)
{
enum dss_clock clks;
clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
if (cpu_is_omap34xx())
clks |= DSS_CLK_96M;
dss_clk_disable(clks);
}
/* DEBUGFS */
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
static void dss_debug_dump_clocks(struct seq_file *s)
{
core_dump_clocks(s);
dss_dump_clocks(s);
dispc_dump_clocks(s);
#ifdef CONFIG_OMAP2_DSS_DSI
dsi_dump_clocks(s);
#endif
}
static int dss_debug_show(struct seq_file *s, void *unused)
{
void (*func)(struct seq_file *) = s->private;
func(s);
return 0;
}
static int dss_debug_open(struct inode *inode, struct file *file)
{
return single_open(file, dss_debug_show, inode->i_private);
}
static const struct file_operations dss_debug_fops = {
.open = dss_debug_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static struct dentry *dss_debugfs_dir;
static int dss_initialize_debugfs(void)
{
dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
if (IS_ERR(dss_debugfs_dir)) {
int err = PTR_ERR(dss_debugfs_dir);
dss_debugfs_dir = NULL;
return err;
}
debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
&dss_debug_dump_clocks, &dss_debug_fops);
debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
&dss_dump_regs, &dss_debug_fops);
debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir,
&dispc_dump_regs, &dss_debug_fops);
#ifdef CONFIG_OMAP2_DSS_RFBI
debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir,
&rfbi_dump_regs, &dss_debug_fops);
#endif
#ifdef CONFIG_OMAP2_DSS_DSI
debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir,
&dsi_dump_regs, &dss_debug_fops);
#endif
#ifdef CONFIG_OMAP2_DSS_VENC
debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
&venc_dump_regs, &dss_debug_fops);
#endif
return 0;
}
static void dss_uninitialize_debugfs(void)
{
if (dss_debugfs_dir)
debugfs_remove_recursive(dss_debugfs_dir);
}
#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
/* PLATFORM DEVICE */
static int omap_dss_probe(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
int skip_init = 0;
int r;
int i;
core.pdev = pdev;
dss_init_overlay_managers(pdev);
dss_init_overlays(pdev);
r = dss_get_clocks();
if (r)
goto fail0;
dss_clk_enable_all_no_ctx();
core.ctx_id = dss_get_ctx_id();
DSSDBG("initial ctx id %u\n", core.ctx_id);
#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
/* DISPC_CONTROL */
if (omap_readl(0x48050440) & 1) /* LCD enabled? */
skip_init = 1;
#endif
r = dss_init(skip_init);
if (r) {
DSSERR("Failed to initialize DSS\n");
goto fail0;
}
#ifdef CONFIG_OMAP2_DSS_RFBI
r = rfbi_init();
if (r) {
DSSERR("Failed to initialize rfbi\n");
goto fail0;
}
#endif
r = dpi_init();
if (r) {
DSSERR("Failed to initialize dpi\n");
goto fail0;
}
r = dispc_init();
if (r) {
DSSERR("Failed to initialize dispc\n");
goto fail0;
}
#ifdef CONFIG_OMAP2_DSS_VENC
r = venc_init(pdev);
if (r) {
DSSERR("Failed to initialize venc\n");
goto fail0;
}
#endif
if (cpu_is_omap34xx()) {
#ifdef CONFIG_OMAP2_DSS_SDI
r = sdi_init(skip_init);
if (r) {
DSSERR("Failed to initialize SDI\n");
goto fail0;
}
#endif
#ifdef CONFIG_OMAP2_DSS_DSI
r = dsi_init(pdev);
if (r) {
DSSERR("Failed to initialize DSI\n");
goto fail0;
}
#endif
}
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
r = dss_initialize_debugfs();
if (r)
goto fail0;
#endif
for (i = 0; i < pdata->num_devices; ++i) {
struct omap_dss_device *dssdev = pdata->devices[i];
r = omap_dss_register_device(dssdev);
if (r)
DSSERR("device reg failed %d\n", i);
if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0)
pdata->default_device = dssdev;
}
dss_clk_disable_all();
return 0;
/* XXX fail correctly */
fail0:
return r;
}
static int omap_dss_remove(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
int i;
int c;
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
dss_uninitialize_debugfs();
#endif
#ifdef CONFIG_OMAP2_DSS_VENC
venc_exit();
#endif
dispc_exit();
dpi_exit();
#ifdef CONFIG_OMAP2_DSS_RFBI
rfbi_exit();
#endif
if (cpu_is_omap34xx()) {
#ifdef CONFIG_OMAP2_DSS_DSI
dsi_exit();
#endif
#ifdef CONFIG_OMAP2_DSS_SDI
sdi_exit();
#endif
}
dss_exit();
/* these should be removed at some point */
c = core.dss_ick->usecount;
if (c > 0) {
DSSERR("warning: dss_ick usecount %d, disabling\n", c);
while (c-- > 0)
clk_disable(core.dss_ick);
}
c = core.dss1_fck->usecount;
if (c > 0) {
DSSERR("warning: dss1_fck usecount %d, disabling\n", c);
while (c-- > 0)
clk_disable(core.dss1_fck);
}
c = core.dss2_fck->usecount;
if (c > 0) {
DSSERR("warning: dss2_fck usecount %d, disabling\n", c);
while (c-- > 0)
clk_disable(core.dss2_fck);
}
c = core.dss_54m_fck->usecount;
if (c > 0) {
DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c);
while (c-- > 0)
clk_disable(core.dss_54m_fck);
}
if (core.dss_96m_fck) {
c = core.dss_96m_fck->usecount;
if (c > 0) {
DSSERR("warning: dss_96m_fck usecount %d, disabling\n",
c);
while (c-- > 0)
clk_disable(core.dss_96m_fck);
}
}
dss_put_clocks();
dss_uninit_overlays(pdev);
dss_uninit_overlay_managers(pdev);
for (i = 0; i < pdata->num_devices; ++i)
omap_dss_unregister_device(pdata->devices[i]);
return 0;
}
static void omap_dss_shutdown(struct platform_device *pdev)
{
DSSDBG("shutdown\n");
dss_disable_all_devices();
}
static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state)
{
DSSDBG("suspend %d\n", state.event);
return dss_suspend_all_devices();
}
static int omap_dss_resume(struct platform_device *pdev)
{
DSSDBG("resume\n");
return dss_resume_all_devices();
}
static struct platform_driver omap_dss_driver = {
.probe = omap_dss_probe,
.remove = omap_dss_remove,
.shutdown = omap_dss_shutdown,
.suspend = omap_dss_suspend,
.resume = omap_dss_resume,
.driver = {
.name = "omapdss",
.owner = THIS_MODULE,
},
};
/* BUS */
static int dss_bus_match(struct device *dev, struct device_driver *driver)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
DSSDBG("bus_match. dev %s/%s, drv %s\n",
dev_name(dev), dssdev->driver_name, driver->name);
return strcmp(dssdev->driver_name, driver->name) == 0;
}
static ssize_t device_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
return snprintf(buf, PAGE_SIZE, "%s\n",
dssdev->name ?
dssdev->name : "");
}
static struct device_attribute default_dev_attrs[] = {
__ATTR(name, S_IRUGO, device_name_show, NULL),
__ATTR_NULL,
};
static ssize_t driver_name_show(struct device_driver *drv, char *buf)
{
struct omap_dss_driver *dssdrv = to_dss_driver(drv);
return snprintf(buf, PAGE_SIZE, "%s\n",
dssdrv->driver.name ?
dssdrv->driver.name : "");
}
static struct driver_attribute default_drv_attrs[] = {
__ATTR(name, S_IRUGO, driver_name_show, NULL),
__ATTR_NULL,
};
static struct bus_type dss_bus_type = {
.name = "omapdss",
.match = dss_bus_match,
.dev_attrs = default_dev_attrs,
.drv_attrs = default_drv_attrs,
};
static void dss_bus_release(struct device *dev)
{
DSSDBG("bus_release\n");
}
static struct device dss_bus = {
.release = dss_bus_release,
};
struct bus_type *dss_get_bus(void)
{
return &dss_bus_type;
}
/* DRIVER */
static int dss_driver_probe(struct device *dev)
{
int r;
struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
struct omap_dss_device *dssdev = to_dss_device(dev);
struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
bool force;
DSSDBG("driver_probe: dev %s/%s, drv %s\n",
dev_name(dev), dssdev->driver_name,
dssdrv->driver.name);
dss_init_device(core.pdev, dssdev);
/* skip this if the device is behind a ctrl */
if (!dssdev->panel.ctrl) {
force = pdata->default_device == dssdev;
dss_recheck_connections(dssdev, force);
}
r = dssdrv->probe(dssdev);
if (r) {
DSSERR("driver probe failed: %d\n", r);
return r;
}
DSSDBG("probe done for device %s\n", dev_name(dev));
dssdev->driver = dssdrv;
return 0;
}
static int dss_driver_remove(struct device *dev)
{
struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
struct omap_dss_device *dssdev = to_dss_device(dev);
DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev),
dssdev->driver_name);
dssdrv->remove(dssdev);
dss_uninit_device(core.pdev, dssdev);
dssdev->driver = NULL;
return 0;
}
int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
{
dssdriver->driver.bus = &dss_bus_type;
dssdriver->driver.probe = dss_driver_probe;
dssdriver->driver.remove = dss_driver_remove;
return driver_register(&dssdriver->driver);
}
EXPORT_SYMBOL(omap_dss_register_driver);
void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
{
driver_unregister(&dssdriver->driver);
}
EXPORT_SYMBOL(omap_dss_unregister_driver);
/* DEVICE */
static void reset_device(struct device *dev, int check)
{
u8 *dev_p = (u8 *)dev;
u8 *dev_end = dev_p + sizeof(*dev);
void *saved_pdata;
saved_pdata = dev->platform_data;
if (check) {
/*
* Check if there is any other setting than platform_data
* in struct device; warn that these will be reset by our
* init.
*/
dev->platform_data = NULL;
while (dev_p < dev_end) {
if (*dev_p) {
WARN("%s: struct device fields will be "
"discarded\n",
__func__);
break;
}
dev_p++;
}
}
memset(dev, 0, sizeof(*dev));
dev->platform_data = saved_pdata;
}
static void omap_dss_dev_release(struct device *dev)
{
reset_device(dev, 0);
}
int omap_dss_register_device(struct omap_dss_device *dssdev)
{
static int dev_num;
static int panel_num;
int r;
WARN_ON(!dssdev->driver_name);
reset_device(&dssdev->dev, 1);
dssdev->dev.bus = &dss_bus_type;
dssdev->dev.parent = &dss_bus;
dssdev->dev.release = omap_dss_dev_release;
dev_set_name(&dssdev->dev, "display%d", dev_num++);
r = device_register(&dssdev->dev);
if (r)
return r;
if (dssdev->ctrl.panel) {
struct omap_dss_device *panel = dssdev->ctrl.panel;
panel->panel.ctrl = dssdev;
reset_device(&panel->dev, 1);
panel->dev.bus = &dss_bus_type;
panel->dev.parent = &dssdev->dev;
panel->dev.release = omap_dss_dev_release;
dev_set_name(&panel->dev, "panel%d", panel_num++);
r = device_register(&panel->dev);
if (r)
return r;
}
return 0;
}
void omap_dss_unregister_device(struct omap_dss_device *dssdev)
{
device_unregister(&dssdev->dev);
if (dssdev->ctrl.panel) {
struct omap_dss_device *panel = dssdev->ctrl.panel;
device_unregister(&panel->dev);
}
}
/* BUS */
static int omap_dss_bus_register(void)
{
int r;
r = bus_register(&dss_bus_type);
if (r) {
DSSERR("bus register failed\n");
return r;
}
dev_set_name(&dss_bus, "omapdss");
r = device_register(&dss_bus);
if (r) {
DSSERR("bus driver register failed\n");
bus_unregister(&dss_bus_type);
return r;
}
return 0;
}
/* INIT */
#ifdef CONFIG_OMAP2_DSS_MODULE
static void omap_dss_bus_unregister(void)
{
device_unregister(&dss_bus);
bus_unregister(&dss_bus_type);
}
static int __init omap_dss_init(void)
{
int r;
r = omap_dss_bus_register();
if (r)
return r;
r = platform_driver_register(&omap_dss_driver);
if (r) {
omap_dss_bus_unregister();
return r;
}
return 0;
}
static void __exit omap_dss_exit(void)
{
platform_driver_unregister(&omap_dss_driver);
omap_dss_bus_unregister();
}
module_init(omap_dss_init);
module_exit(omap_dss_exit);
#else
static int __init omap_dss_init(void)
{
return omap_dss_bus_register();
}
static int __init omap_dss_init2(void)
{
return platform_driver_register(&omap_dss_driver);
}
core_initcall(omap_dss_init);
device_initcall(omap_dss_init2);
#endif
MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
MODULE_LICENSE("GPL v2");
此差异已折叠。
此差异已折叠。
/*
* linux/drivers/video/omap2/dss/dpi.c
*
* Copyright (C) 2009 Nokia Corporation
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
*
* Some code and ideas taken from drivers/video/omap/ driver
* by Imre Deak.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#define DSS_SUBSYS_NAME "DPI"
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <plat/display.h>
#include <plat/cpu.h>
#include "dss.h"
static struct {
int update_enabled;
} dpi;
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req,
unsigned long *fck, int *lck_div, int *pck_div)
{
struct dsi_clock_info dsi_cinfo;
struct dispc_clock_info dispc_cinfo;
int r;
r = dsi_pll_calc_clock_div_pck(is_tft, pck_req, &dsi_cinfo,
&dispc_cinfo);
if (r)
return r;
r = dsi_pll_set_clock_div(&dsi_cinfo);
if (r)
return r;
dss_select_clk_source(0, 1);
r = dispc_set_clock_div(&dispc_cinfo);
if (r)
return r;
*fck = dsi_cinfo.dsi1_pll_fclk;
*lck_div = dispc_cinfo.lck_div;
*pck_div = dispc_cinfo.pck_div;
return 0;
}
#else
static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req,
unsigned long *fck, int *lck_div, int *pck_div)
{
struct dss_clock_info dss_cinfo;
struct dispc_clock_info dispc_cinfo;
int r;
r = dss_calc_clock_div(is_tft, pck_req, &dss_cinfo, &dispc_cinfo);
if (r)
return r;
r = dss_set_clock_div(&dss_cinfo);
if (r)
return r;
r = dispc_set_clock_div(&dispc_cinfo);
if (r)
return r;
*fck = dss_cinfo.fck;
*lck_div = dispc_cinfo.lck_div;
*pck_div = dispc_cinfo.pck_div;
return 0;
}
#endif
static int dpi_set_mode(struct omap_dss_device *dssdev)
{
struct omap_video_timings *t = &dssdev->panel.timings;
int lck_div, pck_div;
unsigned long fck;
unsigned long pck;
bool is_tft;
int r = 0;
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi,
dssdev->panel.acb);
is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000,
&fck, &lck_div, &pck_div);
#else
r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000,
&fck, &lck_div, &pck_div);
#endif
if (r)
goto err0;
pck = fck / lck_div / pck_div / 1000;
if (pck != t->pixel_clock) {
DSSWARN("Could not find exact pixel clock. "
"Requested %d kHz, got %lu kHz\n",
t->pixel_clock, pck);
t->pixel_clock = pck;
}
dispc_set_lcd_timings(t);
err0:
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
return r;
}
static int dpi_basic_init(struct omap_dss_device *dssdev)
{
bool is_tft;
is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT :
OMAP_DSS_LCD_DISPLAY_STN);
dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines);
return 0;
}
static int dpi_display_enable(struct omap_dss_device *dssdev)
{
int r;
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
goto err0;
}
if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
DSSERR("display already enabled\n");
r = -EINVAL;
goto err1;
}
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
r = dpi_basic_init(dssdev);
if (r)
goto err2;
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
dss_clk_enable(DSS_CLK_FCK2);
r = dsi_pll_init(dssdev, 0, 1);
if (r)
goto err3;
#endif
r = dpi_set_mode(dssdev);
if (r)
goto err4;
mdelay(2);
dispc_enable_lcd_out(1);
r = dssdev->driver->enable(dssdev);
if (r)
goto err5;
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
return 0;
err5:
dispc_enable_lcd_out(0);
err4:
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
dsi_pll_uninit();
err3:
dss_clk_disable(DSS_CLK_FCK2);
#endif
err2:
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
err1:
omap_dss_stop_device(dssdev);
err0:
return r;
}
static int dpi_display_resume(struct omap_dss_device *dssdev);
static void dpi_display_disable(struct omap_dss_device *dssdev)
{
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
return;
if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
dpi_display_resume(dssdev);
dssdev->driver->disable(dssdev);
dispc_enable_lcd_out(0);
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
dss_select_clk_source(0, 0);
dsi_pll_uninit();
dss_clk_disable(DSS_CLK_FCK2);
#endif
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
omap_dss_stop_device(dssdev);
}
static int dpi_display_suspend(struct omap_dss_device *dssdev)
{
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return -EINVAL;
DSSDBG("dpi_display_suspend\n");
if (dssdev->driver->suspend)
dssdev->driver->suspend(dssdev);
dispc_enable_lcd_out(0);
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
return 0;
}
static int dpi_display_resume(struct omap_dss_device *dssdev)
{
if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
return -EINVAL;
DSSDBG("dpi_display_resume\n");
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
dispc_enable_lcd_out(1);
if (dssdev->driver->resume)
dssdev->driver->resume(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
return 0;
}
static void dpi_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
DSSDBG("dpi_set_timings\n");
dssdev->panel.timings = *timings;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
dpi_set_mode(dssdev);
dispc_go(OMAP_DSS_CHANNEL_LCD);
}
}
static int dpi_check_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
bool is_tft;
int r;
int lck_div, pck_div;
unsigned long fck;
unsigned long pck;
if (!dispc_lcd_timings_ok(timings))
return -EINVAL;
if (timings->pixel_clock == 0)
return -EINVAL;
is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
{
struct dsi_clock_info dsi_cinfo;
struct dispc_clock_info dispc_cinfo;
r = dsi_pll_calc_clock_div_pck(is_tft,
timings->pixel_clock * 1000,
&dsi_cinfo, &dispc_cinfo);
if (r)
return r;
fck = dsi_cinfo.dsi1_pll_fclk;
lck_div = dispc_cinfo.lck_div;
pck_div = dispc_cinfo.pck_div;
}
#else
{
struct dss_clock_info dss_cinfo;
struct dispc_clock_info dispc_cinfo;
r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000,
&dss_cinfo, &dispc_cinfo);
if (r)
return r;
fck = dss_cinfo.fck;
lck_div = dispc_cinfo.lck_div;
pck_div = dispc_cinfo.pck_div;
}
#endif
pck = fck / lck_div / pck_div / 1000;
timings->pixel_clock = pck;
return 0;
}
static void dpi_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
*timings = dssdev->panel.timings;
}
static int dpi_display_set_update_mode(struct omap_dss_device *dssdev,
enum omap_dss_update_mode mode)
{
if (mode == OMAP_DSS_UPDATE_MANUAL)
return -EINVAL;
if (mode == OMAP_DSS_UPDATE_DISABLED) {
dispc_enable_lcd_out(0);
dpi.update_enabled = 0;
} else {
dispc_enable_lcd_out(1);
dpi.update_enabled = 1;
}
return 0;
}
static enum omap_dss_update_mode dpi_display_get_update_mode(
struct omap_dss_device *dssdev)
{
return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
OMAP_DSS_UPDATE_DISABLED;
}
int dpi_init_display(struct omap_dss_device *dssdev)
{
DSSDBG("init_display\n");
dssdev->enable = dpi_display_enable;
dssdev->disable = dpi_display_disable;
dssdev->suspend = dpi_display_suspend;
dssdev->resume = dpi_display_resume;
dssdev->set_timings = dpi_set_timings;
dssdev->check_timings = dpi_check_timings;
dssdev->get_timings = dpi_get_timings;
dssdev->set_update_mode = dpi_display_set_update_mode;
dssdev->get_update_mode = dpi_display_get_update_mode;
return 0;
}
int dpi_init(void)
{
return 0;
}
void dpi_exit(void)
{
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
menuconfig FB_OMAP2
tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)"
depends on FB && OMAP2_DSS
select OMAP2_VRAM
select OMAP2_VRFB
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
help
Frame buffer driver for OMAP2/3 based boards.
config FB_OMAP2_DEBUG_SUPPORT
bool "Debug support for OMAP2/3 FB"
default y
depends on FB_OMAP2
help
Support for debug output. You have to enable the actual printing
with debug module parameter.
config FB_OMAP2_FORCE_AUTO_UPDATE
bool "Force main display to automatic update mode"
depends on FB_OMAP2
help
Forces main display to automatic update mode (if possible),
and also enables tearsync (if possible). By default
displays that support manual update are started in manual
update mode.
config FB_OMAP2_NUM_FBS
int "Number of framebuffers"
range 1 10
default 3
depends on FB_OMAP2
help
Select the number of framebuffers created. OMAP2/3 has 3 overlays
so normally this would be 3.
obj-$(CONFIG_FB_OMAP2) += omapfb.o
omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* linux/drivers/video/omap2/omapfb.h
*
* Copyright (C) 2008 Nokia Corporation
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
*
* Some code and ideas taken from drivers/video/omap/ driver
* by Imre Deak.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
#ifdef CONFIG_FB_OMAP2_DEBUG_SUPPORT
#define DEBUG
#endif
#include <plat/display.h>
#ifdef DEBUG
extern unsigned int omapfb_debug;
#define DBG(format, ...) \
if (omapfb_debug) \
printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__)
#else
#define DBG(format, ...)
#endif
#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par))
/* max number of overlays to which a framebuffer data can be direct */
#define OMAPFB_MAX_OVL_PER_FB 3
struct omapfb2_mem_region {
u32 paddr;
void __iomem *vaddr;
struct vrfb vrfb;
unsigned long size;
u8 type; /* OMAPFB_PLANE_MEM_* */
bool alloc; /* allocated by the driver */
bool map; /* kernel mapped by the driver */
};
/* appended to fb_info */
struct omapfb_info {
int id;
struct omapfb2_mem_region region;
atomic_t map_count;
int num_overlays;
struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
struct omapfb2_device *fbdev;
enum omap_dss_rotation_type rotation_type;
u8 rotation[OMAPFB_MAX_OVL_PER_FB];
bool mirror;
};
struct omapfb2_device {
struct device *dev;
struct mutex mtx;
u32 pseudo_palette[17];
int state;
unsigned num_fbs;
struct fb_info *fbs[10];
unsigned num_displays;
struct omap_dss_device *displays[10];
unsigned num_overlays;
struct omap_overlay *overlays[10];
unsigned num_managers;
struct omap_overlay_manager *managers[10];
};
struct omapfb_colormode {
enum omap_color_mode dssmode;
u32 bits_per_pixel;
u32 nonstd;
struct fb_bitfield red;
struct fb_bitfield green;
struct fb_bitfield blue;
struct fb_bitfield transp;
};
void set_fb_fix(struct fb_info *fbi);
int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var);
int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type);
int omapfb_apply_changes(struct fb_info *fbi, int init);
int omapfb_create_sysfs(struct omapfb2_device *fbdev);
void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
struct fb_var_screeninfo *var);
/* find the display connected to this fb, if any */
static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
{
struct omapfb_info *ofbi = FB2OFB(fbi);
int i;
/* XXX: returns the display connected to first attached overlay */
for (i = 0; i < ofbi->num_overlays; i++) {
if (ofbi->overlays[i]->manager)
return ofbi->overlays[i]->manager->device;
}
return NULL;
}
static inline void omapfb_lock(struct omapfb2_device *fbdev)
{
mutex_lock(&fbdev->mtx);
}
static inline void omapfb_unlock(struct omapfb2_device *fbdev)
{
mutex_unlock(&fbdev->mtx);
}
static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
int enable)
{
struct omap_overlay_info info;
ovl->get_overlay_info(ovl, &info);
info.enabled = enable;
return ovl->set_overlay_info(ovl, &info);
}
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册