提交 2b831888 编写于 作者: L Linus Torvalds

Merge tag 'fbdev-for-3.8' of git://gitorious.org/linux-omap-dss2/linux

Pull fbdev changes from Tomi Valkeinen:
 "OMAPDSS changes, including:
   - use dynanic debug prints
   - OMAP platform dependency removals
   - Creation of compat-layer, helping us to improve omapdrm
   - Misc cleanups, aiming to make omadss more in line with the upcoming
     common display framework

  Exynos DP changes for the 3.8 merge window:
   - Device Tree support for Samsung Exynos DP
   - SW Link training is cleaned up.
   - HPD interrupt is supported.

  Samsung Framebuffer changes for the 3.8 merge window:
   - The bit definitions of header file are updated.
   - Some minor typos are fixed.
   - Some minor bugs of s3c_fb_check_var() are fixed.

  FB related changes for SH Mobile, Freescale DIU

  Add support for the Solomon SSD1307 OLED Controller"

* tag 'fbdev-for-3.8' of git://gitorious.org/linux-omap-dss2/linux: (191 commits)
  OMAPDSS: fix TV-out issue with DSI PLL
  Revert "OMAPFB: simplify locking"
  OMAPFB: remove silly loop in fb2display()
  OMAPFB: fix error handling in omapfb_find_best_mode()
  OMAPFB: use devm_kzalloc to allocate omapfb2_device
  OMAPDSS: DISPC: remove dispc fck uses
  OMAPDSS: DISPC: get dss clock rate from dss driver
  drivers/video/console/softcursor.c: remove redundant NULL check before kfree()
  drivers/video: add support for the Solomon SSD1307 OLED Controller
  OMAPDSS: use omapdss_compat_init() in other drivers
  OMAPDSS: export dispc functions
  OMAPDSS: export dss_feat functions
  OMAPDSS: export dss_mgr_ops functions
  OMAPDSS: separate compat files in the Makefile
  OMAPDSS: move display sysfs init to compat layer
  OMAPDSS: DPI: use dispc's check_timings
  OMAPDSS: DISPC: add dispc_ovl_check()
  OMAPDSS: move irq handling to dispc-compat
  OMAPDSS: move omap_dispc_wait_for_irq_interruptible_timeout to dispc-compat.c
  OMAPDSS: move blocking mgr enable/disable to compat layer
  ...

Conflicts:
	arch/arm/mach-davinci/devices-da8xx.c
	arch/arm/plat-omap/common.c
	drivers/media/platform/omap/omap_vout.c
