fbdev changes for 3.8:
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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJQyvniAAoJEPo9qoy8lh71IqkQAK9LkVjVk6UQRT2/b39hPF6i PKPRNYxpLxX5u98hiqQfweukGkuC/cmsAJOh5UwX1lFg0TNua8CEYg0iuHgUtLWE gi+HNUhHfGx1+a9yQpTKsiheq7r88IjpghFGahnFhpE4kDzhIROom7B39x8bx9gs 1vnCptmcIq0IlMlmjIktTHw8R36Fd/8xDVEhEtDccxT9AJSePnKBY8SBuRjiyJfP QvXnd131kmHdshQbSVetsEwI1a9NJ9Z6MMRiQK3vtDiBJ7QHUw8wD/+kdR68gQxZ NqTC/s478dvx/bR5CIXHrXxQZGfOCJ0GFzT1rlcRMxECcF0dQYNr3Hid3Zas+mPZ hABpEJE7nV7LoDGhW3oIWPt6MZVFED/HE0F5QrG3/PWYs5UpTwkI9UTkB8Bx6LcA H9ypHzFaOT1SK2/jln9pAfYgo/ITCRf08gcxBvGZUPcybrQy+kbVPdYgDn09cDhR u6ax3k/PMF/6JRdpVRNxLaoEHw/G6vtNjoeRJivZzuIOmGDfGwADGcEnrcZEM3NM muOjk8TfTJgK+gzWleOfr9CQGiWWp1Tht9vF6TSApq4SEqmOK81EZpucrMXY0t6r 9+JmFzS1/+75NeY2YjgHCuqRaqVSMiyyOp1eYV9JIY14rKINbj77OHX8xaMm+Leg ZU4tirie/oEALaIJUann =KVPX -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
2b8318881d
@ -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.
|
||||
|
80
Documentation/devicetree/bindings/video/exynos_dp.txt
Normal file
80
Documentation/devicetree/bindings/video/exynos_dp.txt
Normal file
@ -0,0 +1,80 @@
|
||||
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>;
|
||||
};
|
24
Documentation/devicetree/bindings/video/ssd1307fb.txt
Normal file
24
Documentation/devicetree/bindings/video/ssd1307fb.txt
Normal file
@ -0,0 +1,24 @@
|
||||
* 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 @@ sh_mipi_set_dot_clock_pck_err:
|
||||
|
||||
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,
|
||||
|
@ -1,43 +0,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 @@ probe_err1:
|
||||
}
|
||||
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 */
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <video/exynos_dp.h>
|
||||
|
||||
@ -48,10 +49,6 @@ static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
|
||||
{
|
||||
int timeout_loop = 0;
|
||||
|
||||
exynos_dp_init_hpd(dp);
|
||||
|
||||
usleep_range(200, 210);
|
||||
|
||||
while (exynos_dp_get_plug_in_status(dp) != 0) {
|
||||
timeout_loop++;
|
||||
if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
|
||||
@ -90,9 +87,11 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp)
|
||||
*/
|
||||
|
||||
/* Read Extension Flag, Number of 128-byte EDID extension blocks */
|
||||
exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
|
||||
retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
|
||||
EDID_EXTENSION_FLAG,
|
||||
&extend_block);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (extend_block > 0) {
|
||||
dev_dbg(dp->dev, "EDID data includes a single extension!\n");
|
||||
@ -181,14 +180,15 @@ static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
|
||||
int retval;
|
||||
|
||||
/* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
|
||||
exynos_dp_read_bytes_from_dpcd(dp,
|
||||
DPCD_ADDR_DPCD_REV,
|
||||
12, buf);
|
||||
retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV,
|
||||
12, buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/* Read EDID */
|
||||
for (i = 0; i < 3; i++) {
|
||||
retval = exynos_dp_read_edid(dp);
|
||||
if (retval == 0)
|
||||
if (!retval)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -261,11 +261,10 @@ static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
|
||||
}
|
||||
}
|
||||
|
||||
static void exynos_dp_link_start(struct exynos_dp_device *dp)
|
||||
static int exynos_dp_link_start(struct exynos_dp_device *dp)
|
||||
{
|
||||
u8 buf[4];
|
||||
int lane;
|
||||
int lane_count;
|
||||
int lane, lane_count, pll_tries, retval;
|
||||
|
||||
lane_count = dp->link_train.lane_count;
|
||||
|
||||
@ -275,10 +274,6 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
|
||||
for (lane = 0; lane < lane_count; lane++)
|
||||
dp->link_train.cr_loop[lane] = 0;
|
||||
|
||||
/* Set sink to D0 (Sink Not Ready) mode. */
|
||||
exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE,
|
||||
DPCD_SET_POWER_STATE_D0);
|
||||
|
||||
/* Set link rate and count as you want to establish*/
|
||||
exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
|
||||
exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
|
||||
@ -286,29 +281,46 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
|
||||
/* Setup RX configuration */
|
||||
buf[0] = dp->link_train.link_rate;
|
||||
buf[1] = dp->link_train.lane_count;
|
||||
exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
|
||||
retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
|
||||
2, buf);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/* Set TX pre-emphasis to minimum */
|
||||
for (lane = 0; lane < lane_count; lane++)
|
||||
exynos_dp_set_lane_lane_pre_emphasis(dp,
|
||||
PRE_EMPHASIS_LEVEL_0, lane);
|
||||
|
||||
/* Wait for PLL lock */
|
||||
pll_tries = 0;
|
||||
while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
|
||||
if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
|
||||
dev_err(dp->dev, "Wait for PLL lock timed out\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
pll_tries++;
|
||||
usleep_range(90, 120);
|
||||
}
|
||||
|
||||
/* Set training pattern 1 */
|
||||
exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
|
||||
|
||||
/* Set RX training pattern */
|
||||
exynos_dp_write_byte_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET,
|
||||
DPCD_SCRAMBLING_DISABLED |
|
||||
DPCD_TRAINING_PATTERN_1);
|
||||
retval = exynos_dp_write_byte_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET,
|
||||
DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++)
|
||||
buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
|
||||
DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
|
||||
exynos_dp_write_bytes_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET,
|
||||
lane_count, buf);
|
||||
|
||||
retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
|
||||
lane_count, buf);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
|
||||
@ -332,18 +344,17 @@ static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_dp_channel_eq_ok(u8 link_align[3], int lane_count)
|
||||
static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
|
||||
int lane_count)
|
||||
{
|
||||
int lane;
|
||||
u8 lane_align;
|
||||
u8 lane_status;
|
||||
|
||||
lane_align = link_align[2];
|
||||
if ((lane_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
|
||||
if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
|
||||
return -EINVAL;
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
lane_status = exynos_dp_get_lane_status(link_align, lane);
|
||||
lane_status = exynos_dp_get_lane_status(link_status, lane);
|
||||
lane_status &= DPCD_CHANNEL_EQ_BITS;
|
||||
if (lane_status != DPCD_CHANNEL_EQ_BITS)
|
||||
return -EINVAL;
|
||||
@ -427,60 +438,60 @@ static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
|
||||
dp->link_train.lt_state = FAILED;
|
||||
}
|
||||
|
||||
static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp,
|
||||
u8 adjust_request[2])
|
||||
{
|
||||
int lane, lane_count;
|
||||
u8 voltage_swing, pre_emphasis, training_lane;
|
||||
|
||||
lane_count = dp->link_train.lane_count;
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
voltage_swing = exynos_dp_get_adjust_request_voltage(
|
||||
adjust_request, lane);
|
||||
pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
|
||||
adjust_request, lane);
|
||||
training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
|
||||
DPCD_PRE_EMPHASIS_SET(pre_emphasis);
|
||||
|
||||
if (voltage_swing == VOLTAGE_LEVEL_3)
|
||||
training_lane |= DPCD_MAX_SWING_REACHED;
|
||||
if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
|
||||
training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
|
||||
|
||||
dp->link_train.training_lane[lane] = training_lane;
|
||||
}
|
||||
}
|
||||
|
||||
static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
|
||||
{
|
||||
u8 link_status[2];
|
||||
int lane;
|
||||
int lane_count;
|
||||
|
||||
u8 adjust_request[2];
|
||||
u8 voltage_swing;
|
||||
u8 pre_emphasis;
|
||||
u8 training_lane;
|
||||
int lane, lane_count, retval;
|
||||
u8 voltage_swing, pre_emphasis, training_lane;
|
||||
u8 link_status[2], adjust_request[2];
|
||||
|
||||
usleep_range(100, 101);
|
||||
|
||||
lane_count = dp->link_train.lane_count;
|
||||
|
||||
exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
|
||||
2, link_status);
|
||||
retval = exynos_dp_read_bytes_from_dpcd(dp,
|
||||
DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
retval = exynos_dp_read_bytes_from_dpcd(dp,
|
||||
DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
|
||||
/* set training pattern 2 for EQ */
|
||||
exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
exynos_dp_read_bytes_from_dpcd(dp,
|
||||
DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
|
||||
2, adjust_request);
|
||||
voltage_swing = exynos_dp_get_adjust_request_voltage(
|
||||
adjust_request, lane);
|
||||
pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
|
||||
adjust_request, lane);
|
||||
training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
|
||||
DPCD_PRE_EMPHASIS_SET(pre_emphasis);
|
||||
|
||||
if (voltage_swing == VOLTAGE_LEVEL_3)
|
||||
training_lane |= DPCD_MAX_SWING_REACHED;
|
||||
if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
|
||||
training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
|
||||
|
||||
dp->link_train.training_lane[lane] = training_lane;
|
||||
|
||||
exynos_dp_set_lane_link_training(dp,
|
||||
dp->link_train.training_lane[lane],
|
||||
lane);
|
||||
}
|
||||
|
||||
exynos_dp_write_byte_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET,
|
||||
DPCD_SCRAMBLING_DISABLED |
|
||||
DPCD_TRAINING_PATTERN_2);
|
||||
|
||||
exynos_dp_write_bytes_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET,
|
||||
lane_count,
|
||||
dp->link_train.training_lane);
|
||||
retval = exynos_dp_write_byte_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET,
|
||||
DPCD_SCRAMBLING_DISABLED |
|
||||
DPCD_TRAINING_PATTERN_2);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
dev_info(dp->dev, "Link Training Clock Recovery success\n");
|
||||
dp->link_train.lt_state = EQUALIZER_TRAINING;
|
||||
@ -488,152 +499,116 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
training_lane = exynos_dp_get_lane_link_training(
|
||||
dp, lane);
|
||||
exynos_dp_read_bytes_from_dpcd(dp,
|
||||
DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
|
||||
2, adjust_request);
|
||||
voltage_swing = exynos_dp_get_adjust_request_voltage(
|
||||
adjust_request, lane);
|
||||
pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
|
||||
adjust_request, lane);
|
||||
|
||||
if (voltage_swing == VOLTAGE_LEVEL_3 ||
|
||||
pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
|
||||
dev_err(dp->dev, "voltage or pre emphasis reached max level\n");
|
||||
goto reduce_link_rate;
|
||||
}
|
||||
|
||||
if ((DPCD_VOLTAGE_SWING_GET(training_lane) ==
|
||||
voltage_swing) &&
|
||||
(DPCD_PRE_EMPHASIS_GET(training_lane) ==
|
||||
pre_emphasis)) {
|
||||
if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
|
||||
voltage_swing &&
|
||||
DPCD_PRE_EMPHASIS_GET(training_lane) ==
|
||||
pre_emphasis)
|
||||
dp->link_train.cr_loop[lane]++;
|
||||
if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP) {
|
||||
dev_err(dp->dev, "CR Max loop\n");
|
||||
goto reduce_link_rate;
|
||||
}
|
||||
|
||||
if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
|
||||
voltage_swing == VOLTAGE_LEVEL_3 ||
|
||||
pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
|
||||
dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
|
||||
dp->link_train.cr_loop[lane],
|
||||
voltage_swing, pre_emphasis);
|
||||
exynos_dp_reduce_link_rate(dp);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
|
||||
DPCD_PRE_EMPHASIS_SET(pre_emphasis);
|
||||
|
||||
if (voltage_swing == VOLTAGE_LEVEL_3)
|
||||
training_lane |= DPCD_MAX_SWING_REACHED;
|
||||
if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
|
||||
training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
|
||||
|
||||
dp->link_train.training_lane[lane] = training_lane;
|
||||
|
||||
exynos_dp_set_lane_link_training(dp,
|
||||
dp->link_train.training_lane[lane], lane);
|
||||
}
|
||||
|
||||
exynos_dp_write_bytes_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET,
|
||||
lane_count,
|
||||
dp->link_train.training_lane);
|
||||
}
|
||||
|
||||
return 0;
|
||||
exynos_dp_get_adjust_training_lane(dp, adjust_request);
|
||||
|
||||
reduce_link_rate:
|
||||
exynos_dp_reduce_link_rate(dp);
|
||||
return -EIO;
|
||||
for (lane = 0; lane < lane_count; lane++)
|
||||
exynos_dp_set_lane_link_training(dp,
|
||||
dp->link_train.training_lane[lane], lane);
|
||||
|
||||
retval = exynos_dp_write_bytes_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET, lane_count,
|
||||
dp->link_train.training_lane);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
|
||||
{
|
||||
u8 link_status[2];
|
||||
u8 link_align[3];
|
||||
int lane;
|
||||
int lane_count;
|
||||
int lane, lane_count, retval;
|
||||
u32 reg;
|
||||
|
||||
u8 adjust_request[2];
|
||||
u8 voltage_swing;
|
||||
u8 pre_emphasis;
|
||||
u8 training_lane;
|
||||
u8 link_align, link_status[2], adjust_request[2];
|
||||
|
||||
usleep_range(400, 401);
|
||||
|
||||
lane_count = dp->link_train.lane_count;
|
||||
|
||||
exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
|
||||
2, link_status);
|
||||
retval = exynos_dp_read_bytes_from_dpcd(dp,
|
||||
DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
|
||||
link_align[0] = link_status[0];
|
||||
link_align[1] = link_status[1];
|
||||
|
||||
exynos_dp_read_byte_from_dpcd(dp,
|
||||
DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED,
|
||||
&link_align[2]);
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
exynos_dp_read_bytes_from_dpcd(dp,
|
||||
DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
|
||||
2, adjust_request);
|
||||
voltage_swing = exynos_dp_get_adjust_request_voltage(
|
||||
adjust_request, lane);
|
||||
pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
|
||||
adjust_request, lane);
|
||||
training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
|
||||
DPCD_PRE_EMPHASIS_SET(pre_emphasis);
|
||||
|
||||
if (voltage_swing == VOLTAGE_LEVEL_3)
|
||||
training_lane |= DPCD_MAX_SWING_REACHED;
|
||||
if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
|
||||
training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
|
||||
|
||||
dp->link_train.training_lane[lane] = training_lane;
|
||||
}
|
||||
|
||||
if (exynos_dp_channel_eq_ok(link_align, lane_count) == 0) {
|
||||
/* traing pattern Set to Normal */
|
||||
exynos_dp_training_pattern_dis(dp);
|
||||
|
||||
dev_info(dp->dev, "Link Training success!\n");
|
||||
|
||||
exynos_dp_get_link_bandwidth(dp, ®);
|
||||
dp->link_train.link_rate = reg;
|
||||
dev_dbg(dp->dev, "final bandwidth = %.2x\n",
|
||||
dp->link_train.link_rate);
|
||||
|
||||
exynos_dp_get_lane_count(dp, ®);
|
||||
dp->link_train.lane_count = reg;
|
||||
dev_dbg(dp->dev, "final lane count = %.2x\n",
|
||||
dp->link_train.lane_count);
|
||||
|
||||
/* set enhanced mode if available */
|
||||
exynos_dp_set_enhanced_mode(dp);
|
||||
dp->link_train.lt_state = FINISHED;
|
||||
} else {
|
||||
/* not all locked */
|
||||
dp->link_train.eq_loop++;
|
||||
|
||||
if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
|
||||
dev_err(dp->dev, "EQ Max loop\n");
|
||||
goto reduce_link_rate;
|
||||
}
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++)
|
||||
exynos_dp_set_lane_link_training(dp,
|
||||
dp->link_train.training_lane[lane],
|
||||
lane);
|
||||
|
||||
exynos_dp_write_bytes_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET,
|
||||
lane_count,
|
||||
dp->link_train.training_lane);
|
||||
}
|
||||
} else {
|
||||
goto reduce_link_rate;
|
||||
if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
|
||||
exynos_dp_reduce_link_rate(dp);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
retval = exynos_dp_read_bytes_from_dpcd(dp,
|
||||
DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
reduce_link_rate:
|
||||
exynos_dp_reduce_link_rate(dp);
|
||||
return -EIO;
|
||||
retval = exynos_dp_read_byte_from_dpcd(dp,
|
||||
DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
exynos_dp_get_adjust_training_lane(dp, adjust_request);
|
||||
|
||||
if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) {
|
||||
/* traing pattern Set to Normal */
|
||||
exynos_dp_training_pattern_dis(dp);
|
||||
|
||||
dev_info(dp->dev, "Link Training success!\n");
|
||||
|
||||
exynos_dp_get_link_bandwidth(dp, ®);
|
||||
dp->link_train.link_rate = reg;
|
||||
dev_dbg(dp->dev, "final bandwidth = %.2x\n",
|
||||
dp->link_train.link_rate);
|
||||
|
||||
exynos_dp_get_lane_count(dp, ®);
|
||||
dp->link_train.lane_count = reg;
|
||||
dev_dbg(dp->dev, "final lane count = %.2x\n",
|
||||
dp->link_train.lane_count);
|
||||
|
||||
/* set enhanced mode if available */
|
||||
exynos_dp_set_enhanced_mode(dp);
|
||||
dp->link_train.lt_state = FINISHED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not all locked */
|
||||
dp->link_train.eq_loop++;
|
||||
|
||||
if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
|
||||
dev_err(dp->dev, "EQ Max loop\n");
|
||||
exynos_dp_reduce_link_rate(dp);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++)
|
||||
exynos_dp_set_lane_link_training(dp,
|
||||
dp->link_train.training_lane[lane], lane);
|
||||
|
||||
retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
|
||||
lane_count, dp->link_train.training_lane);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
|
||||
@ -701,16 +676,17 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp,
|
||||
|
||||
static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
|
||||
{
|
||||
int retval = 0;
|
||||
int training_finished = 0;
|
||||
int retval = 0, training_finished = 0;
|
||||
|
||||
dp->link_train.lt_state = START;
|
||||
|
||||
/* Process here */
|
||||
while (!training_finished) {
|
||||
while (!retval && !training_finished) {
|
||||
switch (dp->link_train.lt_state) {
|
||||
case START:
|
||||
exynos_dp_link_start(dp);
|
||||
retval = exynos_dp_link_start(dp);
|
||||
if (retval)
|
||||
dev_err(dp->dev, "LT link start failed!\n");
|
||||
break;
|
||||
case CLOCK_RECOVERY:
|
||||
retval = exynos_dp_process_clock_recovery(dp);
|
||||
@ -729,6 +705,8 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
}
|
||||
if (retval)
|
||||
dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
@ -752,19 +730,15 @@ static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int exynos_dp_config_video(struct exynos_dp_device *dp,
|
||||
struct video_info *video_info)
|
||||
static int exynos_dp_config_video(struct exynos_dp_device *dp)
|
||||
{
|
||||
int retval = 0;
|
||||
int timeout_loop = 0;
|
||||
int done_count = 0;
|
||||
|
||||
exynos_dp_config_video_slave_mode(dp, video_info);
|
||||
exynos_dp_config_video_slave_mode(dp);
|
||||
|
||||
exynos_dp_set_video_color_format(dp, video_info->color_depth,
|
||||
video_info->color_space,
|
||||
video_info->dynamic_range,
|
||||
video_info->ycbcr_coeff);
|
||||
exynos_dp_set_video_color_format(dp);
|
||||
|
||||
if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
|
||||
dev_err(dp->dev, "PLL is not locked yet.\n");
|
||||
@ -852,10 +826,213 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct exynos_dp_device *dp = arg;
|
||||
|
||||
dev_err(dp->dev, "exynos_dp_irq_handler\n");
|
||||
enum dp_irq_type irq_type;
|
||||
|
||||
irq_type = exynos_dp_get_irq_type(dp);
|
||||
switch (irq_type) {
|
||||
case DP_IRQ_TYPE_HP_CABLE_IN:
|
||||
dev_dbg(dp->dev, "Received irq - cable in\n");
|
||||
schedule_work(&dp->hotplug_work);
|
||||
exynos_dp_clear_hotplug_interrupts(dp);
|
||||
break;
|
||||
case DP_IRQ_TYPE_HP_CABLE_OUT:
|
||||
dev_dbg(dp->dev, "Received irq - cable out\n");
|
||||
exynos_dp_clear_hotplug_interrupts(dp);
|
||||
break;
|
||||
case DP_IRQ_TYPE_HP_CHANGE:
|
||||
/*
|
||||
* We get these change notifications once in a while, but there
|
||||
* is nothing we can do with them. Just ignore it for now and
|
||||
* only handle cable changes.
|
||||
*/
|
||||
dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n");
|
||||
exynos_dp_clear_hotplug_interrupts(dp);
|
||||
break;
|
||||
default:
|
||||
dev_err(dp->dev, "Received irq - unknown type!\n");
|
||||
break;
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void exynos_dp_hotplug(struct work_struct *work)
|
||||
{
|
||||
struct exynos_dp_device *dp;
|
||||
int ret;
|
||||
|
||||
dp = container_of(work, struct exynos_dp_device, hotplug_work);
|
||||
|
||||
ret = exynos_dp_detect_hpd(dp);
|
||||
if (ret) {
|
||||
/* Cable has been disconnected, we're done */
|
||||
return;
|
||||
}
|
||||
|
||||
ret = exynos_dp_handle_edid(dp);
|
||||
if (ret) {
|
||||
dev_err(dp->dev, "unable to handle edid\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
|
||||
dp->video_info->link_rate);
|
||||
if (ret) {
|
||||
dev_err(dp->dev, "unable to do link train\n");
|
||||
return;
|
||||
}
|
||||
|
||||
exynos_dp_enable_scramble(dp, 1);
|
||||
exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
|
||||
exynos_dp_enable_enhanced_mode(dp, 1);
|
||||
|
||||
exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
|
||||
exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
|
||||
|
||||
exynos_dp_init_video(dp);
|
||||
ret = exynos_dp_config_video(dp);
|
||||
if (ret)
|
||||
dev_err(dp->dev, "unable to config video\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
|
||||
{
|
||||
struct device_node *dp_node = dev->of_node;
|
||||
struct exynos_dp_platdata *pd;
|
||||
struct video_info *dp_video_config;
|
||||
|
||||
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
|
||||
if (!pd) {
|
||||
dev_err(dev, "memory allocation for pdata failed\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
dp_video_config = devm_kzalloc(dev,
|
||||
sizeof(*dp_video_config), GFP_KERNEL);
|
||||
|
||||
if (!dp_video_config) {
|
||||
dev_err(dev, "memory allocation for video config failed\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
pd->video_info = dp_video_config;
|
||||
|
||||
dp_video_config->h_sync_polarity =
|
||||
of_property_read_bool(dp_node, "hsync-active-high");
|
||||
|
||||
dp_video_config->v_sync_polarity =
|
||||
of_property_read_bool(dp_node, "vsync-active-high");
|
||||
|
||||
dp_video_config->interlaced =
|
||||
of_property_read_bool(dp_node, "interlaced");
|
||||
|
||||
if (of_property_read_u32(dp_node, "samsung,color-space",
|
||||
&dp_video_config->color_space)) {
|
||||
dev_err(dev, "failed to get color-space\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (of_property_read_u32(dp_node, "samsung,dynamic-range",
|
||||
&dp_video_config->dynamic_range)) {
|
||||
dev_err(dev, "failed to get dynamic-range\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
|
||||
&dp_video_config->ycbcr_coeff)) {
|
||||
dev_err(dev, "failed to get ycbcr-coeff\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (of_property_read_u32(dp_node, "samsung,color-depth",
|
||||
&dp_video_config->color_depth)) {
|
||||
dev_err(dev, "failed to get color-depth\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (of_property_read_u32(dp_node, "samsung,link-rate",
|
||||
&dp_video_config->link_rate)) {
|
||||
dev_err(dev, "failed to get link-rate\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (of_property_read_u32(dp_node, "samsung,lane-count",
|
||||
&dp_video_config->lane_count)) {
|
||||
dev_err(dev, "failed to get lane-count\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return pd;
|
||||
}
|
||||
|
||||
static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
|
||||
{
|
||||
struct device_node *dp_phy_node;
|
||||
u32 phy_base;
|
||||
|
||||
dp_phy_node = of_find_node_by_name(dp->dev->of_node, "dptx-phy");
|
||||
if (!dp_phy_node) {
|
||||
dev_err(dp->dev, "could not find dptx-phy node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
|
||||
dev_err(dp->dev, "faild to get reg for dptx-phy\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
|
||||
&dp->enable_mask)) {
|
||||
dev_err(dp->dev, "faild to get enable-mask for dptx-phy\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dp->phy_addr = ioremap(phy_base, SZ_4);
|
||||
if (!dp->phy_addr) {
|
||||
dev_err(dp->dev, "failed to ioremap dp-phy\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exynos_dp_phy_init(struct exynos_dp_device *dp)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = __raw_readl(dp->phy_addr);
|
||||
reg |= dp->enable_mask;
|
||||
__raw_writel(reg, dp->phy_addr);
|
||||
}
|
||||
|
||||
static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = __raw_readl(dp->phy_addr);
|
||||
reg &= ~(dp->enable_mask);
|
||||
__raw_writel(reg, dp->phy_addr);
|
||||
}
|
||||
#else
|
||||
static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void exynos_dp_phy_init(struct exynos_dp_device *dp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
@ -864,12 +1041,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
||||
|
||||
int ret = 0;
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "no platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
|
||||
GFP_KERNEL);
|
||||
if (!dp) {
|
||||
@ -879,6 +1050,22 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
||||
|
||||
dp->dev = &pdev->dev;
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
|
||||
if (IS_ERR(pdata))
|
||||
return PTR_ERR(pdata);
|
||||
|
||||
ret = exynos_dp_dt_parse_phydata(dp);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
pdata = pdev->dev.platform_data;
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "no platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
dp->clock = devm_clk_get(&pdev->dev, "dp");
|
||||
if (IS_ERR(dp->clock)) {
|
||||
dev_err(&pdev->dev, "failed to get clock\n");
|
||||
@ -896,11 +1083,25 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
dp->irq = platform_get_irq(pdev, 0);
|
||||
if (!dp->irq) {
|
||||
if (dp->irq == -ENXIO) {
|
||||
dev_err(&pdev->dev, "failed to get irq\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
|
||||
|
||||
dp->video_info = pdata->video_info;
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
if (dp->phy_addr)
|
||||
exynos_dp_phy_init(dp);
|
||||
} else {
|
||||
if (pdata->phy_init)
|
||||
pdata->phy_init();
|
||||
}
|
||||
|
||||
exynos_dp_init_dp(dp);
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
|
||||
"exynos-dp", dp);
|
||||
if (ret) {
|
||||
@ -908,41 +1109,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
dp->video_info = pdata->video_info;
|
||||
if (pdata->phy_init)
|
||||
pdata->phy_init();
|
||||
|
||||
exynos_dp_init_dp(dp);
|
||||
|
||||
ret = exynos_dp_detect_hpd(dp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to detect hpd\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
exynos_dp_handle_edid(dp);
|
||||
|
||||
ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
|
||||
dp->video_info->link_rate);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to do link train\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
exynos_dp_enable_scramble(dp, 1);
|
||||
exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
|
||||
exynos_dp_enable_enhanced_mode(dp, 1);
|
||||
|
||||
exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
|
||||
exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
|
||||
|
||||
exynos_dp_init_video(dp);
|
||||
ret = exynos_dp_config_video(dp, dp->video_info);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to config video\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, dp);
|
||||
|
||||
return 0;
|
||||
@ -953,23 +1119,41 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
|
||||
struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
|
||||
struct exynos_dp_device *dp = platform_get_drvdata(pdev);
|
||||
|
||||
if (pdata && pdata->phy_exit)
|
||||
pdata->phy_exit();
|
||||
disable_irq(dp->irq);
|
||||
|
||||
if (work_pending(&dp->hotplug_work))
|
||||
flush_work(&dp->hotplug_work);
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
if (dp->phy_addr)
|
||||
exynos_dp_phy_exit(dp);
|
||||
} else {
|
||||
if (pdata->phy_exit)
|
||||
pdata->phy_exit();
|
||||
}
|
||||
|
||||
clk_disable_unprepare(dp->clock);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int exynos_dp_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
|
||||
struct exynos_dp_device *dp = platform_get_drvdata(pdev);
|
||||
struct exynos_dp_platdata *pdata = dev->platform_data;
|
||||
struct exynos_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
||||
if (pdata && pdata->phy_exit)
|
||||
pdata->phy_exit();
|
||||
if (work_pending(&dp->hotplug_work))
|
||||
flush_work(&dp->hotplug_work);
|
||||
|
||||
if (dev->of_node) {
|
||||
if (dp->phy_addr)
|
||||
exynos_dp_phy_exit(dp);
|
||||
} else {
|
||||
if (pdata->phy_exit)
|
||||
pdata->phy_exit();
|
||||
}
|
||||
|
||||
clk_disable_unprepare(dp->clock);
|
||||
|
||||
@ -978,32 +1162,22 @@ static int exynos_dp_suspend(struct device *dev)
|
||||
|
||||
static int exynos_dp_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
|
||||
struct exynos_dp_device *dp = platform_get_drvdata(pdev);
|
||||
struct exynos_dp_platdata *pdata = dev->platform_data;
|
||||
struct exynos_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
||||
if (pdata && pdata->phy_init)
|
||||
pdata->phy_init();
|
||||
if (dev->of_node) {
|
||||
if (dp->phy_addr)
|
||||
exynos_dp_phy_init(dp);
|
||||
} else {
|
||||
if (pdata->phy_init)
|
||||
pdata->phy_init();
|
||||
}
|
||||
|
||||
clk_prepare_enable(dp->clock);
|
||||
|
||||
exynos_dp_init_dp(dp);
|
||||
|
||||
exynos_dp_detect_hpd(dp);
|
||||
exynos_dp_handle_edid(dp);
|
||||
|
||||
exynos_dp_set_link_train(dp, dp->video_info->lane_count,
|
||||
dp->video_info->link_rate);
|
||||
|
||||
exynos_dp_enable_scramble(dp, 1);
|
||||
exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
|
||||
exynos_dp_enable_enhanced_mode(dp, 1);
|
||||
|
||||
exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
|
||||
exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
|
||||
|
||||
exynos_dp_init_video(dp);
|
||||
exynos_dp_config_video(dp, dp->video_info);
|
||||
enable_irq(dp->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1013,6 +1187,12 @@ static const struct dev_pm_ops exynos_dp_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
|
||||
};
|
||||
|
||||
static const struct of_device_id exynos_dp_match[] = {
|
||||
{ .compatible = "samsung,exynos5-dp" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, exynos_dp_match);
|
||||
|
||||
static struct platform_driver exynos_dp_driver = {
|
||||
.probe = exynos_dp_probe,
|
||||
.remove = __devexit_p(exynos_dp_remove),
|
||||
@ -1020,6 +1200,7 @@ static struct platform_driver exynos_dp_driver = {
|
||||
.name = "exynos-dp",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &exynos_dp_pm_ops,
|
||||
.of_match_table = of_match_ptr(exynos_dp_match),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -1,6 +1,3 @@
|
||||
config OMAP2_VRAM
|
||||
bool
|
||||
|
||||
config OMAP2_VRFB
|
||||
bool
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
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,
|
||||
|
||||
|
@ -1,33 +1,30 @@
|
||||
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.
|
||||
|
@ -1,6 +1,10 @@
|
||||
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 @@ err:
|
||||
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 @@ out:
|
||||
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 @@ err:
|
||||
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 @@ out:
|
||||
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 @@ err:
|
||||
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 @@ err1:
|
||||
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 @@ err:
|
||||
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
|
||||
|
667
drivers/video/omap2/dss/dispc-compat.c
Normal file
667
drivers/video/omap2/dss/dispc-compat.c
Normal file
@ -0,0 +1,667 @@
|
||||
/*
|
||||
* 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 = ®istered_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;
|
||||
}
|
30
drivers/video/omap2/dss/dispc-compat.h
Normal file
30
drivers/video/omap2/dss/dispc-compat.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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
|
File diff suppressed because it is too large
Load Diff
321
drivers/video/omap2/dss/display-sysfs.c
Normal file
321
drivers/video/omap2/dss/display-sysfs.c
Normal file
@ -0,0 +1,321 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Nokia Corporation
|
||||
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
|
||||
*
|
||||
* Some code and ideas taken from drivers/video/omap/ driver
|
||||
* by Imre Deak.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define DSS_SUBSYS_NAME "DISPLAY"
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
static ssize_t display_enabled_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
|
||||
}
|
||||
|
||||
static ssize_t display_enabled_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
int r;
|
||||
bool enabled;
|
||||
|
||||
r = strtobool(buf, &enabled);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
|
||||
if (enabled) {
|
||||
r = dssdev->driver->enable(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
} else {
|
||||
dssdev->driver->disable(dssdev);
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t display_tear_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
dssdev->driver->get_te ?
|
||||
dssdev->driver->get_te(dssdev) : 0);
|
||||
}
|
||||
|
||||
static ssize_t display_tear_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
int r;
|
||||
bool te;
|
||||
|
||||
if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
|
||||
return -ENOENT;
|
||||
|
||||
r = strtobool(buf, &te);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dssdev->driver->enable_te(dssdev, te);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t display_timings_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
struct omap_video_timings t;
|
||||
|
||||
if (!dssdev->driver->get_timings)
|
||||
return -ENOENT;
|
||||
|
||||
dssdev->driver->get_timings(dssdev, &t);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
|
||||
t.pixel_clock,
|
||||
t.x_res, t.hfp, t.hbp, t.hsw,
|
||||
t.y_res, t.vfp, t.vbp, t.vsw);
|
||||
}
|
||||
|
||||
static ssize_t display_timings_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
struct omap_video_timings t = dssdev->panel.timings;
|
||||
int r, found;
|
||||
|
||||
if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
|
||||
return -ENOENT;
|
||||
|
||||
found = 0;
|
||||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
if (strncmp("pal", buf, 3) == 0) {
|
||||
t = omap_dss_pal_timings;
|
||||
found = 1;
|
||||
} else if (strncmp("ntsc", buf, 4) == 0) {
|
||||
t = omap_dss_ntsc_timings;
|
||||
found = 1;
|
||||
}
|
||||
#endif
|
||||
if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
|
||||
&t.pixel_clock,
|
||||
&t.x_res, &t.hfp, &t.hbp, &t.hsw,
|
||||
&t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
|
||||
return -EINVAL;
|
||||
|
||||
r = dssdev->driver->check_timings(dssdev, &t);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dssdev->driver->disable(dssdev);
|
||||
dssdev->driver->set_timings(dssdev, &t);
|
||||
r = dssdev->driver->enable(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t display_rotate_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
int rotate;
|
||||
if (!dssdev->driver->get_rotate)
|
||||
return -ENOENT;
|
||||
rotate = dssdev->driver->get_rotate(dssdev);
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
|
||||
}
|
||||
|
||||
static ssize_t display_rotate_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
int rot, r;
|
||||
|
||||
if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
|
||||
return -ENOENT;
|
||||
|
||||
r = kstrtoint(buf, 0, &rot);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dssdev->driver->set_rotate(dssdev, rot);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t display_mirror_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
int mirror;
|
||||
if (!dssdev->driver->get_mirror)
|
||||
return -ENOENT;
|
||||
mirror = dssdev->driver->get_mirror(dssdev);
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
|
||||
}
|
||||
|
||||
static ssize_t display_mirror_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
int r;
|
||||
bool mirror;
|
||||
|
||||
if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
|
||||
return -ENOENT;
|
||||
|
||||
r = strtobool(buf, &mirror);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dssdev->driver->set_mirror(dssdev, mirror);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t display_wss_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
unsigned int wss;
|
||||
|
||||
if (!dssdev->driver->get_wss)
|
||||
return -ENOENT;
|
||||
|
||||
wss = dssdev->driver->get_wss(dssdev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
|
||||
}
|
||||
|
||||
static ssize_t display_wss_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
u32 wss;
|
||||
int r;
|
||||
|
||||
if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
|
||||
return -ENOENT;
|
||||
|
||||
r = kstrtou32(buf, 0, &wss);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (wss > 0xfffff)
|
||||
return -EINVAL;
|
||||
|
||||
r = dssdev->driver->set_wss(dssdev, wss);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
|
||||
display_enabled_show, display_enabled_store);
|
||||
static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
|
||||
display_tear_show, display_tear_store);
|
||||
static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
|
||||
display_timings_show, display_timings_store);
|
||||
static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
|
||||
display_rotate_show, display_rotate_store);
|
||||
static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
|
||||
display_mirror_show, display_mirror_store);
|
||||
static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
|
||||
display_wss_show, display_wss_store);
|
||||
|
||||
static struct device_attribute *display_sysfs_attrs[] = {
|
||||
&dev_attr_enabled,
|
||||
&dev_attr_tear_elim,
|
||||
&dev_attr_timings,
|
||||
&dev_attr_rotate,
|
||||
&dev_attr_mirror,
|
||||
&dev_attr_wss,
|
||||
NULL
|
||||
};
|
||||
|
||||
int display_init_sysfs(struct platform_device *pdev,
|
||||
struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct device_attribute *attr;
|
||||
int i, r;
|
||||
|
||||
/* create device sysfs files */
|
||||
i = 0;
|
||||
while ((attr = display_sysfs_attrs[i++]) != NULL) {
|
||||
r = device_create_file(&dssdev->dev, attr);
|
||||
if (r) {
|
||||
for (i = i - 2; i >= 0; i--) {
|
||||
attr = display_sysfs_attrs[i];
|
||||
device_remove_file(&dssdev->dev, attr);
|
||||
}
|
||||
|
||||
DSSERR("failed to create sysfs file\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* create display? sysfs links */
|
||||
r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
|
||||
dev_name(&dssdev->dev));
|
||||
if (r) {
|
||||
while ((attr = display_sysfs_attrs[i++]) != NULL)
|
||||
device_remove_file(&dssdev->dev, attr);
|
||||
|
||||
DSSERR("failed to create sysfs display link\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void display_uninit_sysfs(struct platform_device *pdev,
|
||||
struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct device_attribute *attr;
|
||||
int i = 0;
|
||||
|
||||
sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
|
||||
|
||||
while ((attr = display_sysfs_attrs[i++]) != NULL)
|
||||
device_remove_file(&dssdev->dev, attr);
|
||||
}
|
@ -31,250 +31,6 @@
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
static ssize_t display_enabled_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
|
||||
}
|
||||
|
||||
static ssize_t display_enabled_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
int r;
|
||||
bool enabled;
|
||||
|
||||
r = strtobool(buf, &enabled);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
|
||||
if (enabled) {
|
||||
r = dssdev->driver->enable(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
} else {
|
||||
dssdev->driver->disable(dssdev);
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t display_tear_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
dssdev->driver->get_te ?
|
||||
dssdev->driver->get_te(dssdev) : 0);
|
||||
}
|
||||
|
||||
static ssize_t display_tear_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
int r;
|
||||
bool te;
|
||||
|
||||
if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
|
||||
return -ENOENT;
|
||||
|
||||
r = strtobool(buf, &te);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dssdev->driver->enable_te(dssdev, te);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t display_timings_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
struct omap_video_timings t;
|
||||
|
||||
if (!dssdev->driver->get_timings)
|
||||
return -ENOENT;
|
||||
|
||||
dssdev->driver->get_timings(dssdev, &t);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
|
||||
t.pixel_clock,
|
||||
t.x_res, t.hfp, t.hbp, t.hsw,
|
||||
t.y_res, t.vfp, t.vbp, t.vsw);
|
||||
}
|
||||
|
||||
static ssize_t display_timings_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
struct omap_video_timings t = dssdev->panel.timings;
|
||||
int r, found;
|
||||
|
||||
if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
|
||||
return -ENOENT;
|
||||
|
||||
found = 0;
|
||||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
if (strncmp("pal", buf, 3) == 0) {
|
||||
t = omap_dss_pal_timings;
|
||||
found = 1;
|
||||
} else if (strncmp("ntsc", buf, 4) == 0) {
|
||||
t = omap_dss_ntsc_timings;
|
||||
found = 1;
|
||||
}
|
||||
#endif
|
||||
if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
|
||||
&t.pixel_clock,
|
||||
&t.x_res, &t.hfp, &t.hbp, &t.hsw,
|
||||
&t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
|
||||
return -EINVAL;
|
||||
|
||||
r = dssdev->driver->check_timings(dssdev, &t);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dssdev->driver->disable(dssdev);
|
||||
dssdev->driver->set_timings(dssdev, &t);
|
||||
r = dssdev->driver->enable(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t display_rotate_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
int rotate;
|
||||
if (!dssdev->driver->get_rotate)
|
||||
return -ENOENT;
|
||||
rotate = dssdev->driver->get_rotate(dssdev);
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
|
||||
}
|
||||
|
||||
static ssize_t display_rotate_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
int rot, r;
|
||||
|
||||
if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
|
||||
return -ENOENT;
|
||||
|
||||
r = kstrtoint(buf, 0, &rot);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dssdev->driver->set_rotate(dssdev, rot);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t display_mirror_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
int mirror;
|
||||
if (!dssdev->driver->get_mirror)
|
||||
return -ENOENT;
|
||||
mirror = dssdev->driver->get_mirror(dssdev);
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
|
||||
}
|
||||
|
||||
static ssize_t display_mirror_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
int r;
|
||||
bool mirror;
|
||||
|
||||
if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
|
||||
return -ENOENT;
|
||||
|
||||
r = strtobool(buf, &mirror);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dssdev->driver->set_mirror(dssdev, mirror);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t display_wss_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
unsigned int wss;
|
||||
|
||||
if (!dssdev->driver->get_wss)
|
||||
return -ENOENT;
|
||||
|
||||
wss = dssdev->driver->get_wss(dssdev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
|
||||
}
|
||||
|
||||
static ssize_t display_wss_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
u32 wss;
|
||||
int r;
|
||||
|
||||
if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
|
||||
return -ENOENT;
|
||||
|
||||
r = kstrtou32(buf, 0, &wss);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (wss > 0xfffff)
|
||||
return -EINVAL;
|
||||
|
||||
r = dssdev->driver->set_wss(dssdev, wss);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
|
||||
display_enabled_show, display_enabled_store);
|
||||
static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
|
||||
display_tear_show, display_tear_store);
|
||||
static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
|
||||
display_timings_show, display_timings_store);
|
||||
static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
|
||||
display_rotate_show, display_rotate_store);
|
||||
static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
|
||||
display_mirror_show, display_mirror_store);
|
||||
static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
|
||||
display_wss_show, display_wss_store);
|
||||
|
||||
static struct device_attribute *display_sysfs_attrs[] = {
|
||||
&dev_attr_enabled,
|
||||
&dev_attr_tear_elim,
|
||||
&dev_attr_timings,
|
||||
&dev_attr_rotate,
|
||||
&dev_attr_mirror,
|
||||
&dev_attr_wss,
|
||||
NULL
|
||||
};
|
||||
|
||||
void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
|
||||
u16 *xres, u16 *yres)
|
||||
{
|
||||
@ -320,136 +76,8 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_default_get_timings);
|
||||
|
||||
/*
|
||||
* Connect dssdev to a manager if the manager is free or if force is specified.
|
||||
* Connect all overlays to that manager if they are free or if force is
|
||||
* specified.
|
||||
*/
|
||||
static int dss_init_connections(struct omap_dss_device *dssdev, bool force)
|
||||
{
|
||||
struct omap_dss_output *out;
|
||||
struct omap_overlay_manager *mgr;
|
||||
int i, r;
|
||||
|
||||
out = omapdss_get_output_from_dssdev(dssdev);
|
||||
|
||||
WARN_ON(dssdev->output);
|
||||
WARN_ON(out->device);
|
||||
|
||||
r = omapdss_output_set_device(out, dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to connect output to new device\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
mgr = omap_dss_get_overlay_manager(dssdev->channel);
|
||||
|
||||
if (mgr->output && !force)
|
||||
return 0;
|
||||
|
||||
if (mgr->output)
|
||||
mgr->unset_output(mgr);
|
||||
|
||||
r = mgr->set_output(mgr, out);
|
||||
if (r) {
|
||||
DSSERR("failed to connect manager to output of new device\n");
|
||||
|
||||
/* remove the output-device connection we just made */
|
||||
omapdss_output_unset_device(out);
|
||||
return r;
|
||||
}
|
||||
|
||||
for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
|
||||
struct omap_overlay *ovl = omap_dss_get_overlay(i);
|
||||
|
||||
if (!ovl->manager || force) {
|
||||
if (ovl->manager)
|
||||
ovl->unset_manager(ovl);
|
||||
|
||||
r = ovl->set_manager(ovl, mgr);
|
||||
if (r) {
|
||||
DSSERR("failed to set initial overlay\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dss_uninit_connections(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->output) {
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
|
||||
if (mgr)
|
||||
mgr->unset_output(mgr);
|
||||
|
||||
omapdss_output_unset_device(dssdev->output);
|
||||
}
|
||||
}
|
||||
|
||||
int dss_init_device(struct platform_device *pdev,
|
||||
struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct device_attribute *attr;
|
||||
int i, r;
|
||||
const char *def_disp_name = dss_get_default_display_name();
|
||||
bool force;
|
||||
|
||||
force = def_disp_name && strcmp(def_disp_name, dssdev->name) == 0;
|
||||
dss_init_connections(dssdev, force);
|
||||
|
||||
/* create device sysfs files */
|
||||
i = 0;
|
||||
while ((attr = display_sysfs_attrs[i++]) != NULL) {
|
||||
r = device_create_file(&dssdev->dev, attr);
|
||||
if (r) {
|
||||
for (i = i - 2; i >= 0; i--) {
|
||||
attr = display_sysfs_attrs[i];
|
||||
device_remove_file(&dssdev->dev, attr);
|
||||
}
|
||||
|
||||
dss_uninit_connections(dssdev);
|
||||
|
||||
DSSERR("failed to create sysfs file\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* create display? sysfs links */
|
||||
r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
|
||||
dev_name(&dssdev->dev));
|
||||
if (r) {
|
||||
while ((attr = display_sysfs_attrs[i++]) != NULL)
|
||||
device_remove_file(&dssdev->dev, attr);
|
||||
|
||||
dss_uninit_connections(dssdev);
|
||||
|
||||
DSSERR("failed to create sysfs display link\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dss_uninit_device(struct platform_device *pdev,
|
||||
struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct device_attribute *attr;
|
||||
int i = 0;
|
||||
|
||||
sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
|
||||
|
||||
while ((attr = display_sysfs_attrs[i++]) != NULL)
|
||||
device_remove_file(&dssdev->dev, attr);
|
||||
|
||||
dss_uninit_connections(dssdev);
|
||||
}
|
||||
|
||||
static int dss_suspend_device(struct device *dev, void *data)
|
||||
{
|
||||
int r;
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
@ -457,15 +85,7 @@ static int dss_suspend_device(struct device *dev, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dssdev->driver->suspend) {
|
||||
DSSERR("display '%s' doesn't implement suspend\n",
|
||||
dssdev->name);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
r = dssdev->driver->suspend(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
dssdev->driver->disable(dssdev);
|
||||
|
||||
dssdev->activate_after_resume = true;
|
||||
|
||||
@ -492,8 +112,8 @@ static int dss_resume_device(struct device *dev, void *data)
|
||||
int r;
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
|
||||
if (dssdev->activate_after_resume && dssdev->driver->resume) {
|
||||
r = dssdev->driver->resume(dssdev);
|
||||
if (dssdev->activate_after_resume) {
|
||||
r = dssdev->driver->enable(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -49,34 +49,53 @@ static struct {
|
||||
struct omap_dss_output output;
|
||||
} dpi;
|
||||
|
||||
static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
|
||||
static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
|
||||
{
|
||||
int dsi_module;
|
||||
/*
|
||||
* XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
|
||||
* would also be used for DISPC fclk. Meaning, when the DPI output is
|
||||
* disabled, DISPC clock will be disabled, and TV out will stop.
|
||||
*/
|
||||
switch (omapdss_get_version()) {
|
||||
case OMAPDSS_VER_OMAP24xx:
|
||||
case OMAPDSS_VER_OMAP34xx_ES1:
|
||||
case OMAPDSS_VER_OMAP34xx_ES3:
|
||||
case OMAPDSS_VER_OMAP3630:
|
||||
case OMAPDSS_VER_AM35xx:
|
||||
return NULL;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
dsi_module = clk == OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ? 0 : 1;
|
||||
|
||||
return dsi_get_dsidev_from_id(dsi_module);
|
||||
switch (channel) {
|
||||
case OMAP_DSS_CHANNEL_LCD:
|
||||
return dsi_get_dsidev_from_id(0);
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return dsi_get_dsidev_from_id(1);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev)
|
||||
static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
|
||||
{
|
||||
if (dssdev->clocks.dispc.dispc_fclk_src ==
|
||||
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
|
||||
dssdev->clocks.dispc.dispc_fclk_src ==
|
||||
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC ||
|
||||
dssdev->clocks.dispc.channel.lcd_clk_src ==
|
||||
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
|
||||
dssdev->clocks.dispc.channel.lcd_clk_src ==
|
||||
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
switch (channel) {
|
||||
case OMAP_DSS_CHANNEL_LCD:
|
||||
return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
|
||||
default:
|
||||
/* this shouldn't happen */
|
||||
WARN_ON(1);
|
||||
return OMAP_DSS_CLK_SRC_FCK;
|
||||
}
|
||||
}
|
||||
|
||||
static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
|
||||
unsigned long pck_req, unsigned long *fck, int *lck_div,
|
||||
int *pck_div)
|
||||
{
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
struct dsi_clock_info dsi_cinfo;
|
||||
struct dispc_clock_info dispc_cinfo;
|
||||
int r;
|
||||
@ -90,7 +109,8 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
|
||||
dss_select_lcd_clk_source(mgr->id,
|
||||
dpi_get_alt_clk_src(mgr->id));
|
||||
|
||||
dpi.mgr_config.clock_info = dispc_cinfo;
|
||||
|
||||
@ -135,7 +155,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
|
||||
unsigned long pck;
|
||||
int r = 0;
|
||||
|
||||
if (dpi_use_dsi_pll(dssdev))
|
||||
if (dpi.dsidev)
|
||||
r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck,
|
||||
&lck_div, &pck_div);
|
||||
else
|
||||
@ -214,7 +234,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
|
||||
if (r)
|
||||
goto err_src_sel;
|
||||
|
||||
if (dpi_use_dsi_pll(dssdev)) {
|
||||
if (dpi.dsidev) {
|
||||
r = dsi_runtime_get(dpi.dsidev);
|
||||
if (r)
|
||||
goto err_get_dsi;
|
||||
@ -242,10 +262,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
|
||||
|
||||
err_mgr_enable:
|
||||
err_set_mode:
|
||||
if (dpi_use_dsi_pll(dssdev))
|
||||
if (dpi.dsidev)
|
||||
dsi_pll_uninit(dpi.dsidev, true);
|
||||
err_dsi_pll_init:
|
||||
if (dpi_use_dsi_pll(dssdev))
|
||||
if (dpi.dsidev)
|
||||
dsi_runtime_put(dpi.dsidev);
|
||||
err_get_dsi:
|
||||
err_src_sel:
|
||||
@ -271,8 +291,8 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
|
||||
|
||||
dss_mgr_disable(mgr);
|
||||
|
||||
if (dpi_use_dsi_pll(dssdev)) {
|
||||
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
|
||||
if (dpi.dsidev) {
|
||||
dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
|
||||
dsi_pll_uninit(dpi.dsidev, true);
|
||||
dsi_runtime_put(dpi.dsidev);
|
||||
}
|
||||
@ -311,13 +331,13 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
|
||||
unsigned long pck;
|
||||
struct dispc_clock_info dispc_cinfo;
|
||||
|
||||
if (dss_mgr_check_timings(mgr, timings))
|
||||
if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
|
||||
return -EINVAL;
|
||||
|
||||
if (timings->pixel_clock == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (dpi_use_dsi_pll(dssdev)) {
|
||||
if (dpi.dsidev) {
|
||||
struct dsi_clock_info dsi_cinfo;
|
||||
r = dsi_pll_calc_clock_div_pck(dpi.dsidev,
|
||||
timings->pixel_clock * 1000,
|
||||
@ -359,8 +379,32 @@ void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
|
||||
|
||||
static int __init dpi_verify_dsi_pll(struct platform_device *dsidev)
|
||||
{
|
||||
int r;
|
||||
|
||||
/* do initial setup with the PLL to see if it is operational */
|
||||
|
||||
r = dsi_runtime_get(dsidev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dsi_pll_init(dsidev, 0, 1);
|
||||
if (r) {
|
||||
dsi_runtime_put(dsidev);
|
||||
return r;
|
||||
}
|
||||
|
||||
dsi_pll_uninit(dsidev, true);
|
||||
dsi_runtime_put(dsidev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init dpi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct platform_device *dsidev;
|
||||
|
||||
DSSDBG("init_display\n");
|
||||
|
||||
if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
|
||||
@ -377,19 +421,30 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
|
||||
dpi.vdds_dsi_reg = vdds_dsi;
|
||||
}
|
||||
|
||||
if (dpi_use_dsi_pll(dssdev)) {
|
||||
enum omap_dss_clk_source dispc_fclk_src =
|
||||
dssdev->clocks.dispc.dispc_fclk_src;
|
||||
dpi.dsidev = dpi_get_dsidev(dispc_fclk_src);
|
||||
/*
|
||||
* XXX We shouldn't need dssdev->channel for this. The dsi pll clock
|
||||
* source for DPI is SoC integration detail, not something that should
|
||||
* be configured in the dssdev
|
||||
*/
|
||||
dsidev = dpi_get_dsidev(dssdev->channel);
|
||||
|
||||
if (dsidev && dpi_verify_dsi_pll(dsidev)) {
|
||||
dsidev = NULL;
|
||||
DSSWARN("DSI PLL not operational\n");
|
||||
}
|
||||
|
||||
if (dsidev)
|
||||
DSSDBG("using DSI PLL for DPI clock\n");
|
||||
|
||||
dpi.dsidev = dsidev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
const char *def_disp_name = dss_get_default_display_name();
|
||||
const char *def_disp_name = omapdss_get_default_display_name();
|
||||
struct omap_dss_device *def_dssdev;
|
||||
int i;
|
||||
|
||||
@ -438,9 +493,18 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev)
|
||||
return;
|
||||
}
|
||||
|
||||
r = omapdss_output_set_device(&dpi.output, dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to connect output to new device: %s\n",
|
||||
dssdev->name);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
||||
r = dss_add_device(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s register failed: %d\n", dssdev->name, r);
|
||||
omapdss_output_unset_device(&dpi.output);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
/*#define VERBOSE_IRQ*/
|
||||
#define DSI_CATCH_MISSING_TE
|
||||
|
||||
struct dsi_reg { u16 idx; };
|
||||
@ -535,42 +534,38 @@ static inline void dsi_perf_show(struct platform_device *dsidev,
|
||||
}
|
||||
#endif
|
||||
|
||||
static int verbose_irq;
|
||||
|
||||
static void print_irq_status(u32 status)
|
||||
{
|
||||
if (status == 0)
|
||||
return;
|
||||
|
||||
#ifndef VERBOSE_IRQ
|
||||
if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
|
||||
if (!verbose_irq && (status & ~DSI_IRQ_CHANNEL_MASK) == 0)
|
||||
return;
|
||||
#endif
|
||||
printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
|
||||
|
||||
#define PIS(x) \
|
||||
if (status & DSI_IRQ_##x) \
|
||||
printk(#x " ");
|
||||
#ifdef VERBOSE_IRQ
|
||||
PIS(VC0);
|
||||
PIS(VC1);
|
||||
PIS(VC2);
|
||||
PIS(VC3);
|
||||
#endif
|
||||
PIS(WAKEUP);
|
||||
PIS(RESYNC);
|
||||
PIS(PLL_LOCK);
|
||||
PIS(PLL_UNLOCK);
|
||||
PIS(PLL_RECALL);
|
||||
PIS(COMPLEXIO_ERR);
|
||||
PIS(HS_TX_TIMEOUT);
|
||||
PIS(LP_RX_TIMEOUT);
|
||||
PIS(TE_TRIGGER);
|
||||
PIS(ACK_TRIGGER);
|
||||
PIS(SYNC_LOST);
|
||||
PIS(LDO_POWER_GOOD);
|
||||
PIS(TA_TIMEOUT);
|
||||
#define PIS(x) (status & DSI_IRQ_##x) ? (#x " ") : ""
|
||||
|
||||
pr_debug("DSI IRQ: 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||
status,
|
||||
verbose_irq ? PIS(VC0) : "",
|
||||
verbose_irq ? PIS(VC1) : "",
|
||||
verbose_irq ? PIS(VC2) : "",
|
||||
verbose_irq ? PIS(VC3) : "",
|
||||
PIS(WAKEUP),
|
||||
PIS(RESYNC),
|
||||
PIS(PLL_LOCK),
|
||||
PIS(PLL_UNLOCK),
|
||||
PIS(PLL_RECALL),
|
||||
PIS(COMPLEXIO_ERR),
|
||||
PIS(HS_TX_TIMEOUT),
|
||||
PIS(LP_RX_TIMEOUT),
|
||||
PIS(TE_TRIGGER),
|
||||
PIS(ACK_TRIGGER),
|
||||
PIS(SYNC_LOST),
|
||||
PIS(LDO_POWER_GOOD),
|
||||
PIS(TA_TIMEOUT));
|
||||
#undef PIS
|
||||
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
static void print_irq_status_vc(int channel, u32 status)
|
||||
@ -578,28 +573,24 @@ static void print_irq_status_vc(int channel, u32 status)
|
||||
if (status == 0)
|
||||
return;
|
||||
|
||||
#ifndef VERBOSE_IRQ
|
||||
if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
|
||||
if (!verbose_irq && (status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
|
||||
return;
|
||||
#endif
|
||||
printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
|
||||
|
||||
#define PIS(x) \
|
||||
if (status & DSI_VC_IRQ_##x) \
|
||||
printk(#x " ");
|
||||
PIS(CS);
|
||||
PIS(ECC_CORR);
|
||||
#ifdef VERBOSE_IRQ
|
||||
PIS(PACKET_SENT);
|
||||
#endif
|
||||
PIS(FIFO_TX_OVF);
|
||||
PIS(FIFO_RX_OVF);
|
||||
PIS(BTA);
|
||||
PIS(ECC_NO_CORR);
|
||||
PIS(FIFO_TX_UDF);
|
||||
PIS(PP_BUSY_CHANGE);
|
||||
#define PIS(x) (status & DSI_VC_IRQ_##x) ? (#x " ") : ""
|
||||
|
||||
pr_debug("DSI VC(%d) IRQ 0x%x: %s%s%s%s%s%s%s%s%s\n",
|
||||
channel,
|
||||
status,
|
||||
PIS(CS),
|
||||
PIS(ECC_CORR),
|
||||
PIS(ECC_NO_CORR),
|
||||
verbose_irq ? PIS(PACKET_SENT) : "",
|
||||
PIS(BTA),
|
||||
PIS(FIFO_TX_OVF),
|
||||
PIS(FIFO_RX_OVF),
|
||||
PIS(FIFO_TX_UDF),
|
||||
PIS(PP_BUSY_CHANGE));
|
||||
#undef PIS
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
static void print_irq_status_cio(u32 status)
|
||||
@ -607,34 +598,31 @@ static void print_irq_status_cio(u32 status)
|
||||
if (status == 0)
|
||||
return;
|
||||
|
||||
printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
|
||||
#define PIS(x) (status & DSI_CIO_IRQ_##x) ? (#x " ") : ""
|
||||
|
||||
#define PIS(x) \
|
||||
if (status & DSI_CIO_IRQ_##x) \
|
||||
printk(#x " ");
|
||||
PIS(ERRSYNCESC1);
|
||||
PIS(ERRSYNCESC2);
|
||||
PIS(ERRSYNCESC3);
|
||||
PIS(ERRESC1);
|
||||
PIS(ERRESC2);
|
||||
PIS(ERRESC3);
|
||||
PIS(ERRCONTROL1);
|
||||
PIS(ERRCONTROL2);
|
||||
PIS(ERRCONTROL3);
|
||||
PIS(STATEULPS1);
|
||||
PIS(STATEULPS2);
|
||||
PIS(STATEULPS3);
|
||||
PIS(ERRCONTENTIONLP0_1);
|
||||
PIS(ERRCONTENTIONLP1_1);
|
||||
PIS(ERRCONTENTIONLP0_2);
|
||||
PIS(ERRCONTENTIONLP1_2);
|
||||
PIS(ERRCONTENTIONLP0_3);
|
||||
PIS(ERRCONTENTIONLP1_3);
|
||||
PIS(ULPSACTIVENOT_ALL0);
|
||||
PIS(ULPSACTIVENOT_ALL1);
|
||||
pr_debug("DSI CIO IRQ 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||
status,
|
||||
PIS(ERRSYNCESC1),
|
||||
PIS(ERRSYNCESC2),
|
||||
PIS(ERRSYNCESC3),
|
||||
PIS(ERRESC1),
|
||||
PIS(ERRESC2),
|
||||
PIS(ERRESC3),
|
||||
PIS(ERRCONTROL1),
|
||||
PIS(ERRCONTROL2),
|
||||
PIS(ERRCONTROL3),
|
||||
PIS(STATEULPS1),
|
||||
PIS(STATEULPS2),
|
||||
PIS(STATEULPS3),
|
||||
PIS(ERRCONTENTIONLP0_1),
|
||||
PIS(ERRCONTENTIONLP1_1),
|
||||
PIS(ERRCONTENTIONLP0_2),
|
||||
PIS(ERRCONTENTIONLP1_2),
|
||||
PIS(ERRCONTENTIONLP0_3),
|
||||
PIS(ERRCONTENTIONLP1_3),
|
||||
PIS(ULPSACTIVENOT_ALL0),
|
||||
PIS(ULPSACTIVENOT_ALL1));
|
||||
#undef PIS
|
||||
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
||||
@ -1116,28 +1104,16 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void _dsi_print_reset_status(struct platform_device *dsidev)
|
||||
{
|
||||
u32 l;
|
||||
int b0, b1, b2;
|
||||
|
||||
if (!dss_debug)
|
||||
return;
|
||||
|
||||
/* A dummy read using the SCP interface to any DSIPHY register is
|
||||
* required after DSIPHY reset to complete the reset of the DSI complex
|
||||
* I/O. */
|
||||
l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
|
||||
|
||||
printk(KERN_DEBUG "DSI resets: ");
|
||||
|
||||
l = dsi_read_reg(dsidev, DSI_PLL_STATUS);
|
||||
printk("PLL (%d) ", FLD_GET(l, 0, 0));
|
||||
|
||||
l = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
|
||||
printk("CIO (%d) ", FLD_GET(l, 29, 29));
|
||||
|
||||
if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
|
||||
b0 = 28;
|
||||
b1 = 27;
|
||||
@ -1148,18 +1124,21 @@ static void _dsi_print_reset_status(struct platform_device *dsidev)
|
||||
b2 = 26;
|
||||
}
|
||||
|
||||
l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
|
||||
printk("PHY (%x%x%x, %d, %d, %d)\n",
|
||||
FLD_GET(l, b0, b0),
|
||||
FLD_GET(l, b1, b1),
|
||||
FLD_GET(l, b2, b2),
|
||||
FLD_GET(l, 29, 29),
|
||||
FLD_GET(l, 30, 30),
|
||||
FLD_GET(l, 31, 31));
|
||||
#define DSI_FLD_GET(fld, start, end)\
|
||||
FLD_GET(dsi_read_reg(dsidev, DSI_##fld), start, end)
|
||||
|
||||
pr_debug("DSI resets: PLL (%d) CIO (%d) PHY (%x%x%x, %d, %d, %d)\n",
|
||||
DSI_FLD_GET(PLL_STATUS, 0, 0),
|
||||
DSI_FLD_GET(COMPLEXIO_CFG1, 29, 29),
|
||||
DSI_FLD_GET(DSIPHY_CFG5, b0, b0),
|
||||
DSI_FLD_GET(DSIPHY_CFG5, b1, b1),
|
||||
DSI_FLD_GET(DSIPHY_CFG5, b2, b2),
|
||||
DSI_FLD_GET(DSIPHY_CFG5, 29, 29),
|
||||
DSI_FLD_GET(DSIPHY_CFG5, 30, 30),
|
||||
DSI_FLD_GET(DSIPHY_CFG5, 31, 31));
|
||||
|
||||
#undef DSI_FLD_GET
|
||||
}
|
||||
#else
|
||||
#define _dsi_print_reset_status(x)
|
||||
#endif
|
||||
|
||||
static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
|
||||
{
|
||||
@ -1407,6 +1386,11 @@ retry:
|
||||
cur.dsi_pll_hsdiv_dispc_clk =
|
||||
cur.clkin4ddr / cur.regm_dispc;
|
||||
|
||||
if (cur.regm_dispc > 1 &&
|
||||
cur.regm_dispc % 2 != 0 &&
|
||||
req_pck >= 1000000)
|
||||
continue;
|
||||
|
||||
/* this will narrow down the search a bit,
|
||||
* but still give pixclocks below what was
|
||||
* requested */
|
||||
@ -1621,7 +1605,7 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
|
||||
u8 regn_start, regn_end, regm_start, regm_end;
|
||||
u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
|
||||
|
||||
DSSDBGF();
|
||||
DSSDBG("DSI PLL clock config starts");
|
||||
|
||||
dsi->current_cinfo.clkin = cinfo->clkin;
|
||||
dsi->current_cinfo.fint = cinfo->fint;
|
||||
@ -1757,11 +1741,21 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
|
||||
|
||||
DSSDBG("PLL init\n");
|
||||
|
||||
/*
|
||||
* It seems that on many OMAPs we need to enable both to have a
|
||||
* functional HSDivider.
|
||||
*/
|
||||
enable_hsclk = enable_hsdiv = true;
|
||||
|
||||
if (dsi->vdds_dsi_reg == NULL) {
|
||||
struct regulator *vdds_dsi;
|
||||
|
||||
vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
|
||||
|
||||
/* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
|
||||
if (IS_ERR(vdds_dsi))
|
||||
vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
|
||||
|
||||
if (IS_ERR(vdds_dsi)) {
|
||||
DSSERR("can't get VDDS_DSI regulator\n");
|
||||
return PTR_ERR(vdds_dsi);
|
||||
@ -2440,7 +2434,7 @@ static int dsi_cio_init(struct platform_device *dsidev)
|
||||
int r;
|
||||
u32 l;
|
||||
|
||||
DSSDBGF();
|
||||
DSSDBG("DSI CIO init starts");
|
||||
|
||||
r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
|
||||
if (r)
|
||||
@ -2791,7 +2785,7 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
|
||||
{
|
||||
u32 r;
|
||||
|
||||
DSSDBGF("%d", channel);
|
||||
DSSDBG("Initial config of virtual channel %d", channel);
|
||||
|
||||
r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
|
||||
|
||||
@ -2823,7 +2817,7 @@ static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
|
||||
if (dsi->vc[channel].source == source)
|
||||
return 0;
|
||||
|
||||
DSSDBGF("%d", channel);
|
||||
DSSDBG("Source config of virtual channel %d", channel);
|
||||
|
||||
dsi_sync_vc(dsidev, channel);
|
||||
|
||||
@ -3581,7 +3575,7 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
|
||||
int r, i;
|
||||
unsigned mask;
|
||||
|
||||
DSSDBGF();
|
||||
DSSDBG("Entering ULPS");
|
||||
|
||||
WARN_ON(!dsi_bus_is_locked(dsidev));
|
||||
|
||||
@ -4285,7 +4279,7 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
|
||||
unsigned long pck;
|
||||
int r;
|
||||
|
||||
DSSDBGF("ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
|
||||
DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
|
||||
|
||||
mutex_lock(&dsi->lock);
|
||||
|
||||
@ -4541,7 +4535,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
|
||||
dsi_handle_framedone(dsi->pdev, -ETIMEDOUT);
|
||||
}
|
||||
|
||||
static void dsi_framedone_irq_callback(void *data, u32 mask)
|
||||
static void dsi_framedone_irq_callback(void *data)
|
||||
{
|
||||
struct platform_device *dsidev = (struct platform_device *) data;
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
@ -4615,7 +4609,6 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
int r;
|
||||
u32 irq = 0;
|
||||
|
||||
if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
|
||||
dsi->timings.hsw = 1;
|
||||
@ -4625,12 +4618,10 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
|
||||
dsi->timings.vfp = 0;
|
||||
dsi->timings.vbp = 0;
|
||||
|
||||
irq = dispc_mgr_get_framedone_irq(mgr->id);
|
||||
|
||||
r = omap_dispc_register_isr(dsi_framedone_irq_callback,
|
||||
(void *) dsidev, irq);
|
||||
r = dss_mgr_register_framedone_handler(mgr,
|
||||
dsi_framedone_irq_callback, dsidev);
|
||||
if (r) {
|
||||
DSSERR("can't get FRAMEDONE irq\n");
|
||||
DSSERR("can't register FRAMEDONE handler\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -4668,8 +4659,8 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
|
||||
return 0;
|
||||
err1:
|
||||
if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
|
||||
omap_dispc_unregister_isr(dsi_framedone_irq_callback,
|
||||
(void *) dsidev, irq);
|
||||
dss_mgr_unregister_framedone_handler(mgr,
|
||||
dsi_framedone_irq_callback, dsidev);
|
||||
err:
|
||||
return r;
|
||||
}
|
||||
@ -4680,14 +4671,9 @@ static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
|
||||
if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
|
||||
u32 irq;
|
||||
|
||||
irq = dispc_mgr_get_framedone_irq(mgr->id);
|
||||
|
||||
omap_dispc_unregister_isr(dsi_framedone_irq_callback,
|
||||
(void *) dsidev, irq);
|
||||
}
|
||||
if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
|
||||
dss_mgr_unregister_framedone_handler(mgr,
|
||||
dsi_framedone_irq_callback, dsidev);
|
||||
}
|
||||
|
||||
static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
|
||||
@ -4730,7 +4716,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
|
||||
if (r)
|
||||
goto err1;
|
||||
|
||||
dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
|
||||
dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src);
|
||||
dss_select_lcd_clk_source(mgr->id,
|
||||
dssdev->clocks.dispc.channel.lcd_clk_src);
|
||||
@ -4765,7 +4750,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
|
||||
err3:
|
||||
dsi_cio_uninit(dsidev);
|
||||
err2:
|
||||
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
|
||||
dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
|
||||
dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
|
||||
|
||||
@ -4792,7 +4776,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
|
||||
dsi_vc_enable(dsidev, 2, 0);
|
||||
dsi_vc_enable(dsidev, 3, 0);
|
||||
|
||||
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
|
||||
dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
|
||||
dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
|
||||
dsi_cio_uninit(dsidev);
|
||||
@ -4981,6 +4964,10 @@ static int __init dsi_init_display(struct omap_dss_device *dssdev)
|
||||
|
||||
vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
|
||||
|
||||
/* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
|
||||
if (IS_ERR(vdds_dsi))
|
||||
vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
|
||||
|
||||
if (IS_ERR(vdds_dsi)) {
|
||||
DSSERR("can't get VDDS_DSI regulator\n");
|
||||
return PTR_ERR(vdds_dsi);
|
||||
@ -5121,7 +5108,7 @@ static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *p
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
|
||||
const char *def_disp_name = dss_get_default_display_name();
|
||||
const char *def_disp_name = omapdss_get_default_display_name();
|
||||
struct omap_dss_device *def_dssdev;
|
||||
int i;
|
||||
|
||||
@ -5151,6 +5138,7 @@ static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *p
|
||||
|
||||
static void __init dsi_probe_pdata(struct platform_device *dsidev)
|
||||
{
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
struct omap_dss_device *plat_dssdev;
|
||||
struct omap_dss_device *dssdev;
|
||||
int r;
|
||||
@ -5173,9 +5161,18 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
|
||||
return;
|
||||
}
|
||||
|
||||
r = omapdss_output_set_device(&dsi->output, dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to connect output to new device: %s\n",
|
||||
dssdev->name);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
||||
r = dss_add_device(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s register failed: %d\n", dssdev->name, r);
|
||||
omapdss_output_unset_device(&dsi->output);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
@ -76,6 +77,7 @@ static struct {
|
||||
|
||||
struct clk *dpll4_m4_ck;
|
||||
struct clk *dss_clk;
|
||||
unsigned long dss_clk_rate;
|
||||
|
||||
unsigned long cache_req_pck;
|
||||
unsigned long cache_prate;
|
||||
@ -96,6 +98,8 @@ static const char * const dss_generic_clk_source_names[] = {
|
||||
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC",
|
||||
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI",
|
||||
[OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
|
||||
[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DSI_PLL2_HSDIV_DISPC",
|
||||
[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI",
|
||||
};
|
||||
|
||||
static inline void dss_write_reg(const struct dss_reg idx, u32 val)
|
||||
@ -151,6 +155,21 @@ static void dss_restore_context(void)
|
||||
#undef SR
|
||||
#undef RR
|
||||
|
||||
int dss_get_ctx_loss_count(void)
|
||||
{
|
||||
struct omap_dss_board_info *board_data = dss.pdev->dev.platform_data;
|
||||
int cnt;
|
||||
|
||||
if (!board_data->get_context_loss_count)
|
||||
return -ENOENT;
|
||||
|
||||
cnt = board_data->get_context_loss_count(&dss.pdev->dev);
|
||||
|
||||
WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
void dss_sdi_init(int datapairs)
|
||||
{
|
||||
u32 l;
|
||||
@ -301,7 +320,7 @@ static void dss_dump_regs(struct seq_file *s)
|
||||
#undef DUMPREG
|
||||
}
|
||||
|
||||
void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
|
||||
static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
|
||||
{
|
||||
struct platform_device *dsidev;
|
||||
int b;
|
||||
@ -372,8 +391,10 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
|
||||
struct platform_device *dsidev;
|
||||
int b, ix, pos;
|
||||
|
||||
if (!dss_has_feature(FEAT_LCD_CLK_SRC))
|
||||
if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
|
||||
dss_select_dispc_clk_source(clk_src);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (clk_src) {
|
||||
case OMAP_DSS_CLK_SRC_FCK:
|
||||
@ -429,6 +450,29 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate clock rates using dividers in cinfo */
|
||||
int dss_calc_clock_rates(struct dss_clock_info *cinfo)
|
||||
{
|
||||
if (dss.dpll4_m4_ck) {
|
||||
unsigned long prate;
|
||||
|
||||
if (cinfo->fck_div > dss.feat->fck_div_max ||
|
||||
cinfo->fck_div == 0)
|
||||
return -EINVAL;
|
||||
|
||||
prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
|
||||
|
||||
cinfo->fck = prate / cinfo->fck_div *
|
||||
dss.feat->dss_fck_multiplier;
|
||||
} else {
|
||||
if (cinfo->fck_div != 0)
|
||||
return -EINVAL;
|
||||
cinfo->fck = clk_get_rate(dss.dss_clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dss_set_clock_div(struct dss_clock_info *cinfo)
|
||||
{
|
||||
if (dss.dpll4_m4_ck) {
|
||||
@ -446,6 +490,10 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
|
||||
|
||||
WARN_ONCE(dss.dss_clk_rate != cinfo->fck, "clk rate mismatch");
|
||||
|
||||
DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
|
||||
|
||||
return 0;
|
||||
@ -459,6 +507,41 @@ unsigned long dss_get_dpll4_rate(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long dss_get_dispc_clk_rate(void)
|
||||
{
|
||||
return dss.dss_clk_rate;
|
||||
}
|
||||
|
||||
static int dss_setup_default_clock(void)
|
||||
{
|
||||
unsigned long max_dss_fck, prate;
|
||||
unsigned fck_div;
|
||||
struct dss_clock_info dss_cinfo = { 0 };
|
||||
int r;
|
||||
|
||||
if (dss.dpll4_m4_ck == NULL)
|
||||
return 0;
|
||||
|
||||
max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
|
||||
|
||||
prate = dss_get_dpll4_rate();
|
||||
|
||||
fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
|
||||
max_dss_fck);
|
||||
|
||||
dss_cinfo.fck_div = fck_div;
|
||||
|
||||
r = dss_calc_clock_rates(&dss_cinfo);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dss_set_clock_div(&dss_cinfo);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
|
||||
struct dispc_clock_info *dispc_cinfo)
|
||||
{
|
||||
@ -748,7 +831,7 @@ static void dss_runtime_put(void)
|
||||
}
|
||||
|
||||
/* DEBUGFS */
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
|
||||
#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
|
||||
void dss_debug_dump_clocks(struct seq_file *s)
|
||||
{
|
||||
dss_dump_clocks(s);
|
||||
@ -796,7 +879,6 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
|
||||
|
||||
static int __init dss_init_features(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
const struct dss_features *src;
|
||||
struct dss_features *dst;
|
||||
|
||||
@ -806,7 +888,7 @@ static int __init dss_init_features(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
switch (pdata->version) {
|
||||
switch (omapdss_get_version()) {
|
||||
case OMAPDSS_VER_OMAP24xx:
|
||||
src = &omap24xx_dss_feats;
|
||||
break;
|
||||
@ -871,15 +953,23 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dss_setup_default_clock();
|
||||
if (r)
|
||||
goto err_setup_clocks;
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
r = dss_runtime_get();
|
||||
if (r)
|
||||
goto err_runtime_get;
|
||||
|
||||
dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
|
||||
|
||||
/* Select DPLL */
|
||||
REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
|
||||
|
||||
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
|
||||
REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
|
||||
@ -903,6 +993,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
|
||||
|
||||
err_runtime_get:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
err_setup_clocks:
|
||||
dss_put_clocks();
|
||||
return r;
|
||||
}
|
||||
|
@ -23,44 +23,20 @@
|
||||
#ifndef __OMAP2_DSS_H
|
||||
#define __OMAP2_DSS_H
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
|
||||
#define DEBUG
|
||||
#endif
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
extern bool dss_debug;
|
||||
#ifdef DSS_SUBSYS_NAME
|
||||
#define DSSDBG(format, ...) \
|
||||
if (dss_debug) \
|
||||
printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
|
||||
## __VA_ARGS__)
|
||||
#else
|
||||
#define DSSDBG(format, ...) \
|
||||
if (dss_debug) \
|
||||
printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
|
||||
#ifdef pr_fmt
|
||||
#undef pr_fmt
|
||||
#endif
|
||||
|
||||
#ifdef DSS_SUBSYS_NAME
|
||||
#define DSSDBGF(format, ...) \
|
||||
if (dss_debug) \
|
||||
printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
|
||||
": %s(" format ")\n", \
|
||||
__func__, \
|
||||
## __VA_ARGS__)
|
||||
#define pr_fmt(fmt) DSS_SUBSYS_NAME ": " fmt
|
||||
#else
|
||||
#define DSSDBGF(format, ...) \
|
||||
if (dss_debug) \
|
||||
printk(KERN_DEBUG "omapdss: " \
|
||||
": %s(" format ")\n", \
|
||||
__func__, \
|
||||
## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#else /* DEBUG */
|
||||
#define DSSDBG(format, ...)
|
||||
#define DSSDBGF(format, ...)
|
||||
#define pr_fmt(fmt) fmt
|
||||
#endif
|
||||
|
||||
#define DSSDBG(format, ...) \
|
||||
pr_debug(format, ## __VA_ARGS__)
|
||||
|
||||
#ifdef DSS_SUBSYS_NAME
|
||||
#define DSSERR(format, ...) \
|
||||
@ -186,11 +162,10 @@ struct seq_file;
|
||||
struct platform_device;
|
||||
|
||||
/* core */
|
||||
const char *dss_get_default_display_name(void);
|
||||
struct platform_device *dss_get_core_pdev(void);
|
||||
struct bus_type *dss_get_bus(void);
|
||||
struct regulator *dss_get_vdds_dsi(void);
|
||||
struct regulator *dss_get_vdds_sdi(void);
|
||||
int dss_get_ctx_loss_count(struct device *dev);
|
||||
int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
|
||||
void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
|
||||
int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
|
||||
@ -204,55 +179,18 @@ void dss_put_device(struct omap_dss_device *dssdev);
|
||||
void dss_copy_device_pdata(struct omap_dss_device *dst,
|
||||
const struct omap_dss_device *src);
|
||||
|
||||
/* apply */
|
||||
void dss_apply_init(void);
|
||||
int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr);
|
||||
int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
|
||||
void dss_mgr_start_update(struct omap_overlay_manager *mgr);
|
||||
int omap_dss_mgr_apply(struct omap_overlay_manager *mgr);
|
||||
|
||||
int dss_mgr_enable(struct omap_overlay_manager *mgr);
|
||||
void dss_mgr_disable(struct omap_overlay_manager *mgr);
|
||||
int dss_mgr_set_info(struct omap_overlay_manager *mgr,
|
||||
struct omap_overlay_manager_info *info);
|
||||
void dss_mgr_get_info(struct omap_overlay_manager *mgr,
|
||||
struct omap_overlay_manager_info *info);
|
||||
int dss_mgr_set_device(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_device *dssdev);
|
||||
int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
|
||||
int dss_mgr_set_output(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_output *output);
|
||||
int dss_mgr_unset_output(struct omap_overlay_manager *mgr);
|
||||
void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
|
||||
const struct omap_video_timings *timings);
|
||||
void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
|
||||
const struct dss_lcd_mgr_config *config);
|
||||
const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
|
||||
|
||||
bool dss_ovl_is_enabled(struct omap_overlay *ovl);
|
||||
int dss_ovl_enable(struct omap_overlay *ovl);
|
||||
int dss_ovl_disable(struct omap_overlay *ovl);
|
||||
int dss_ovl_set_info(struct omap_overlay *ovl,
|
||||
struct omap_overlay_info *info);
|
||||
void dss_ovl_get_info(struct omap_overlay *ovl,
|
||||
struct omap_overlay_info *info);
|
||||
int dss_ovl_set_manager(struct omap_overlay *ovl,
|
||||
struct omap_overlay_manager *mgr);
|
||||
int dss_ovl_unset_manager(struct omap_overlay *ovl);
|
||||
|
||||
/* output */
|
||||
void dss_register_output(struct omap_dss_output *out);
|
||||
void dss_unregister_output(struct omap_dss_output *out);
|
||||
struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev);
|
||||
|
||||
/* display */
|
||||
int dss_suspend_all_devices(void);
|
||||
int dss_resume_all_devices(void);
|
||||
void dss_disable_all_devices(void);
|
||||
|
||||
int dss_init_device(struct platform_device *pdev,
|
||||
int display_init_sysfs(struct platform_device *pdev,
|
||||
struct omap_dss_device *dssdev);
|
||||
void dss_uninit_device(struct platform_device *pdev,
|
||||
void display_uninit_sysfs(struct platform_device *pdev,
|
||||
struct omap_dss_device *dssdev);
|
||||
|
||||
/* manager */
|
||||
@ -299,21 +237,23 @@ void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
|
||||
int dss_init_platform_driver(void) __init;
|
||||
void dss_uninit_platform_driver(void);
|
||||
|
||||
unsigned long dss_get_dispc_clk_rate(void);
|
||||
int dss_dpi_select_source(enum omap_channel channel);
|
||||
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
|
||||
enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
|
||||
const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
|
||||
void dss_dump_clocks(struct seq_file *s);
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
|
||||
#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
|
||||
void dss_debug_dump_clocks(struct seq_file *s);
|
||||
#endif
|
||||
|
||||
int dss_get_ctx_loss_count(void);
|
||||
|
||||
void dss_sdi_init(int datapairs);
|
||||
int dss_sdi_enable(void);
|
||||
void dss_sdi_disable(void);
|
||||
|
||||
void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src);
|
||||
void dss_select_dsi_clk_source(int dsi_module,
|
||||
enum omap_dss_clk_source clk_src);
|
||||
void dss_select_lcd_clk_source(enum omap_channel channel,
|
||||
@ -326,6 +266,7 @@ void dss_set_venc_output(enum omap_dss_venc_type type);
|
||||
void dss_set_dac_pwrdn_bgz(bool enable);
|
||||
|
||||
unsigned long dss_get_dpll4_rate(void);
|
||||
int dss_calc_clock_rates(struct dss_clock_info *cinfo);
|
||||
int dss_set_clock_div(struct dss_clock_info *cinfo);
|
||||
int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
|
||||
struct dispc_clock_info *dispc_cinfo);
|
||||
@ -413,8 +354,6 @@ static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
|
||||
}
|
||||
static inline struct platform_device *dsi_get_dsidev_from_id(int module)
|
||||
{
|
||||
WARN("%s: DSI not compiled in, returning platform device as NULL\n",
|
||||
__func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
@ -427,15 +366,10 @@ void dpi_uninit_platform_driver(void) __exit;
|
||||
int dispc_init_platform_driver(void) __init;
|
||||
void dispc_uninit_platform_driver(void) __exit;
|
||||
void dispc_dump_clocks(struct seq_file *s);
|
||||
void dispc_irq_handler(void);
|
||||
|
||||
int dispc_runtime_get(void);
|
||||
void dispc_runtime_put(void);
|
||||
|
||||
void dispc_enable_sidle(void);
|
||||
void dispc_disable_sidle(void);
|
||||
|
||||
void dispc_lcd_enable_signal_polarity(bool act_high);
|
||||
void dispc_lcd_enable_signal(bool enable);
|
||||
void dispc_pck_free_enable(bool enable);
|
||||
void dispc_enable_fifomerge(bool enable);
|
||||
@ -455,36 +389,14 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
|
||||
void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
|
||||
u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
|
||||
bool manual_update);
|
||||
int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
|
||||
bool replication, const struct omap_video_timings *mgr_timings,
|
||||
bool mem_to_mem);
|
||||
int dispc_ovl_enable(enum omap_plane plane, bool enable);
|
||||
void dispc_ovl_set_channel_out(enum omap_plane plane,
|
||||
enum omap_channel channel);
|
||||
|
||||
void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
|
||||
u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
|
||||
u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
|
||||
bool dispc_mgr_go_busy(enum omap_channel channel);
|
||||
void dispc_mgr_go(enum omap_channel channel);
|
||||
bool dispc_mgr_is_enabled(enum omap_channel channel);
|
||||
void dispc_mgr_enable(enum omap_channel channel, bool enable);
|
||||
bool dispc_mgr_is_channel_enabled(enum omap_channel channel);
|
||||
void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode);
|
||||
void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
|
||||
void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
|
||||
void dispc_mgr_set_lcd_type_tft(enum omap_channel channel);
|
||||
void dispc_mgr_set_timings(enum omap_channel channel,
|
||||
struct omap_video_timings *timings);
|
||||
unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
|
||||
unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
|
||||
unsigned long dispc_core_clk_rate(void);
|
||||
void dispc_mgr_set_clock_div(enum omap_channel channel,
|
||||
struct dispc_clock_info *cinfo);
|
||||
const struct dispc_clock_info *cinfo);
|
||||
int dispc_mgr_get_clock_div(enum omap_channel channel,
|
||||
struct dispc_clock_info *cinfo);
|
||||
void dispc_mgr_setup(enum omap_channel channel,
|
||||
struct omap_overlay_manager_info *info);
|
||||
|
||||
u32 dispc_wb_get_framedone_irq(void);
|
||||
bool dispc_wb_go_busy(void);
|
||||
@ -536,6 +448,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)
|
||||
#endif
|
||||
int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
|
||||
void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
|
||||
int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev);
|
||||
void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev);
|
||||
void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
|
||||
|
@ -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);
|
||||
|
@ -60,6 +60,7 @@
|
||||
static struct {
|
||||
struct mutex lock;
|
||||
struct platform_device *pdev;
|
||||
|
||||
struct hdmi_ip_data ip_data;
|
||||
|
||||
struct clk *sys_clk;
|
||||
@ -295,6 +296,12 @@ static const struct hdmi_config vesa_timings[] = {
|
||||
false, },
|
||||
{ 0x55, HDMI_DVI },
|
||||
},
|
||||
{
|
||||
{ 1920, 1200, 154000, 32, 48, 80, 6, 3, 26,
|
||||
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
|
||||
false, },
|
||||
{ 0x44, HDMI_DVI },
|
||||
},
|
||||
};
|
||||
|
||||
static int hdmi_runtime_get(void)
|
||||
@ -323,7 +330,6 @@ static void hdmi_runtime_put(void)
|
||||
|
||||
static int __init hdmi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = hdmi.pdev->dev.platform_data;
|
||||
int r;
|
||||
|
||||
struct gpio gpios[] = {
|
||||
@ -334,13 +340,17 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
|
||||
|
||||
DSSDBG("init_display\n");
|
||||
|
||||
dss_init_hdmi_ip_ops(&hdmi.ip_data, pdata->version);
|
||||
dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
|
||||
|
||||
if (hdmi.vdda_hdmi_dac_reg == NULL) {
|
||||
struct regulator *reg;
|
||||
|
||||
reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
|
||||
|
||||
/* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */
|
||||
if (IS_ERR(reg))
|
||||
reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC");
|
||||
|
||||
if (IS_ERR(reg)) {
|
||||
DSSERR("can't get VDDA_HDMI_DAC regulator\n");
|
||||
return PTR_ERR(reg);
|
||||
@ -356,7 +366,7 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev)
|
||||
static void hdmi_uninit_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("uninit_display\n");
|
||||
|
||||
@ -399,7 +409,8 @@ static bool hdmi_timings_compare(struct omap_video_timings *timing1,
|
||||
{
|
||||
int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
|
||||
|
||||
if ((timing2->pixel_clock == timing1->pixel_clock) &&
|
||||
if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) ==
|
||||
DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) &&
|
||||
(timing2->x_res == timing1->x_res) &&
|
||||
(timing2->y_res == timing1->y_res)) {
|
||||
|
||||
@ -501,12 +512,9 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
|
||||
DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
|
||||
}
|
||||
|
||||
static int hdmi_power_on(struct omap_dss_device *dssdev)
|
||||
static int hdmi_power_on_core(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
struct omap_video_timings *p;
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
unsigned long phy;
|
||||
|
||||
gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
|
||||
gpio_set_value(hdmi.ls_oe_gpio, 1);
|
||||
@ -522,6 +530,38 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
|
||||
if (r)
|
||||
goto err_runtime_get;
|
||||
|
||||
/* Make selection of HDMI in DSS */
|
||||
dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
|
||||
|
||||
return 0;
|
||||
|
||||
err_runtime_get:
|
||||
regulator_disable(hdmi.vdda_hdmi_dac_reg);
|
||||
err_vdac_enable:
|
||||
gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
|
||||
gpio_set_value(hdmi.ls_oe_gpio, 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void hdmi_power_off_core(struct omap_dss_device *dssdev)
|
||||
{
|
||||
hdmi_runtime_put();
|
||||
regulator_disable(hdmi.vdda_hdmi_dac_reg);
|
||||
gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
|
||||
gpio_set_value(hdmi.ls_oe_gpio, 0);
|
||||
}
|
||||
|
||||
static int hdmi_power_on_full(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
struct omap_video_timings *p;
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
unsigned long phy;
|
||||
|
||||
r = hdmi_power_on_core(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dss_mgr_disable(mgr);
|
||||
|
||||
p = &hdmi.ip_data.cfg.timings;
|
||||
@ -549,17 +589,6 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
|
||||
|
||||
hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
|
||||
|
||||
/* Make selection of HDMI in DSS */
|
||||
dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
|
||||
|
||||
/* Select the dispc clock source as PRCM clock, to ensure that it is not
|
||||
* DSI PLL source as the clock selected by DSI PLL might not be
|
||||
* sufficient for the resolution selected / that can be changed
|
||||
* dynamically by user. This can be moved to single location , say
|
||||
* Boardfile.
|
||||
*/
|
||||
dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
|
||||
|
||||
/* bypass TV gamma table */
|
||||
dispc_enable_gamma_table(0);
|
||||
|
||||
@ -583,16 +612,11 @@ err_vid_enable:
|
||||
err_phy_enable:
|
||||
hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
|
||||
err_pll_enable:
|
||||
hdmi_runtime_put();
|
||||
err_runtime_get:
|
||||
regulator_disable(hdmi.vdda_hdmi_dac_reg);
|
||||
err_vdac_enable:
|
||||
gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
|
||||
gpio_set_value(hdmi.ls_oe_gpio, 0);
|
||||
hdmi_power_off_core(dssdev);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static void hdmi_power_off(struct omap_dss_device *dssdev)
|
||||
static void hdmi_power_off_full(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
|
||||
@ -601,12 +625,8 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
|
||||
hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
|
||||
hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
|
||||
hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
|
||||
hdmi_runtime_put();
|
||||
|
||||
regulator_disable(hdmi.vdda_hdmi_dac_reg);
|
||||
|
||||
gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
|
||||
gpio_set_value(hdmi.ls_oe_gpio, 0);
|
||||
hdmi_power_off_core(dssdev);
|
||||
}
|
||||
|
||||
int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
|
||||
@ -716,7 +736,7 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
|
||||
goto err0;
|
||||
}
|
||||
|
||||
r = hdmi_power_on(dssdev);
|
||||
r = hdmi_power_on_full(dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to power on device\n");
|
||||
goto err1;
|
||||
@ -738,13 +758,48 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
|
||||
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
hdmi_power_off(dssdev);
|
||||
hdmi_power_off_full(dssdev);
|
||||
|
||||
omap_dss_stop_device(dssdev);
|
||||
|
||||
mutex_unlock(&hdmi.lock);
|
||||
}
|
||||
|
||||
int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
DSSDBG("ENTER omapdss_hdmi_core_enable\n");
|
||||
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
|
||||
|
||||
r = hdmi_power_on_core(dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to power on device\n");
|
||||
goto err0;
|
||||
}
|
||||
|
||||
mutex_unlock(&hdmi.lock);
|
||||
return 0;
|
||||
|
||||
err0:
|
||||
mutex_unlock(&hdmi.lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("Enter omapdss_hdmi_core_disable\n");
|
||||
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
hdmi_power_off_core(dssdev);
|
||||
|
||||
mutex_unlock(&hdmi.lock);
|
||||
}
|
||||
|
||||
static int hdmi_get_clocks(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *clk;
|
||||
@ -913,7 +968,7 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
|
||||
static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
const char *def_disp_name = dss_get_default_display_name();
|
||||
const char *def_disp_name = omapdss_get_default_display_name();
|
||||
struct omap_dss_device *def_dssdev;
|
||||
int i;
|
||||
|
||||
@ -971,9 +1026,19 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
|
||||
return;
|
||||
}
|
||||
|
||||
r = omapdss_output_set_device(&hdmi.output, dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to connect output to new device: %s\n",
|
||||
dssdev->name);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
||||
r = dss_add_device(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s register failed: %d\n", dssdev->name, r);
|
||||
omapdss_output_unset_device(&hdmi.output);
|
||||
hdmi_uninit_display(dssdev);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
@ -1000,22 +1065,22 @@ static void __exit hdmi_uninit_output(struct platform_device *pdev)
|
||||
/* HDMI HW IP initialisation */
|
||||
static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *hdmi_mem;
|
||||
struct resource *res;
|
||||
int r;
|
||||
|
||||
hdmi.pdev = pdev;
|
||||
|
||||
mutex_init(&hdmi.lock);
|
||||
mutex_init(&hdmi.ip_data.lock);
|
||||
|
||||
hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
|
||||
if (!hdmi_mem) {
|
||||
res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
DSSERR("can't get IORESOURCE_MEM HDMI\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Base address taken from platform */
|
||||
hdmi.ip_data.base_wp = ioremap(hdmi_mem->start,
|
||||
resource_size(hdmi_mem));
|
||||
hdmi.ip_data.base_wp = devm_request_and_ioremap(&pdev->dev, res);
|
||||
if (!hdmi.ip_data.base_wp) {
|
||||
DSSERR("can't ioremap WP\n");
|
||||
return -ENOMEM;
|
||||
@ -1023,7 +1088,7 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
|
||||
|
||||
r = hdmi_get_clocks(pdev);
|
||||
if (r) {
|
||||
iounmap(hdmi.ip_data.base_wp);
|
||||
DSSERR("can't get clocks\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -1034,9 +1099,11 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
|
||||
hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
|
||||
hdmi.ip_data.phy_offset = HDMI_PHY;
|
||||
|
||||
mutex_init(&hdmi.ip_data.lock);
|
||||
|
||||
hdmi_panel_init();
|
||||
r = hdmi_panel_init();
|
||||
if (r) {
|
||||
DSSERR("can't init panel\n");
|
||||
goto err_panel_init;
|
||||
}
|
||||
|
||||
dss_debugfs_create_file("hdmi", hdmi_dump_regs);
|
||||
|
||||
@ -1045,6 +1112,10 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
|
||||
hdmi_probe_pdata(pdev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_panel_init:
|
||||
hdmi_put_clocks();
|
||||
return r;
|
||||
}
|
||||
|
||||
static int __exit hdmi_remove_child(struct device *dev, void *data)
|
||||
@ -1068,8 +1139,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
|
||||
|
||||
hdmi_put_clocks();
|
||||
|
||||
iounmap(hdmi.ip_data.base_wp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -280,58 +280,6 @@ static void hdmi_panel_disable(struct omap_dss_device *dssdev)
|
||||
mutex_unlock(&hdmi.lock);
|
||||
}
|
||||
|
||||
static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: notify audio users that the display was suspended. For now,
|
||||
* disable audio locally to not break our audio state machine.
|
||||
*/
|
||||
hdmi_panel_audio_disable(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
omapdss_hdmi_display_disable(dssdev);
|
||||
|
||||
err:
|
||||
mutex_unlock(&hdmi.lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int hdmi_panel_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = omapdss_hdmi_display_enable(dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to power on\n");
|
||||
goto err;
|
||||
}
|
||||
/* TODO: notify audio users that the panel resumed. */
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
err:
|
||||
mutex_unlock(&hdmi.lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void hdmi_get_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
@ -379,20 +327,22 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
|
||||
static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
|
||||
{
|
||||
int r;
|
||||
bool need_enable;
|
||||
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
r = omapdss_hdmi_display_enable(dssdev);
|
||||
need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED;
|
||||
|
||||
if (need_enable) {
|
||||
r = omapdss_hdmi_core_enable(dssdev);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = omapdss_hdmi_read_edid(buf, len);
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
|
||||
dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
|
||||
omapdss_hdmi_display_disable(dssdev);
|
||||
if (need_enable)
|
||||
omapdss_hdmi_core_disable(dssdev);
|
||||
err:
|
||||
mutex_unlock(&hdmi.lock);
|
||||
|
||||
@ -402,20 +352,22 @@ err:
|
||||
static bool hdmi_detect(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
bool need_enable;
|
||||
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
r = omapdss_hdmi_display_enable(dssdev);
|
||||
need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED;
|
||||
|
||||
if (need_enable) {
|
||||
r = omapdss_hdmi_core_enable(dssdev);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = omapdss_hdmi_detect();
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
|
||||
dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
|
||||
omapdss_hdmi_display_disable(dssdev);
|
||||
if (need_enable)
|
||||
omapdss_hdmi_core_disable(dssdev);
|
||||
err:
|
||||
mutex_unlock(&hdmi.lock);
|
||||
|
||||
@ -427,8 +379,6 @@ static struct omap_dss_driver hdmi_driver = {
|
||||
.remove = hdmi_panel_remove,
|
||||
.enable = hdmi_panel_enable,
|
||||
.disable = hdmi_panel_disable,
|
||||
.suspend = hdmi_panel_suspend,
|
||||
.resume = hdmi_panel_resume,
|
||||
.get_timings = hdmi_get_timings,
|
||||
.set_timings = hdmi_set_timings,
|
||||
.check_timings = hdmi_check_timings,
|
||||
@ -454,9 +404,7 @@ int hdmi_panel_init(void)
|
||||
spin_lock_init(&hdmi.audio_lock);
|
||||
#endif
|
||||
|
||||
omap_dss_register_driver(&hdmi_driver);
|
||||
|
||||
return 0;
|
||||
return omap_dss_register_driver(&hdmi_driver);
|
||||
}
|
||||
|
||||
void hdmi_panel_exit(void)
|
||||
|
@ -36,36 +36,6 @@
|
||||
static int num_managers;
|
||||
static struct omap_overlay_manager *managers;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int dss_init_overlay_managers(struct platform_device *pdev)
|
||||
{
|
||||
int i, r;
|
||||
@ -99,15 +69,6 @@ int dss_init_overlay_managers(struct platform_device *pdev)
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
mgr->caps = 0;
|
||||
mgr->supported_displays =
|
||||
dss_feat_get_supported_displays(mgr->id);
|
||||
|
@ -114,35 +114,67 @@ struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev)
|
||||
static const struct dss_mgr_ops *dss_mgr_ops;
|
||||
|
||||
int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops)
|
||||
{
|
||||
struct omap_dss_output *out = NULL;
|
||||
enum omap_dss_output_id id;
|
||||
if (dss_mgr_ops)
|
||||
return -EBUSY;
|
||||
|
||||
switch (dssdev->type) {
|
||||
case OMAP_DISPLAY_TYPE_DPI:
|
||||
out = omap_dss_get_output(OMAP_DSS_OUTPUT_DPI);
|
||||
break;
|
||||
case OMAP_DISPLAY_TYPE_DBI:
|
||||
out = omap_dss_get_output(OMAP_DSS_OUTPUT_DBI);
|
||||
break;
|
||||
case OMAP_DISPLAY_TYPE_SDI:
|
||||
out = omap_dss_get_output(OMAP_DSS_OUTPUT_SDI);
|
||||
break;
|
||||
case OMAP_DISPLAY_TYPE_VENC:
|
||||
out = omap_dss_get_output(OMAP_DSS_OUTPUT_VENC);
|
||||
break;
|
||||
case OMAP_DISPLAY_TYPE_HDMI:
|
||||
out = omap_dss_get_output(OMAP_DSS_OUTPUT_HDMI);
|
||||
break;
|
||||
case OMAP_DISPLAY_TYPE_DSI:
|
||||
id = dssdev->phy.dsi.module == 0 ? OMAP_DSS_OUTPUT_DSI1 :
|
||||
OMAP_DSS_OUTPUT_DSI2;
|
||||
out = omap_dss_get_output(id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dss_mgr_ops = mgr_ops;
|
||||
|
||||
return out;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dss_install_mgr_ops);
|
||||
|
||||
void dss_uninstall_mgr_ops(void)
|
||||
{
|
||||
dss_mgr_ops = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(dss_uninstall_mgr_ops);
|
||||
|
||||
void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
|
||||
const struct omap_video_timings *timings)
|
||||
{
|
||||
dss_mgr_ops->set_timings(mgr, timings);
|
||||
}
|
||||
EXPORT_SYMBOL(dss_mgr_set_timings);
|
||||
|
||||
void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
|
||||
const struct dss_lcd_mgr_config *config)
|
||||
{
|
||||
dss_mgr_ops->set_lcd_config(mgr, config);
|
||||
}
|
||||
EXPORT_SYMBOL(dss_mgr_set_lcd_config);
|
||||
|
||||
int dss_mgr_enable(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
return dss_mgr_ops->enable(mgr);
|
||||
}
|
||||
EXPORT_SYMBOL(dss_mgr_enable);
|
||||
|
||||
void dss_mgr_disable(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
dss_mgr_ops->disable(mgr);
|
||||
}
|
||||
EXPORT_SYMBOL(dss_mgr_disable);
|
||||
|
||||
void dss_mgr_start_update(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
dss_mgr_ops->start_update(mgr);
|
||||
}
|
||||
EXPORT_SYMBOL(dss_mgr_start_update);
|
||||
|
||||
int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
|
||||
void (*handler)(void *), void *data)
|
||||
{
|
||||
return dss_mgr_ops->register_framedone_handler(mgr, handler, data);
|
||||
}
|
||||
EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
|
||||
|
||||
void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
|
||||
void (*handler)(void *), void *data)
|
||||
{
|
||||
dss_mgr_ops->unregister_framedone_handler(mgr, handler, data);
|
||||
}
|
||||
EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);
|
||||
|
@ -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);
|
||||
|
@ -342,7 +342,7 @@ static int rfbi_transfer_area(struct omap_dss_device *dssdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void framedone_callback(void *data, u32 mask)
|
||||
static void framedone_callback(void *data)
|
||||
{
|
||||
void (*callback)(void *data);
|
||||
|
||||
@ -908,8 +908,8 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
|
||||
goto err0;
|
||||
}
|
||||
|
||||
r = omap_dispc_register_isr(framedone_callback, NULL,
|
||||
DISPC_IRQ_FRAMEDONE);
|
||||
r = dss_mgr_register_framedone_handler(out->manager,
|
||||
framedone_callback, NULL);
|
||||
if (r) {
|
||||
DSSERR("can't get FRAMEDONE irq\n");
|
||||
goto err1;
|
||||
@ -933,8 +933,10 @@ EXPORT_SYMBOL(omapdss_rfbi_display_enable);
|
||||
|
||||
void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
omap_dispc_unregister_isr(framedone_callback, NULL,
|
||||
DISPC_IRQ_FRAMEDONE);
|
||||
struct omap_dss_output *out = dssdev->output;
|
||||
|
||||
dss_mgr_unregister_framedone_handler(out->manager,
|
||||
framedone_callback, NULL);
|
||||
omap_dss_stop_device(dssdev);
|
||||
|
||||
rfbi_runtime_put();
|
||||
@ -950,7 +952,7 @@ static int __init rfbi_init_display(struct omap_dss_device *dssdev)
|
||||
static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
const char *def_disp_name = dss_get_default_display_name();
|
||||
const char *def_disp_name = omapdss_get_default_display_name();
|
||||
struct omap_dss_device *def_dssdev;
|
||||
int i;
|
||||
|
||||
@ -999,9 +1001,18 @@ static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
|
||||
return;
|
||||
}
|
||||
|
||||
r = omapdss_output_set_device(&rfbi.output, dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to connect output to new device: %s\n",
|
||||
dssdev->name);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
||||
r = dss_add_device(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s register failed: %d\n", dssdev->name, r);
|
||||
omapdss_output_unset_device(&rfbi.output);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
|
||||
static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
const char *def_disp_name = dss_get_default_display_name();
|
||||
const char *def_disp_name = omapdss_get_default_display_name();
|
||||
struct omap_dss_device *def_dssdev;
|
||||
int i;
|
||||
|
||||
@ -254,9 +254,18 @@ static void __init sdi_probe_pdata(struct platform_device *sdidev)
|
||||
return;
|
||||
}
|
||||
|
||||
r = omapdss_output_set_device(&sdi.output, dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to connect output to new device: %s\n",
|
||||
dssdev->name);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
||||
r = dss_add_device(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s register failed: %d\n", dssdev->name, r);
|
||||
omapdss_output_unset_device(&sdi.output);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
@ -102,6 +102,8 @@ struct ti_hdmi_ip_ops {
|
||||
|
||||
int (*audio_config)(struct hdmi_ip_data *ip_data,
|
||||
struct omap_dss_audio *audio);
|
||||
|
||||
int (*audio_get_dma_port)(u32 *offset, u32 *size);
|
||||
#endif
|
||||
|
||||
};
|
||||
@ -183,5 +185,6 @@ int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data);
|
||||
void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data);
|
||||
int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
|
||||
struct omap_dss_audio *audio);
|
||||
int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -899,7 +899,7 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
|
||||
#define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\
|
||||
hdmi_read_reg(hdmi_av_base(ip_data), r))
|
||||
#define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
|
||||
(i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \
|
||||
(i < 10) ? 32 - (int)strlen(#r) : 31 - (int)strlen(#r), " ", \
|
||||
hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r)))
|
||||
|
||||
DUMPCORE(HDMI_CORE_SYS_VND_IDL);
|
||||
@ -1418,4 +1418,13 @@ void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data)
|
||||
REG_FLD_MOD(hdmi_wp_base(ip_data),
|
||||
HDMI_WP_AUDIO_CTRL, false, 30, 30);
|
||||
}
|
||||
|
||||
int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size)
|
||||
{
|
||||
if (!offset || !size)
|
||||
return -EINVAL;
|
||||
*offset = HDMI_WP_AUDIO_DATA;
|
||||
*size = 4;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -744,7 +744,7 @@ static void venc_put_clocks(void)
|
||||
static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
const char *def_disp_name = dss_get_default_display_name();
|
||||
const char *def_disp_name = omapdss_get_default_display_name();
|
||||
struct omap_dss_device *def_dssdev;
|
||||
int i;
|
||||
|
||||
@ -795,9 +795,18 @@ static void __init venc_probe_pdata(struct platform_device *vencdev)
|
||||
return;
|
||||
}
|
||||
|
||||
r = omapdss_output_set_device(&venc.output, dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to connect output to new device: %s\n",
|
||||
dssdev->name);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
||||
r = dss_add_device(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s register failed: %d\n", dssdev->name, r);
|
||||
omapdss_output_unset_device(&venc.output);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
@ -157,12 +157,6 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
|
||||
goto end;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
|
||||
/* suspended is the same as disabled with venc */
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
goto end;
|
||||
}
|
||||
|
||||
omapdss_venc_display_disable(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
@ -170,17 +164,6 @@ end:
|
||||
mutex_unlock(&venc_panel.lock);
|
||||
}
|
||||
|
||||
static int venc_panel_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
venc_panel_disable(dssdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int venc_panel_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return venc_panel_enable(dssdev);
|
||||
}
|
||||
|
||||
static void venc_panel_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
@ -222,8 +205,6 @@ static struct omap_dss_driver venc_driver = {
|
||||
|
||||
.enable = venc_panel_enable,
|
||||
.disable = venc_panel_disable,
|
||||
.suspend = venc_panel_suspend,
|
||||
.resume = venc_panel_resume,
|
||||
|
||||
.get_resolution = omapdss_default_get_resolution,
|
||||
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
|
||||
|
@ -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
|
||||
|
@ -28,10 +28,10 @@
|
||||
#include <linux/omapfb.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omapvrfb.h>
|
||||
#include <plat/vram.h>
|
||||
|
||||
#include "omapfb.h"
|
||||
|
||||
@ -211,6 +211,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
|
||||
{
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_device *fbdev = ofbi->fbdev;
|
||||
struct omap_dss_device *display = fb2display(fbi);
|
||||
struct omapfb2_mem_region *rg;
|
||||
int r = 0, i;
|
||||
size_t size;
|
||||
@ -220,6 +221,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
|
||||
|
||||
size = PAGE_ALIGN(mi->size);
|
||||
|
||||
if (display && display->driver->sync)
|
||||
display->driver->sync(display);
|
||||
|
||||
rg = ofbi->region;
|
||||
|
||||
down_write_nested(&rg->lock, rg->id);
|
||||
@ -279,7 +283,7 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omapfb_update_window_nolock(struct fb_info *fbi,
|
||||
static int omapfb_update_window(struct fb_info *fbi,
|
||||
u32 x, u32 y, u32 w, u32 h)
|
||||
{
|
||||
struct omap_dss_device *display = fb2display(fbi);
|
||||
@ -299,27 +303,6 @@ static int omapfb_update_window_nolock(struct fb_info *fbi,
|
||||
return display->driver->update(display, x, y, w, h);
|
||||
}
|
||||
|
||||
/* This function is exported for SGX driver use */
|
||||
int omapfb_update_window(struct fb_info *fbi,
|
||||
u32 x, u32 y, u32 w, u32 h)
|
||||
{
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_device *fbdev = ofbi->fbdev;
|
||||
int r;
|
||||
|
||||
if (!lock_fb_info(fbi))
|
||||
return -ENODEV;
|
||||
omapfb_lock(fbdev);
|
||||
|
||||
r = omapfb_update_window_nolock(fbi, x, y, w, h);
|
||||
|
||||
omapfb_unlock(fbdev);
|
||||
unlock_fb_info(fbi);
|
||||
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(omapfb_update_window);
|
||||
|
||||
int omapfb_set_update_mode(struct fb_info *fbi,
|
||||
enum omapfb_update_mode mode)
|
||||
{
|
||||
@ -646,7 +629,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
||||
break;
|
||||
}
|
||||
|
||||
r = omapfb_update_window_nolock(fbi, p.uwnd_o.x, p.uwnd_o.y,
|
||||
r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
|
||||
p.uwnd_o.width, p.uwnd_o.height);
|
||||
break;
|
||||
|
||||
@ -663,7 +646,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
||||
break;
|
||||
}
|
||||
|
||||
r = omapfb_update_window_nolock(fbi, p.uwnd.x, p.uwnd.y,
|
||||
r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
|
||||
p.uwnd.width, p.uwnd.height);
|
||||
break;
|
||||
|
||||
@ -853,14 +836,15 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
||||
break;
|
||||
|
||||
case OMAPFB_GET_VRAM_INFO: {
|
||||
unsigned long vram, free, largest;
|
||||
|
||||
DBG("ioctl GET_VRAM_INFO\n");
|
||||
|
||||
omap_vram_get_info(&vram, &free, &largest);
|
||||
p.vram_info.total = vram;
|
||||
p.vram_info.free = free;
|
||||
p.vram_info.largest_free_block = largest;
|
||||
/*
|
||||
* We don't have the ability to get this vram info anymore.
|
||||
* Fill in something that should keep the applications working.
|
||||
*/
|
||||
p.vram_info.total = SZ_1M * 64;
|
||||
p.vram_info.free = SZ_1M * 64;
|
||||
p.vram_info.largest_free_block = SZ_1M * 64;
|
||||
|
||||
if (copy_to_user((void __user *)arg, &p.vram_info,
|
||||
sizeof(p.vram_info)))
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include <linux/omapfb.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <plat/vram.h>
|
||||
#include <video/omapvrfb.h>
|
||||
|
||||
#include "omapfb.h"
|
||||
@ -1258,11 +1257,10 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
|
||||
|
||||
switch (blank) {
|
||||
case FB_BLANK_UNBLANK:
|
||||
if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
|
||||
if (display->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
goto exit;
|
||||
|
||||
if (display->driver->resume)
|
||||
r = display->driver->resume(display);
|
||||
r = display->driver->enable(display);
|
||||
|
||||
if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
|
||||
d->update_mode == OMAPFB_AUTO_UPDATE &&
|
||||
@ -1283,8 +1281,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
|
||||
if (d->auto_update_work_enabled)
|
||||
omapfb_stop_auto_update(fbdev, display);
|
||||
|
||||
if (display->driver->suspend)
|
||||
r = display->driver->suspend(display);
|
||||
display->driver->disable(display);
|
||||
|
||||
break;
|
||||
|
||||
@ -1335,24 +1332,25 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
|
||||
|
||||
rg = ofbi->region;
|
||||
|
||||
if (rg->token == NULL)
|
||||
return;
|
||||
|
||||
WARN_ON(atomic_read(&rg->map_count));
|
||||
|
||||
if (rg->paddr)
|
||||
if (omap_vram_free(rg->paddr, rg->size))
|
||||
dev_err(fbdev->dev, "VRAM FREE failed\n");
|
||||
|
||||
if (rg->vaddr)
|
||||
iounmap(rg->vaddr);
|
||||
|
||||
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
|
||||
/* unmap the 0 angle rotation */
|
||||
if (rg->vrfb.vaddr[0]) {
|
||||
iounmap(rg->vrfb.vaddr[0]);
|
||||
omap_vrfb_release_ctx(&rg->vrfb);
|
||||
rg->vrfb.vaddr[0] = NULL;
|
||||
}
|
||||
|
||||
omap_vrfb_release_ctx(&rg->vrfb);
|
||||
}
|
||||
|
||||
dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle,
|
||||
&rg->attrs);
|
||||
|
||||
rg->token = NULL;
|
||||
rg->vaddr = NULL;
|
||||
rg->paddr = 0;
|
||||
rg->alloc = 0;
|
||||
@ -1387,7 +1385,9 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_device *fbdev = ofbi->fbdev;
|
||||
struct omapfb2_mem_region *rg;
|
||||
void __iomem *vaddr;
|
||||
void *token;
|
||||
DEFINE_DMA_ATTRS(attrs);
|
||||
dma_addr_t dma_handle;
|
||||
int r;
|
||||
|
||||
rg = ofbi->region;
|
||||
@ -1402,42 +1402,40 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
|
||||
if (!paddr) {
|
||||
DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
|
||||
r = omap_vram_alloc(size, &paddr);
|
||||
} else {
|
||||
DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
|
||||
ofbi->id);
|
||||
r = omap_vram_reserve(paddr, size);
|
||||
}
|
||||
dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
|
||||
|
||||
if (r) {
|
||||
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
|
||||
dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
|
||||
|
||||
DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
|
||||
|
||||
token = dma_alloc_attrs(fbdev->dev, size, &dma_handle,
|
||||
GFP_KERNEL, &attrs);
|
||||
|
||||
if (token == NULL) {
|
||||
dev_err(fbdev->dev, "failed to allocate framebuffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
|
||||
vaddr = ioremap_wc(paddr, size);
|
||||
DBG("allocated VRAM paddr %lx, vaddr %p\n",
|
||||
(unsigned long)dma_handle, token);
|
||||
|
||||
if (!vaddr) {
|
||||
dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
|
||||
omap_vram_free(paddr, size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
|
||||
} else {
|
||||
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
|
||||
r = omap_vrfb_request_ctx(&rg->vrfb);
|
||||
if (r) {
|
||||
dma_free_attrs(fbdev->dev, size, token, dma_handle,
|
||||
&attrs);
|
||||
dev_err(fbdev->dev, "vrfb create ctx failed\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
vaddr = NULL;
|
||||
}
|
||||
|
||||
rg->paddr = paddr;
|
||||
rg->vaddr = vaddr;
|
||||
rg->attrs = attrs;
|
||||
rg->token = token;
|
||||
rg->dma_handle = dma_handle;
|
||||
|
||||
rg->paddr = (unsigned long)dma_handle;
|
||||
rg->vaddr = (void __iomem *)token;
|
||||
rg->size = size;
|
||||
rg->alloc = 1;
|
||||
|
||||
@ -1531,6 +1529,9 @@ static int omapfb_parse_vram_param(const char *param, int max_entries,
|
||||
|
||||
}
|
||||
|
||||
WARN_ONCE(paddr,
|
||||
"reserving memory at predefined address not supported\n");
|
||||
|
||||
paddrs[fbnum] = paddr;
|
||||
sizes[fbnum] = size;
|
||||
|
||||
@ -1610,7 +1611,6 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
|
||||
{
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_device *fbdev = ofbi->fbdev;
|
||||
struct omap_dss_device *display = fb2display(fbi);
|
||||
struct omapfb2_mem_region *rg = ofbi->region;
|
||||
unsigned long old_size = rg->size;
|
||||
unsigned long old_paddr = rg->paddr;
|
||||
@ -1625,9 +1625,6 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
|
||||
if (old_size == size && old_type == type)
|
||||
return 0;
|
||||
|
||||
if (display && display->driver->sync)
|
||||
display->driver->sync(display);
|
||||
|
||||
omapfb_free_fbmem(fbi);
|
||||
|
||||
if (size == 0) {
|
||||
@ -1882,7 +1879,6 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
|
||||
}
|
||||
|
||||
dev_set_drvdata(fbdev->dev, NULL);
|
||||
kfree(fbdev);
|
||||
}
|
||||
|
||||
static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
|
||||
@ -2258,26 +2254,28 @@ static int omapfb_find_best_mode(struct omap_dss_device *display,
|
||||
{
|
||||
struct fb_monspecs *specs;
|
||||
u8 *edid;
|
||||
int r, i, best_xres, best_idx, len;
|
||||
int r, i, best_idx, len;
|
||||
|
||||
if (!display->driver->read_edid)
|
||||
return -ENODEV;
|
||||
|
||||
len = 0x80 * 2;
|
||||
edid = kmalloc(len, GFP_KERNEL);
|
||||
if (edid == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
r = display->driver->read_edid(display, edid, len);
|
||||
if (r < 0)
|
||||
goto err1;
|
||||
|
||||
specs = kzalloc(sizeof(*specs), GFP_KERNEL);
|
||||
if (specs == NULL) {
|
||||
r = -ENOMEM;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
fb_edid_to_monspecs(edid, specs);
|
||||
|
||||
if (edid[126] > 0)
|
||||
fb_edid_add_monspecs(edid + 0x80, specs);
|
||||
|
||||
best_xres = 0;
|
||||
best_idx = -1;
|
||||
|
||||
for (i = 0; i < specs->modedb_len; ++i) {
|
||||
@ -2293,16 +2291,20 @@ static int omapfb_find_best_mode(struct omap_dss_device *display,
|
||||
if (m->xres == 2880 || m->xres == 1440)
|
||||
continue;
|
||||
|
||||
if (m->vmode & FB_VMODE_INTERLACED ||
|
||||
m->vmode & FB_VMODE_DOUBLE)
|
||||
continue;
|
||||
|
||||
fb_videomode_to_omap_timings(m, display, &t);
|
||||
|
||||
r = display->driver->check_timings(display, &t);
|
||||
if (r == 0 && best_xres < m->xres) {
|
||||
best_xres = m->xres;
|
||||
if (r == 0) {
|
||||
best_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_xres == 0) {
|
||||
if (best_idx == -1) {
|
||||
r = -ENOENT;
|
||||
goto err2;
|
||||
}
|
||||
@ -2371,15 +2373,62 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omapfb_init_connections(struct omapfb2_device *fbdev,
|
||||
struct omap_dss_device *def_dssdev)
|
||||
{
|
||||
int i, r;
|
||||
struct omap_overlay_manager *mgr;
|
||||
|
||||
if (!def_dssdev->output) {
|
||||
dev_err(fbdev->dev, "no output for the default display\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < fbdev->num_displays; ++i) {
|
||||
struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
|
||||
struct omap_dss_output *out = dssdev->output;
|
||||
|
||||
mgr = omap_dss_get_overlay_manager(dssdev->channel);
|
||||
|
||||
if (!mgr || !out)
|
||||
continue;
|
||||
|
||||
if (mgr->output)
|
||||
mgr->unset_output(mgr);
|
||||
|
||||
mgr->set_output(mgr, out);
|
||||
}
|
||||
|
||||
mgr = def_dssdev->output->manager;
|
||||
|
||||
if (!mgr) {
|
||||
dev_err(fbdev->dev, "no ovl manager for the default display\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < fbdev->num_overlays; i++) {
|
||||
struct omap_overlay *ovl = fbdev->overlays[i];
|
||||
|
||||
if (ovl->manager)
|
||||
ovl->unset_manager(ovl);
|
||||
|
||||
r = ovl->set_manager(ovl, mgr);
|
||||
if (r)
|
||||
dev_warn(fbdev->dev,
|
||||
"failed to connect overlay %s to manager %s\n",
|
||||
ovl->name, mgr->name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init omapfb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct omapfb2_device *fbdev = NULL;
|
||||
int r = 0;
|
||||
int i;
|
||||
struct omap_overlay *ovl;
|
||||
struct omap_dss_device *def_display;
|
||||
struct omap_dss_device *dssdev;
|
||||
struct omap_dss_device *ovl_device;
|
||||
|
||||
DBG("omapfb_probe\n");
|
||||
|
||||
@ -2389,7 +2438,8 @@ static int __init omapfb_probe(struct platform_device *pdev)
|
||||
goto err0;
|
||||
}
|
||||
|
||||
fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
|
||||
fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device),
|
||||
GFP_KERNEL);
|
||||
if (fbdev == NULL) {
|
||||
r = -ENOMEM;
|
||||
goto err0;
|
||||
@ -2401,13 +2451,15 @@ static int __init omapfb_probe(struct platform_device *pdev)
|
||||
"ignoring the module parameter vrfb=y\n");
|
||||
}
|
||||
|
||||
r = omapdss_compat_init();
|
||||
if (r)
|
||||
goto err0;
|
||||
|
||||
mutex_init(&fbdev->mtx);
|
||||
|
||||
fbdev->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, fbdev);
|
||||
|
||||
r = 0;
|
||||
fbdev->num_displays = 0;
|
||||
dssdev = NULL;
|
||||
for_each_dss_dev(dssdev) {
|
||||
@ -2430,9 +2482,6 @@ static int __init omapfb_probe(struct platform_device *pdev)
|
||||
d->update_mode = OMAPFB_AUTO_UPDATE;
|
||||
}
|
||||
|
||||
if (r)
|
||||
goto cleanup;
|
||||
|
||||
if (fbdev->num_displays == 0) {
|
||||
dev_err(&pdev->dev, "no displays\n");
|
||||
r = -EINVAL;
|
||||
@ -2447,15 +2496,33 @@ static int __init omapfb_probe(struct platform_device *pdev)
|
||||
for (i = 0; i < fbdev->num_managers; i++)
|
||||
fbdev->managers[i] = omap_dss_get_overlay_manager(i);
|
||||
|
||||
/* gfx overlay should be the default one. find a display
|
||||
* connected to that, and use it as default display */
|
||||
ovl = omap_dss_get_overlay(0);
|
||||
ovl_device = ovl->get_device(ovl);
|
||||
if (ovl_device) {
|
||||
def_display = ovl_device;
|
||||
} else {
|
||||
dev_warn(&pdev->dev, "cannot find default display\n");
|
||||
def_display = NULL;
|
||||
def_display = NULL;
|
||||
|
||||
for (i = 0; i < fbdev->num_displays; ++i) {
|
||||
struct omap_dss_device *dssdev;
|
||||
const char *def_name;
|
||||
|
||||
def_name = omapdss_get_default_display_name();
|
||||
|
||||
dssdev = fbdev->displays[i].dssdev;
|
||||
|
||||
if (def_name == NULL ||
|
||||
(dssdev->name && strcmp(def_name, dssdev->name) == 0)) {
|
||||
def_display = dssdev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (def_display == NULL) {
|
||||
dev_err(fbdev->dev, "failed to find default display\n");
|
||||
r = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
r = omapfb_init_connections(fbdev, def_display);
|
||||
if (r) {
|
||||
dev_err(fbdev->dev, "failed to init overlay connections\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (def_mode && strlen(def_mode) > 0) {
|
||||
@ -2506,6 +2573,7 @@ static int __init omapfb_probe(struct platform_device *pdev)
|
||||
|
||||
cleanup:
|
||||
omapfb_free_resources(fbdev);
|
||||
omapdss_compat_uninit();
|
||||
err0:
|
||||
dev_err(&pdev->dev, "failed to setup omapfb\n");
|
||||
return r;
|
||||
@ -2521,6 +2589,8 @@ static int __exit omapfb_remove(struct platform_device *pdev)
|
||||
|
||||
omapfb_free_resources(fbdev);
|
||||
|
||||
omapdss_compat_uninit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -441,6 +441,7 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
|
||||
struct fb_info *fbi = dev_get_drvdata(dev);
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_device *fbdev = ofbi->fbdev;
|
||||
struct omap_dss_device *display = fb2display(fbi);
|
||||
struct omapfb2_mem_region *rg;
|
||||
unsigned long size;
|
||||
int r;
|
||||
@ -455,6 +456,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
|
||||
if (!lock_fb_info(fbi))
|
||||
return -ENODEV;
|
||||
|
||||
if (display && display->driver->sync)
|
||||
display->driver->sync(display);
|
||||
|
||||
rg = ofbi->region;
|
||||
|
||||
down_write_nested(&rg->lock, rg->id);
|
||||
|
@ -28,6 +28,8 @@
|
||||
#endif
|
||||
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/dma-attrs.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
@ -49,6 +51,9 @@ extern bool omapfb_debug;
|
||||
|
||||
struct omapfb2_mem_region {
|
||||
int id;
|
||||
struct dma_attrs attrs;
|
||||
void *token;
|
||||
dma_addr_t dma_handle;
|
||||
u32 paddr;
|
||||
void __iomem *vaddr;
|
||||
struct vrfb vrfb;
|
||||
@ -124,9 +129,6 @@ void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
|
||||
|
||||
int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
|
||||
|
||||
int omapfb_update_window(struct fb_info *fbi,
|
||||
u32 x, u32 y, u32 w, u32 h);
|
||||
|
||||
int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
|
||||
struct fb_var_screeninfo *var);
|
||||
|
||||
@ -144,16 +146,16 @@ int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
|
||||
static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
|
||||
{
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
int i;
|
||||
struct omap_overlay *ovl;
|
||||
|
||||
/* XXX: returns the display connected to first attached overlay */
|
||||
for (i = 0; i < ofbi->num_overlays; i++) {
|
||||
struct omap_overlay *ovl = ofbi->overlays[i];
|
||||
|
||||
return ovl->get_device(ovl);
|
||||
}
|
||||
if (ofbi->num_overlays == 0)
|
||||
return NULL;
|
||||
|
||||
return NULL;
|
||||
ovl = ofbi->overlays[0];
|
||||
|
||||
return ovl->get_device(ovl);
|
||||
}
|
||||
|
||||
static inline struct omapfb_display_data *get_display_data(
|
||||
|
@ -1,514 +0,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.
|
||||
*/
|
||||
|
||||
/*#define DEBUG*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include <plat/vram.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
|
||||
#else
|
||||
#define DBG(format, ...)
|
||||
#endif
|
||||
|
||||
/* postponed regions are used to temporarily store region information at boot
|
||||
* time when we cannot yet allocate the region list */
|
||||
#define MAX_POSTPONED_REGIONS 10
|
||||
|
||||
static bool vram_initialized;
|
||||
static int postponed_cnt;
|
||||
static struct {
|
||||
unsigned long paddr;
|
||||
size_t size;
|
||||
} postponed_regions[MAX_POSTPONED_REGIONS];
|
||||
|
||||
struct vram_alloc {
|
||||
struct list_head list;
|
||||
unsigned long paddr;
|
||||
unsigned pages;
|
||||
};
|
||||
|
||||
struct vram_region {
|
||||
struct list_head list;
|
||||
struct list_head alloc_list;
|
||||
unsigned long paddr;
|
||||
unsigned pages;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(region_mutex);
|
||||
static LIST_HEAD(region_list);
|
||||
|
||||
static struct vram_region *omap_vram_create_region(unsigned long paddr,
|
||||
unsigned pages)
|
||||
{
|
||||
struct vram_region *rm;
|
||||
|
||||
rm = kzalloc(sizeof(*rm), GFP_KERNEL);
|
||||
|
||||
if (rm) {
|
||||
INIT_LIST_HEAD(&rm->alloc_list);
|
||||
rm->paddr = paddr;
|
||||
rm->pages = pages;
|
||||
}
|
||||
|
||||
return rm;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void omap_vram_free_region(struct vram_region *vr)
|
||||
{
|
||||
list_del(&vr->list);
|
||||
kfree(vr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
|
||||
unsigned long paddr, unsigned pages)
|
||||
{
|
||||
struct vram_alloc *va;
|
||||
struct vram_alloc *new;
|
||||
|
||||
new = kzalloc(sizeof(*va), GFP_KERNEL);
|
||||
|
||||
if (!new)
|
||||
return NULL;
|
||||
|
||||
new->paddr = paddr;
|
||||
new->pages = pages;
|
||||
|
||||
list_for_each_entry(va, &vr->alloc_list, list) {
|
||||
if (va->paddr > new->paddr)
|
||||
break;
|
||||
}
|
||||
|
||||
list_add_tail(&new->list, &va->list);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
static void omap_vram_free_allocation(struct vram_alloc *va)
|
||||
{
|
||||
list_del(&va->list);
|
||||
kfree(va);
|
||||
}
|
||||
|
||||
int omap_vram_add_region(unsigned long paddr, size_t size)
|
||||
{
|
||||
struct vram_region *rm;
|
||||
unsigned pages;
|
||||
|
||||
if (vram_initialized) {
|
||||
DBG("adding region paddr %08lx size %d\n",
|
||||
paddr, size);
|
||||
|
||||
size &= PAGE_MASK;
|
||||
pages = size >> PAGE_SHIFT;
|
||||
|
||||
rm = omap_vram_create_region(paddr, pages);
|
||||
if (rm == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
list_add(&rm->list, ®ion_list);
|
||||
} else {
|
||||
if (postponed_cnt == MAX_POSTPONED_REGIONS)
|
||||
return -ENOMEM;
|
||||
|
||||
postponed_regions[postponed_cnt].paddr = paddr;
|
||||
postponed_regions[postponed_cnt].size = size;
|
||||
|
||||
++postponed_cnt;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omap_vram_free(unsigned long paddr, size_t size)
|
||||
{
|
||||
struct vram_region *rm;
|
||||
struct vram_alloc *alloc;
|
||||
unsigned start, end;
|
||||
|
||||
DBG("free mem paddr %08lx size %d\n", paddr, size);
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
|
||||
mutex_lock(®ion_mutex);
|
||||
|
||||
list_for_each_entry(rm, ®ion_list, list) {
|
||||
list_for_each_entry(alloc, &rm->alloc_list, list) {
|
||||
start = alloc->paddr;
|
||||
end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
|
||||
|
||||
if (start >= paddr && end < paddr + size)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(®ion_mutex);
|
||||
return -EINVAL;
|
||||
|
||||
found:
|
||||
omap_vram_free_allocation(alloc);
|
||||
|
||||
mutex_unlock(®ion_mutex);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_vram_free);
|
||||
|
||||
static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
|
||||
{
|
||||
struct vram_region *rm;
|
||||
struct vram_alloc *alloc;
|
||||
size_t size;
|
||||
|
||||
size = pages << PAGE_SHIFT;
|
||||
|
||||
list_for_each_entry(rm, ®ion_list, list) {
|
||||
unsigned long start, end;
|
||||
|
||||
DBG("checking region %lx %d\n", rm->paddr, rm->pages);
|
||||
|
||||
start = rm->paddr;
|
||||
end = start + (rm->pages << PAGE_SHIFT) - 1;
|
||||
if (start > paddr || end < paddr + size - 1)
|
||||
continue;
|
||||
|
||||
DBG("block ok, checking allocs\n");
|
||||
|
||||
list_for_each_entry(alloc, &rm->alloc_list, list) {
|
||||
end = alloc->paddr - 1;
|
||||
|
||||
if (start <= paddr && end >= paddr + size - 1)
|
||||
goto found;
|
||||
|
||||
start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
|
||||
}
|
||||
|
||||
end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1;
|
||||
|
||||
if (!(start <= paddr && end >= paddr + size - 1))
|
||||
continue;
|
||||
found:
|
||||
DBG("found area start %lx, end %lx\n", start, end);
|
||||
|
||||
if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int omap_vram_reserve(unsigned long paddr, size_t size)
|
||||
{
|
||||
unsigned pages;
|
||||
int r;
|
||||
|
||||
DBG("reserve mem paddr %08lx size %d\n", paddr, size);
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
pages = size >> PAGE_SHIFT;
|
||||
|
||||
mutex_lock(®ion_mutex);
|
||||
|
||||
r = _omap_vram_reserve(paddr, pages);
|
||||
|
||||
mutex_unlock(®ion_mutex);
|
||||
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_vram_reserve);
|
||||
|
||||
static int _omap_vram_alloc(unsigned pages, unsigned long *paddr)
|
||||
{
|
||||
struct vram_region *rm;
|
||||
struct vram_alloc *alloc;
|
||||
|
||||
list_for_each_entry(rm, ®ion_list, list) {
|
||||
unsigned long start, end;
|
||||
|
||||
DBG("checking region %lx %d\n", rm->paddr, rm->pages);
|
||||
|
||||
start = rm->paddr;
|
||||
|
||||
list_for_each_entry(alloc, &rm->alloc_list, list) {
|
||||
end = alloc->paddr;
|
||||
|
||||
if (end - start >= pages << PAGE_SHIFT)
|
||||
goto found;
|
||||
|
||||
start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
|
||||
}
|
||||
|
||||
end = rm->paddr + (rm->pages << PAGE_SHIFT);
|
||||
found:
|
||||
if (end - start < pages << PAGE_SHIFT)
|
||||
continue;
|
||||
|
||||
DBG("found %lx, end %lx\n", start, end);
|
||||
|
||||
alloc = omap_vram_create_allocation(rm, start, pages);
|
||||
if (alloc == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
*paddr = start;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int omap_vram_alloc(size_t size, unsigned long *paddr)
|
||||
{
|
||||
unsigned pages;
|
||||
int r;
|
||||
|
||||
BUG_ON(!size);
|
||||
|
||||
DBG("alloc mem size %d\n", size);
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
pages = size >> PAGE_SHIFT;
|
||||
|
||||
mutex_lock(®ion_mutex);
|
||||
|
||||
r = _omap_vram_alloc(pages, paddr);
|
||||
|
||||
mutex_unlock(®ion_mutex);
|
||||
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_vram_alloc);
|
||||
|
||||
void omap_vram_get_info(unsigned long *vram,
|
||||
unsigned long *free_vram,
|
||||
unsigned long *largest_free_block)
|
||||
{
|
||||
struct vram_region *vr;
|
||||
struct vram_alloc *va;
|
||||
|
||||
*vram = 0;
|
||||
*free_vram = 0;
|
||||
*largest_free_block = 0;
|
||||
|
||||
mutex_lock(®ion_mutex);
|
||||
|
||||
list_for_each_entry(vr, ®ion_list, list) {
|
||||
unsigned free;
|
||||
unsigned long pa;
|
||||
|
||||
pa = vr->paddr;
|
||||
*vram += vr->pages << PAGE_SHIFT;
|
||||
|
||||
list_for_each_entry(va, &vr->alloc_list, list) {
|
||||
free = va->paddr - pa;
|
||||
*free_vram += free;
|
||||
if (free > *largest_free_block)
|
||||
*largest_free_block = free;
|
||||
pa = va->paddr + (va->pages << PAGE_SHIFT);
|
||||
}
|
||||
|
||||
free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa;
|
||||
*free_vram += free;
|
||||
if (free > *largest_free_block)
|
||||
*largest_free_block = free;
|
||||
}
|
||||
|
||||
mutex_unlock(®ion_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(omap_vram_get_info);
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
static int vram_debug_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct vram_region *vr;
|
||||
struct vram_alloc *va;
|
||||
unsigned size;
|
||||
|
||||
mutex_lock(®ion_mutex);
|
||||
|
||||
list_for_each_entry(vr, ®ion_list, list) {
|
||||
size = vr->pages << PAGE_SHIFT;
|
||||
seq_printf(s, "%08lx-%08lx (%d bytes)\n",
|
||||
vr->paddr, vr->paddr + size - 1,
|
||||
size);
|
||||
|
||||
list_for_each_entry(va, &vr->alloc_list, list) {
|
||||
size = va->pages << PAGE_SHIFT;
|
||||
seq_printf(s, " %08lx-%08lx (%d bytes)\n",
|
||||
va->paddr, va->paddr + size - 1,
|
||||
size);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(®ion_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vram_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, vram_debug_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations vram_debug_fops = {
|
||||
.open = vram_debug_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int __init omap_vram_create_debugfs(void)
|
||||
{
|
||||
struct dentry *d;
|
||||
|
||||
d = debugfs_create_file("vram", S_IRUGO, NULL,
|
||||
NULL, &vram_debug_fops);
|
||||
if (IS_ERR(d))
|
||||
return PTR_ERR(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static __init int omap_vram_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
vram_initialized = 1;
|
||||
|
||||
for (i = 0; i < postponed_cnt; i++)
|
||||
omap_vram_add_region(postponed_regions[i].paddr,
|
||||
postponed_regions[i].size);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
if (omap_vram_create_debugfs())
|
||||
pr_err("VRAM: Failed to create debugfs file\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(omap_vram_init);
|
||||
|
||||
/* boottime vram alloc stuff */
|
||||
|
||||
/* set from board file */
|
||||
static u32 omap_vram_sdram_start __initdata;
|
||||
static u32 omap_vram_sdram_size __initdata;
|
||||
|
||||
/* set from kernel cmdline */
|
||||
static u32 omap_vram_def_sdram_size __initdata;
|
||||
static u32 omap_vram_def_sdram_start __initdata;
|
||||
|
||||
static int __init omap_vram_early_vram(char *p)
|
||||
{
|
||||
omap_vram_def_sdram_size = memparse(p, &p);
|
||||
if (*p == ',')
|
||||
omap_vram_def_sdram_start = simple_strtoul(p + 1, &p, 16);
|
||||
return 0;
|
||||
}
|
||||
early_param("vram", omap_vram_early_vram);
|
||||
|
||||
/*
|
||||
* Called from map_io. We need to call to this early enough so that we
|
||||
* can reserve the fixed SDRAM regions before VM could get hold of them.
|
||||
*/
|
||||
void __init omap_vram_reserve_sdram_memblock(void)
|
||||
{
|
||||
u32 paddr;
|
||||
u32 size = 0;
|
||||
|
||||
/* cmdline arg overrides the board file definition */
|
||||
if (omap_vram_def_sdram_size) {
|
||||
size = omap_vram_def_sdram_size;
|
||||
paddr = omap_vram_def_sdram_start;
|
||||
}
|
||||
|
||||
if (!size) {
|
||||
size = omap_vram_sdram_size;
|
||||
paddr = omap_vram_sdram_start;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OMAP2_VRAM_SIZE
|
||||
if (!size) {
|
||||
size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024;
|
||||
paddr = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!size)
|
||||
return;
|
||||
|
||||
size = ALIGN(size, SZ_2M);
|
||||
|
||||
if (paddr) {
|
||||
if (paddr & ~PAGE_MASK) {
|
||||
pr_err("VRAM start address 0x%08x not page aligned\n",
|
||||
paddr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!memblock_is_region_memory(paddr, size)) {
|
||||
pr_err("Illegal SDRAM region 0x%08x..0x%08x for VRAM\n",
|
||||
paddr, paddr + size - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (memblock_is_region_reserved(paddr, size)) {
|
||||
pr_err("FB: failed to reserve VRAM - busy\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (memblock_reserve(paddr, size) < 0) {
|
||||
pr_err("FB: failed to reserve VRAM - no memory\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
paddr = memblock_alloc(size, SZ_2M);
|
||||
}
|
||||
|
||||
memblock_free(paddr, size);
|
||||
memblock_remove(paddr, size);
|
||||
|
||||
omap_vram_add_region(paddr, size);
|
||||
|
||||
pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
|
||||
}
|
||||
|
||||
void __init omap_vram_set_sdram_vram(u32 size, u32 start)
|
||||
{
|
||||
omap_vram_sdram_start = start;
|
||||
omap_vram_sdram_size = size;
|
||||
}
|
@ -189,7 +189,7 @@ struct s3c_fb_vsync {
|
||||
|
||||
/**
|
||||
* struct s3c_fb - overall hardware state of the hardware
|
||||
* @slock: The spinlock protection for this data sturucture.
|
||||
* @slock: The spinlock protection for this data structure.
|
||||
* @dev: The device that we bound to, for printing, etc.
|
||||
* @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
|
||||
* @lcd_clk: The clk (sclk) feeding pixclk.
|
||||
@ -268,10 +268,10 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
|
||||
case 8:
|
||||
if (sfb->variant.palette[win->index] != 0) {
|
||||
/* non palletised, A:1,R:2,G:3,B:2 mode */
|
||||
var->red.offset = 4;
|
||||
var->red.offset = 5;
|
||||
var->green.offset = 2;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 5;
|
||||
var->red.length = 2;
|
||||
var->green.length = 3;
|
||||
var->blue.length = 2;
|
||||
var->transp.offset = 7;
|
||||
@ -288,6 +288,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
|
||||
/* 666 with one bit alpha/transparency */
|
||||
var->transp.offset = 18;
|
||||
var->transp.length = 1;
|
||||
/* drop through */
|
||||
case 18:
|
||||
var->bits_per_pixel = 32;
|
||||
|
||||
@ -329,6 +330,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
|
||||
|
||||
default:
|
||||
dev_err(sfb->dev, "invalid bpp\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(sfb->dev, "%s: verified parameters\n", __func__);
|
||||
@ -1544,8 +1546,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int s3c_fb_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct s3c_fb *sfb = platform_get_drvdata(pdev);
|
||||
struct s3c_fb *sfb = dev_get_drvdata(dev);
|
||||
struct s3c_fb_win *win;
|
||||
int win_no;
|
||||
|
||||
@ -1572,8 +1573,7 @@ static int s3c_fb_suspend(struct device *dev)
|
||||
|
||||
static int s3c_fb_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct s3c_fb *sfb = platform_get_drvdata(pdev);
|
||||
struct s3c_fb *sfb = dev_get_drvdata(dev);
|
||||
struct s3c_fb_platdata *pd = sfb->pdata;
|
||||
struct s3c_fb_win *win;
|
||||
int win_no;
|
||||
@ -1623,7 +1623,7 @@ static int s3c_fb_resume(struct device *dev)
|
||||
if (!win)
|
||||
continue;
|
||||
|
||||
dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
|
||||
dev_dbg(dev, "resuming window %d\n", win_no);
|
||||
s3c_fb_set_par(win->fbinfo);
|
||||
}
|
||||
|
||||
@ -1636,8 +1636,7 @@ static int s3c_fb_resume(struct device *dev)
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int s3c_fb_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct s3c_fb *sfb = platform_get_drvdata(pdev);
|
||||
struct s3c_fb *sfb = dev_get_drvdata(dev);
|
||||
|
||||
if (!sfb->variant.has_clksel)
|
||||
clk_disable_unprepare(sfb->lcd_clk);
|
||||
@ -1649,8 +1648,7 @@ static int s3c_fb_runtime_suspend(struct device *dev)
|
||||
|
||||
static int s3c_fb_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct s3c_fb *sfb = platform_get_drvdata(pdev);
|
||||
struct s3c_fb *sfb = dev_get_drvdata(dev);
|
||||
struct s3c_fb_platdata *pd = sfb->pdata;
|
||||
|
||||
clk_prepare_enable(sfb->bus_clk);
|
||||
@ -1910,7 +1908,7 @@ static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
|
||||
static struct s3c_fb_driverdata s3c_fb_data_exynos5 = {
|
||||
.variant = {
|
||||
.nr_windows = 5,
|
||||
.vidtcon = VIDTCON0,
|
||||
.vidtcon = FIMD_V8_VIDTCON0,
|
||||
.wincon = WINCON(0),
|
||||
.winmap = WINxMAP(0),
|
||||
.keycon = WKEYCON,
|
||||
|
@ -127,13 +127,12 @@ static void sh_mipi_shutdown(struct platform_device *pdev)
|
||||
sh_mipi_dsi_enable(mipi, false);
|
||||
}
|
||||
|
||||
static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
|
||||
static int sh_mipi_setup(struct sh_mipi *mipi, const struct fb_videomode *mode)
|
||||
{
|
||||
void __iomem *base = mipi->base;
|
||||
struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
|
||||
struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
|
||||
u32 pctype, datatype, pixfmt, linelength, vmctr2;
|
||||
u32 tmp, top, bottom, delay, div;
|
||||
bool yuv;
|
||||
int bpp;
|
||||
|
||||
/*
|
||||
@ -146,95 +145,79 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
|
||||
pctype = 0;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
|
||||
linelength = ch->lcd_modes[0].xres * 3;
|
||||
yuv = false;
|
||||
linelength = mode->xres * 3;
|
||||
break;
|
||||
case MIPI_RGB565:
|
||||
pctype = 1;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
|
||||
linelength = ch->lcd_modes[0].xres * 2;
|
||||
yuv = false;
|
||||
linelength = mode->xres * 2;
|
||||
break;
|
||||
case MIPI_RGB666_LP:
|
||||
pctype = 2;
|
||||
datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
|
||||
linelength = ch->lcd_modes[0].xres * 3;
|
||||
yuv = false;
|
||||
linelength = mode->xres * 3;
|
||||
break;
|
||||
case MIPI_RGB666:
|
||||
pctype = 3;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
|
||||
linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8;
|
||||
yuv = false;
|
||||
linelength = (mode->xres * 18 + 7) / 8;
|
||||
break;
|
||||
case MIPI_BGR888:
|
||||
pctype = 8;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
|
||||
linelength = ch->lcd_modes[0].xres * 3;
|
||||
yuv = false;
|
||||
linelength = mode->xres * 3;
|
||||
break;
|
||||
case MIPI_BGR565:
|
||||
pctype = 9;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
|
||||
linelength = ch->lcd_modes[0].xres * 2;
|
||||
yuv = false;
|
||||
linelength = mode->xres * 2;
|
||||
break;
|
||||
case MIPI_BGR666_LP:
|
||||
pctype = 0xa;
|
||||
datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
|
||||
linelength = ch->lcd_modes[0].xres * 3;
|
||||
yuv = false;
|
||||
linelength = mode->xres * 3;
|
||||
break;
|
||||
case MIPI_BGR666:
|
||||
pctype = 0xb;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
|
||||
linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8;
|
||||
yuv = false;
|
||||
linelength = (mode->xres * 18 + 7) / 8;
|
||||
break;
|
||||
case MIPI_YUYV:
|
||||
pctype = 4;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
|
||||
linelength = ch->lcd_modes[0].xres * 2;
|
||||
yuv = true;
|
||||
linelength = mode->xres * 2;
|
||||
break;
|
||||
case MIPI_UYVY:
|
||||
pctype = 5;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
|
||||
linelength = ch->lcd_modes[0].xres * 2;
|
||||
yuv = true;
|
||||
linelength = mode->xres * 2;
|
||||
break;
|
||||
case MIPI_YUV420_L:
|
||||
pctype = 6;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
|
||||
linelength = (ch->lcd_modes[0].xres * 12 + 7) / 8;
|
||||
yuv = true;
|
||||
linelength = (mode->xres * 12 + 7) / 8;
|
||||
break;
|
||||
case MIPI_YUV420:
|
||||
pctype = 7;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
|
||||
/* Length of U/V line */
|
||||
linelength = (ch->lcd_modes[0].xres + 1) / 2;
|
||||
yuv = true;
|
||||
linelength = (mode->xres + 1) / 2;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((yuv && ch->interface_type != YUV422) ||
|
||||
(!yuv && ch->interface_type != RGB24))
|
||||
return -EINVAL;
|
||||
|
||||
if (!pdata->lane)
|
||||
return -EINVAL;
|
||||
|
||||
@ -293,7 +276,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
|
||||
*/
|
||||
iowrite32(0x00000006, mipi->linkbase + DTCTR);
|
||||
/* VSYNC width = 2 (<< 17) */
|
||||
iowrite32((ch->lcd_modes[0].vsync_len << pdata->vsynw_offset) |
|
||||
iowrite32((mode->vsync_len << pdata->vsynw_offset) |
|
||||
(pdata->clksrc << 16) | (pctype << 12) | datatype,
|
||||
mipi->linkbase + VMCTR1);
|
||||
|
||||
@ -327,7 +310,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
|
||||
top = linelength << 16; /* RGBLEN */
|
||||
bottom = 0x00000001;
|
||||
if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */
|
||||
bottom = (pdata->lane * ch->lcd_modes[0].hsync_len) - 10;
|
||||
bottom = (pdata->lane * mode->hsync_len) - 10;
|
||||
iowrite32(top | bottom , mipi->linkbase + VMLEN1);
|
||||
|
||||
/*
|
||||
@ -347,18 +330,18 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
|
||||
div = 2;
|
||||
|
||||
if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */
|
||||
top = ch->lcd_modes[0].hsync_len + ch->lcd_modes[0].left_margin;
|
||||
top = mode->hsync_len + mode->left_margin;
|
||||
top = ((pdata->lane * top / div) - 10) << 16;
|
||||
}
|
||||
if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */
|
||||
bottom = ch->lcd_modes[0].right_margin;
|
||||
bottom = mode->right_margin;
|
||||
bottom = (pdata->lane * bottom / div) - 12;
|
||||
}
|
||||
|
||||
bpp = linelength / ch->lcd_modes[0].xres; /* byte / pixel */
|
||||
bpp = linelength / mode->xres; /* byte / pixel */
|
||||
if ((pdata->lane / div) > bpp) {
|
||||
tmp = ch->lcd_modes[0].xres / bpp; /* output cycle */
|
||||
tmp = ch->lcd_modes[0].xres - tmp; /* (input - output) cycle */
|
||||
tmp = mode->xres / bpp; /* output cycle */
|
||||
tmp = mode->xres - tmp; /* (input - output) cycle */
|
||||
delay = (pdata->lane * tmp);
|
||||
}
|
||||
|
||||
@ -369,7 +352,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
|
||||
/* setup LCD panel */
|
||||
|
||||
/* cf. drivers/video/omap/lcd_mipid.c */
|
||||
sh_mipi_dcs(ch->chan, MIPI_DCS_EXIT_SLEEP_MODE);
|
||||
sh_mipi_dcs(pdata->channel, MIPI_DCS_EXIT_SLEEP_MODE);
|
||||
msleep(120);
|
||||
/*
|
||||
* [7] - Page Address Mode
|
||||
@ -381,11 +364,11 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
|
||||
* [1] - Flip Horizontal
|
||||
* [0] - Flip Vertical
|
||||
*/
|
||||
sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
|
||||
sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
|
||||
/* cf. set_data_lines() */
|
||||
sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_PIXEL_FORMAT,
|
||||
sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_PIXEL_FORMAT,
|
||||
pixfmt << 4);
|
||||
sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON);
|
||||
sh_mipi_dcs(pdata->channel, MIPI_DCS_SET_DISPLAY_ON);
|
||||
|
||||
/* Enable timeout counters */
|
||||
iowrite32(0x00000f00, base + DSICTRL);
|
||||
@ -405,7 +388,7 @@ static int mipi_display_on(struct sh_mobile_lcdc_entity *entity)
|
||||
if (ret < 0)
|
||||
goto mipi_display_on_fail1;
|
||||
|
||||
ret = sh_mipi_setup(mipi, pdata);
|
||||
ret = sh_mipi_setup(mipi, &entity->def_mode);
|
||||
if (ret < 0)
|
||||
goto mipi_display_on_fail2;
|
||||
|
||||
|
@ -438,7 +438,7 @@ static unsigned long lcdc_sys_read_data(void *handle)
|
||||
return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK;
|
||||
}
|
||||
|
||||
struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
|
||||
static struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
|
||||
lcdc_sys_write_index,
|
||||
lcdc_sys_write_data,
|
||||
lcdc_sys_read_data,
|
||||
@ -586,8 +586,8 @@ static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
|
||||
* Just turn on, if we run a resume here, the
|
||||
* logo disappears.
|
||||
*/
|
||||
info->var.width = monspec->max_x * 10;
|
||||
info->var.height = monspec->max_y * 10;
|
||||
info->var.width = ch->display.width;
|
||||
info->var.height = ch->display.height;
|
||||
sh_mobile_lcdc_display_on(ch);
|
||||
} else {
|
||||
/* New monitor or have to wake up */
|
||||
@ -1614,6 +1614,15 @@ static int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
sh_mobile_lcdc_overlay_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
||||
{
|
||||
struct sh_mobile_lcdc_overlay *ovl = info->par;
|
||||
|
||||
return dma_mmap_coherent(ovl->channel->lcdc->dev, vma, ovl->fb_mem,
|
||||
ovl->dma_handle, ovl->fb_size);
|
||||
}
|
||||
|
||||
static struct fb_ops sh_mobile_lcdc_overlay_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_read = fb_sys_read,
|
||||
@ -1626,6 +1635,7 @@ static struct fb_ops sh_mobile_lcdc_overlay_ops = {
|
||||
.fb_ioctl = sh_mobile_lcdc_overlay_ioctl,
|
||||
.fb_check_var = sh_mobile_lcdc_overlay_check_var,
|
||||
.fb_set_par = sh_mobile_lcdc_overlay_set_par,
|
||||
.fb_mmap = sh_mobile_lcdc_overlay_mmap,
|
||||
};
|
||||
|
||||
static void
|
||||
@ -2093,6 +2103,15 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sh_mobile_lcdc_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
||||
{
|
||||
struct sh_mobile_lcdc_chan *ch = info->par;
|
||||
|
||||
return dma_mmap_coherent(ch->lcdc->dev, vma, ch->fb_mem,
|
||||
ch->dma_handle, ch->fb_size);
|
||||
}
|
||||
|
||||
static struct fb_ops sh_mobile_lcdc_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_setcolreg = sh_mobile_lcdc_setcolreg,
|
||||
@ -2108,6 +2127,7 @@ static struct fb_ops sh_mobile_lcdc_ops = {
|
||||
.fb_release = sh_mobile_lcdc_release,
|
||||
.fb_check_var = sh_mobile_lcdc_check_var,
|
||||
.fb_set_par = sh_mobile_lcdc_set_par,
|
||||
.fb_mmap = sh_mobile_lcdc_mmap,
|
||||
};
|
||||
|
||||
static void
|
||||
@ -2167,7 +2187,7 @@ sh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch)
|
||||
|
||||
static int __devinit
|
||||
sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
|
||||
const struct fb_videomode *mode,
|
||||
const struct fb_videomode *modes,
|
||||
unsigned int num_modes)
|
||||
{
|
||||
struct sh_mobile_lcdc_priv *priv = ch->lcdc;
|
||||
@ -2193,7 +2213,7 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
|
||||
info->pseudo_palette = &ch->pseudo_palette;
|
||||
info->par = ch;
|
||||
|
||||
fb_videomode_to_modelist(mode, num_modes, &info->modelist);
|
||||
fb_videomode_to_modelist(modes, num_modes, &info->modelist);
|
||||
|
||||
ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
|
||||
if (ret < 0) {
|
||||
@ -2227,9 +2247,9 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
|
||||
* default.
|
||||
*/
|
||||
var = &info->var;
|
||||
fb_videomode_to_var(var, mode);
|
||||
var->width = ch->cfg->panel_cfg.width;
|
||||
var->height = ch->cfg->panel_cfg.height;
|
||||
fb_videomode_to_var(var, modes);
|
||||
var->width = ch->display.width;
|
||||
var->height = ch->display.height;
|
||||
var->xres_virtual = ch->xres_virtual;
|
||||
var->yres_virtual = ch->yres_virtual;
|
||||
var->activate = FB_ACTIVATE_NOW;
|
||||
@ -2262,6 +2282,7 @@ static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
|
||||
bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
|
||||
brightness = 0;
|
||||
|
||||
ch->bl_brightness = brightness;
|
||||
return ch->cfg->bl_info.set_brightness(brightness);
|
||||
}
|
||||
|
||||
@ -2269,7 +2290,7 @@ static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev)
|
||||
{
|
||||
struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
|
||||
|
||||
return ch->cfg->bl_info.get_brightness();
|
||||
return ch->bl_brightness;
|
||||
}
|
||||
|
||||
static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev,
|
||||
@ -2516,10 +2537,10 @@ static int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *
|
||||
}
|
||||
|
||||
static int __devinit
|
||||
sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
|
||||
struct sh_mobile_lcdc_overlay *ovl)
|
||||
sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_overlay *ovl)
|
||||
{
|
||||
const struct sh_mobile_lcdc_format_info *format;
|
||||
struct device *dev = ovl->channel->lcdc->dev;
|
||||
int ret;
|
||||
|
||||
if (ovl->cfg->fourcc == 0)
|
||||
@ -2528,7 +2549,7 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
|
||||
/* Validate the format. */
|
||||
format = sh_mobile_format_info(ovl->cfg->fourcc);
|
||||
if (format == NULL) {
|
||||
dev_err(priv->dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc);
|
||||
dev_err(dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -2556,10 +2577,10 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
|
||||
/* Allocate frame buffer memory. */
|
||||
ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres
|
||||
* format->bpp / 8 * 2;
|
||||
ovl->fb_mem = dma_alloc_coherent(priv->dev, ovl->fb_size,
|
||||
&ovl->dma_handle, GFP_KERNEL);
|
||||
ovl->fb_mem = dma_alloc_coherent(dev, ovl->fb_size, &ovl->dma_handle,
|
||||
GFP_KERNEL);
|
||||
if (!ovl->fb_mem) {
|
||||
dev_err(priv->dev, "unable to allocate buffer\n");
|
||||
dev_err(dev, "unable to allocate buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -2571,11 +2592,11 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
|
||||
}
|
||||
|
||||
static int __devinit
|
||||
sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
|
||||
struct sh_mobile_lcdc_chan *ch)
|
||||
sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch)
|
||||
{
|
||||
const struct sh_mobile_lcdc_format_info *format;
|
||||
const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg;
|
||||
struct device *dev = ch->lcdc->dev;
|
||||
const struct fb_videomode *max_mode;
|
||||
const struct fb_videomode *mode;
|
||||
unsigned int num_modes;
|
||||
@ -2588,7 +2609,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
|
||||
/* Validate the format. */
|
||||
format = sh_mobile_format_info(cfg->fourcc);
|
||||
if (format == NULL) {
|
||||
dev_err(priv->dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
|
||||
dev_err(dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -2604,7 +2625,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
|
||||
/* NV12/NV21 buffers must have even number of lines */
|
||||
if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
|
||||
cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
|
||||
dev_err(priv->dev, "yres must be multiple of 2 for "
|
||||
dev_err(dev, "yres must be multiple of 2 for "
|
||||
"YCbCr420 mode.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -2618,7 +2639,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
|
||||
if (!max_size)
|
||||
max_size = MAX_XRES * MAX_YRES;
|
||||
else
|
||||
dev_dbg(priv->dev, "Found largest videomode %ux%u\n",
|
||||
dev_dbg(dev, "Found largest videomode %ux%u\n",
|
||||
max_mode->xres, max_mode->yres);
|
||||
|
||||
if (cfg->lcd_modes == NULL) {
|
||||
@ -2652,10 +2673,10 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
|
||||
|
||||
/* Allocate frame buffer memory. */
|
||||
ch->fb_size = max_size * format->bpp / 8 * 2;
|
||||
ch->fb_mem = dma_alloc_coherent(priv->dev, ch->fb_size, &ch->dma_handle,
|
||||
ch->fb_mem = dma_alloc_coherent(dev, ch->fb_size, &ch->dma_handle,
|
||||
GFP_KERNEL);
|
||||
if (ch->fb_mem == NULL) {
|
||||
dev_err(priv->dev, "unable to allocate buffer\n");
|
||||
dev_err(dev, "unable to allocate buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -2663,8 +2684,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
|
||||
if (cfg->tx_dev) {
|
||||
if (!cfg->tx_dev->dev.driver ||
|
||||
!try_module_get(cfg->tx_dev->dev.driver->owner)) {
|
||||
dev_warn(priv->dev,
|
||||
"unable to get transmitter device\n");
|
||||
dev_warn(dev, "unable to get transmitter device\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ch->tx_dev = platform_get_drvdata(cfg->tx_dev);
|
||||
@ -2772,9 +2792,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
for (i = 0; i < num_channels; i++) {
|
||||
struct sh_mobile_lcdc_chan *ch = priv->ch + i;
|
||||
struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
|
||||
|
||||
error = sh_mobile_lcdc_channel_init(priv, ch);
|
||||
error = sh_mobile_lcdc_channel_init(ch);
|
||||
if (error)
|
||||
goto err1;
|
||||
}
|
||||
@ -2785,7 +2805,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
|
||||
ovl->cfg = &pdata->overlays[i];
|
||||
ovl->channel = &priv->ch[0];
|
||||
|
||||
error = sh_mobile_lcdc_overlay_init(priv, ovl);
|
||||
error = sh_mobile_lcdc_overlay_init(ovl);
|
||||
if (error)
|
||||
goto err1;
|
||||
}
|
||||
|
@ -94,6 +94,7 @@ struct sh_mobile_lcdc_chan {
|
||||
|
||||
/* Backlight */
|
||||
struct backlight_device *bl;
|
||||
unsigned int bl_brightness;
|
||||
|
||||
/* FB */
|
||||
struct fb_info *info;
|
||||
|
396
drivers/video/ssd1307fb.c
Normal file
396
drivers/video/ssd1307fb.c
Normal file
@ -0,0 +1,396 @@
|
||||
/*
|
||||
* Driver for the Solomon SSD1307 OLED controler
|
||||
*
|
||||
* Copyright 2012 Free Electrons
|
||||
*
|
||||
* Licensed under the GPLv2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define SSD1307FB_WIDTH 96
|
||||
#define SSD1307FB_HEIGHT 16
|
||||
|
||||
#define SSD1307FB_DATA 0x40
|
||||
#define SSD1307FB_COMMAND 0x80
|
||||
|
||||
#define SSD1307FB_CONTRAST 0x81
|
||||
#define SSD1307FB_SEG_REMAP_ON 0xa1
|
||||
#define SSD1307FB_DISPLAY_OFF 0xae
|
||||
#define SSD1307FB_DISPLAY_ON 0xaf
|
||||
#define SSD1307FB_START_PAGE_ADDRESS 0xb0
|
||||
|
||||
struct ssd1307fb_par {
|
||||
struct i2c_client *client;
|
||||
struct fb_info *info;
|
||||
struct pwm_device *pwm;
|
||||
u32 pwm_period;
|
||||
int reset;
|
||||
};
|
||||
|
||||
static struct fb_fix_screeninfo ssd1307fb_fix __devinitdata = {
|
||||
.id = "Solomon SSD1307",
|
||||
.type = FB_TYPE_PACKED_PIXELS,
|
||||
.visual = FB_VISUAL_MONO10,
|
||||
.xpanstep = 0,
|
||||
.ypanstep = 0,
|
||||
.ywrapstep = 0,
|
||||
.line_length = SSD1307FB_WIDTH / 8,
|
||||
.accel = FB_ACCEL_NONE,
|
||||
};
|
||||
|
||||
static struct fb_var_screeninfo ssd1307fb_var __devinitdata = {
|
||||
.xres = SSD1307FB_WIDTH,
|
||||
.yres = SSD1307FB_HEIGHT,
|
||||
.xres_virtual = SSD1307FB_WIDTH,
|
||||
.yres_virtual = SSD1307FB_HEIGHT,
|
||||
.bits_per_pixel = 1,
|
||||
};
|
||||
|
||||
static int ssd1307fb_write_array(struct i2c_client *client, u8 type, u8 *cmd, u32 len)
|
||||
{
|
||||
u8 *buf;
|
||||
int ret = 0;
|
||||
|
||||
buf = kzalloc(len + 1, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
dev_err(&client->dev, "Couldn't allocate sending buffer.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
buf[0] = type;
|
||||
memcpy(buf + 1, cmd, len);
|
||||
|
||||
ret = i2c_master_send(client, buf, len + 1);
|
||||
if (ret != len + 1) {
|
||||
dev_err(&client->dev, "Couldn't send I2C command.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int ssd1307fb_write_cmd_array(struct i2c_client *client, u8 *cmd, u32 len)
|
||||
{
|
||||
return ssd1307fb_write_array(client, SSD1307FB_COMMAND, cmd, len);
|
||||
}
|
||||
|
||||
static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd)
|
||||
{
|
||||
return ssd1307fb_write_cmd_array(client, &cmd, 1);
|
||||
}
|
||||
|
||||
static inline int ssd1307fb_write_data_array(struct i2c_client *client, u8 *cmd, u32 len)
|
||||
{
|
||||
return ssd1307fb_write_array(client, SSD1307FB_DATA, cmd, len);
|
||||
}
|
||||
|
||||
static inline int ssd1307fb_write_data(struct i2c_client *client, u8 data)
|
||||
{
|
||||
return ssd1307fb_write_data_array(client, &data, 1);
|
||||
}
|
||||
|
||||
static void ssd1307fb_update_display(struct ssd1307fb_par *par)
|
||||
{
|
||||
u8 *vmem = par->info->screen_base;
|
||||
int i, j, k;
|
||||
|
||||
/*
|
||||
* The screen is divided in pages, each having a height of 8
|
||||
* pixels, and the width of the screen. When sending a byte of
|
||||
* data to the controller, it gives the 8 bits for the current
|
||||
* column. I.e, the first byte are the 8 bits of the first
|
||||
* column, then the 8 bits for the second column, etc.
|
||||
*
|
||||
*
|
||||
* Representation of the screen, assuming it is 5 bits
|
||||
* wide. Each letter-number combination is a bit that controls
|
||||
* one pixel.
|
||||
*
|
||||
* A0 A1 A2 A3 A4
|
||||
* B0 B1 B2 B3 B4
|
||||
* C0 C1 C2 C3 C4
|
||||
* D0 D1 D2 D3 D4
|
||||
* E0 E1 E2 E3 E4
|
||||
* F0 F1 F2 F3 F4
|
||||
* G0 G1 G2 G3 G4
|
||||
* H0 H1 H2 H3 H4
|
||||
*
|
||||
* If you want to update this screen, you need to send 5 bytes:
|
||||
* (1) A0 B0 C0 D0 E0 F0 G0 H0
|
||||
* (2) A1 B1 C1 D1 E1 F1 G1 H1
|
||||
* (3) A2 B2 C2 D2 E2 F2 G2 H2
|
||||
* (4) A3 B3 C3 D3 E3 F3 G3 H3
|
||||
* (5) A4 B4 C4 D4 E4 F4 G4 H4
|
||||
*/
|
||||
|
||||
for (i = 0; i < (SSD1307FB_HEIGHT / 8); i++) {
|
||||
ssd1307fb_write_cmd(par->client, SSD1307FB_START_PAGE_ADDRESS + (i + 1));
|
||||
ssd1307fb_write_cmd(par->client, 0x00);
|
||||
ssd1307fb_write_cmd(par->client, 0x10);
|
||||
|
||||
for (j = 0; j < SSD1307FB_WIDTH; j++) {
|
||||
u8 buf = 0;
|
||||
for (k = 0; k < 8; k++) {
|
||||
u32 page_length = SSD1307FB_WIDTH * i;
|
||||
u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8;
|
||||
u8 byte = *(vmem + index);
|
||||
u8 bit = byte & (1 << (7 - (j % 8)));
|
||||
bit = bit >> (7 - (j % 8));
|
||||
buf |= bit << k;
|
||||
}
|
||||
ssd1307fb_write_data(par->client, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ssd1307fb_par *par = info->par;
|
||||
unsigned long total_size;
|
||||
unsigned long p = *ppos;
|
||||
u8 __iomem *dst;
|
||||
|
||||
total_size = info->fix.smem_len;
|
||||
|
||||
if (p > total_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (count + p > total_size)
|
||||
count = total_size - p;
|
||||
|
||||
if (!count)
|
||||
return -EINVAL;
|
||||
|
||||
dst = (void __force *) (info->screen_base + p);
|
||||
|
||||
if (copy_from_user(dst, buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
ssd1307fb_update_display(par);
|
||||
|
||||
*ppos += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
|
||||
{
|
||||
struct ssd1307fb_par *par = info->par;
|
||||
sys_fillrect(info, rect);
|
||||
ssd1307fb_update_display(par);
|
||||
}
|
||||
|
||||
static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
|
||||
{
|
||||
struct ssd1307fb_par *par = info->par;
|
||||
sys_copyarea(info, area);
|
||||
ssd1307fb_update_display(par);
|
||||
}
|
||||
|
||||
static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image)
|
||||
{
|
||||
struct ssd1307fb_par *par = info->par;
|
||||
sys_imageblit(info, image);
|
||||
ssd1307fb_update_display(par);
|
||||
}
|
||||
|
||||
static struct fb_ops ssd1307fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_read = fb_sys_read,
|
||||
.fb_write = ssd1307fb_write,
|
||||
.fb_fillrect = ssd1307fb_fillrect,
|
||||
.fb_copyarea = ssd1307fb_copyarea,
|
||||
.fb_imageblit = ssd1307fb_imageblit,
|
||||
};
|
||||
|
||||
static void ssd1307fb_deferred_io(struct fb_info *info,
|
||||
struct list_head *pagelist)
|
||||
{
|
||||
ssd1307fb_update_display(info->par);
|
||||
}
|
||||
|
||||
static struct fb_deferred_io ssd1307fb_defio = {
|
||||
.delay = HZ,
|
||||
.deferred_io = ssd1307fb_deferred_io,
|
||||
};
|
||||
|
||||
static int __devinit ssd1307fb_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
struct fb_info *info;
|
||||
u32 vmem_size = SSD1307FB_WIDTH * SSD1307FB_HEIGHT / 8;
|
||||
struct ssd1307fb_par *par;
|
||||
u8 *vmem;
|
||||
int ret;
|
||||
|
||||
if (!client->dev.of_node) {
|
||||
dev_err(&client->dev, "No device tree data found!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info = framebuffer_alloc(sizeof(struct ssd1307fb_par), &client->dev);
|
||||
if (!info) {
|
||||
dev_err(&client->dev, "Couldn't allocate framebuffer.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
|
||||
if (!vmem) {
|
||||
dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
|
||||
ret = -ENOMEM;
|
||||
goto fb_alloc_error;
|
||||
}
|
||||
|
||||
info->fbops = &ssd1307fb_ops;
|
||||
info->fix = ssd1307fb_fix;
|
||||
info->fbdefio = &ssd1307fb_defio;
|
||||
|
||||
info->var = ssd1307fb_var;
|
||||
info->var.red.length = 1;
|
||||
info->var.red.offset = 0;
|
||||
info->var.green.length = 1;
|
||||
info->var.green.offset = 0;
|
||||
info->var.blue.length = 1;
|
||||
info->var.blue.offset = 0;
|
||||
|
||||
info->screen_base = (u8 __force __iomem *)vmem;
|
||||
info->fix.smem_start = (unsigned long)vmem;
|
||||
info->fix.smem_len = vmem_size;
|
||||
|
||||
fb_deferred_io_init(info);
|
||||
|
||||
par = info->par;
|
||||
par->info = info;
|
||||
par->client = client;
|
||||
|
||||
par->reset = of_get_named_gpio(client->dev.of_node,
|
||||
"reset-gpios", 0);
|
||||
if (!gpio_is_valid(par->reset)) {
|
||||
ret = -EINVAL;
|
||||
goto reset_oled_error;
|
||||
}
|
||||
|
||||
ret = devm_gpio_request_one(&client->dev, par->reset,
|
||||
GPIOF_OUT_INIT_HIGH,
|
||||
"oled-reset");
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"failed to request gpio %d: %d\n",
|
||||
par->reset, ret);
|
||||
goto reset_oled_error;
|
||||
}
|
||||
|
||||
par->pwm = pwm_get(&client->dev, NULL);
|
||||
if (IS_ERR(par->pwm)) {
|
||||
dev_err(&client->dev, "Could not get PWM from device tree!\n");
|
||||
ret = PTR_ERR(par->pwm);
|
||||
goto pwm_error;
|
||||
}
|
||||
|
||||
par->pwm_period = pwm_get_period(par->pwm);
|
||||
|
||||
dev_dbg(&client->dev, "Using PWM%d with a %dns period.\n", par->pwm->pwm, par->pwm_period);
|
||||
|
||||
ret = register_framebuffer(info);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "Couldn't register the framebuffer\n");
|
||||
goto fbreg_error;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, info);
|
||||
|
||||
/* Reset the screen */
|
||||
gpio_set_value(par->reset, 0);
|
||||
udelay(4);
|
||||
gpio_set_value(par->reset, 1);
|
||||
udelay(4);
|
||||
|
||||
/* Enable the PWM */
|
||||
pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
|
||||
pwm_enable(par->pwm);
|
||||
|
||||
/* Map column 127 of the OLED to segment 0 */
|
||||
ret = ssd1307fb_write_cmd(client, SSD1307FB_SEG_REMAP_ON);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "Couldn't remap the screen.\n");
|
||||
goto remap_error;
|
||||
}
|
||||
|
||||
/* Turn on the display */
|
||||
ret = ssd1307fb_write_cmd(client, SSD1307FB_DISPLAY_ON);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "Couldn't turn the display on.\n");
|
||||
goto remap_error;
|
||||
}
|
||||
|
||||
dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size);
|
||||
|
||||
return 0;
|
||||
|
||||
remap_error:
|
||||
unregister_framebuffer(info);
|
||||
pwm_disable(par->pwm);
|
||||
fbreg_error:
|
||||
pwm_put(par->pwm);
|
||||
pwm_error:
|
||||
reset_oled_error:
|
||||
fb_deferred_io_cleanup(info);
|
||||
fb_alloc_error:
|
||||
framebuffer_release(info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit ssd1307fb_remove(struct i2c_client *client)
|
||||
{
|
||||
struct fb_info *info = i2c_get_clientdata(client);
|
||||
struct ssd1307fb_par *par = info->par;
|
||||
|
||||
unregister_framebuffer(info);
|
||||
pwm_disable(par->pwm);
|
||||
pwm_put(par->pwm);
|
||||
fb_deferred_io_cleanup(info);
|
||||
framebuffer_release(info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ssd1307fb_i2c_id[] = {
|
||||
{ "ssd1307fb", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id);
|
||||
|
||||
static const struct of_device_id ssd1307fb_of_match[] = {
|
||||
{ .compatible = "solomon,ssd1307fb-i2c" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
|
||||
|
||||
static struct i2c_driver ssd1307fb_driver = {
|
||||
.probe = ssd1307fb_probe,
|
||||
.remove = __devexit_p(ssd1307fb_remove),
|
||||
.id_table = ssd1307fb_i2c_id,
|
||||
.driver = {
|
||||
.name = "ssd1307fb",
|
||||
.of_match_table = of_match_ptr(ssd1307fb_of_match),
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
module_i2c_driver(ssd1307fb_driver);
|
||||
|
||||
MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controler");
|
||||
MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
|
||||
MODULE_LICENSE("GPL");
|
@ -46,6 +46,15 @@ struct aoi_display_offset {
|
||||
#define MFB_SET_PIXFMT _IOW('M', 8, __u32)
|
||||
#define MFB_GET_PIXFMT _IOR('M', 8, __u32)
|
||||
|
||||
/*
|
||||
* The MPC5121 BSP comes with a gamma_set utility that initializes the
|
||||
* gamma table. Unfortunately, it uses bad values for the IOCTL commands,
|
||||
* but there's nothing we can do about it now. These ioctls are only
|
||||
* supported on the MPC5121.
|
||||
*/
|
||||
#define MFB_SET_GAMMA _IOW('M', 1, __u8)
|
||||
#define MFB_GET_GAMMA _IOR('M', 1, __u8)
|
||||
|
||||
/*
|
||||
* The original definitions of MFB_SET_PIXFMT and MFB_GET_PIXFMT used the
|
||||
* wrong value for 'size' field of the ioctl. The current macros above use the
|
||||
|
@ -12,10 +12,6 @@
|
||||
#ifndef DA8XX_FB_H
|
||||
#define DA8XX_FB_H
|
||||
|
||||
enum panel_type {
|
||||
QVGA = 0
|
||||
};
|
||||
|
||||
enum panel_shade {
|
||||
MONOCHROME = 0,
|
||||
COLOR_ACTIVE,
|
||||
@ -27,13 +23,6 @@ enum raster_load_mode {
|
||||
LOAD_PALETTE,
|
||||
};
|
||||
|
||||
struct display_panel {
|
||||
enum panel_type panel_type; /* QVGA */
|
||||
int max_bpp;
|
||||
int min_bpp;
|
||||
enum panel_shade panel_shade;
|
||||
};
|
||||
|
||||
struct da8xx_lcdc_platform_data {
|
||||
const char manu_name[10];
|
||||
void *controller_data;
|
||||
@ -42,7 +31,7 @@ struct da8xx_lcdc_platform_data {
|
||||
};
|
||||
|
||||
struct lcd_ctrl_config {
|
||||
const struct display_panel *p_disp_panel;
|
||||
enum panel_shade panel_shade;
|
||||
|
||||
/* AC Bias Pin Frequency */
|
||||
int ac_bias;
|
||||
@ -68,18 +57,9 @@ struct lcd_ctrl_config {
|
||||
/* Mono 8-bit Mode: 1=D0-D7 or 0=D0-D3 */
|
||||
unsigned char mono_8bit_mode;
|
||||
|
||||
/* Invert line clock */
|
||||
unsigned char invert_line_clock;
|
||||
|
||||
/* Invert frame clock */
|
||||
unsigned char invert_frm_clock;
|
||||
|
||||
/* Horizontal and Vertical Sync Edge: 0=rising 1=falling */
|
||||
unsigned char sync_edge;
|
||||
|
||||
/* Horizontal and Vertical Sync: Control: 0=ignore */
|
||||
unsigned char sync_ctrl;
|
||||
|
||||
/* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */
|
||||
unsigned char raster_order;
|
||||
|
||||
@ -103,5 +83,8 @@ struct lcd_sync_arg {
|
||||
#define FBIPUT_HSYNC _IOW('F', 9, int)
|
||||
#define FBIPUT_VSYNC _IOW('F', 10, int)
|
||||
|
||||
/* Proprietary FB_SYNC_ flags */
|
||||
#define FB_SYNC_CLK_INVERT 0x40000000
|
||||
|
||||
#endif /* ifndef DA8XX_FB_H */
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#define DISPC_IRQ_FRAMEDONE (1 << 0)
|
||||
#define DISPC_IRQ_VSYNC (1 << 1)
|
||||
@ -55,6 +56,7 @@
|
||||
|
||||
struct omap_dss_device;
|
||||
struct omap_overlay_manager;
|
||||
struct dss_lcd_mgr_config;
|
||||
struct snd_aes_iec958;
|
||||
struct snd_cea_861_aud_if;
|
||||
|
||||
@ -158,7 +160,6 @@ enum omap_display_caps {
|
||||
enum omap_dss_display_state {
|
||||
OMAP_DSS_DISPLAY_DISABLED = 0,
|
||||
OMAP_DSS_DISPLAY_ACTIVE,
|
||||
OMAP_DSS_DISPLAY_SUSPENDED,
|
||||
};
|
||||
|
||||
enum omap_dss_audio_state {
|
||||
@ -621,10 +622,6 @@ struct omap_dss_device {
|
||||
struct {
|
||||
struct omap_video_timings timings;
|
||||
|
||||
int acbi; /* ac-bias pin transitions per interrupt */
|
||||
/* Unit: line clocks */
|
||||
int acb; /* ac-bias pin frequency */
|
||||
|
||||
enum omap_dss_dsi_pixel_format dsi_pix_fmt;
|
||||
enum omap_dss_dsi_mode dsi_mode;
|
||||
struct omap_dss_dsi_videomode_timings dsi_vm_timings;
|
||||
@ -686,8 +683,6 @@ struct omap_dss_driver {
|
||||
|
||||
int (*enable)(struct omap_dss_device *display);
|
||||
void (*disable)(struct omap_dss_device *display);
|
||||
int (*suspend)(struct omap_dss_device *display);
|
||||
int (*resume)(struct omap_dss_device *display);
|
||||
int (*run_test)(struct omap_dss_device *display, int test);
|
||||
|
||||
int (*update)(struct omap_dss_device *dssdev,
|
||||
@ -745,6 +740,8 @@ struct omap_dss_driver {
|
||||
|
||||
};
|
||||
|
||||
enum omapdss_version omapdss_get_version(void);
|
||||
|
||||
int omap_dss_register_driver(struct omap_dss_driver *);
|
||||
void omap_dss_unregister_driver(struct omap_dss_driver *);
|
||||
|
||||
@ -754,10 +751,19 @@ void omap_dss_put_device(struct omap_dss_device *dssdev);
|
||||
struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
|
||||
struct omap_dss_device *omap_dss_find_device(void *data,
|
||||
int (*match)(struct omap_dss_device *dssdev, void *data));
|
||||
const char *omapdss_get_default_display_name(void);
|
||||
|
||||
int omap_dss_start_device(struct omap_dss_device *dssdev);
|
||||
void omap_dss_stop_device(struct omap_dss_device *dssdev);
|
||||
|
||||
int dss_feat_get_num_mgrs(void);
|
||||
int dss_feat_get_num_ovls(void);
|
||||
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);
|
||||
|
||||
|
||||
|
||||
int omap_dss_get_num_overlay_managers(void);
|
||||
struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
|
||||
|
||||
@ -779,9 +785,43 @@ typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
|
||||
int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
|
||||
int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
|
||||
|
||||
int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout);
|
||||
int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
|
||||
unsigned long timeout);
|
||||
u32 dispc_read_irqstatus(void);
|
||||
void dispc_clear_irqstatus(u32 mask);
|
||||
u32 dispc_read_irqenable(void);
|
||||
void dispc_write_irqenable(u32 mask);
|
||||
|
||||
int dispc_request_irq(irq_handler_t handler, void *dev_id);
|
||||
void dispc_free_irq(void *dev_id);
|
||||
|
||||
int dispc_runtime_get(void);
|
||||
void dispc_runtime_put(void);
|
||||
|
||||
void dispc_mgr_enable(enum omap_channel channel, bool enable);
|
||||
bool dispc_mgr_is_enabled(enum omap_channel channel);
|
||||
u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
|
||||
u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
|
||||
u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel);
|
||||
bool dispc_mgr_go_busy(enum omap_channel channel);
|
||||
void dispc_mgr_go(enum omap_channel channel);
|
||||
void dispc_mgr_set_lcd_config(enum omap_channel channel,
|
||||
const struct dss_lcd_mgr_config *config);
|
||||
void dispc_mgr_set_timings(enum omap_channel channel,
|
||||
const struct omap_video_timings *timings);
|
||||
void dispc_mgr_setup(enum omap_channel channel,
|
||||
const struct omap_overlay_manager_info *info);
|
||||
|
||||
int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
|
||||
const struct omap_overlay_info *oi,
|
||||
const struct omap_video_timings *timings,
|
||||
int *x_predecim, int *y_predecim);
|
||||
|
||||
int dispc_ovl_enable(enum omap_plane plane, bool enable);
|
||||
bool dispc_ovl_enabled(enum omap_plane plane);
|
||||
void dispc_ovl_set_channel_out(enum omap_plane plane,
|
||||
enum omap_channel channel);
|
||||
int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
|
||||
bool replication, const struct omap_video_timings *mgr_timings,
|
||||
bool mem_to_mem);
|
||||
|
||||
#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
|
||||
#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
|
||||
@ -840,4 +880,35 @@ void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
|
||||
void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
|
||||
struct rfbi_timings *timings);
|
||||
|
||||
int omapdss_compat_init(void);
|
||||
void omapdss_compat_uninit(void);
|
||||
|
||||
struct dss_mgr_ops {
|
||||
void (*start_update)(struct omap_overlay_manager *mgr);
|
||||
int (*enable)(struct omap_overlay_manager *mgr);
|
||||
void (*disable)(struct omap_overlay_manager *mgr);
|
||||
void (*set_timings)(struct omap_overlay_manager *mgr,
|
||||
const struct omap_video_timings *timings);
|
||||
void (*set_lcd_config)(struct omap_overlay_manager *mgr,
|
||||
const struct dss_lcd_mgr_config *config);
|
||||
int (*register_framedone_handler)(struct omap_overlay_manager *mgr,
|
||||
void (*handler)(void *), void *data);
|
||||
void (*unregister_framedone_handler)(struct omap_overlay_manager *mgr,
|
||||
void (*handler)(void *), void *data);
|
||||
};
|
||||
|
||||
int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops);
|
||||
void dss_uninstall_mgr_ops(void);
|
||||
|
||||
void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
|
||||
const struct omap_video_timings *timings);
|
||||
void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
|
||||
const struct dss_lcd_mgr_config *config);
|
||||
int dss_mgr_enable(struct omap_overlay_manager *mgr);
|
||||
void dss_mgr_disable(struct omap_overlay_manager *mgr);
|
||||
void dss_mgr_start_update(struct omap_overlay_manager *mgr);
|
||||
int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
|
||||
void (*handler)(void *), void *data);
|
||||
void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
|
||||
void (*handler)(void *), void *data);
|
||||
#endif
|
||||
|
@ -24,12 +24,15 @@
|
||||
|
||||
#define VIDCON0 (0x00)
|
||||
#define VIDCON0_INTERLACE (1 << 29)
|
||||
#define VIDCON0_VIDOUT_MASK (0x3 << 26)
|
||||
#define VIDCON0_VIDOUT_MASK (0x7 << 26)
|
||||
#define VIDCON0_VIDOUT_SHIFT (26)
|
||||
#define VIDCON0_VIDOUT_RGB (0x0 << 26)
|
||||
#define VIDCON0_VIDOUT_TV (0x1 << 26)
|
||||
#define VIDCON0_VIDOUT_I80_LDI0 (0x2 << 26)
|
||||
#define VIDCON0_VIDOUT_I80_LDI1 (0x3 << 26)
|
||||
#define VIDCON0_VIDOUT_WB_RGB (0x4 << 26)
|
||||
#define VIDCON0_VIDOUT_WB_I80_LDI0 (0x6 << 26)
|
||||
#define VIDCON0_VIDOUT_WB_I80_LDI1 (0x7 << 26)
|
||||
|
||||
#define VIDCON0_L1_DATA_MASK (0x7 << 23)
|
||||
#define VIDCON0_L1_DATA_SHIFT (23)
|
||||
@ -77,6 +80,7 @@
|
||||
#define VIDCON1_LINECNT_MASK (0x7ff << 16)
|
||||
#define VIDCON1_LINECNT_SHIFT (16)
|
||||
#define VIDCON1_LINECNT_GET(_v) (((_v) >> 16) & 0x7ff)
|
||||
#define VIDCON1_FSTATUS_EVEN (1 << 15)
|
||||
#define VIDCON1_VSTATUS_MASK (0x3 << 13)
|
||||
#define VIDCON1_VSTATUS_SHIFT (13)
|
||||
#define VIDCON1_VSTATUS_VSYNC (0x0 << 13)
|
||||
@ -116,6 +120,7 @@
|
||||
|
||||
/* VIDTCON0 */
|
||||
|
||||
#define VIDTCON0 (0x10)
|
||||
#define VIDTCON0_VBPDE_MASK (0xff << 24)
|
||||
#define VIDTCON0_VBPDE_SHIFT (24)
|
||||
#define VIDTCON0_VBPDE_LIMIT (0xff)
|
||||
@ -138,6 +143,7 @@
|
||||
|
||||
/* VIDTCON1 */
|
||||
|
||||
#define VIDTCON1 (0x14)
|
||||
#define VIDTCON1_VFPDE_MASK (0xff << 24)
|
||||
#define VIDTCON1_VFPDE_SHIFT (24)
|
||||
#define VIDTCON1_VFPDE_LIMIT (0xff)
|
||||
@ -158,6 +164,7 @@
|
||||
#define VIDTCON1_HSPW_LIMIT (0xff)
|
||||
#define VIDTCON1_HSPW(_x) ((_x) << 0)
|
||||
|
||||
#define VIDTCON2 (0x18)
|
||||
#define VIDTCON2 (0x18)
|
||||
#define VIDTCON2_LINEVAL_E(_x) ((((_x) & 0x800) >> 11) << 23)
|
||||
#define VIDTCON2_LINEVAL_MASK (0x7ff << 11)
|
||||
@ -173,18 +180,27 @@
|
||||
|
||||
/* WINCONx */
|
||||
|
||||
|
||||
#define WINCON(_win) (0x20 + ((_win) * 4))
|
||||
#define WINCONx_CSCWIDTH_MASK (0x3 << 26)
|
||||
#define WINCONx_CSCWIDTH_SHIFT (26)
|
||||
#define WINCONx_CSCWIDTH_WIDE (0x0 << 26)
|
||||
#define WINCONx_CSCWIDTH_NARROW (0x3 << 26)
|
||||
#define WINCONx_ENLOCAL (1 << 22)
|
||||
#define WINCONx_BUFSTATUS (1 << 21)
|
||||
#define WINCONx_BUFSEL (1 << 20)
|
||||
#define WINCONx_BUFAUTOEN (1 << 19)
|
||||
#define WINCONx_BITSWP (1 << 18)
|
||||
#define WINCONx_BYTSWP (1 << 17)
|
||||
#define WINCONx_HAWSWP (1 << 16)
|
||||
#define WINCONx_WSWP (1 << 15)
|
||||
#define WINCONx_YCbCr (1 << 13)
|
||||
#define WINCONx_BURSTLEN_MASK (0x3 << 9)
|
||||
#define WINCONx_BURSTLEN_SHIFT (9)
|
||||
#define WINCONx_BURSTLEN_16WORD (0x0 << 9)
|
||||
#define WINCONx_BURSTLEN_8WORD (0x1 << 9)
|
||||
#define WINCONx_BURSTLEN_4WORD (0x2 << 9)
|
||||
|
||||
#define WINCONx_ENWIN (1 << 0)
|
||||
|
||||
#define WINCON0_BPPMODE_MASK (0xf << 2)
|
||||
#define WINCON0_BPPMODE_SHIFT (2)
|
||||
#define WINCON0_BPPMODE_1BPP (0x0 << 2)
|
||||
@ -196,9 +212,8 @@
|
||||
#define WINCON0_BPPMODE_18BPP_666 (0x8 << 2)
|
||||
#define WINCON0_BPPMODE_24BPP_888 (0xb << 2)
|
||||
|
||||
#define WINCON1_LOCALSEL_CAMIF (1 << 23)
|
||||
#define WINCON1_BLD_PIX (1 << 6)
|
||||
|
||||
#define WINCON1_ALPHA_SEL (1 << 1)
|
||||
#define WINCON1_BPPMODE_MASK (0xf << 2)
|
||||
#define WINCON1_BPPMODE_SHIFT (2)
|
||||
#define WINCON1_BPPMODE_1BPP (0x0 << 2)
|
||||
@ -216,6 +231,7 @@
|
||||
#define WINCON1_BPPMODE_24BPP_A1887 (0xc << 2)
|
||||
#define WINCON1_BPPMODE_25BPP_A1888 (0xd << 2)
|
||||
#define WINCON1_BPPMODE_28BPP_A4888 (0xd << 2)
|
||||
#define WINCON1_ALPHA_SEL (1 << 1)
|
||||
|
||||
/* S5PV210 */
|
||||
#define SHADOWCON (0x34)
|
||||
@ -225,6 +241,9 @@
|
||||
/* Local input channels (windows 0-2) */
|
||||
#define SHADOWCON_CHx_LOCAL_ENABLE(_win) (1 << (5 + (_win)))
|
||||
|
||||
/* VIDOSDx */
|
||||
|
||||
#define VIDOSD_BASE (0x40)
|
||||
#define VIDOSDxA_TOPLEFT_X_E(_x) ((((_x) & 0x800) >> 11) << 23)
|
||||
#define VIDOSDxA_TOPLEFT_X_MASK (0x7ff << 11)
|
||||
#define VIDOSDxA_TOPLEFT_X_SHIFT (11)
|
||||
@ -293,6 +312,7 @@
|
||||
|
||||
/* Interrupt controls and status */
|
||||
|
||||
#define VIDINTCON0 (0x130)
|
||||
#define VIDINTCON0_FIFOINTERVAL_MASK (0x3f << 20)
|
||||
#define VIDINTCON0_FIFOINTERVAL_SHIFT (20)
|
||||
#define VIDINTCON0_FIFOINTERVAL_LIMIT (0x3f)
|
||||
@ -321,6 +341,9 @@
|
||||
#define VIDINTCON0_FIFIOSEL_SHIFT (5)
|
||||
#define VIDINTCON0_FIFIOSEL_WINDOW0 (0x1 << 5)
|
||||
#define VIDINTCON0_FIFIOSEL_WINDOW1 (0x2 << 5)
|
||||
#define VIDINTCON0_FIFIOSEL_WINDOW2 (0x10 << 5)
|
||||
#define VIDINTCON0_FIFIOSEL_WINDOW3 (0x20 << 5)
|
||||
#define VIDINTCON0_FIFIOSEL_WINDOW4 (0x40 << 5)
|
||||
|
||||
#define VIDINTCON0_FIFOLEVEL_MASK (0x7 << 2)
|
||||
#define VIDINTCON0_FIFOLEVEL_SHIFT (2)
|
||||
@ -357,16 +380,39 @@
|
||||
#define WxKEYCON1_COLVAL_LIMIT (0xffffff)
|
||||
#define WxKEYCON1_COLVAL(_x) ((_x) << 0)
|
||||
|
||||
/* Dithering control */
|
||||
#define DITHMODE (0x170)
|
||||
#define DITHMODE_R_POS_MASK (0x3 << 5)
|
||||
#define DITHMODE_R_POS_SHIFT (5)
|
||||
#define DITHMODE_R_POS_8BIT (0x0 << 5)
|
||||
#define DITHMODE_R_POS_6BIT (0x1 << 5)
|
||||
#define DITHMODE_R_POS_5BIT (0x2 << 5)
|
||||
#define DITHMODE_G_POS_MASK (0x3 << 3)
|
||||
#define DITHMODE_G_POS_SHIFT (3)
|
||||
#define DITHMODE_G_POS_8BIT (0x0 << 3)
|
||||
#define DITHMODE_G_POS_6BIT (0x1 << 3)
|
||||
#define DITHMODE_G_POS_5BIT (0x2 << 3)
|
||||
#define DITHMODE_B_POS_MASK (0x3 << 1)
|
||||
#define DITHMODE_B_POS_SHIFT (1)
|
||||
#define DITHMODE_B_POS_8BIT (0x0 << 1)
|
||||
#define DITHMODE_B_POS_6BIT (0x1 << 1)
|
||||
#define DITHMODE_B_POS_5BIT (0x2 << 1)
|
||||
#define DITHMODE_DITH_EN (1 << 0)
|
||||
|
||||
/* Window blanking (MAP) */
|
||||
|
||||
#define WINxMAP(_win) (0x180 + ((_win) * 4))
|
||||
#define WINxMAP_MAP (1 << 24)
|
||||
#define WINxMAP_MAP_COLOUR_MASK (0xffffff << 0)
|
||||
#define WINxMAP_MAP_COLOUR_SHIFT (0)
|
||||
#define WINxMAP_MAP_COLOUR_LIMIT (0xffffff)
|
||||
#define WINxMAP_MAP_COLOUR(_x) ((_x) << 0)
|
||||
|
||||
/* Winodw palette control */
|
||||
#define WPALCON (0x1A0)
|
||||
#define WPALCON_PAL_UPDATE (1 << 9)
|
||||
#define WPALCON_W4PAL_16BPP_A555 (1 << 8)
|
||||
#define WPALCON_W3PAL_16BPP_A555 (1 << 7)
|
||||
#define WPALCON_W2PAL_16BPP_A555 (1 << 6)
|
||||
#define WPALCON_W1PAL_MASK (0x7 << 3)
|
||||
#define WPALCON_W1PAL_SHIFT (3)
|
||||
#define WPALCON_W1PAL_25BPP_A888 (0x0 << 3)
|
||||
@ -376,7 +422,6 @@
|
||||
#define WPALCON_W1PAL_18BPP (0x4 << 3)
|
||||
#define WPALCON_W1PAL_16BPP_A555 (0x5 << 3)
|
||||
#define WPALCON_W1PAL_16BPP_565 (0x6 << 3)
|
||||
|
||||
#define WPALCON_W0PAL_MASK (0x7 << 0)
|
||||
#define WPALCON_W0PAL_SHIFT (0)
|
||||
#define WPALCON_W0PAL_25BPP_A888 (0x0 << 0)
|
||||
@ -394,115 +439,6 @@
|
||||
#define BLENDCON_NEW_4BIT_ALPHA_VALUE (0 << 0)
|
||||
|
||||
#define S3C_FB_MAX_WIN (5) /* number of hardware windows available. */
|
||||
#define VIDCON1_FSTATUS_EVEN (1 << 15)
|
||||
|
||||
/* Video timing controls */
|
||||
#define VIDTCON0 (0x10)
|
||||
#define VIDTCON1 (0x14)
|
||||
#define VIDTCON2 (0x18)
|
||||
|
||||
/* Window position controls */
|
||||
|
||||
#define WINCON(_win) (0x20 + ((_win) * 4))
|
||||
|
||||
/* OSD1 and OSD4 do not have register D */
|
||||
|
||||
#define VIDOSD_BASE (0x40)
|
||||
|
||||
#define VIDINTCON0 (0x130)
|
||||
|
||||
/* WINCONx */
|
||||
|
||||
#define WINCONx_CSCWIDTH_MASK (0x3 << 26)
|
||||
#define WINCONx_CSCWIDTH_SHIFT (26)
|
||||
#define WINCONx_CSCWIDTH_WIDE (0x0 << 26)
|
||||
#define WINCONx_CSCWIDTH_NARROW (0x3 << 26)
|
||||
|
||||
#define WINCONx_ENLOCAL (1 << 22)
|
||||
#define WINCONx_BUFSTATUS (1 << 21)
|
||||
#define WINCONx_BUFSEL (1 << 20)
|
||||
#define WINCONx_BUFAUTOEN (1 << 19)
|
||||
#define WINCONx_YCbCr (1 << 13)
|
||||
|
||||
#define WINCON1_LOCALSEL_CAMIF (1 << 23)
|
||||
|
||||
#define WINCON2_LOCALSEL_CAMIF (1 << 23)
|
||||
#define WINCON2_BLD_PIX (1 << 6)
|
||||
|
||||
#define WINCON2_ALPHA_SEL (1 << 1)
|
||||
#define WINCON2_BPPMODE_MASK (0xf << 2)
|
||||
#define WINCON2_BPPMODE_SHIFT (2)
|
||||
#define WINCON2_BPPMODE_1BPP (0x0 << 2)
|
||||
#define WINCON2_BPPMODE_2BPP (0x1 << 2)
|
||||
#define WINCON2_BPPMODE_4BPP (0x2 << 2)
|
||||
#define WINCON2_BPPMODE_8BPP_1232 (0x4 << 2)
|
||||
#define WINCON2_BPPMODE_16BPP_565 (0x5 << 2)
|
||||
#define WINCON2_BPPMODE_16BPP_A1555 (0x6 << 2)
|
||||
#define WINCON2_BPPMODE_16BPP_I1555 (0x7 << 2)
|
||||
#define WINCON2_BPPMODE_18BPP_666 (0x8 << 2)
|
||||
#define WINCON2_BPPMODE_18BPP_A1665 (0x9 << 2)
|
||||
#define WINCON2_BPPMODE_19BPP_A1666 (0xa << 2)
|
||||
#define WINCON2_BPPMODE_24BPP_888 (0xb << 2)
|
||||
#define WINCON2_BPPMODE_24BPP_A1887 (0xc << 2)
|
||||
#define WINCON2_BPPMODE_25BPP_A1888 (0xd << 2)
|
||||
#define WINCON2_BPPMODE_28BPP_A4888 (0xd << 2)
|
||||
|
||||
#define WINCON3_BLD_PIX (1 << 6)
|
||||
|
||||
#define WINCON3_ALPHA_SEL (1 << 1)
|
||||
#define WINCON3_BPPMODE_MASK (0xf << 2)
|
||||
#define WINCON3_BPPMODE_SHIFT (2)
|
||||
#define WINCON3_BPPMODE_1BPP (0x0 << 2)
|
||||
#define WINCON3_BPPMODE_2BPP (0x1 << 2)
|
||||
#define WINCON3_BPPMODE_4BPP (0x2 << 2)
|
||||
#define WINCON3_BPPMODE_16BPP_565 (0x5 << 2)
|
||||
#define WINCON3_BPPMODE_16BPP_A1555 (0x6 << 2)
|
||||
#define WINCON3_BPPMODE_16BPP_I1555 (0x7 << 2)
|
||||
#define WINCON3_BPPMODE_18BPP_666 (0x8 << 2)
|
||||
#define WINCON3_BPPMODE_18BPP_A1665 (0x9 << 2)
|
||||
#define WINCON3_BPPMODE_19BPP_A1666 (0xa << 2)
|
||||
#define WINCON3_BPPMODE_24BPP_888 (0xb << 2)
|
||||
#define WINCON3_BPPMODE_24BPP_A1887 (0xc << 2)
|
||||
#define WINCON3_BPPMODE_25BPP_A1888 (0xd << 2)
|
||||
#define WINCON3_BPPMODE_28BPP_A4888 (0xd << 2)
|
||||
|
||||
#define VIDINTCON0_FIFIOSEL_WINDOW2 (0x10 << 5)
|
||||
#define VIDINTCON0_FIFIOSEL_WINDOW3 (0x20 << 5)
|
||||
#define VIDINTCON0_FIFIOSEL_WINDOW4 (0x40 << 5)
|
||||
|
||||
#define DITHMODE (0x170)
|
||||
#define WINxMAP(_win) (0x180 + ((_win) * 4))
|
||||
|
||||
|
||||
#define DITHMODE_R_POS_MASK (0x3 << 5)
|
||||
#define DITHMODE_R_POS_SHIFT (5)
|
||||
#define DITHMODE_R_POS_8BIT (0x0 << 5)
|
||||
#define DITHMODE_R_POS_6BIT (0x1 << 5)
|
||||
#define DITHMODE_R_POS_5BIT (0x2 << 5)
|
||||
|
||||
#define DITHMODE_G_POS_MASK (0x3 << 3)
|
||||
#define DITHMODE_G_POS_SHIFT (3)
|
||||
#define DITHMODE_G_POS_8BIT (0x0 << 3)
|
||||
#define DITHMODE_G_POS_6BIT (0x1 << 3)
|
||||
#define DITHMODE_G_POS_5BIT (0x2 << 3)
|
||||
|
||||
#define DITHMODE_B_POS_MASK (0x3 << 1)
|
||||
#define DITHMODE_B_POS_SHIFT (1)
|
||||
#define DITHMODE_B_POS_8BIT (0x0 << 1)
|
||||
#define DITHMODE_B_POS_6BIT (0x1 << 1)
|
||||
#define DITHMODE_B_POS_5BIT (0x2 << 1)
|
||||
|
||||
#define DITHMODE_DITH_EN (1 << 0)
|
||||
|
||||
#define WPALCON (0x1A0)
|
||||
|
||||
/* Palette control */
|
||||
/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L),
|
||||
* but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */
|
||||
#define WPALCON_W4PAL_16BPP_A555 (1 << 8)
|
||||
#define WPALCON_W3PAL_16BPP_A555 (1 << 7)
|
||||
#define WPALCON_W2PAL_16BPP_A555 (1 << 6)
|
||||
|
||||
|
||||
/* Notes on per-window bpp settings
|
||||
*
|
||||
|
@ -25,8 +25,6 @@ enum sh_mipi_dsi_data_fmt {
|
||||
MIPI_YUV420,
|
||||
};
|
||||
|
||||
struct sh_mobile_lcdc_chan_cfg;
|
||||
|
||||
#define SH_MIPI_DSI_HSABM (1 << 0)
|
||||
#define SH_MIPI_DSI_HBPBM (1 << 1)
|
||||
#define SH_MIPI_DSI_HFPBM (1 << 2)
|
||||
@ -47,7 +45,7 @@ struct sh_mobile_lcdc_chan_cfg;
|
||||
|
||||
struct sh_mipi_dsi_info {
|
||||
enum sh_mipi_dsi_data_fmt data_format;
|
||||
struct sh_mobile_lcdc_chan_cfg *lcd_chan;
|
||||
int channel;
|
||||
int lane;
|
||||
unsigned long flags;
|
||||
u32 clksrc;
|
||||
|
@ -163,7 +163,6 @@ struct sh_mobile_lcdc_bl_info {
|
||||
const char *name;
|
||||
int max_brightness;
|
||||
int (*set_brightness)(int brightness);
|
||||
int (*get_brightness)(void);
|
||||
};
|
||||
|
||||
struct sh_mobile_lcdc_overlay_cfg {
|
||||
|
Loading…
Reference in New Issue
Block a user