......@@ -285,7 +285,10 @@ FB0 +-- GFX ---- LCD ---- LCD
Misc notes
----------
OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator.
OMAP FB allocates the framebuffer memory using the standard dma allocator. You
can enable Contiguous Memory Allocator (CONFIG_CMA) to improve the dma
allocator, and if CMA is enabled, you use "cma=" kernel parameter to increase
the global memory area for CMA.
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.
......@@ -301,11 +304,6 @@ framebuffer parameters.
Kernel boot arguments
---------------------
vram=<size>[,<physaddr>]
- Amount of total VRAM to preallocate and optionally a physical start
memory address. 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.
......
The Exynos display port interface should be configured based on
the type of panel connected to it.
We use two nodes:
-dp-controller node
-dptx-phy node(defined inside dp-controller node)
For the DP-PHY initialization, we use the dptx-phy node.
Required properties for dptx-phy:
-reg:
Base address of DP PHY register.
-samsung,enable-mask:
The bit-mask used to enable/disable DP PHY.
For the Panel initialization, we read data from dp-controller node.
Required properties for dp-controller:
-compatible:
should be "samsung,exynos5-dp".
-reg:
physical base address of the controller and length
of memory mapped region.
-interrupts:
interrupt combiner values.
-interrupt-parent:
phandle to Interrupt combiner node.
-samsung,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
-samsung,dynamic-range:
dynamic range for input video data.
VESA = 0, CEA = 1
-samsung,ycbcr-coeff:
YCbCr co-efficients for input video.
COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
-samsung,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
-samsung,link-rate:
link rate supported by the panel.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
-samsung,lane-count:
number of lanes supported by the panel.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
Optional properties for dp-controller:
-interlaced:
interlace scan mode.
Progressive if defined, Interlaced if not defined
-vsync-active-high:
VSYNC polarity configuration.
High if defined, Low if not defined
-hsync-active-high:
HSYNC polarity configuration.
High if defined, Low if not defined
Example:
SOC specific portion:
dp-controller {
compatible = "samsung,exynos5-dp";
reg = <0x145b0000 0x10000>;
interrupts = <10 3>;
interrupt-parent = <&combiner>;
dptx-phy {
reg = <0x10040720>;
samsung,enable-mask = <1>;
};
};
Board Specific portion:
dp-controller {
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
};
* Solomon SSD1307 Framebuffer Driver
Required properties:
- compatible: Should be "solomon,ssd1307fb-<bus>". The only supported bus for
now is i2c.
- reg: Should contain address of the controller on the I2C bus. Most likely
0x3c or 0x3d
- pwm: Should contain the pwm to use according to the OF device tree PWM
specification [0]
- reset-gpios: Should contain the GPIO used to reset the OLED display
Optional properties:
- reset-active-low: Is the reset gpio is active on physical low?
[0]: Documentation/devicetree/bindings/pwm/pwm.txt
Examples:
ssd1307: oled@3c {
compatible = "solomon,ssd1307fb-i2c";
reg = <0x3c>;
pwms = <&pwm 4 3000>;
reset-gpios = <&gpio2 7>;
reset-active-low;
};
......@@ -3162,6 +3162,12 @@ F: drivers/video/
F: include/video/
F: include/linux/fb.h
FREESCALE DIU FRAMEBUFFER DRIVER
M: Timur Tabi <timur@freescale.com>
L: linux-fbdev@vger.kernel.org
S: Supported
F: drivers/video/fsl-diu-fb.*
FREESCALE DMA DRIVER
M: Li Yang <leoli@freescale.com>
M: Zhang Wei <zw@zh-kernel.org>
......
......@@ -408,7 +408,7 @@ static struct clk_lookup da830_clks[] = {
CLK(NULL, "pwm2", &pwm2_clk),
CLK("eqep.0", NULL, &eqep0_clk),
CLK("eqep.1", NULL, &eqep1_clk),
CLK("da8xx_lcdc.0", NULL, &lcdc_clk),
CLK("da8xx_lcdc.0", "fck", &lcdc_clk),
CLK("davinci-mcasp.0", NULL, &mcasp0_clk),
CLK("davinci-mcasp.1", NULL, &mcasp1_clk),
CLK("davinci-mcasp.2", NULL, &mcasp2_clk),
......
......@@ -403,7 +403,7 @@ static struct clk_lookup da850_clks[] = {
CLK(NULL, "rmii", &rmii_clk),
CLK("davinci_emac.1", NULL, &emac_clk),
CLK("davinci-mcasp.0", NULL, &mcasp_clk),
CLK("da8xx_lcdc.0", NULL, &lcdc_clk),
CLK("da8xx_lcdc.0", "fck", &lcdc_clk),
CLK("davinci_mmc.0", NULL, &mmcsd0_clk),
CLK("davinci_mmc.1", NULL, &mmcsd1_clk),
CLK(NULL, "aemif", &aemif_clk),
......
......@@ -589,29 +589,9 @@ int __init da8xx_register_uio_pruss(void)
return platform_device_register(&da8xx_uio_pruss_dev);
}
static const struct display_panel disp_panel = {
QVGA,
16,
16,
COLOR_ACTIVE,
};
static struct lcd_ctrl_config lcd_cfg = {
&disp_panel,
.ac_bias = 255,
.ac_bias_intrpt = 0,
.dma_burst_sz = 16,
.panel_shade = COLOR_ACTIVE,
.bpp = 16,
.fdd = 255,
.tft_alt_mode = 0,
.stn_565_mode = 0,
.mono_8bit_mode = 0,
.invert_line_clock = 1,
.invert_frm_clock = 1,
.sync_edge = 0,
.sync_ctrl = 1,
.raster_order = 0,
.fifo_th = 6,
};
struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata = {
......
......@@ -53,6 +53,7 @@ static struct dev_pm_domain davinci_pm_domain = {
static struct pm_clk_notifier_block platform_bus_notifier = {
.pm_domain = &davinci_pm_domain,
.con_ids = { "fck", NULL, },
};
static int __init davinci_pm_runtime_init(void)
......
......@@ -16,7 +16,6 @@
#include <linux/mm.h>
#include <asm/mach-types.h>
#include <video/omapdss.h>
#include <plat/vram.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
#include "board-rx51.h"
......@@ -87,17 +86,4 @@ static int __init rx51_video_init(void)
}
subsys_initcall(rx51_video_init);
void __init rx51_video_mem_init(void)
{
/*
* GFX 864x480x32bpp
* VID1/2 1280x720x32bpp double buffered
*/
omap_vram_set_sdram_vram(PAGE_ALIGN(864 * 480 * 4) +
2 * PAGE_ALIGN(1280 * 720 * 4 * 2), 0);
}
#else
void __init rx51_video_mem_init(void) { }
#endif /* defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) */
......@@ -34,8 +34,6 @@
#define RX51_GPIO_SLEEP_IND 162
extern void rx51_video_mem_init(void);
static struct gpio_led gpio_leds[] = {
{
.name = "sleep_ind",
......@@ -112,7 +110,6 @@ static void __init rx51_init(void)
static void __init rx51_reserve(void)
{
rx51_video_mem_init();
omap_reserve();
}
......
......@@ -102,17 +102,20 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {
{ "dss_hdmi", "omapdss_hdmi", -1 },
};
static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
static void __init omap4_tpd12s015_mux_pads(void)
{
u32 reg;
u16 control_i2c_1;
omap_mux_init_signal("hdmi_cec",
OMAP_PIN_INPUT_PULLUP);
omap_mux_init_signal("hdmi_ddc_scl",
OMAP_PIN_INPUT_PULLUP);
omap_mux_init_signal("hdmi_ddc_sda",
OMAP_PIN_INPUT_PULLUP);
}
static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
{
u32 reg;
u16 control_i2c_1;
/*
* CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and
......@@ -163,8 +166,10 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
int __init omap_hdmi_init(enum omap_hdmi_flags flags)
{
if (cpu_is_omap44xx())
if (cpu_is_omap44xx()) {
omap4_hdmi_mux_pads(flags);
omap4_tpd12s015_mux_pads();
}
return 0;
}
......
......@@ -213,95 +213,6 @@ static struct platform_device irda_device = {
.num_resources = ARRAY_SIZE(irda_resources),
};
static unsigned char lcd_backlight_seq[3][2] = {
{ 0x04, 0x07 },
{ 0x23, 0x80 },
{ 0x03, 0x01 },
};
static void lcd_backlight_on(void)
{
struct i2c_adapter *a;
struct i2c_msg msg;
int k;
a = i2c_get_adapter(1);
for (k = 0; a && k < 3; k++) {
msg.addr = 0x6d;
msg.buf = &lcd_backlight_seq[k][0];
msg.len = 2;
msg.flags = 0;
if (i2c_transfer(a, &msg, 1) != 1)
break;
}
}
static void lcd_backlight_reset(void)
{
gpio_set_value(GPIO_PORT235, 0);
mdelay(24);
gpio_set_value(GPIO_PORT235, 1);
}
/* LCDC0 */
static const struct fb_videomode lcdc0_modes[] = {
{
.name = "R63302(QHD)",
.xres = 544,
.yres = 961,
.left_margin = 72,
.right_margin = 600,
.hsync_len = 16,
.upper_margin = 8,
.lower_margin = 8,
.vsync_len = 2,
.sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
},
};
static struct sh_mobile_lcdc_info lcdc0_info = {
.clock_source = LCDC_CLK_PERIPHERAL,
.ch[0] = {
.chan = LCDC_CHAN_MAINLCD,
.interface_type = RGB24,
.clock_divider = 1,
.flags = LCDC_FLAGS_DWPOL,
.fourcc = V4L2_PIX_FMT_RGB565,
.lcd_modes = lcdc0_modes,
.num_modes = ARRAY_SIZE(lcdc0_modes),
.panel_cfg = {
.width = 44,
.height = 79,
.display_on = lcd_backlight_on,
.display_off = lcd_backlight_reset,
},
}
};
static struct resource lcdc0_resources[] = {
[0] = {
.name = "LCDC0",
.start = 0xfe940000, /* P4-only space */
.end = 0xfe943fff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = intcs_evt2irq(0x580),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device lcdc0_device = {
.name = "sh_mobile_lcdc_fb",
.num_resources = ARRAY_SIZE(lcdc0_resources),
.resource = lcdc0_resources,
.id = 0,
.dev = {
.platform_data = &lcdc0_info,
.coherent_dma_mask = ~0,
},
};
/* MIPI-DSI */
static struct resource mipidsi0_resources[] = {
[0] = {
......@@ -358,7 +269,7 @@ static int sh_mipi_set_dot_clock(struct platform_device *pdev,
static struct sh_mipi_dsi_info mipidsi0_info = {
.data_format = MIPI_RGB888,
.lcd_chan = &lcdc0_info.ch[0],
.channel = LCDC_CHAN_MAINLCD,
.lane = 2,
.vsynw_offset = 20,
.clksrc = 1,
......@@ -378,6 +289,109 @@ static struct platform_device mipidsi0_device = {
},
};
static unsigned char lcd_backlight_seq[3][2] = {
{ 0x04, 0x07 },
{ 0x23, 0x80 },
{ 0x03, 0x01 },
};
static int lcd_backlight_set_brightness(int brightness)
{
struct i2c_adapter *adap;
struct i2c_msg msg;
unsigned int i;
int ret;
if (brightness == 0) {
/* Reset the chip */
gpio_set_value(GPIO_PORT235, 0);
mdelay(24);
gpio_set_value(GPIO_PORT235, 1);
return 0;
}
adap = i2c_get_adapter(1);
if (adap == NULL)
return -ENODEV;
for (i = 0; i < ARRAY_SIZE(lcd_backlight_seq); i++) {
msg.addr = 0x6d;
msg.buf = &lcd_backlight_seq[i][0];
msg.len = 2;
msg.flags = 0;
ret = i2c_transfer(adap, &msg, 1);
if (ret < 0)
break;
}
i2c_put_adapter(adap);
return ret < 0 ? ret : 0;
}
/* LCDC0 */
static const struct fb_videomode lcdc0_modes[] = {
{
.name = "R63302(QHD)",
.xres = 544,
.yres = 961,
.left_margin = 72,
.right_margin = 600,
.hsync_len = 16,
.upper_margin = 8,
.lower_margin = 8,
.vsync_len = 2,
.sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
},
};
static struct sh_mobile_lcdc_info lcdc0_info = {
.clock_source = LCDC_CLK_PERIPHERAL,
.ch[0] = {
.chan = LCDC_CHAN_MAINLCD,
.interface_type = RGB24,
.clock_divider = 1,
.flags = LCDC_FLAGS_DWPOL,
.fourcc = V4L2_PIX_FMT_RGB565,
.lcd_modes = lcdc0_modes,
.num_modes = ARRAY_SIZE(lcdc0_modes),
.panel_cfg = {
.width = 44,
.height = 79,
},
.bl_info = {
.name = "sh_mobile_lcdc_bl",
.max_brightness = 1,
.set_brightness = lcd_backlight_set_brightness,
},
.tx_dev = &mipidsi0_device,
}
};
static struct resource lcdc0_resources[] = {
[0] = {
.name = "LCDC0",
.start = 0xfe940000, /* P4-only space */
.end = 0xfe943fff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = intcs_evt2irq(0x580),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device lcdc0_device = {
.name = "sh_mobile_lcdc_fb",
.num_resources = ARRAY_SIZE(lcdc0_resources),
.resource = lcdc0_resources,
.id = 0,
.dev = {
.platform_data = &lcdc0_info,
.coherent_dma_mask = ~0,
},
};
/* Fixed 2.8V regulators to be used by SDHI0 */
static struct regulator_consumer_supply fixed2v8_power_consumers[] =
{
......@@ -531,8 +545,8 @@ static struct platform_device *ag5evm_devices[] __initdata = {
&fsi_device,
&mmc_device,
&irda_device,
&lcdc0_device,
&mipidsi0_device,
&lcdc0_device,
&sdhi0_device,
&sdhi1_device,
};
......@@ -621,7 +635,7 @@ static void __init ag5evm_init(void)
/* LCD backlight controller */
gpio_request(GPIO_PORT235, NULL); /* RESET */
gpio_direction_output(GPIO_PORT235, 0);
lcd_backlight_reset();
lcd_backlight_set_brightness(0);
/* enable SDHI0 on CN15 [SD I/F] */
gpio_request(GPIO_FN_SDHIWP0, NULL);
......
......@@ -552,11 +552,9 @@ static struct resource mipidsi0_resources[] = {
},
};
static struct sh_mobile_lcdc_info lcdc_info;
static struct sh_mipi_dsi_info mipidsi0_info = {
.data_format = MIPI_RGB888,
.lcd_chan = &lcdc_info.ch[0],
.channel = LCDC_CHAN_MAINLCD,
.lane = 2,
.vsynw_offset = 17,
.phyctrl = 0x6 << 8,
......
......@@ -370,11 +370,6 @@ static int mackerel_set_brightness(int brightness)
return 0;
}
static int mackerel_get_brightness(void)
{
return gpio_get_value(GPIO_PORT31);
}
static const struct sh_mobile_meram_cfg lcd_meram_cfg = {
.icb[0] = {
.meram_size = 0x40,
......@@ -403,7 +398,6 @@ static struct sh_mobile_lcdc_info lcdc_info = {
.name = "sh_mobile_lcdc_bl",
.max_brightness = 1,
.set_brightness = mackerel_set_brightness,
.get_brightness = mackerel_get_brightness,
},
.meram_cfg = &lcd_meram_cfg,
}
......
......@@ -29,6 +29,7 @@
#include <linux/memblock.h>
#include <linux/io.h>
#include <linux/omapfb.h>
#include <linux/dma-mapping.h>
#include <asm/mach/map.h>
......@@ -105,7 +106,7 @@ static struct platform_device omap_fb_device = {
.id = -1,
.dev = {
.dma_mask = &omap_fb_dma_mask,
.coherent_dma_mask = ~(u32)0,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &omapfb_config,
},
.num_resources = 0,
......@@ -141,7 +142,7 @@ static struct platform_device omap_fb_device = {
.id = -1,
.dev = {
.dma_mask = &omap_fb_dma_mask,
.coherent_dma_mask = ~(u32)0,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &omapfb_config,
},
.num_resources = 0,
......
/*
* 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>
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(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_reserve_sdram_memblock(void);
#else
static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { }
static inline void omap_vram_reserve_sdram_memblock(void) { }
#endif
#endif
......@@ -179,11 +179,6 @@ static int ap320_wvga_set_brightness(int brightness)
return 0;
}
static int ap320_wvga_get_brightness(void)
{
return gpio_get_value(GPIO_PTS3);
}
static void ap320_wvga_power_on(void)
{
msleep(100);
......@@ -232,7 +227,6 @@ static struct sh_mobile_lcdc_info lcdc_info = {
.name = "sh_mobile_lcdc_bl",
.max_brightness = 1,
.set_brightness = ap320_wvga_set_brightness,
.get_brightness = ap320_wvga_get_brightness,
},
}
};
......
......@@ -329,11 +329,6 @@ static int ecovec24_set_brightness(int brightness)
return 0;
}
static int ecovec24_get_brightness(void)
{
return gpio_get_value(GPIO_PTR1);
}
static struct sh_mobile_lcdc_info lcdc_info = {
.ch[0] = {
.interface_type = RGB18,
......@@ -347,7 +342,6 @@ static struct sh_mobile_lcdc_info lcdc_info = {
.name = "sh_mobile_lcdc_bl",
.max_brightness = 1,
.set_brightness = ecovec24_set_brightness,
.get_brightness = ecovec24_get_brightness,
},
}
};
......
......@@ -283,7 +283,7 @@ void kfr2r09_lcd_start(void *sohandle, struct sh_mobile_lcdc_sys_bus_ops *so)
#define MAIN_MLED4 0x40
#define MAIN_MSW 0x80
static int kfr2r09_lcd_backlight(int on)
int kfr2r09_lcd_set_brightness(int brightness)
{
struct i2c_adapter *a;
struct i2c_msg msg;
......@@ -295,7 +295,7 @@ static int kfr2r09_lcd_backlight(int on)
return -ENODEV;
buf[0] = 0x00;
if (on)
if (brightness)
buf[1] = CTRL_CPSW | CTRL_C10 | CTRL_CKSW;
else
buf[1] = 0;
......@@ -309,7 +309,7 @@ static int kfr2r09_lcd_backlight(int on)
return -ENODEV;
buf[0] = 0x01;
if (on)
if (brightness)
buf[1] = MAIN_MSW | MAIN_MLED4 | 0x0c;
else
buf[1] = 0;
......@@ -324,13 +324,3 @@ static int kfr2r09_lcd_backlight(int on)
return 0;
}
void kfr2r09_lcd_on(void)
{
kfr2r09_lcd_backlight(1);
}
void kfr2r09_lcd_off(void)
{
kfr2r09_lcd_backlight(0);
}
......@@ -158,8 +158,11 @@ static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
.height = 58,
.setup_sys = kfr2r09_lcd_setup,
.start_transfer = kfr2r09_lcd_start,
.display_on = kfr2r09_lcd_on,
.display_off = kfr2r09_lcd_off,
},
.bl_info = {
.name = "sh_mobile_lcdc_bl",
.max_brightness = 1,
.set_brightness = kfr2r09_lcd_set_brightness,
},
.sys_bus_cfg = {
.ldmt2r = 0x07010904,
......
......@@ -4,15 +4,13 @@
#include <video/sh_mobile_lcdc.h>
#if defined(CONFIG_FB_SH_MOBILE_LCDC) || defined(CONFIG_FB_SH_MOBILE_LCDC_MODULE)
void kfr2r09_lcd_on(void);
void kfr2r09_lcd_off(void);
int kfr2r09_lcd_set_brightness(int brightness);
int kfr2r09_lcd_setup(void *sys_ops_handle,
struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
void kfr2r09_lcd_start(void *sys_ops_handle,
struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
#else
static void kfr2r09_lcd_on(void) {}
static void kfr2r09_lcd_off(void) {}
static int kfr2r09_lcd_set_brightness(int brightness) {}
static int kfr2r09_lcd_setup(void *sys_ops_handle,
struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
{
......
......@@ -44,8 +44,6 @@
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <plat/cpu.h>
#include <linux/omap-dma.h>
#include <video/omapvrfb.h>
#include <video/omapdss.h>
......@@ -2043,7 +2041,7 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
vout->vid_info.id = k + 1;
/* Set VRFB as rotation_type for omap2 and omap3 */
if (cpu_is_omap24xx() || cpu_is_omap34xx())
if (omap_vout_dss_omap24xx() || omap_vout_dss_omap34xx())
vout->vid_info.rotation_type = VOUT_ROT_VRFB;
/* Setup the default configuration for the video devices
......@@ -2160,14 +2158,23 @@ static int __init omap_vout_probe(struct platform_device *pdev)
struct omap_dss_device *def_display;
struct omap2video_device *vid_dev = NULL;
ret = omapdss_compat_init();
if (ret) {
dev_err(&pdev->dev, "failed to init dss\n");
return ret;
}
if (pdev->num_resources == 0) {
dev_err(&pdev->dev, "probed for an unknown device\n");
return -ENODEV;
ret = -ENODEV;
goto err_dss_init;
}
vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL);
if (vid_dev == NULL)
return -ENOMEM;
if (vid_dev == NULL) {
ret = -ENOMEM;
goto err_dss_init;
}
vid_dev->num_displays = 0;
for_each_dss_dev(dssdev) {
......@@ -2262,6 +2269,8 @@ static int __init omap_vout_probe(struct platform_device *pdev)
}
probe_err0:
kfree(vid_dev);
err_dss_init:
omapdss_compat_uninit();
return ret;
}
......
......@@ -26,7 +26,7 @@
#include <linux/dma-mapping.h>
#include <plat/cpu.h>
#include <video/omapdss.h>
#include "omap_voutlib.h"
......@@ -124,7 +124,7 @@ int omap_vout_new_window(struct v4l2_rect *crop,
win->chromakey = new_win->chromakey;
/* Adjust the cropping window to allow for resizing limitation */
if (cpu_is_omap24xx()) {
if (omap_vout_dss_omap24xx()) {
/* For 24xx limit is 8x to 1/2x scaling. */
if ((crop->height/win->w.height) >= 2)
crop->height = win->w.height * 2;
......@@ -140,7 +140,7 @@ int omap_vout_new_window(struct v4l2_rect *crop,
if (crop->height != win->w.height)
crop->width = 768;
}
} else if (cpu_is_omap34xx()) {
} else if (omap_vout_dss_omap34xx()) {
/* For 34xx limit is 8x to 1/4x scaling. */
if ((crop->height/win->w.height) >= 4)
crop->height = win->w.height * 4;
......@@ -196,7 +196,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
if (try_crop.width <= 0 || try_crop.height <= 0)
return -EINVAL;
if (cpu_is_omap24xx()) {
if (omap_vout_dss_omap24xx()) {
if (try_crop.height != win->w.height) {
/* If we're resizing vertically, we can't support a
* crop width wider than 768 pixels.
......@@ -207,9 +207,9 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
}
/* vertical resizing */
vresize = (1024 * try_crop.height) / win->w.height;
if (cpu_is_omap24xx() && (vresize > 2048))
if (omap_vout_dss_omap24xx() && (vresize > 2048))
vresize = 2048;
else if (cpu_is_omap34xx() && (vresize > 4096))
else if (omap_vout_dss_omap34xx() && (vresize > 4096))
vresize = 4096;
win->w.height = ((1024 * try_crop.height) / vresize) & ~1;
......@@ -226,9 +226,9 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
}
/* horizontal resizing */
hresize = (1024 * try_crop.width) / win->w.width;
if (cpu_is_omap24xx() && (hresize > 2048))
if (omap_vout_dss_omap24xx() && (hresize > 2048))
hresize = 2048;
else if (cpu_is_omap34xx() && (hresize > 4096))
else if (omap_vout_dss_omap34xx() && (hresize > 4096))
hresize = 4096;
win->w.width = ((1024 * try_crop.width) / hresize) & ~1;
......@@ -243,7 +243,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
if (try_crop.width == 0)
try_crop.width = 2;
}
if (cpu_is_omap24xx()) {
if (omap_vout_dss_omap24xx()) {
if ((try_crop.height/win->w.height) >= 2)
try_crop.height = win->w.height * 2;
......@@ -258,7 +258,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
if (try_crop.height != win->w.height)
try_crop.width = 768;
}
} else if (cpu_is_omap34xx()) {
} else if (omap_vout_dss_omap34xx()) {
if ((try_crop.height/win->w.height) >= 4)
try_crop.height = win->w.height * 4;
......@@ -337,3 +337,21 @@ void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size)
}
free_pages((unsigned long) virtaddr, order);
}
bool omap_vout_dss_omap24xx(void)
{
return omapdss_get_version() == OMAPDSS_VER_OMAP24xx;
}
bool omap_vout_dss_omap34xx(void)
{
switch (omapdss_get_version()) {
case OMAPDSS_VER_OMAP34xx_ES1:
case OMAPDSS_VER_OMAP34xx_ES3:
case OMAPDSS_VER_OMAP3630:
case OMAPDSS_VER_AM35xx:
return true;
default:
return false;
}
}
......@@ -32,5 +32,8 @@ void omap_vout_new_format(struct v4l2_pix_format *pix,
struct v4l2_window *win);
unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr);
void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size);
bool omap_vout_dss_omap24xx(void);
bool omap_vout_dss_omap34xx(void);
#endif /* #ifndef OMAP_VOUTLIB_H */
......@@ -565,6 +565,14 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
dev->dev_private = priv;
ret = omapdss_compat_init();
if (ret) {
dev_err(dev->dev, "coult not init omapdss\n");
dev->dev_private = NULL;
kfree(priv);
return ret;
}
priv->wq = alloc_ordered_workqueue("omapdrm", 0);
INIT_LIST_HEAD(&priv->obj_list);
......@@ -576,6 +584,7 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
dev->dev_private = NULL;
kfree(priv);
omapdss_compat_uninit();
return ret;
}
......@@ -610,6 +619,8 @@ static int dev_unload(struct drm_device *dev)
flush_workqueue(priv->wq);
destroy_workqueue(priv->wq);
omapdss_compat_uninit();
kfree(dev->dev_private);
dev->dev_private = NULL;
......
......@@ -2045,7 +2045,7 @@ config FB_S3C_DEBUG_REGWRITE
bool "Debug register writes"
depends on FB_S3C
---help---
Show all register writes via printk(KERN_DEBUG)
Show all register writes via pr_debug()
config FB_S3C2410
tristate "S3C2410 LCD framebuffer support"
......@@ -2442,4 +2442,19 @@ config FB_SH_MOBILE_MERAM
Up to 4 memory channels can be configured, allowing 4 RGB or
2 YCbCr framebuffers to be configured.
config FB_SSD1307
tristate "Solomon SSD1307 framebuffer support"
depends on FB && I2C
depends on OF
depends on GENERIC_GPIO
select FB_SYS_FOPS
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
select FB_DEFERRED_IO
select PWM
help
This driver implements support for the Solomon SSD1307
OLED controller over I2C.
endmenu
......@@ -161,6 +161,7 @@ obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o
obj-$(CONFIG_FB_MX3) += mx3fb.o
obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o
obj-$(CONFIG_FB_MXS) += mxsfb.o
obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o
# the test framebuffer is last
obj-$(CONFIG_FB_VIRTUAL) += vfb.o
......
......@@ -35,8 +35,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
dsize = s_pitch * cursor->image.height;
if (dsize + sizeof(struct fb_image) != ops->cursor_size) {
if (ops->cursor_src != NULL)
kfree(ops->cursor_src);
kfree(ops->cursor_src);
ops->cursor_size = dsize + sizeof(struct fb_image);
ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC);
......
......@@ -213,62 +213,51 @@ static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = {
.accel = FB_ACCEL_NONE
};
struct da8xx_panel {
const char name[25]; /* Full name <vendor>_<model> */
unsigned short width;
unsigned short height;
int hfp; /* Horizontal front porch */
int hbp; /* Horizontal back porch */
int hsw; /* Horizontal Sync Pulse Width */
int vfp; /* Vertical front porch */
int vbp; /* Vertical back porch */
int vsw; /* Vertical Sync Pulse Width */
unsigned int pxl_clk; /* Pixel clock */
unsigned char invert_pxl_clk; /* Invert Pixel clock */
};
static struct da8xx_panel known_lcd_panels[] = {
static struct fb_videomode known_lcd_panels[] = {
/* Sharp LCD035Q3DG01 */
[0] = {
.name = "Sharp_LCD035Q3DG01",
.width = 320,
.height = 240,
.hfp = 8,
.hbp = 6,
.hsw = 0,
.vfp = 2,
.vbp = 2,
.vsw = 0,
.pxl_clk = 4608000,
.invert_pxl_clk = 1,
.name = "Sharp_LCD035Q3DG01",
.xres = 320,
.yres = 240,
.pixclock = 4608000,
.left_margin = 6,
.right_margin = 8,
.upper_margin = 2,
.lower_margin = 2,
.hsync_len = 0,
.vsync_len = 0,
.sync = FB_SYNC_CLK_INVERT |
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
},
/* Sharp LK043T1DG01 */
[1] = {
.name = "Sharp_LK043T1DG01",
.width = 480,
.height = 272,
.hfp = 2,
.hbp = 2,
.hsw = 41,
.vfp = 2,
.vbp = 2,
.vsw = 10,
.pxl_clk = 7833600,
.invert_pxl_clk = 0,
.name = "Sharp_LK043T1DG01",
.xres = 480,
.yres = 272,
.pixclock = 7833600,
.left_margin = 2,
.right_margin = 2,
.upper_margin = 2,
.lower_margin = 2,
.hsync_len = 41,
.vsync_len = 10,
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.flag = 0,
},
[2] = {
/* Hitachi SP10Q010 */
.name = "SP10Q010",
.width = 320,
.height = 240,
.hfp = 10,
.hbp = 10,
.hsw = 10,
.vfp = 10,
.vbp = 10,
.vsw = 10,
.pxl_clk = 7833600,
.invert_pxl_clk = 0,
.name = "SP10Q010",
.xres = 320,
.yres = 240,
.pixclock = 7833600,
.left_margin = 10,
.right_margin = 10,
.upper_margin = 10,
.lower_margin = 10,
.hsync_len = 10,
.vsync_len = 10,
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.flag = 0,
},
};
......@@ -399,10 +388,9 @@ static int lcd_cfg_dma(int burst_size, int fifo_th)
reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8);
break;
case 16:
default:
reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16);
break;
default:
return -EINVAL;
}
reg |= (fifo_th << 8);
......@@ -447,7 +435,8 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
}
static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
static int lcd_cfg_display(const struct lcd_ctrl_config *cfg,
struct fb_videomode *panel)
{
u32 reg;
u32 reg_int;
......@@ -456,7 +445,7 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
LCD_MONO_8BIT_MODE |
LCD_MONOCHROME_MODE);
switch (cfg->p_disp_panel->panel_shade) {
switch (cfg->panel_shade) {
case MONOCHROME:
reg |= LCD_MONOCHROME_MODE;
if (cfg->mono_8bit_mode)
......@@ -469,7 +458,9 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
break;
case COLOR_PASSIVE:
if (cfg->stn_565_mode)
/* AC bias applicable only for Pasive panels */
lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
if (cfg->bpp == 12 && cfg->stn_565_mode)
reg |= LCD_STN_565_ENABLE;
break;
......@@ -490,22 +481,19 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
if (cfg->sync_ctrl)
reg |= LCD_SYNC_CTRL;
else
reg &= ~LCD_SYNC_CTRL;
reg |= LCD_SYNC_CTRL;
if (cfg->sync_edge)
reg |= LCD_SYNC_EDGE;
else
reg &= ~LCD_SYNC_EDGE;
if (cfg->invert_line_clock)
if (panel->sync & FB_SYNC_HOR_HIGH_ACT)
reg |= LCD_INVERT_LINE_CLOCK;
else
reg &= ~LCD_INVERT_LINE_CLOCK;
if (cfg->invert_frm_clock)
if (panel->sync & FB_SYNC_VERT_HIGH_ACT)
reg |= LCD_INVERT_FRAME_CLOCK;
else
reg &= ~LCD_INVERT_FRAME_CLOCK;
......@@ -728,7 +716,7 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
}
static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
struct da8xx_panel *panel)
struct fb_videomode *panel)
{
u32 bpp;
int ret = 0;
......@@ -738,7 +726,7 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
/* Calculate the divider */
lcd_calc_clk_divider(par);
if (panel->invert_pxl_clk)
if (panel->sync & FB_SYNC_CLK_INVERT)
lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
else
......@@ -750,30 +738,23 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
if (ret < 0)
return ret;
/* Configure the AC bias properties. */
lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
/* Configure the vertical and horizontal sync properties. */
lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp);
lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp);
lcd_cfg_vertical_sync(panel->lower_margin, panel->vsync_len,
panel->upper_margin);
lcd_cfg_horizontal_sync(panel->right_margin, panel->hsync_len,
panel->left_margin);
/* Configure for disply */
ret = lcd_cfg_display(cfg);
ret = lcd_cfg_display(cfg, panel);
if (ret < 0)
return ret;
if (QVGA != cfg->p_disp_panel->panel_type)
return -EINVAL;
bpp = cfg->bpp;
if (cfg->bpp <= cfg->p_disp_panel->max_bpp &&
cfg->bpp >= cfg->p_disp_panel->min_bpp)
bpp = cfg->bpp;
else
bpp = cfg->p_disp_panel->max_bpp;
if (bpp == 12)
bpp = 16;
ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width,
(unsigned int)panel->height, bpp,
ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->xres,
(unsigned int)panel->yres, bpp,
cfg->raster_order);
if (ret < 0)
return ret;
......@@ -1235,7 +1216,7 @@ static int __devinit fb_probe(struct platform_device *device)
struct da8xx_lcdc_platform_data *fb_pdata =
device->dev.platform_data;
struct lcd_ctrl_config *lcd_cfg;
struct da8xx_panel *lcdc_info;
struct fb_videomode *lcdc_info;
struct fb_info *da8xx_fb_info;
struct clk *fb_clk = NULL;
struct da8xx_fb_par *par;
......@@ -1267,7 +1248,7 @@ static int __devinit fb_probe(struct platform_device *device)
goto err_request_mem;
}
fb_clk = clk_get(&device->dev, NULL);
fb_clk = clk_get(&device->dev, "fck");
if (IS_ERR(fb_clk)) {
dev_err(&device->dev, "Can not get device clock\n");
ret = -ENODEV;
......@@ -1283,6 +1264,7 @@ static int __devinit fb_probe(struct platform_device *device)
lcd_revision = LCD_VERSION_1;
break;
case 0x4F200800:
case 0x4F201000:
lcd_revision = LCD_VERSION_2;
break;
default:
......@@ -1323,7 +1305,7 @@ static int __devinit fb_probe(struct platform_device *device)
#ifdef CONFIG_CPU_FREQ
par->lcd_fck_rate = clk_get_rate(fb_clk);
#endif
par->pxl_clk = lcdc_info->pxl_clk;
par->pxl_clk = lcdc_info->pixclock;
if (fb_pdata->panel_power_ctrl) {
par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
par->panel_power_ctrl(1);
......@@ -1336,8 +1318,8 @@ static int __devinit fb_probe(struct platform_device *device)
}
/* allocate frame buffer */
par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp;
ulcm = lcm((lcdc_info->width * lcd_cfg->bpp)/8, PAGE_SIZE);
par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE);
par->vram_size = roundup(par->vram_size/8, ulcm);
par->vram_size = par->vram_size * LCD_NUM_BUFFERS;
......@@ -1355,10 +1337,10 @@ static int __devinit fb_probe(struct platform_device *device)
da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt;
da8xx_fb_fix.smem_start = par->vram_phys;
da8xx_fb_fix.smem_len = par->vram_size;
da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8;
da8xx_fb_fix.line_length = (lcdc_info->xres * lcd_cfg->bpp) / 8;
par->dma_start = par->vram_phys;
par->dma_end = par->dma_start + lcdc_info->height *
par->dma_end = par->dma_start + lcdc_info->yres *
da8xx_fb_fix.line_length - 1;
/* allocate palette buffer */
......@@ -1384,22 +1366,22 @@ static int __devinit fb_probe(struct platform_device *device)
/* Initialize par */
da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp;
da8xx_fb_var.xres = lcdc_info->width;
da8xx_fb_var.xres_virtual = lcdc_info->width;
da8xx_fb_var.xres = lcdc_info->xres;
da8xx_fb_var.xres_virtual = lcdc_info->xres;
da8xx_fb_var.yres = lcdc_info->height;
da8xx_fb_var.yres_virtual = lcdc_info->height * LCD_NUM_BUFFERS;
da8xx_fb_var.yres = lcdc_info->yres;
da8xx_fb_var.yres_virtual = lcdc_info->yres * LCD_NUM_BUFFERS;
da8xx_fb_var.grayscale =
lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0;
lcd_cfg->panel_shade == MONOCHROME ? 1 : 0;
da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
da8xx_fb_var.hsync_len = lcdc_info->hsw;
da8xx_fb_var.vsync_len = lcdc_info->vsw;
da8xx_fb_var.right_margin = lcdc_info->hfp;
da8xx_fb_var.left_margin = lcdc_info->hbp;
da8xx_fb_var.lower_margin = lcdc_info->vfp;
da8xx_fb_var.upper_margin = lcdc_info->vbp;
da8xx_fb_var.hsync_len = lcdc_info->hsync_len;
da8xx_fb_var.vsync_len = lcdc_info->vsync_len;
da8xx_fb_var.right_margin = lcdc_info->right_margin;
da8xx_fb_var.left_margin = lcdc_info->left_margin;
da8xx_fb_var.lower_margin = lcdc_info->lower_margin;
da8xx_fb_var.upper_margin = lcdc_info->upper_margin;
da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par);
/* Initialize fbinfo */
......
......@@ -13,6 +13,13 @@
#ifndef _EXYNOS_DP_CORE_H
#define _EXYNOS_DP_CORE_H
enum dp_irq_type {
DP_IRQ_TYPE_HP_CABLE_IN,
DP_IRQ_TYPE_HP_CABLE_OUT,
DP_IRQ_TYPE_HP_CHANGE,
DP_IRQ_TYPE_UNKNOWN,
};
struct link_train {
int eq_loop;
int cr_loop[4];
......@@ -29,9 +36,12 @@ struct exynos_dp_device {
struct clk *clock;
unsigned int irq;
void __iomem *reg_base;
void __iomem *phy_addr;
unsigned int enable_mask;
struct video_info *video_info;
struct link_train link_train;
struct work_struct hotplug_work;
};
/* exynos_dp_reg.c */
......@@ -50,6 +60,8 @@ void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
bool enable);
void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
void exynos_dp_init_hpd(struct exynos_dp_device *dp);
enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
void exynos_dp_reset_aux(struct exynos_dp_device *dp);
void exynos_dp_init_aux(struct exynos_dp_device *dp);
int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
......@@ -107,11 +119,7 @@ u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
void exynos_dp_reset_macro(struct exynos_dp_device *dp);
void exynos_dp_init_video(struct exynos_dp_device *dp);
void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
u32 color_depth,
u32 color_space,
u32 dynamic_range,
u32 ycbcr_coeff);
void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
enum clock_recovery_m_value_type type,
......@@ -121,8 +129,7 @@ void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
void exynos_dp_start_video(struct exynos_dp_device *dp);
int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
struct video_info *video_info);
void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
......
......@@ -19,11 +19,11 @@
#include "exynos_dp_core.h"
#include "exynos_dp_reg.h"
#define COMMON_INT_MASK_1 (0)
#define COMMON_INT_MASK_2 (0)
#define COMMON_INT_MASK_3 (0)
#define COMMON_INT_MASK_4 (0)
#define INT_STA_MASK (0)
#define COMMON_INT_MASK_1 0
#define COMMON_INT_MASK_2 0
#define COMMON_INT_MASK_3 0
#define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG)
#define INT_STA_MASK INT_HPD
void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
{
......@@ -88,7 +88,7 @@ void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
{
/* Set interrupt pin assertion polarity as high */
writel(INT_POL, dp->reg_base + EXYNOS_DP_INT_CTL);
writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
/* Clear pending regisers */
writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
......@@ -324,7 +324,7 @@ void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
}
void exynos_dp_init_hpd(struct exynos_dp_device *dp)
void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
{
u32 reg;
......@@ -333,12 +333,38 @@ void exynos_dp_init_hpd(struct exynos_dp_device *dp)
reg = INT_HPD;
writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
}
void exynos_dp_init_hpd(struct exynos_dp_device *dp)
{
u32 reg;
exynos_dp_clear_hotplug_interrupts(dp);
reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
reg &= ~(F_HPD | HPD_CTRL);
writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
}
enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
{
u32 reg;
/* Parse hotplug interrupt status register */
reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
if (reg & PLUG)
return DP_IRQ_TYPE_HP_CABLE_IN;
if (reg & HPD_LOST)
return DP_IRQ_TYPE_HP_CABLE_OUT;
if (reg & HOTPLUG_CHG)
return DP_IRQ_TYPE_HP_CHANGE;
return DP_IRQ_TYPE_UNKNOWN;
}
void exynos_dp_reset_aux(struct exynos_dp_device *dp)
{
u32 reg;
......@@ -491,7 +517,7 @@ int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
int i;
int retval;
for (i = 0; i < 10; i++) {
for (i = 0; i < 3; i++) {
/* Clear AUX CH data buffer */
reg = BUF_CLR;
writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
......@@ -552,7 +578,7 @@ int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
else
cur_data_count = count - start_offset;
for (i = 0; i < 10; i++) {
for (i = 0; i < 3; i++) {
/* Select DPCD device address */
reg = AUX_ADDR_7_0(reg_addr + start_offset);
writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
......@@ -617,7 +643,7 @@ int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
cur_data_count = count - start_offset;
/* AUX CH Request Transaction process */
for (i = 0; i < 10; i++) {
for (i = 0; i < 3; i++) {
/* Select DPCD device address */
reg = AUX_ADDR_7_0(reg_addr + start_offset);
writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
......@@ -700,17 +726,15 @@ int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
int i;
int retval;
for (i = 0; i < 10; i++) {
for (i = 0; i < 3; i++) {
/* Clear AUX CH data buffer */
reg = BUF_CLR;
writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
/* Select EDID device */
retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
if (retval != 0) {
dev_err(dp->dev, "Select EDID device fail!\n");
if (retval != 0)
continue;
}
/*
* Set I2C transaction and read data
......@@ -750,7 +774,7 @@ int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
int retval = 0;
for (i = 0; i < count; i += 16) {
for (j = 0; j < 100; j++) {
for (j = 0; j < 3; j++) {
/* Clear AUX CH data buffer */
reg = BUF_CLR;
writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
......@@ -1034,24 +1058,20 @@ void exynos_dp_init_video(struct exynos_dp_device *dp)
writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
}
void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
u32 color_depth,
u32 color_space,
u32 dynamic_range,
u32 ycbcr_coeff)
void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
{
u32 reg;
/* Configure the input color depth, color space, dynamic range */
reg = (dynamic_range << IN_D_RANGE_SHIFT) |
(color_depth << IN_BPC_SHIFT) |
(color_space << IN_COLOR_F_SHIFT);
reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
(dp->video_info->color_depth << IN_BPC_SHIFT) |
(dp->video_info->color_space << IN_COLOR_F_SHIFT);
writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
reg &= ~IN_YC_COEFFI_MASK;
if (ycbcr_coeff)
if (dp->video_info->ycbcr_coeff)
reg |= IN_YC_COEFFI_ITU709;
else
reg |= IN_YC_COEFFI_ITU601;
......@@ -1178,8 +1198,7 @@ int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
return 0;
}
void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
struct video_info *video_info)
void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
{
u32 reg;
......@@ -1190,17 +1209,17 @@ void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
reg &= ~INTERACE_SCAN_CFG;
reg |= (video_info->interlaced << 2);
reg |= (dp->video_info->interlaced << 2);
writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
reg &= ~VSYNC_POLARITY_CFG;
reg |= (video_info->v_sync_polarity << 1);
reg |= (dp->video_info->v_sync_polarity << 1);
writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
reg &= ~HSYNC_POLARITY_CFG;
reg |= (video_info->h_sync_polarity << 0);
reg |= (dp->video_info->h_sync_polarity << 0);
writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
......
......@@ -242,7 +242,8 @@
/* EXYNOS_DP_INT_CTL */
#define SOFT_INT_CTRL (0x1 << 2)
#define INT_POL (0x1 << 0)
#define INT_POL1 (0x1 << 1)
#define INT_POL0 (0x1 << 0)
/* EXYNOS_DP_SYS_CTL_1 */
#define DET_STA (0x1 << 2)
......
......@@ -337,13 +337,11 @@ struct mfb_info {
int registered;
unsigned long pseudo_palette[16];
struct diu_ad *ad;
int cursor_reset;
unsigned char g_alpha;
unsigned int count;
int x_aoi_d; /* aoi display x offset to physical screen */
int y_aoi_d; /* aoi display y offset to physical screen */
struct fsl_diu_data *parent;
u8 *edid_data;
};
/**
......@@ -378,6 +376,8 @@ struct fsl_diu_data {
struct diu_ad ad[NUM_AOIS] __aligned(8);
u8 gamma[256 * 3] __aligned(32);
u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32);
uint8_t edid_data[EDID_LENGTH];
bool has_edid;
} __aligned(32);
/* Determine the DMA address of a member of the fsl_diu_data structure */
......@@ -430,6 +430,22 @@ static struct mfb_info mfb_template[] = {
},
};
#ifdef DEBUG
static void __attribute__ ((unused)) fsl_diu_dump(struct diu __iomem *hw)
{
mb();
pr_debug("DIU: desc=%08x,%08x,%08x, gamma=%08x pallete=%08x "
"cursor=%08x curs_pos=%08x diu_mode=%08x bgnd=%08x "
"disp_size=%08x hsyn_para=%08x vsyn_para=%08x syn_pol=%08x "
"thresholds=%08x int_mask=%08x plut=%08x\n",
hw->desc[0], hw->desc[1], hw->desc[2], hw->gamma,
hw->pallete, hw->cursor, hw->curs_pos, hw->diu_mode,
hw->bgnd, hw->disp_size, hw->hsyn_para, hw->vsyn_para,
hw->syn_pol, hw->thresholds, hw->int_mask, hw->plut);
rmb();
}
#endif
/**
* fsl_diu_name_to_port - convert a port name to a monitor port enum
*
......@@ -481,8 +497,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
switch (mfbi->index) {
case PLANE0:
if (hw->desc[0] != ad->paddr)
wr_reg_wa(&hw->desc[0], ad->paddr);
wr_reg_wa(&hw->desc[0], ad->paddr);
break;
case PLANE1_AOI0:
cmfbi = &data->mfb[2];
......@@ -534,8 +549,7 @@ static void fsl_diu_disable_panel(struct fb_info *info)
switch (mfbi->index) {
case PLANE0:
if (hw->desc[0] != data->dummy_ad.paddr)
wr_reg_wa(&hw->desc[0], data->dummy_ad.paddr);
wr_reg_wa(&hw->desc[0], 0);
break;
case PLANE1_AOI0:
cmfbi = &data->mfb[2];
......@@ -792,7 +806,8 @@ static void update_lcdc(struct fb_info *info)
hw = data->diu_reg;
diu_ops.set_monitor_port(data->monitor_port);
if (diu_ops.set_monitor_port)
diu_ops.set_monitor_port(data->monitor_port);
gamma_table_base = data->gamma;
/* Prep for DIU init - gamma table, cursor table */
......@@ -811,12 +826,8 @@ static void update_lcdc(struct fb_info *info)
out_be32(&hw->gamma, DMA_ADDR(data, gamma));
out_be32(&hw->cursor, DMA_ADDR(data, cursor));
out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */
out_be32(&hw->bgnd_wb, 0); /* BGND_WB */
out_be32(&hw->disp_size, (var->yres << 16 | var->xres));
/* DISP SIZE */
out_be32(&hw->wb_size, 0); /* WB SIZE */
out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */
out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */
out_be32(&hw->disp_size, (var->yres << 16) | var->xres);
/* Horizontal and vertical configuration register */
temp = var->left_margin << 22 | /* BP_H */
......@@ -833,9 +844,20 @@ static void update_lcdc(struct fb_info *info)
diu_ops.set_pixel_clock(var->pixclock);
out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */
out_be32(&hw->int_status, 0); /* INTERRUPT STATUS */
#ifndef CONFIG_PPC_MPC512x
/*
* The PLUT register is defined differently on the MPC5121 than it
* is on other SOCs. Unfortunately, there's no documentation that
* explains how it's supposed to be programmed, so for now, we leave
* it at the default value on the MPC5121.
*
* For other SOCs, program it for the highest priority, which will
* reduce the chance of underrun. Technically, we should scale the
* priority to match the screen resolution, but doing that properly
* requires delicate fine-tuning for each use-case.
*/
out_be32(&hw->plut, 0x01F5F666);
#endif
/* Enable the DIU */
enable_lcdc(info);
......@@ -965,7 +987,6 @@ static int fsl_diu_set_par(struct fb_info *info)
hw = data->diu_reg;
set_fix(info);
mfbi->cursor_reset = 1;
len = info->var.yres_virtual * info->fix.line_length;
/* Alloc & dealloc each time resolution/bpp change */
......@@ -1107,6 +1128,12 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
if (!arg)
return -EINVAL;
dev_dbg(info->dev, "ioctl %08x (dir=%s%s type=%u nr=%u size=%u)\n", cmd,
_IOC_DIR(cmd) & _IOC_READ ? "R" : "",
_IOC_DIR(cmd) & _IOC_WRITE ? "W" : "",
_IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
switch (cmd) {
case MFB_SET_PIXFMT_OLD:
dev_warn(info->dev,
......@@ -1180,6 +1207,23 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
ad->ckmin_b = ck.blue_min;
}
break;
#ifdef CONFIG_PPC_MPC512x
case MFB_SET_GAMMA: {
struct fsl_diu_data *data = mfbi->parent;
if (copy_from_user(data->gamma, buf, sizeof(data->gamma)))
return -EFAULT;
setbits32(&data->diu_reg->gamma, 0); /* Force table reload */
break;
}
case MFB_GET_GAMMA: {
struct fsl_diu_data *data = mfbi->parent;
if (copy_to_user(buf, data->gamma, sizeof(data->gamma)))
return -EFAULT;
break;
}
#endif
default:
dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd);
return -ENOIOCTLCMD;
......@@ -1206,8 +1250,22 @@ static int fsl_diu_open(struct fb_info *info, int user)
res = fsl_diu_set_par(info);
if (res < 0)
mfbi->count--;
else
else {
struct fsl_diu_data *data = mfbi->parent;
#ifdef CONFIG_NOT_COHERENT_CACHE
/*
* Enable underrun detection and vertical sync
* interrupts.
*/
clrbits32(&data->diu_reg->int_mask,
INT_UNDRUN | INT_VSYNC);
#else
/* Enable underrun detection */
clrbits32(&data->diu_reg->int_mask, INT_UNDRUN);
#endif
fsl_diu_enable_panel(info);
}
}
spin_unlock(&diu_lock);
......@@ -1223,8 +1281,13 @@ static int fsl_diu_release(struct fb_info *info, int user)
spin_lock(&diu_lock);
mfbi->count--;
if (mfbi->count == 0)
if (mfbi->count == 0) {
struct fsl_diu_data *data = mfbi->parent;
/* Disable interrupts */
out_be32(&data->diu_reg->int_mask, 0xffffffff);
fsl_diu_disable_panel(info);
}
spin_unlock(&diu_lock);
return res;
......@@ -1248,6 +1311,7 @@ static int __devinit install_fb(struct fb_info *info)
{
int rc;
struct mfb_info *mfbi = info->par;
struct fsl_diu_data *data = mfbi->parent;
const char *aoi_mode, *init_aoi_mode = "320x240";
struct fb_videomode *db = fsl_diu_mode_db;
unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db);
......@@ -1264,9 +1328,9 @@ static int __devinit install_fb(struct fb_info *info)
return rc;
if (mfbi->index == PLANE0) {
if (mfbi->edid_data) {
if (data->has_edid) {
/* Now build modedb from EDID */
fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs);
fb_edid_to_monspecs(data->edid_data, &info->monspecs);
fb_videomode_to_modelist(info->monspecs.modedb,
info->monspecs.modedb_len,
&info->modelist);
......@@ -1284,7 +1348,7 @@ static int __devinit install_fb(struct fb_info *info)
* For plane 0 we continue and look into
* driver's internal modedb.
*/
if ((mfbi->index == PLANE0) && mfbi->edid_data)
if ((mfbi->index == PLANE0) && data->has_edid)
has_default_mode = 0;
else
return -EINVAL;
......@@ -1348,9 +1412,6 @@ static void uninstall_fb(struct fb_info *info)
if (!mfbi->registered)
return;
if (mfbi->index == PLANE0)
kfree(mfbi->edid_data);
unregister_framebuffer(info);
unmap_video_memory(info);
if (&info->cmap)
......@@ -1362,7 +1423,7 @@ static void uninstall_fb(struct fb_info *info)
static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
{
struct diu __iomem *hw = dev_id;
unsigned int status = in_be32(&hw->int_status);
uint32_t status = in_be32(&hw->int_status);
if (status) {
/* This is the workaround for underrun */
......@@ -1387,40 +1448,6 @@ static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
return IRQ_NONE;
}
static int request_irq_local(struct fsl_diu_data *data)
{
struct diu __iomem *hw = data->diu_reg;
u32 ints;
int ret;
/* Read to clear the status */
in_be32(&hw->int_status);
ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw);
if (!ret) {
ints = INT_PARERR | INT_LS_BF_VS;
#if !defined(CONFIG_NOT_COHERENT_CACHE)
ints |= INT_VSYNC;
#endif
/* Read to clear the status */
in_be32(&hw->int_status);
out_be32(&hw->int_mask, ints);
}
return ret;
}
static void free_irq_local(struct fsl_diu_data *data)
{
struct diu __iomem *hw = data->diu_reg;
/* Disable all LCDC interrupt */
out_be32(&hw->int_mask, 0x1f);
free_irq(data->irq, NULL);
}
#ifdef CONFIG_PM
/*
* Power management hooks. Note that we won't be called from IRQ context,
......@@ -1496,8 +1523,8 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct mfb_info *mfbi;
struct fsl_diu_data *data;
int diu_mode;
dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */
const void *prop;
unsigned int i;
int ret;
......@@ -1541,17 +1568,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
mfbi->parent = data;
mfbi->ad = &data->ad[i];
}
if (mfbi->index == PLANE0) {
const u8 *prop;
int len;
/* Get EDID */
prop = of_get_property(np, "edid", &len);
if (prop && len == EDID_LENGTH)
mfbi->edid_data = kmemdup(prop, EDID_LENGTH,
GFP_KERNEL);
}
/* Get the EDID data from the device tree, if present */
prop = of_get_property(np, "edid", &ret);
if (prop && ret == EDID_LENGTH) {
memcpy(data->edid_data, prop, EDID_LENGTH);
data->has_edid = true;
}
data->diu_reg = of_iomap(np, 0);
......@@ -1561,10 +1584,6 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
goto error;
}
diu_mode = in_be32(&data->diu_reg->diu_mode);
if (diu_mode == MFB_MODE0)
out_be32(&data->diu_reg->diu_mode, 0); /* disable DIU */
/* Get the IRQ of the DIU */
data->irq = irq_of_parse_and_map(np, 0);
......@@ -1586,11 +1605,11 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad);
/*
* Let DIU display splash screen if it was pre-initialized
* by the bootloader, set dummy area descriptor otherwise.
* Let DIU continue to display splash screen if it was pre-initialized
* by the bootloader; otherwise, clear the display.
*/
if (diu_mode == MFB_MODE0)
out_be32(&data->diu_reg->desc[0], data->dummy_ad.paddr);
if (in_be32(&data->diu_reg->diu_mode) == MFB_MODE0)
out_be32(&data->diu_reg->desc[0], 0);
out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr);
out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr);
......@@ -1603,7 +1622,16 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
}
}
if (request_irq_local(data)) {
/*
* Older versions of U-Boot leave interrupts enabled, so disable
* all of them and clear the status register.
*/
out_be32(&data->diu_reg->int_mask, 0xffffffff);
in_be32(&data->diu_reg->int_status);
ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb",
&data->diu_reg);
if (ret) {
dev_err(&pdev->dev, "could not claim irq\n");
goto error;
}
......@@ -1638,7 +1666,8 @@ static int fsl_diu_remove(struct platform_device *pdev)
data = dev_get_drvdata(&pdev->dev);
disable_lcdc(&data->fsl_diu_info[0]);
free_irq_local(data);
free_irq(data->irq, &data->diu_reg);
for (i = 0; i < NUM_AOIS; i++)
uninstall_fb(&data->fsl_diu_info[i]);
......@@ -1741,6 +1770,9 @@ static int __init fsl_diu_init(void)
coherence_data_size = be32_to_cpup(prop) * 13;
coherence_data_size /= 8;
pr_debug("fsl-diu-fb: coherence data size is %zu bytes\n",
coherence_data_size);
prop = of_get_property(np, "d-cache-line-size", NULL);
if (prop == NULL) {
pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' "
......@@ -1750,10 +1782,17 @@ static int __init fsl_diu_init(void)
}
d_cache_line_size = be32_to_cpup(prop);
pr_debug("fsl-diu-fb: cache lines size is %u bytes\n",
d_cache_line_size);
of_node_put(np);
coherence_data = vmalloc(coherence_data_size);
if (!coherence_data)
if (!coherence_data) {
pr_err("fsl-diu-fb: could not allocate coherence data "
"(size=%zu)\n", coherence_data_size);
return -ENOMEM;
}
#endif
ret = platform_driver_register(&fsl_diu_driver);
......
config OMAP2_VRAM
bool
config OMAP2_VRFB
bool
......
obj-$(CONFIG_OMAP2_VRAM) += vram.o
obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
obj-$(CONFIG_OMAP2_DSS) += dss/
......
......@@ -710,27 +710,6 @@ static void acx_panel_disable(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
static int acx_panel_suspend(struct omap_dss_device *dssdev)
{
dev_dbg(&dssdev->dev, "%s\n", __func__);
acx_panel_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
return 0;
}
static int acx_panel_resume(struct omap_dss_device *dssdev)
{
int r;
dev_dbg(&dssdev->dev, "%s\n", __func__);
r = acx_panel_power_on(dssdev);
if (r)
return r;
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
return 0;
}
static void acx_panel_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
......@@ -752,8 +731,6 @@ static struct omap_dss_driver acx_panel_driver = {
.enable = acx_panel_enable,
.disable = acx_panel_disable,
.suspend = acx_panel_suspend,
.resume = acx_panel_resume,
.set_timings = acx_panel_set_timings,
.check_timings = acx_panel_check_timings,
......
......@@ -688,40 +688,6 @@ static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
mutex_unlock(&drv_data->lock);
}
static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
{
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
mutex_lock(&drv_data->lock);
generic_dpi_panel_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
mutex_unlock(&drv_data->lock);
return 0;
}
static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
{
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
int r;
mutex_lock(&drv_data->lock);
r = generic_dpi_panel_power_on(dssdev);
if (r)
goto err;
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
err:
mutex_unlock(&drv_data->lock);
return r;
}
static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
......@@ -769,8 +735,6 @@ static struct omap_dss_driver dpi_driver = {
.enable = generic_dpi_panel_enable,
.disable = generic_dpi_panel_disable,
.suspend = generic_dpi_panel_suspend,
.resume = generic_dpi_panel_resume,
.set_timings = generic_dpi_panel_set_timings,
.get_timings = generic_dpi_panel_get_timings,
......
......@@ -143,46 +143,12 @@ static void lb035q02_panel_disable(struct omap_dss_device *dssdev)
mutex_unlock(&ld->lock);
}
static int lb035q02_panel_suspend(struct omap_dss_device *dssdev)
{
struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
mutex_lock(&ld->lock);
lb035q02_panel_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
mutex_unlock(&ld->lock);
return 0;
}
static int lb035q02_panel_resume(struct omap_dss_device *dssdev)
{
struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
int r;
mutex_lock(&ld->lock);
r = lb035q02_panel_power_on(dssdev);
if (r)
goto err;
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
mutex_unlock(&ld->lock);
return 0;
err:
mutex_unlock(&ld->lock);
return r;
}
static struct omap_dss_driver lb035q02_driver = {
.probe = lb035q02_panel_probe,
.remove = lb035q02_panel_remove,
.enable = lb035q02_panel_enable,
.disable = lb035q02_panel_disable,
.suspend = lb035q02_panel_suspend,
.resume = lb035q02_panel_resume,
.driver = {
.name = "lgphilips_lb035q02_panel",
......
......@@ -574,54 +574,6 @@ static void n8x0_panel_disable(struct omap_dss_device *dssdev)
mutex_unlock(&ddata->lock);
}
static int n8x0_panel_suspend(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = get_drv_data(dssdev);
dev_dbg(&dssdev->dev, "suspend\n");
mutex_lock(&ddata->lock);
rfbi_bus_lock();
n8x0_panel_power_off(dssdev);
rfbi_bus_unlock();
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
mutex_unlock(&ddata->lock);
return 0;
}
static int n8x0_panel_resume(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = get_drv_data(dssdev);
int r;
dev_dbg(&dssdev->dev, "resume\n");
mutex_lock(&ddata->lock);
rfbi_bus_lock();
r = n8x0_panel_power_on(dssdev);
rfbi_bus_unlock();
if (r) {
mutex_unlock(&ddata->lock);
return r;
}
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
mutex_unlock(&ddata->lock);
return 0;
}
static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
u16 *xres, u16 *yres)
{
......@@ -683,8 +635,6 @@ static struct omap_dss_driver n8x0_panel_driver = {
.enable = n8x0_panel_enable,
.disable = n8x0_panel_disable,
.suspend = n8x0_panel_suspend,
.resume = n8x0_panel_resume,
.update = n8x0_panel_update,
.sync = n8x0_panel_sync,
......@@ -702,18 +652,25 @@ static struct omap_dss_driver n8x0_panel_driver = {
static int mipid_spi_probe(struct spi_device *spi)
{
int r;
dev_dbg(&spi->dev, "mipid_spi_probe\n");
spi->mode = SPI_MODE_0;
s_drv_data.spidev = spi;
return 0;
r = omap_dss_register_driver(&n8x0_panel_driver);
if (r)
pr_err("n8x0_panel: dss driver registration failed\n");
return r;
}
static int mipid_spi_remove(struct spi_device *spi)
{
dev_dbg(&spi->dev, "mipid_spi_remove\n");
omap_dss_unregister_driver(&n8x0_panel_driver);
return 0;
}
......@@ -725,34 +682,6 @@ static struct spi_driver mipid_spi_driver = {
.probe = mipid_spi_probe,
.remove = __devexit_p(mipid_spi_remove),
};
module_spi_driver(mipid_spi_driver);
static int __init n8x0_panel_drv_init(void)
{
int r;
r = spi_register_driver(&mipid_spi_driver);
if (r) {
pr_err("n8x0_panel: spi driver registration failed\n");
return r;
}
r = omap_dss_register_driver(&n8x0_panel_driver);
if (r) {
pr_err("n8x0_panel: dss driver registration failed\n");
spi_unregister_driver(&mipid_spi_driver);
return r;
}
return 0;
}
static void __exit n8x0_panel_drv_exit(void)
{
spi_unregister_driver(&mipid_spi_driver);
omap_dss_unregister_driver(&n8x0_panel_driver);
}
module_init(n8x0_panel_drv_init);
module_exit(n8x0_panel_drv_exit);
MODULE_LICENSE("GPL");
......@@ -236,28 +236,6 @@ static void nec_8048_panel_disable(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
static int nec_8048_panel_suspend(struct omap_dss_device *dssdev)
{
nec_8048_panel_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
return 0;
}
static int nec_8048_panel_resume(struct omap_dss_device *dssdev)
{
int r;
r = nec_8048_panel_power_on(dssdev);
if (r)
return r;
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
return 0;
}
static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev)
{
return 16;
......@@ -268,8 +246,6 @@ static struct omap_dss_driver nec_8048_driver = {
.remove = nec_8048_panel_remove,
.enable = nec_8048_panel_enable,
.disable = nec_8048_panel_disable,
.suspend = nec_8048_panel_suspend,
.resume = nec_8048_panel_resume,
.get_recommended_bpp = nec_8048_recommended_bpp,
.driver = {
......
......@@ -50,6 +50,7 @@ struct picodlp_i2c_data {
static struct i2c_device_id picodlp_i2c_id[] = {
{ "picodlp_i2c_driver", 0 },
{ }
};
struct picodlp_i2c_command {
......@@ -503,47 +504,6 @@ static void picodlp_panel_disable(struct omap_dss_device *dssdev)
dev_dbg(&dssdev->dev, "disabling picodlp panel\n");
}
static int picodlp_panel_suspend(struct omap_dss_device *dssdev)
{
struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
mutex_lock(&picod->lock);
/* Turn off DLP Power */
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
mutex_unlock(&picod->lock);
dev_err(&dssdev->dev, "unable to suspend picodlp panel,"
" panel is not ACTIVE\n");
return -EINVAL;
}
picodlp_panel_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
mutex_unlock(&picod->lock);
dev_dbg(&dssdev->dev, "suspending picodlp panel\n");
return 0;
}
static int picodlp_panel_resume(struct omap_dss_device *dssdev)
{
struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
int r;
mutex_lock(&picod->lock);
if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
mutex_unlock(&picod->lock);
dev_err(&dssdev->dev, "unable to resume picodlp panel,"
" panel is not ACTIVE\n");
return -EINVAL;
}
r = picodlp_panel_power_on(dssdev);
mutex_unlock(&picod->lock);
dev_dbg(&dssdev->dev, "resuming picodlp panel\n");
return r;
}
static void picodlp_get_resolution(struct omap_dss_device *dssdev,
u16 *xres, u16 *yres)
{
......@@ -560,9 +520,6 @@ static struct omap_dss_driver picodlp_driver = {
.get_resolution = picodlp_get_resolution,
.suspend = picodlp_panel_suspend,
.resume = picodlp_panel_resume,
.driver = {
.name = "picodlp_panel",
.owner = THIS_MODULE,
......
......@@ -194,29 +194,12 @@ static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
{
sharp_ls_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
return 0;
}
static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
{
int r;
r = sharp_ls_power_on(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
return r;
}
static struct omap_dss_driver sharp_ls_driver = {
.probe = sharp_ls_panel_probe,
.remove = __exit_p(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",
......
......@@ -1245,76 +1245,6 @@ static void taal_disable(struct omap_dss_device *dssdev)
mutex_unlock(&td->lock);
}
static int taal_suspend(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
int r;
dev_dbg(&dssdev->dev, "suspend\n");
mutex_lock(&td->lock);
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
r = -EINVAL;
goto err;
}
taal_cancel_ulps_work(dssdev);
taal_cancel_esd_work(dssdev);
dsi_bus_lock(dssdev);
r = taal_wake_up(dssdev);
if (!r)
taal_power_off(dssdev);
dsi_bus_unlock(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
mutex_unlock(&td->lock);
return 0;
err:
mutex_unlock(&td->lock);
return r;
}
static int taal_resume(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
int r;
dev_dbg(&dssdev->dev, "resume\n");
mutex_lock(&td->lock);
if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
r = -EINVAL;
goto err;
}
dsi_bus_lock(dssdev);
r = taal_power_on(dssdev);
dsi_bus_unlock(dssdev);
if (r) {
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
} else {
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
taal_queue_esd_work(dssdev);
}
mutex_unlock(&td->lock);
return r;
err:
mutex_unlock(&td->lock);
return r;
}
static void taal_framedone_cb(int err, void *data)
{
struct omap_dss_device *dssdev = data;
......@@ -1818,8 +1748,6 @@ static struct omap_dss_driver taal_driver = {
.enable = taal_enable,
.disable = taal_disable,
.suspend = taal_suspend,
.resume = taal_resume,
.update = taal_update,
.sync = taal_sync,
......
......@@ -189,37 +189,6 @@ static void tfp410_disable(struct omap_dss_device *dssdev)
mutex_unlock(&ddata->lock);
}
static int tfp410_suspend(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
mutex_lock(&ddata->lock);
tfp410_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
mutex_unlock(&ddata->lock);
return 0;
}
static int tfp410_resume(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
int r;
mutex_lock(&ddata->lock);
r = tfp410_power_on(dssdev);
if (r == 0)
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
mutex_unlock(&ddata->lock);
return r;
}
static void tfp410_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
......@@ -355,8 +324,6 @@ static struct omap_dss_driver tfp410_driver = {
.enable = tfp410_enable,
.disable = tfp410_disable,
.suspend = tfp410_suspend,
.resume = tfp410_resume,
.set_timings = tfp410_set_timings,
.get_timings = tfp410_get_timings,
......
......@@ -401,24 +401,6 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
static int tpo_td043_suspend(struct omap_dss_device *dssdev)
{
dev_dbg(&dssdev->dev, "suspend\n");
tpo_td043_disable_dss(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
return 0;
}
static int tpo_td043_resume(struct omap_dss_device *dssdev)
{
dev_dbg(&dssdev->dev, "resume\n");
return tpo_td043_enable_dss(dssdev);
}
static int tpo_td043_probe(struct omap_dss_device *dssdev)
{
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
......@@ -500,8 +482,6 @@ static struct omap_dss_driver tpo_td043_driver = {
.enable = tpo_td043_enable,
.disable = tpo_td043_disable,
.suspend = tpo_td043_suspend,
.resume = tpo_td043_resume,
.set_mirror = tpo_td043_set_hmirror,
.get_mirror = tpo_td043_get_hmirror,
......
menuconfig OMAP2_DSS
tristate "OMAP2+ Display Subsystem support"
depends on ARCH_OMAP2PLUS
help
OMAP2+ Display Subsystem support.
if OMAP2_DSS
config OMAP2_VRAM_SIZE
int "VRAM size (MB)"
range 0 32
default 0
config OMAP2_DSS_DEBUG
bool "Debug support"
default n
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.
This enables printing of debug messages. Alternatively, debug messages
can also be enabled by setting CONFIG_DYNAMIC_DEBUG and then setting
appropriate flags in <debugfs>/dynamic_debug/control.
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
config OMAP2_DSS_DEBUGFS
bool "Debugfs filesystem support"
depends on DEBUG_FS
default n
help
This enables debug messages. You need to enable printing
with 'debug' module parameter.
This enables debugfs for OMAPDSS at <debugfs>/omapdss. This enables
querying about clock configuration and register configuration of dss,
dispc, dsi, hdmi and rfbi.
config OMAP2_DSS_COLLECT_IRQ_STATS
bool "Collect DSS IRQ statistics"
depends on OMAP2_DSS_DEBUG_SUPPORT
depends on OMAP2_DSS_DEBUGFS
default n
help
Collect DSS IRQ statistics, printable via debugfs.
......@@ -62,7 +59,6 @@ config OMAP2_DSS_VENC
config OMAP4_DSS_HDMI
bool "HDMI support"
depends on ARCH_OMAP4
default y
help
HDMI Interface. This adds the High Definition Multimedia Interface.
......@@ -70,11 +66,9 @@ config OMAP4_DSS_HDMI
config OMAP4_DSS_HDMI_AUDIO
bool
depends on OMAP4_DSS_HDMI
config OMAP2_DSS_SDI
bool "SDI support"
depends on ARCH_OMAP3
default n
help
SDI (Serial Display Interface) support.
......@@ -84,7 +78,6 @@ config OMAP2_DSS_SDI
config OMAP2_DSS_DSI
bool "DSI support"
depends on ARCH_OMAP3 || ARCH_OMAP4 || ARCH_OMAP5
default n
help
MIPI DSI (Display Serial Interface) support.
......
obj-$(CONFIG_OMAP2_DSS) += omapdss.o
# Core DSS files
omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
manager.o manager-sysfs.o overlay.o overlay-sysfs.o output.o apply.o
output.o
# DSS compat layer files
omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \
dispc-compat.o display-sysfs.o
omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
......@@ -8,3 +12,4 @@ omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
hdmi_panel.o ti_hdmi_4xxx_ip.o
ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
......@@ -18,6 +18,7 @@
#define DSS_SUBSYS_NAME "APPLY"
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
......@@ -26,6 +27,7 @@
#include "dss.h"
#include "dss_features.h"
#include "dispc-compat.h"
/*
* We have 4 levels of cache for the dispc settings. First two are in SW and
......@@ -70,7 +72,6 @@ struct ovl_priv_data {
bool shadow_extra_info_dirty;
bool enabled;
enum omap_channel channel;
u32 fifo_low, fifo_high;
/*
......@@ -105,6 +106,9 @@ struct mgr_priv_data {
struct omap_video_timings timings;
struct dss_lcd_mgr_config lcd_config;
void (*framedone_handler)(void *);
void *framedone_handler_data;
};
static struct {
......@@ -132,7 +136,7 @@ static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
return &dss_data.mgr_priv_data_array[mgr->id];
}
void dss_apply_init(void)
static void apply_init_priv(void)
{
const int num_ovls = dss_feat_get_num_ovls();
struct mgr_priv_data *mp;
......@@ -414,11 +418,46 @@ static void wait_pending_extra_info_updates(void)
r = wait_for_completion_timeout(&extra_updated_completion, t);
if (r == 0)
DSSWARN("timeout in wait_pending_extra_info_updates\n");
else if (r < 0)
DSSERR("wait_pending_extra_info_updates failed: %d\n", r);
}
int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
{
return ovl->manager ?
(ovl->manager->output ? ovl->manager->output->device : NULL) :
NULL;
}
static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
{
return mgr->output ? mgr->output->device : NULL;
}
static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
{
unsigned long timeout = msecs_to_jiffies(500);
struct omap_dss_device *dssdev = mgr->get_device(mgr);
u32 irq;
int r;
r = dispc_runtime_get();
if (r)
return r;
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
irq = DISPC_IRQ_EVSYNC_ODD;
else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
irq = DISPC_IRQ_EVSYNC_EVEN;
else
irq = dispc_mgr_get_vsync_irq(mgr->id);
r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
dispc_runtime_put();
return r;
}
static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
{
unsigned long timeout = msecs_to_jiffies(500);
struct mgr_priv_data *mp = get_mgr_priv(mgr);
......@@ -488,7 +527,7 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
return r;
}
int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
{
unsigned long timeout = msecs_to_jiffies(500);
struct ovl_priv_data *op;
......@@ -573,7 +612,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
struct mgr_priv_data *mp;
int r;
DSSDBGF("%d", ovl->id);
DSSDBG("writing ovl %d regs", ovl->id);
if (!op->enabled || !op->info_dirty)
return;
......@@ -608,7 +647,7 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
struct ovl_priv_data *op = get_ovl_priv(ovl);
struct mgr_priv_data *mp;
DSSDBGF("%d", ovl->id);
DSSDBG("writing ovl %d regs extra", ovl->id);
if (!op->extra_info_dirty)
return;
......@@ -617,7 +656,6 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
* disabled */
dispc_ovl_enable(ovl->id, op->enabled);
dispc_ovl_set_channel_out(ovl->id, op->channel);
dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
mp = get_mgr_priv(ovl->manager);
......@@ -632,7 +670,7 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
struct mgr_priv_data *mp = get_mgr_priv(mgr);
struct omap_overlay *ovl;
DSSDBGF("%d", mgr->id);
DSSDBG("writing mgr %d regs", mgr->id);
if (!mp->enabled)
return;
......@@ -658,7 +696,7 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
DSSDBGF("%d", mgr->id);
DSSDBG("writing mgr %d regs extra", mgr->id);
if (!mp->extra_info_dirty)
return;
......@@ -666,22 +704,8 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
dispc_mgr_set_timings(mgr->id, &mp->timings);
/* lcd_config parameters */
if (dss_mgr_is_lcd(mgr->id)) {
dispc_mgr_set_io_pad_mode(mp->lcd_config.io_pad_mode);
dispc_mgr_enable_stallmode(mgr->id, mp->lcd_config.stallmode);
dispc_mgr_enable_fifohandcheck(mgr->id,
mp->lcd_config.fifohandcheck);
dispc_mgr_set_clock_div(mgr->id, &mp->lcd_config.clock_info);
dispc_mgr_set_tft_data_lines(mgr->id,
mp->lcd_config.video_port_width);
dispc_lcd_enable_signal_polarity(mp->lcd_config.lcden_sig_polarity);
dispc_mgr_set_lcd_type_tft(mgr->id);
}
if (dss_mgr_is_lcd(mgr->id))
dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config);
mp->extra_info_dirty = false;
if (mp->updating)
......@@ -761,7 +785,7 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
}
}
void dss_mgr_start_update(struct omap_overlay_manager *mgr)
static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
unsigned long flags;
......@@ -786,9 +810,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
if (!dss_data.irq_enabled && need_isr())
dss_register_vsync_isr();
dispc_mgr_enable(mgr->id, true);
mgr_clear_shadow_dirty(mgr);
dispc_mgr_enable_sync(mgr->id);
spin_unlock_irqrestore(&data_lock, flags);
}
......@@ -845,7 +867,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
for (i = 0; i < num_mgrs; i++) {
struct omap_overlay_manager *mgr;
struct mgr_priv_data *mp;
bool was_updating;
mgr = omap_dss_get_overlay_manager(i);
mp = get_mgr_priv(mgr);
......@@ -853,7 +874,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
if (!mp->enabled)
continue;
was_updating = mp->updating;
mp->updating = dispc_mgr_is_enabled(i);
if (!mgr_manual_update(mgr)) {
......@@ -872,6 +892,21 @@ static void dss_apply_irq_handler(void *data, u32 mask)
if (!extra_updating)
complete_all(&extra_updated_completion);
/* call framedone handlers for manual update displays */
for (i = 0; i < num_mgrs; i++) {
struct omap_overlay_manager *mgr;
struct mgr_priv_data *mp;
mgr = omap_dss_get_overlay_manager(i);
mp = get_mgr_priv(mgr);
if (!mgr_manual_update(mgr) || !mp->framedone_handler)
continue;
if (mask & dispc_mgr_get_framedone_irq(i))
mp->framedone_handler(mp->framedone_handler_data);
}
if (!need_isr())
dss_unregister_vsync_isr();
......@@ -906,7 +941,7 @@ static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
mp->info = mp->user_info;
}
int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
{
unsigned long flags;
struct omap_overlay *ovl;
......@@ -1005,7 +1040,7 @@ static void dss_setup_fifos(void)
}
}
int dss_mgr_enable(struct omap_overlay_manager *mgr)
static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
unsigned long flags;
......@@ -1035,10 +1070,13 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
if (!mgr_manual_update(mgr))
mp->updating = true;
if (!dss_data.irq_enabled && need_isr())
dss_register_vsync_isr();
spin_unlock_irqrestore(&data_lock, flags);
if (!mgr_manual_update(mgr))
dispc_mgr_enable(mgr->id, true);
dispc_mgr_enable_sync(mgr->id);
out:
mutex_unlock(&apply_lock);
......@@ -1052,7 +1090,7 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
return r;
}
void dss_mgr_disable(struct omap_overlay_manager *mgr)
static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
unsigned long flags;
......@@ -1063,7 +1101,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
goto out;
if (!mgr_manual_update(mgr))
dispc_mgr_enable(mgr->id, false);
dispc_mgr_disable_sync(mgr->id);
spin_lock_irqsave(&data_lock, flags);
......@@ -1076,7 +1114,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
mutex_unlock(&apply_lock);
}
int dss_mgr_set_info(struct omap_overlay_manager *mgr,
static int dss_mgr_set_info(struct omap_overlay_manager *mgr,
struct omap_overlay_manager_info *info)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
......@@ -1097,7 +1135,7 @@ int dss_mgr_set_info(struct omap_overlay_manager *mgr,
return 0;
}
void dss_mgr_get_info(struct omap_overlay_manager *mgr,
static void dss_mgr_get_info(struct omap_overlay_manager *mgr,
struct omap_overlay_manager_info *info)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
......@@ -1110,7 +1148,7 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
spin_unlock_irqrestore(&data_lock, flags);
}
int dss_mgr_set_output(struct omap_overlay_manager *mgr,
static int dss_mgr_set_output(struct omap_overlay_manager *mgr,
struct omap_dss_output *output)
{
int r;
......@@ -1142,7 +1180,7 @@ int dss_mgr_set_output(struct omap_overlay_manager *mgr,
return r;
}
int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
static int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
{
int r;
struct mgr_priv_data *mp = get_mgr_priv(mgr);
......@@ -1189,7 +1227,7 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
mp->extra_info_dirty = true;
}
void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
static void dss_mgr_set_timings_compat(struct omap_overlay_manager *mgr,
const struct omap_video_timings *timings)
{
unsigned long flags;
......@@ -1217,7 +1255,7 @@ static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
mp->extra_info_dirty = true;
}
void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
static void dss_mgr_set_lcd_config_compat(struct omap_overlay_manager *mgr,
const struct dss_lcd_mgr_config *config)
{
unsigned long flags;
......@@ -1236,7 +1274,7 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
spin_unlock_irqrestore(&data_lock, flags);
}
int dss_ovl_set_info(struct omap_overlay *ovl,
static int dss_ovl_set_info(struct omap_overlay *ovl,
struct omap_overlay_info *info)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
......@@ -1257,7 +1295,7 @@ int dss_ovl_set_info(struct omap_overlay *ovl,
return 0;
}
void dss_ovl_get_info(struct omap_overlay *ovl,
static void dss_ovl_get_info(struct omap_overlay *ovl,
struct omap_overlay_info *info)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
......@@ -1270,7 +1308,7 @@ void dss_ovl_get_info(struct omap_overlay *ovl,
spin_unlock_irqrestore(&data_lock, flags);
}
int dss_ovl_set_manager(struct omap_overlay *ovl,
static int dss_ovl_set_manager(struct omap_overlay *ovl,
struct omap_overlay_manager *mgr)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
......@@ -1289,45 +1327,40 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,
goto err;
}
r = dispc_runtime_get();
if (r)
goto err;
spin_lock_irqsave(&data_lock, flags);
if (op->enabled) {
spin_unlock_irqrestore(&data_lock, flags);
DSSERR("overlay has to be disabled to change the manager\n");
r = -EINVAL;
goto err;
goto err1;
}
op->channel = mgr->id;
op->extra_info_dirty = true;
dispc_ovl_set_channel_out(ovl->id, mgr->id);
ovl->manager = mgr;
list_add_tail(&ovl->list, &mgr->overlays);
spin_unlock_irqrestore(&data_lock, flags);
/* XXX: When there is an overlay on a DSI manual update display, and
* the overlay is first disabled, then moved to tv, and enabled, we
* seem to get SYNC_LOST_DIGIT error.
*
* Waiting doesn't seem to help, but updating the manual update display
* after disabling the overlay seems to fix this. This hints that the
* overlay is perhaps somehow tied to the LCD output until the output
* is updated.
*
* Userspace workaround for this is to update the LCD after disabling
* the overlay, but before moving the overlay to TV.
*/
dispc_runtime_put();
mutex_unlock(&apply_lock);
return 0;
err1:
dispc_runtime_put();
err:
mutex_unlock(&apply_lock);
return r;
}
int dss_ovl_unset_manager(struct omap_overlay *ovl)
static int dss_ovl_unset_manager(struct omap_overlay *ovl)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
unsigned long flags;
......@@ -1355,9 +1388,24 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
/* wait for pending extra_info updates to ensure the ovl is disabled */
wait_pending_extra_info_updates();
/*
* For a manual update display, there is no guarantee that the overlay
* is really disabled in HW, we may need an extra update from this
* manager before the configurations can go in. Return an error if the
* overlay needed an update from the manager.
*
* TODO: Instead of returning an error, try to do a dummy manager update
* here to disable the overlay in hardware. Use the *GATED fields in
* the DISPC_CONFIG registers to do a dummy update.
*/
spin_lock_irqsave(&data_lock, flags);
op->channel = -1;
if (ovl_manual_update(ovl) && op->extra_info_dirty) {
spin_unlock_irqrestore(&data_lock, flags);
DSSERR("need an update to change the manager\n");
r = -EINVAL;
goto err;
}
ovl->manager = NULL;
list_del(&ovl->list);
......@@ -1372,7 +1420,7 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
return r;
}
bool dss_ovl_is_enabled(struct omap_overlay *ovl)
static bool dss_ovl_is_enabled(struct omap_overlay *ovl)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
unsigned long flags;
......@@ -1387,7 +1435,7 @@ bool dss_ovl_is_enabled(struct omap_overlay *ovl)
return e;
}
int dss_ovl_enable(struct omap_overlay *ovl)
static int dss_ovl_enable(struct omap_overlay *ovl)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
unsigned long flags;
......@@ -1437,7 +1485,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
return r;
}
int dss_ovl_disable(struct omap_overlay *ovl)
static int dss_ovl_disable(struct omap_overlay *ovl)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
unsigned long flags;
......@@ -1472,3 +1520,152 @@ int dss_ovl_disable(struct omap_overlay *ovl)
return r;
}
static int dss_mgr_register_framedone_handler_compat(struct omap_overlay_manager *mgr,
void (*handler)(void *), void *data)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
if (mp->framedone_handler)
return -EBUSY;
mp->framedone_handler = handler;
mp->framedone_handler_data = data;
return 0;
}
static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_manager *mgr,
void (*handler)(void *), void *data)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
WARN_ON(mp->framedone_handler != handler ||
mp->framedone_handler_data != data);
mp->framedone_handler = NULL;
mp->framedone_handler_data = NULL;
}
static const struct dss_mgr_ops apply_mgr_ops = {
.start_update = dss_mgr_start_update_compat,
.enable = dss_mgr_enable_compat,
.disable = dss_mgr_disable_compat,
.set_timings = dss_mgr_set_timings_compat,
.set_lcd_config = dss_mgr_set_lcd_config_compat,
.register_framedone_handler = dss_mgr_register_framedone_handler_compat,
.unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat,
};
static int compat_refcnt;
static DEFINE_MUTEX(compat_init_lock);
int omapdss_compat_init(void)
{
struct platform_device *pdev = dss_get_core_pdev();
struct omap_dss_device *dssdev = NULL;
int i, r;
mutex_lock(&compat_init_lock);
if (compat_refcnt++ > 0)
goto out;
apply_init_priv();
dss_init_overlay_managers(pdev);
dss_init_overlays(pdev);
for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
struct omap_overlay_manager *mgr;
mgr = omap_dss_get_overlay_manager(i);
mgr->set_output = &dss_mgr_set_output;
mgr->unset_output = &dss_mgr_unset_output;
mgr->apply = &omap_dss_mgr_apply;
mgr->set_manager_info = &dss_mgr_set_info;
mgr->get_manager_info = &dss_mgr_get_info;
mgr->wait_for_go = &dss_mgr_wait_for_go;
mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
mgr->get_device = &dss_mgr_get_device;
}
for (i = 0; i < omap_dss_get_num_overlays(); i++) {
struct omap_overlay *ovl = omap_dss_get_overlay(i);
ovl->is_enabled = &dss_ovl_is_enabled;
ovl->enable = &dss_ovl_enable;
ovl->disable = &dss_ovl_disable;
ovl->set_manager = &dss_ovl_set_manager;
ovl->unset_manager = &dss_ovl_unset_manager;
ovl->set_overlay_info = &dss_ovl_set_info;
ovl->get_overlay_info = &dss_ovl_get_info;
ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
ovl->get_device = &dss_ovl_get_device;
}
r = dss_install_mgr_ops(&apply_mgr_ops);
if (r)
goto err_mgr_ops;
for_each_dss_dev(dssdev) {
r = display_init_sysfs(pdev, dssdev);
/* XXX uninit sysfs files on error */
if (r)
goto err_disp_sysfs;
}
dispc_runtime_get();
r = dss_dispc_initialize_irq();
if (r)
goto err_init_irq;
dispc_runtime_put();
out:
mutex_unlock(&compat_init_lock);
return 0;
err_init_irq:
dispc_runtime_put();
err_disp_sysfs:
dss_uninstall_mgr_ops();
err_mgr_ops:
dss_uninit_overlay_managers(pdev);
dss_uninit_overlays(pdev);
compat_refcnt--;
mutex_unlock(&compat_init_lock);
return r;
}
EXPORT_SYMBOL(omapdss_compat_init);
void omapdss_compat_uninit(void)
{
struct platform_device *pdev = dss_get_core_pdev();
struct omap_dss_device *dssdev = NULL;
mutex_lock(&compat_init_lock);
if (--compat_refcnt > 0)
goto out;
dss_dispc_uninitialize_irq();
for_each_dss_dev(dssdev)
display_uninit_sysfs(pdev, dssdev);
dss_uninstall_mgr_ops();
dss_uninit_overlay_managers(pdev);
dss_uninit_overlays(pdev);
out:
mutex_unlock(&compat_init_lock);
}
EXPORT_SYMBOL(omapdss_compat_uninit);
......@@ -53,15 +53,23 @@ static char *def_disp_name;
module_param_named(def_disp, def_disp_name, charp, 0);
MODULE_PARM_DESC(def_disp, "default display name");
#ifdef DEBUG
bool dss_debug;
module_param_named(debug, dss_debug, bool, 0644);
#endif
const char *dss_get_default_display_name(void)
const char *omapdss_get_default_display_name(void)
{
return core.default_display_name;
}
EXPORT_SYMBOL(omapdss_get_default_display_name);
enum omapdss_version omapdss_get_version(void)
{
struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
return pdata->version;
}
EXPORT_SYMBOL(omapdss_get_version);
struct platform_device *dss_get_core_pdev(void)
{
return core.pdev;
}
/* REGULATORS */
......@@ -93,21 +101,6 @@ struct regulator *dss_get_vdds_sdi(void)
return reg;
}
int dss_get_ctx_loss_count(struct device *dev)
{
struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
int cnt;
if (!board_data->get_context_loss_count)
return -ENOENT;
cnt = board_data->get_context_loss_count(dev);
WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
return cnt;
}
int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
{
struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
......@@ -122,7 +115,7 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask)
{
struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
if (!board_data->dsi_enable_pads)
if (!board_data->dsi_disable_pads)
return;
return board_data->dsi_disable_pads(dsi_id, lane_mask);
......@@ -138,7 +131,7 @@ int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
return 0;
}
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
static int dss_debug_show(struct seq_file *s, void *unused)
{
void (*func)(struct seq_file *) = s->private;
......@@ -193,7 +186,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
return 0;
}
#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
#else /* CONFIG_OMAP2_DSS_DEBUGFS */
static inline int dss_initialize_debugfs(void)
{
return 0;
......@@ -205,7 +198,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
{
return 0;
}
#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
#endif /* CONFIG_OMAP2_DSS_DEBUGFS */
/* PLATFORM DEVICE */
static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)
......@@ -237,12 +230,7 @@ static int __init omap_dss_probe(struct platform_device *pdev)
core.pdev = pdev;
dss_features_init(pdata->version);
dss_apply_init();
dss_init_overlay_managers(pdev);
dss_init_overlays(pdev);
dss_features_init(omapdss_get_version());
r = dss_initialize_debugfs();
if (r)
......@@ -268,9 +256,6 @@ static int omap_dss_remove(struct platform_device *pdev)
dss_uninitialize_debugfs();
dss_uninit_overlays(pdev);
dss_uninit_overlay_managers(pdev);
return 0;
}
......@@ -358,15 +343,10 @@ static int dss_driver_probe(struct device *dev)
dev_name(dev), dssdev->driver_name,
dssdrv->driver.name);
r = dss_init_device(core.pdev, dssdev);
if (r)
return r;
r = dssdrv->probe(dssdev);
if (r) {
DSSERR("driver probe failed: %d\n", r);
dss_uninit_device(core.pdev, dssdev);
return r;
}
......@@ -387,8 +367,6 @@ static int dss_driver_remove(struct device *dev)
dssdrv->remove(dssdev);
dss_uninit_device(core.pdev, dssdev);
dssdev->driver = NULL;
return 0;
......@@ -507,6 +485,9 @@ static int __init omap_dss_bus_register(void)
/* INIT */
static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
#ifdef CONFIG_OMAP2_DSS_DSI
dsi_init_platform_driver,
#endif
#ifdef CONFIG_OMAP2_DSS_DPI
dpi_init_platform_driver,
#endif
......@@ -519,15 +500,15 @@ static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
#ifdef CONFIG_OMAP2_DSS_VENC
venc_init_platform_driver,
#endif
#ifdef CONFIG_OMAP2_DSS_DSI
dsi_init_platform_driver,
#endif
#ifdef CONFIG_OMAP4_DSS_HDMI
hdmi_init_platform_driver,
#endif
};
static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
#ifdef CONFIG_OMAP2_DSS_DSI
dsi_uninit_platform_driver,
#endif
#ifdef CONFIG_OMAP2_DSS_DPI
dpi_uninit_platform_driver,
#endif
......@@ -540,9 +521,6 @@ static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
#ifdef CONFIG_OMAP2_DSS_VENC
venc_uninit_platform_driver,
#endif
#ifdef CONFIG_OMAP2_DSS_DSI
dsi_uninit_platform_driver,
#endif
#ifdef CONFIG_OMAP4_DSS_HDMI
hdmi_uninit_platform_driver,
#endif
......
/*
* Copyright (C) 2012 Texas Instruments
* Author: Tomi Valkeinen <tomi.valkeinen@ti.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/>.
*/
#define DSS_SUBSYS_NAME "APPLY"
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/seq_file.h>
#include <video/omapdss.h>
#include "dss.h"
#include "dss_features.h"
#include "dispc-compat.h"
#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
DISPC_IRQ_OCP_ERR | \
DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
DISPC_IRQ_SYNC_LOST | \
DISPC_IRQ_SYNC_LOST_DIGIT)
#define DISPC_MAX_NR_ISRS 8
struct omap_dispc_isr_data {
omap_dispc_isr_t isr;
void *arg;
u32 mask;
};
struct dispc_irq_stats {
unsigned long last_reset;
unsigned irq_count;
unsigned irqs[32];
};
static struct {
spinlock_t irq_lock;
u32 irq_error_mask;
struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
u32 error_irqs;
struct work_struct error_work;
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
spinlock_t irq_stats_lock;
struct dispc_irq_stats irq_stats;
#endif
} dispc_compat;
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
static void dispc_dump_irqs(struct seq_file *s)
{
unsigned long flags;
struct dispc_irq_stats stats;
spin_lock_irqsave(&dispc_compat.irq_stats_lock, flags);
stats = dispc_compat.irq_stats;
memset(&dispc_compat.irq_stats, 0, sizeof(dispc_compat.irq_stats));
dispc_compat.irq_stats.last_reset = jiffies;
spin_unlock_irqrestore(&dispc_compat.irq_stats_lock, flags);
seq_printf(s, "period %u ms\n",
jiffies_to_msecs(jiffies - stats.last_reset));
seq_printf(s, "irqs %d\n", stats.irq_count);
#define PIS(x) \
seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
PIS(FRAMEDONE);
PIS(VSYNC);
PIS(EVSYNC_EVEN);
PIS(EVSYNC_ODD);
PIS(ACBIAS_COUNT_STAT);
PIS(PROG_LINE_NUM);
PIS(GFX_FIFO_UNDERFLOW);
PIS(GFX_END_WIN);
PIS(PAL_GAMMA_MASK);
PIS(OCP_ERR);
PIS(VID1_FIFO_UNDERFLOW);
PIS(VID1_END_WIN);
PIS(VID2_FIFO_UNDERFLOW);
PIS(VID2_END_WIN);
if (dss_feat_get_num_ovls() > 3) {
PIS(VID3_FIFO_UNDERFLOW);
PIS(VID3_END_WIN);
}
PIS(SYNC_LOST);
PIS(SYNC_LOST_DIGIT);
PIS(WAKEUP);
if (dss_has_feature(FEAT_MGR_LCD2)) {
PIS(FRAMEDONE2);
PIS(VSYNC2);
PIS(ACBIAS_COUNT_STAT2);
PIS(SYNC_LOST2);
}
if (dss_has_feature(FEAT_MGR_LCD3)) {
PIS(FRAMEDONE3);
PIS(VSYNC3);
PIS(ACBIAS_COUNT_STAT3);
PIS(SYNC_LOST3);
}
#undef PIS
}
#endif
/* dispc.irq_lock has to be locked by the caller */
static void _omap_dispc_set_irqs(void)
{
u32 mask;
int i;
struct omap_dispc_isr_data *isr_data;
mask = dispc_compat.irq_error_mask;
for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
isr_data = &dispc_compat.registered_isr[i];
if (isr_data->isr == NULL)
continue;
mask |= isr_data->mask;
}
dispc_write_irqenable(mask);
}
int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
{
int i;
int ret;
unsigned long flags;
struct omap_dispc_isr_data *isr_data;
if (isr == NULL)
return -EINVAL;
spin_lock_irqsave(&dispc_compat.irq_lock, flags);
/* check for duplicate entry */
for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
isr_data = &dispc_compat.registered_isr[i];
if (isr_data->isr == isr && isr_data->arg == arg &&
isr_data->mask == mask) {
ret = -EINVAL;
goto err;
}
}
isr_data = NULL;
ret = -EBUSY;
for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
isr_data = &dispc_compat.registered_isr[i];
if (isr_data->isr != NULL)
continue;
isr_data->isr = isr;
isr_data->arg = arg;
isr_data->mask = mask;
ret = 0;
break;
}
if (ret)
goto err;
_omap_dispc_set_irqs();
spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
return 0;
err:
spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
return ret;
}
EXPORT_SYMBOL(omap_dispc_register_isr);
int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
{
int i;
unsigned long flags;
int ret = -EINVAL;
struct omap_dispc_isr_data *isr_data;
spin_lock_irqsave(&dispc_compat.irq_lock, flags);
for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
isr_data = &dispc_compat.registered_isr[i];
if (isr_data->isr != isr || isr_data->arg != arg ||
isr_data->mask != mask)
continue;
/* found the correct isr */
isr_data->isr = NULL;
isr_data->arg = NULL;
isr_data->mask = 0;
ret = 0;
break;
}
if (ret == 0)
_omap_dispc_set_irqs();
spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
return ret;
}
EXPORT_SYMBOL(omap_dispc_unregister_isr);
static void print_irq_status(u32 status)
{
if ((status & dispc_compat.irq_error_mask) == 0)
return;
#define PIS(x) (status & DISPC_IRQ_##x) ? (#x " ") : ""
pr_debug("DISPC IRQ: 0x%x: %s%s%s%s%s%s%s%s%s\n",
status,
PIS(OCP_ERR),
PIS(GFX_FIFO_UNDERFLOW),
PIS(VID1_FIFO_UNDERFLOW),
PIS(VID2_FIFO_UNDERFLOW),
dss_feat_get_num_ovls() > 3 ? PIS(VID3_FIFO_UNDERFLOW) : "",
PIS(SYNC_LOST),
PIS(SYNC_LOST_DIGIT),
dss_has_feature(FEAT_MGR_LCD2) ? PIS(SYNC_LOST2) : "",
dss_has_feature(FEAT_MGR_LCD3) ? PIS(SYNC_LOST3) : "");
#undef PIS
}
/* Called from dss.c. Note that we don't touch clocks here,
* but we presume they are on because we got an IRQ. However,
* an irq handler may turn the clocks off, so we may not have
* clock later in the function. */
static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
{
int i;
u32 irqstatus, irqenable;
u32 handledirqs = 0;
u32 unhandled_errors;
struct omap_dispc_isr_data *isr_data;
struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
spin_lock(&dispc_compat.irq_lock);
irqstatus = dispc_read_irqstatus();
irqenable = dispc_read_irqenable();
/* IRQ is not for us */
if (!(irqstatus & irqenable)) {
spin_unlock(&dispc_compat.irq_lock);
return IRQ_NONE;
}
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
spin_lock(&dispc_compat.irq_stats_lock);
dispc_compat.irq_stats.irq_count++;
dss_collect_irq_stats(irqstatus, dispc_compat.irq_stats.irqs);
spin_unlock(&dispc_compat.irq_stats_lock);
#endif
print_irq_status(irqstatus);
/* Ack the interrupt. Do it here before clocks are possibly turned
* off */
dispc_clear_irqstatus(irqstatus);
/* flush posted write */
dispc_read_irqstatus();
/* make a copy and unlock, so that isrs can unregister
* themselves */
memcpy(registered_isr, dispc_compat.registered_isr,
sizeof(registered_isr));
spin_unlock(&dispc_compat.irq_lock);
for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
isr_data = &registered_isr[i];
if (!isr_data->isr)
continue;
if (isr_data->mask & irqstatus) {
isr_data->isr(isr_data->arg, irqstatus);
handledirqs |= isr_data->mask;
}
}
spin_lock(&dispc_compat.irq_lock);
unhandled_errors = irqstatus & ~handledirqs & dispc_compat.irq_error_mask;
if (unhandled_errors) {
dispc_compat.error_irqs |= unhandled_errors;
dispc_compat.irq_error_mask &= ~unhandled_errors;
_omap_dispc_set_irqs();
schedule_work(&dispc_compat.error_work);
}
spin_unlock(&dispc_compat.irq_lock);
return IRQ_HANDLED;
}
static void dispc_error_worker(struct work_struct *work)
{
int i;
u32 errors;
unsigned long flags;
static const unsigned fifo_underflow_bits[] = {
DISPC_IRQ_GFX_FIFO_UNDERFLOW,
DISPC_IRQ_VID1_FIFO_UNDERFLOW,
DISPC_IRQ_VID2_FIFO_UNDERFLOW,
DISPC_IRQ_VID3_FIFO_UNDERFLOW,
};
spin_lock_irqsave(&dispc_compat.irq_lock, flags);
errors = dispc_compat.error_irqs;
dispc_compat.error_irqs = 0;
spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
dispc_runtime_get();
for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
struct omap_overlay *ovl;
unsigned bit;
ovl = omap_dss_get_overlay(i);
bit = fifo_underflow_bits[i];
if (bit & errors) {
DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
ovl->name);
dispc_ovl_enable(ovl->id, false);
dispc_mgr_go(ovl->manager->id);
msleep(50);
}
}
for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
struct omap_overlay_manager *mgr;
unsigned bit;
mgr = omap_dss_get_overlay_manager(i);
bit = dispc_mgr_get_sync_lost_irq(i);
if (bit & errors) {
int j;
DSSERR("SYNC_LOST on channel %s, restarting the output "
"with video overlays disabled\n",
mgr->name);
dss_mgr_disable(mgr);
for (j = 0; j < omap_dss_get_num_overlays(); ++j) {
struct omap_overlay *ovl;
ovl = omap_dss_get_overlay(j);
if (ovl->id != OMAP_DSS_GFX &&
ovl->manager == mgr)
ovl->disable(ovl);
}
dss_mgr_enable(mgr);
}
}
if (errors & DISPC_IRQ_OCP_ERR) {
DSSERR("OCP_ERR\n");
for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
struct omap_overlay_manager *mgr;
mgr = omap_dss_get_overlay_manager(i);
dss_mgr_disable(mgr);
}
}
spin_lock_irqsave(&dispc_compat.irq_lock, flags);
dispc_compat.irq_error_mask |= errors;
_omap_dispc_set_irqs();
spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
dispc_runtime_put();
}
int dss_dispc_initialize_irq(void)
{
int r;
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
spin_lock_init(&dispc_compat.irq_stats_lock);
dispc_compat.irq_stats.last_reset = jiffies;
dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
#endif
spin_lock_init(&dispc_compat.irq_lock);
memset(dispc_compat.registered_isr, 0,
sizeof(dispc_compat.registered_isr));
dispc_compat.irq_error_mask = DISPC_IRQ_MASK_ERROR;
if (dss_has_feature(FEAT_MGR_LCD2))
dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
if (dss_has_feature(FEAT_MGR_LCD3))
dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
if (dss_feat_get_num_ovls() > 3)
dispc_compat.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
/*
* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
* so clear it
*/
dispc_clear_irqstatus(dispc_read_irqstatus());
INIT_WORK(&dispc_compat.error_work, dispc_error_worker);
_omap_dispc_set_irqs();
r = dispc_request_irq(omap_dispc_irq_handler, &dispc_compat);
if (r) {
DSSERR("dispc_request_irq failed\n");
return r;
}
return 0;
}
void dss_dispc_uninitialize_irq(void)
{
dispc_free_irq(&dispc_compat);
}
static void dispc_mgr_disable_isr(void *data, u32 mask)
{
struct completion *compl = data;
complete(compl);
}
static void dispc_mgr_enable_lcd_out(enum omap_channel channel)
{
dispc_mgr_enable(channel, true);
}
static void dispc_mgr_disable_lcd_out(enum omap_channel channel)
{
DECLARE_COMPLETION_ONSTACK(framedone_compl);
int r;
u32 irq;
if (dispc_mgr_is_enabled(channel) == false)
return;
/*
* When we disable LCD output, we need to wait for FRAMEDONE to know
* that DISPC has finished with the LCD output.
*/
irq = dispc_mgr_get_framedone_irq(channel);
r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
irq);
if (r)
DSSERR("failed to register FRAMEDONE isr\n");
dispc_mgr_enable(channel, false);
/* if we couldn't register for framedone, just sleep and exit */
if (r) {
msleep(100);
return;
}
if (!wait_for_completion_timeout(&framedone_compl,
msecs_to_jiffies(100)))
DSSERR("timeout waiting for FRAME DONE\n");
r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
irq);
if (r)
DSSERR("failed to unregister FRAMEDONE isr\n");
}
static void dispc_digit_out_enable_isr(void *data, u32 mask)
{
struct completion *compl = data;
/* ignore any sync lost interrupts */
if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD))
complete(compl);
}
static void dispc_mgr_enable_digit_out(void)
{
DECLARE_COMPLETION_ONSTACK(vsync_compl);
int r;
u32 irq_mask;
if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true)
return;
/*
* Digit output produces some sync lost interrupts during the first
* frame when enabling. Those need to be ignored, so we register for the
* sync lost irq to prevent the error handler from triggering.
*/
irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) |
dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT);
r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl,
irq_mask);
if (r) {
DSSERR("failed to register %x isr\n", irq_mask);
return;
}
dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true);
/* wait for the first evsync */
if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100)))
DSSERR("timeout waiting for digit out to start\n");
r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl,
irq_mask);
if (r)
DSSERR("failed to unregister %x isr\n", irq_mask);
}
static void dispc_mgr_disable_digit_out(void)
{
DECLARE_COMPLETION_ONSTACK(framedone_compl);
int r, i;
u32 irq_mask;
int num_irqs;
if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false)
return;
/*
* When we disable the digit output, we need to wait for FRAMEDONE to
* know that DISPC has finished with the output.
*/
irq_mask = dispc_mgr_get_framedone_irq(OMAP_DSS_CHANNEL_DIGIT);
num_irqs = 1;
if (!irq_mask) {
/*
* omap 2/3 don't have framedone irq for TV, so we need to use
* vsyncs for this.
*/
irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT);
/*
* We need to wait for both even and odd vsyncs. Note that this
* is not totally reliable, as we could get a vsync interrupt
* before we disable the output, which leads to timeout in the
* wait_for_completion.
*/
num_irqs = 2;
}
r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
irq_mask);
if (r)
DSSERR("failed to register %x isr\n", irq_mask);
dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, false);
/* if we couldn't register the irq, just sleep and exit */
if (r) {
msleep(100);
return;
}
for (i = 0; i < num_irqs; ++i) {
if (!wait_for_completion_timeout(&framedone_compl,
msecs_to_jiffies(100)))
DSSERR("timeout waiting for digit out to stop\n");
}
r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
irq_mask);
if (r)
DSSERR("failed to unregister %x isr\n", irq_mask);
}
void dispc_mgr_enable_sync(enum omap_channel channel)
{
if (dss_mgr_is_lcd(channel))
dispc_mgr_enable_lcd_out(channel);
else if (channel == OMAP_DSS_CHANNEL_DIGIT)
dispc_mgr_enable_digit_out();
else
WARN_ON(1);
}
void dispc_mgr_disable_sync(enum omap_channel channel)
{
if (dss_mgr_is_lcd(channel))
dispc_mgr_disable_lcd_out(channel);
else if (channel == OMAP_DSS_CHANNEL_DIGIT)
dispc_mgr_disable_digit_out();
else
WARN_ON(1);
}
int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
unsigned long timeout)
{
void dispc_irq_wait_handler(void *data, u32 mask)
{
complete((struct completion *)data);
}
int r;
DECLARE_COMPLETION_ONSTACK(completion);
r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
irqmask);
if (r)
return r;
timeout = wait_for_completion_interruptible_timeout(&completion,
timeout);
omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
if (timeout == 0)
return -ETIMEDOUT;
if (timeout == -ERESTARTSYS)
return -ERESTARTSYS;
return 0;
}
/*
* Copyright (C) 2012 Texas Instruments
* Author: Tomi Valkeinen <tomi.valkeinen@ti.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 __OMAP2_DSS_DISPC_COMPAT_H
#define __OMAP2_DSS_DISPC_COMPAT_H
void dispc_mgr_enable_sync(enum omap_channel channel);
void dispc_mgr_disable_sync(enum omap_channel channel);
int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
unsigned long timeout);
int dss_dispc_initialize_irq(void);
void dss_dispc_uninitialize_irq(void);
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -18,6 +18,7 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/err.h>
#include <linux/slab.h>
......@@ -429,8 +430,6 @@ static const struct dss_param_range omap2_dss_param_range[] = {
* scaler cannot scale a image with width more than 768.
*/
[FEAT_PARAM_LINEWIDTH] = { 1, 768 },
[FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
[FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
};
static const struct dss_param_range omap3_dss_param_range[] = {
......@@ -445,8 +444,6 @@ static const struct dss_param_range omap3_dss_param_range[] = {
[FEAT_PARAM_DSI_FCK] = { 0, 173000000 },
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
[FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
[FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
[FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
};
static const struct dss_param_range omap4_dss_param_range[] = {
......@@ -461,8 +458,6 @@ static const struct dss_param_range omap4_dss_param_range[] = {
[FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
[FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
[FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
[FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
};
static const struct dss_param_range omap5_dss_param_range[] = {
......@@ -477,8 +472,6 @@ static const struct dss_param_range omap5_dss_param_range[] = {
[FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
[FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
[FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
[FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
};
static const enum dss_feat_id omap2_dss_feat_list[] = {
......@@ -820,6 +813,7 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
.audio_start = ti_hdmi_4xxx_audio_start,
.audio_stop = ti_hdmi_4xxx_audio_stop,
.audio_config = ti_hdmi_4xxx_audio_config,
.audio_get_dma_port = ti_hdmi_4xxx_audio_get_dma_port,
#endif
};
......@@ -846,11 +840,13 @@ int dss_feat_get_num_mgrs(void)
{
return omap_current_dss_features->num_mgrs;
}
EXPORT_SYMBOL(dss_feat_get_num_mgrs);
int dss_feat_get_num_ovls(void)
{
return omap_current_dss_features->num_ovls;
}
EXPORT_SYMBOL(dss_feat_get_num_ovls);
int dss_feat_get_num_wbs(void)
{
......@@ -871,16 +867,19 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel
{
return omap_current_dss_features->supported_displays[channel];
}
EXPORT_SYMBOL(dss_feat_get_supported_displays);
enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
{
return omap_current_dss_features->supported_outputs[channel];
}
EXPORT_SYMBOL(dss_feat_get_supported_outputs);
enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
{
return omap_current_dss_features->supported_color_modes[plane];
}
EXPORT_SYMBOL(dss_feat_get_supported_color_modes);
enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
{
......
......@@ -98,19 +98,12 @@ enum dss_range_param {
FEAT_PARAM_DSI_FCK,
FEAT_PARAM_DOWNSCALE,
FEAT_PARAM_LINEWIDTH,
FEAT_PARAM_MGR_WIDTH,
FEAT_PARAM_MGR_HEIGHT,
};
/* DSS Feature Functions */
int dss_feat_get_num_mgrs(void);
int dss_feat_get_num_ovls(void);
int dss_feat_get_num_wbs(void);
unsigned long dss_feat_get_param_min(enum dss_range_param param);
unsigned long dss_feat_get_param_max(enum dss_range_param param);
enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
bool dss_feat_color_mode_supported(enum omap_plane plane,
enum omap_color_mode color_mode);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -38,13 +38,6 @@
static int num_overlays;
static struct omap_overlay *overlays;
static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
{
return ovl->manager ?
(ovl->manager->output ? ovl->manager->output->device : NULL) :
NULL;
}
int omap_dss_get_num_overlays(void)
{
return num_overlays;
......@@ -93,16 +86,6 @@ void dss_init_overlays(struct platform_device *pdev)
break;
}
ovl->is_enabled = &dss_ovl_is_enabled;
ovl->enable = &dss_ovl_enable;
ovl->disable = &dss_ovl_disable;
ovl->set_manager = &dss_ovl_set_manager;
ovl->unset_manager = &dss_ovl_unset_manager;
ovl->set_overlay_info = &dss_ovl_set_info;
ovl->get_overlay_info = &dss_ovl_get_info;
ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
ovl->get_device = &dss_ovl_get_device;
ovl->caps = dss_feat_get_overlay_caps(ovl->id);
ovl->supported_modes =
dss_feat_get_supported_color_modes(ovl->id);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -2,7 +2,6 @@ menuconfig FB_OMAP2
tristate "OMAP2+ frame buffer support"
depends on FB && OMAP2_DSS && !DRM_OMAP
select OMAP2_VRAM
select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册