mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-17 23:25:46 +08:00
Merge tag 'omapdss-for-3.8' of git://gitorious.org/linux-omap-dss2/linux into for-linus
OMAPDSS changes for 3.8, 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 * tag 'omapdss-for-3.8' of git://gitorious.org/linux-omap-dss2/linux: (140 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 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 OMAPDSS: manage framedone irq with mgr ops OMAPDSS: add manager ops ...
This commit is contained in:
commit
e7f5c9a16e
@ -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.
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -100,17 +100,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
|
||||
@ -161,8 +164,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;
|
||||
}
|
||||
@ -284,6 +289,35 @@ err:
|
||||
return ERR_PTR(r);
|
||||
}
|
||||
|
||||
static enum omapdss_version __init omap_display_get_version(void)
|
||||
{
|
||||
if (cpu_is_omap24xx())
|
||||
return OMAPDSS_VER_OMAP24xx;
|
||||
else if (cpu_is_omap3630())
|
||||
return OMAPDSS_VER_OMAP3630;
|
||||
else if (cpu_is_omap34xx()) {
|
||||
if (soc_is_am35xx()) {
|
||||
return OMAPDSS_VER_AM35xx;
|
||||
} else {
|
||||
if (omap_rev() < OMAP3430_REV_ES3_0)
|
||||
return OMAPDSS_VER_OMAP34xx_ES1;
|
||||
else
|
||||
return OMAPDSS_VER_OMAP34xx_ES3;
|
||||
}
|
||||
} else if (omap_rev() == OMAP4430_REV_ES1_0)
|
||||
return OMAPDSS_VER_OMAP4430_ES1;
|
||||
else if (omap_rev() == OMAP4430_REV_ES2_0 ||
|
||||
omap_rev() == OMAP4430_REV_ES2_1 ||
|
||||
omap_rev() == OMAP4430_REV_ES2_2)
|
||||
return OMAPDSS_VER_OMAP4430_ES2;
|
||||
else if (cpu_is_omap44xx())
|
||||
return OMAPDSS_VER_OMAP4;
|
||||
else if (soc_is_omap54xx())
|
||||
return OMAPDSS_VER_OMAP5;
|
||||
else
|
||||
return OMAPDSS_VER_UNKNOWN;
|
||||
}
|
||||
|
||||
int __init omap_display_init(struct omap_dss_board_info *board_data)
|
||||
{
|
||||
int r = 0;
|
||||
@ -291,9 +325,18 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
|
||||
int i, oh_count;
|
||||
const struct omap_dss_hwmod_data *curr_dss_hwmod;
|
||||
struct platform_device *dss_pdev;
|
||||
enum omapdss_version ver;
|
||||
|
||||
/* create omapdss device */
|
||||
|
||||
ver = omap_display_get_version();
|
||||
|
||||
if (ver == OMAPDSS_VER_UNKNOWN) {
|
||||
pr_err("DSS not supported on this SoC\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
board_data->version = ver;
|
||||
board_data->dsi_enable_pads = omap_dsi_enable_pads;
|
||||
board_data->dsi_disable_pads = omap_dsi_disable_pads;
|
||||
board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count;
|
||||
|
@ -160,19 +160,3 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
|
||||
sdrc_write_reg(l, SDRC_POWER);
|
||||
omap2_sms_save_context();
|
||||
}
|
||||
|
||||
void omap2_sms_write_rot_control(u32 val, unsigned ctx)
|
||||
{
|
||||
sms_write_reg(val, SMS_ROT_CONTROL(ctx));
|
||||
}
|
||||
|
||||
void omap2_sms_write_rot_size(u32 val, unsigned ctx)
|
||||
{
|
||||
sms_write_reg(val, SMS_ROT_SIZE(ctx));
|
||||
}
|
||||
|
||||
void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
|
||||
{
|
||||
sms_write_reg(val, SMS_ROT_PHYSICAL_BA(ctx));
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <plat/common.h>
|
||||
#include <plat/vram.h>
|
||||
#include <linux/platform_data/dsp-omap.h>
|
||||
#include <plat/dma.h>
|
||||
|
||||
@ -25,7 +24,6 @@
|
||||
|
||||
void __init omap_reserve(void)
|
||||
{
|
||||
omap_vram_reserve_sdram_memblock();
|
||||
omap_dsp_reserve_sdram_memblock();
|
||||
omap_secure_ram_reserve_memblock();
|
||||
omap_barrier_reserve_memblock();
|
||||
|
@ -29,10 +29,72 @@
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/omapfb.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#ifdef CONFIG_OMAP2_VRFB
|
||||
|
||||
/*
|
||||
* The first memory resource is the register region for VRFB,
|
||||
* the rest are VRFB virtual memory areas for each VRFB context.
|
||||
*/
|
||||
|
||||
static const struct resource omap2_vrfb_resources[] = {
|
||||
DEFINE_RES_MEM_NAMED(0x68008000u, 0x40, "vrfb-regs"),
|
||||
DEFINE_RES_MEM_NAMED(0x70000000u, 0x4000000, "vrfb-area-0"),
|
||||
DEFINE_RES_MEM_NAMED(0x74000000u, 0x4000000, "vrfb-area-1"),
|
||||
DEFINE_RES_MEM_NAMED(0x78000000u, 0x4000000, "vrfb-area-2"),
|
||||
DEFINE_RES_MEM_NAMED(0x7c000000u, 0x4000000, "vrfb-area-3"),
|
||||
};
|
||||
|
||||
static const struct resource omap3_vrfb_resources[] = {
|
||||
DEFINE_RES_MEM_NAMED(0x6C000180u, 0xc0, "vrfb-regs"),
|
||||
DEFINE_RES_MEM_NAMED(0x70000000u, 0x4000000, "vrfb-area-0"),
|
||||
DEFINE_RES_MEM_NAMED(0x74000000u, 0x4000000, "vrfb-area-1"),
|
||||
DEFINE_RES_MEM_NAMED(0x78000000u, 0x4000000, "vrfb-area-2"),
|
||||
DEFINE_RES_MEM_NAMED(0x7c000000u, 0x4000000, "vrfb-area-3"),
|
||||
DEFINE_RES_MEM_NAMED(0xe0000000u, 0x4000000, "vrfb-area-4"),
|
||||
DEFINE_RES_MEM_NAMED(0xe4000000u, 0x4000000, "vrfb-area-5"),
|
||||
DEFINE_RES_MEM_NAMED(0xe8000000u, 0x4000000, "vrfb-area-6"),
|
||||
DEFINE_RES_MEM_NAMED(0xec000000u, 0x4000000, "vrfb-area-7"),
|
||||
DEFINE_RES_MEM_NAMED(0xf0000000u, 0x4000000, "vrfb-area-8"),
|
||||
DEFINE_RES_MEM_NAMED(0xf4000000u, 0x4000000, "vrfb-area-9"),
|
||||
DEFINE_RES_MEM_NAMED(0xf8000000u, 0x4000000, "vrfb-area-10"),
|
||||
DEFINE_RES_MEM_NAMED(0xfc000000u, 0x4000000, "vrfb-area-11"),
|
||||
};
|
||||
|
||||
static int __init omap_init_vrfb(void)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
const struct resource *res;
|
||||
unsigned int num_res;
|
||||
|
||||
if (cpu_is_omap24xx()) {
|
||||
res = omap2_vrfb_resources;
|
||||
num_res = ARRAY_SIZE(omap2_vrfb_resources);
|
||||
} else if (cpu_is_omap34xx()) {
|
||||
res = omap3_vrfb_resources;
|
||||
num_res = ARRAY_SIZE(omap3_vrfb_resources);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pdev = platform_device_register_resndata(NULL, "omapvrfb", -1,
|
||||
res, num_res, NULL, 0);
|
||||
|
||||
if (IS_ERR(pdev))
|
||||
return PTR_ERR(pdev);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(omap_init_vrfb);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
|
||||
|
||||
static bool omapfb_lcd_configured;
|
||||
@ -45,7 +107,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,
|
||||
@ -81,7 +143,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,
|
||||
|
@ -94,9 +94,6 @@
|
||||
/* SMS register offsets - read/write with sms_{read,write}_reg() */
|
||||
|
||||
#define SMS_SYSCONFIG 0x010
|
||||
#define SMS_ROT_CONTROL(context) (0x180 + 0x10 * context)
|
||||
#define SMS_ROT_SIZE(context) (0x184 + 0x10 * context)
|
||||
#define SMS_ROT_PHYSICAL_BA(context) (0x188 + 0x10 * context)
|
||||
/* REVISIT: fill in other SMS registers here */
|
||||
|
||||
|
||||
@ -137,10 +134,6 @@ int omap2_sdrc_get_params(unsigned long r,
|
||||
void omap2_sms_save_context(void);
|
||||
void omap2_sms_restore_context(void);
|
||||
|
||||
void omap2_sms_write_rot_control(u32 val, unsigned ctx);
|
||||
void omap2_sms_write_rot_size(u32 val, unsigned ctx);
|
||||
void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx);
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP2
|
||||
|
||||
struct memory_timings {
|
||||
|
@ -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
|
@ -44,9 +44,7 @@
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/dma.h>
|
||||
#include <plat/vrfb.h>
|
||||
#include <video/omapvrfb.h>
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include "omap_voutlib.h"
|
||||
@ -2064,7 +2062,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
|
||||
@ -2186,14 +2184,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) {
|
||||
@ -2288,6 +2295,8 @@ probe_err1:
|
||||
}
|
||||
probe_err0:
|
||||
kfree(vid_dev);
|
||||
err_dss_init:
|
||||
omapdss_compat_uninit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <media/v4l2-device.h>
|
||||
|
||||
#include <plat/dma.h>
|
||||
#include <plat/vrfb.h>
|
||||
#include <video/omapvrfb.h>
|
||||
|
||||
#include "omap_voutdef.h"
|
||||
#include "omap_voutlib.h"
|
||||
|
@ -12,7 +12,7 @@
|
||||
#define OMAP_VOUTDEF_H
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <plat/vrfb.h>
|
||||
#include <video/omapvrfb.h>
|
||||
|
||||
#define YUYV_BPP 2
|
||||
#define RGB565_BPP 2
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -572,6 +572,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);
|
||||
@ -583,6 +591,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;
|
||||
}
|
||||
|
||||
@ -618,6 +627,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;
|
||||
|
||||
|
@ -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();
|
||||
|
||||
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,11 +32,10 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
@ -78,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;
|
||||
@ -98,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)
|
||||
@ -153,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;
|
||||
@ -303,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;
|
||||
@ -374,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:
|
||||
@ -431,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) {
|
||||
@ -448,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;
|
||||
@ -461,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)
|
||||
{
|
||||
@ -750,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,29 +877,45 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
|
||||
.dpi_select_source = &dss_dpi_select_source_omap5,
|
||||
};
|
||||
|
||||
static int __init dss_init_features(struct device *dev)
|
||||
static int __init dss_init_features(struct platform_device *pdev)
|
||||
{
|
||||
const struct dss_features *src;
|
||||
struct dss_features *dst;
|
||||
|
||||
dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
|
||||
dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
|
||||
if (!dst) {
|
||||
dev_err(dev, "Failed to allocate local DSS Features\n");
|
||||
dev_err(&pdev->dev, "Failed to allocate local DSS Features\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (cpu_is_omap24xx())
|
||||
switch (omapdss_get_version()) {
|
||||
case OMAPDSS_VER_OMAP24xx:
|
||||
src = &omap24xx_dss_feats;
|
||||
else if (cpu_is_omap3630())
|
||||
src = &omap3630_dss_feats;
|
||||
else if (cpu_is_omap34xx())
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP34xx_ES1:
|
||||
case OMAPDSS_VER_OMAP34xx_ES3:
|
||||
case OMAPDSS_VER_AM35xx:
|
||||
src = &omap34xx_dss_feats;
|
||||
else if (cpu_is_omap44xx())
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP3630:
|
||||
src = &omap3630_dss_feats;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP4430_ES1:
|
||||
case OMAPDSS_VER_OMAP4430_ES2:
|
||||
case OMAPDSS_VER_OMAP4:
|
||||
src = &omap44xx_dss_feats;
|
||||
else if (soc_is_omap54xx())
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP5:
|
||||
src = &omap54xx_dss_feats;
|
||||
else
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
dss.feat = dst;
|
||||
@ -835,7 +932,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
|
||||
|
||||
dss.pdev = pdev;
|
||||
|
||||
r = dss_init_features(&dss.pdev->dev);
|
||||
r = dss_init_features(dss.pdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -856,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 */
|
||||
@ -888,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,12 +18,12 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
@ -430,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[] = {
|
||||
@ -446,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[] = {
|
||||
@ -462,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[] = {
|
||||
@ -478,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[] = {
|
||||
@ -821,14 +813,25 @@ 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
|
||||
|
||||
};
|
||||
|
||||
void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data)
|
||||
void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
|
||||
enum omapdss_version version)
|
||||
{
|
||||
if (cpu_is_omap44xx())
|
||||
switch (version) {
|
||||
case OMAPDSS_VER_OMAP4430_ES1:
|
||||
case OMAPDSS_VER_OMAP4430_ES2:
|
||||
case OMAPDSS_VER_OMAP4:
|
||||
ip_data->ops = &omap4_hdmi_functions;
|
||||
break;
|
||||
default:
|
||||
ip_data->ops = NULL;
|
||||
}
|
||||
|
||||
WARN_ON(ip_data->ops == NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -837,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)
|
||||
{
|
||||
@ -862,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)
|
||||
{
|
||||
@ -929,29 +937,44 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type)
|
||||
return omap_current_dss_features->supported_rotation_types & rot_type;
|
||||
}
|
||||
|
||||
void dss_features_init(void)
|
||||
void dss_features_init(enum omapdss_version version)
|
||||
{
|
||||
if (cpu_is_omap24xx())
|
||||
switch (version) {
|
||||
case OMAPDSS_VER_OMAP24xx:
|
||||
omap_current_dss_features = &omap2_dss_features;
|
||||
else if (cpu_is_omap3630())
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP34xx_ES1:
|
||||
case OMAPDSS_VER_OMAP34xx_ES3:
|
||||
omap_current_dss_features = &omap3430_dss_features;
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP3630:
|
||||
omap_current_dss_features = &omap3630_dss_features;
|
||||
else if (cpu_is_omap34xx()) {
|
||||
if (soc_is_am35xx()) {
|
||||
omap_current_dss_features = &am35xx_dss_features;
|
||||
} else {
|
||||
omap_current_dss_features = &omap3430_dss_features;
|
||||
}
|
||||
}
|
||||
else if (omap_rev() == OMAP4430_REV_ES1_0)
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP4430_ES1:
|
||||
omap_current_dss_features = &omap4430_es1_0_dss_features;
|
||||
else if (omap_rev() == OMAP4430_REV_ES2_0 ||
|
||||
omap_rev() == OMAP4430_REV_ES2_1 ||
|
||||
omap_rev() == OMAP4430_REV_ES2_2)
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP4430_ES2:
|
||||
omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
|
||||
else if (cpu_is_omap44xx())
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP4:
|
||||
omap_current_dss_features = &omap4_dss_features;
|
||||
else if (soc_is_omap54xx())
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_OMAP5:
|
||||
omap_current_dss_features = &omap5_dss_features;
|
||||
else
|
||||
break;
|
||||
|
||||
case OMAPDSS_VER_AM35xx:
|
||||
omap_current_dss_features = &am35xx_dss_features;
|
||||
break;
|
||||
|
||||
default:
|
||||
DSSWARN("Unsupported OMAP version");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
@ -123,8 +116,9 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type);
|
||||
|
||||
bool dss_has_feature(enum dss_feat_id id);
|
||||
void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
|
||||
void dss_features_init(void);
|
||||
void dss_features_init(enum omapdss_version version);
|
||||
#if defined(CONFIG_OMAP4_DSS_HDMI)
|
||||
void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data);
|
||||
void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
|
||||
enum omapdss_version version);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -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)
|
||||
@ -333,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);
|
||||
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);
|
||||
@ -355,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");
|
||||
|
||||
@ -398,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)) {
|
||||
|
||||
@ -500,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);
|
||||
@ -521,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;
|
||||
@ -548,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);
|
||||
|
||||
@ -582,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;
|
||||
|
||||
@ -600,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,
|
||||
@ -715,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;
|
||||
@ -737,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;
|
||||
@ -912,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;
|
||||
|
||||
@ -970,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;
|
||||
}
|
||||
@ -999,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;
|
||||
@ -1022,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;
|
||||
}
|
||||
|
||||
@ -1033,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);
|
||||
|
||||
@ -1044,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)
|
||||
@ -1067,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 <plat/vrfb.h>
|
||||
#include <plat/vram.h>
|
||||
#include <video/omapvrfb.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,9 +31,7 @@
|
||||
#include <linux/omapfb.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/vram.h>
|
||||
#include <plat/vrfb.h>
|
||||
#include <video/omapvrfb.h>
|
||||
|
||||
#include "omapfb.h"
|
||||
|
||||
@ -1259,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 &&
|
||||
@ -1284,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;
|
||||
|
||||
@ -1336,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;
|
||||
@ -1388,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;
|
||||
@ -1403,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;
|
||||
|
||||
@ -1532,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;
|
||||
|
||||
@ -1611,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;
|
||||
@ -1626,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) {
|
||||
@ -1883,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)
|
||||
@ -2259,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) {
|
||||
@ -2294,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;
|
||||
}
|
||||
@ -2372,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");
|
||||
|
||||
@ -2390,28 +2438,28 @@ 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;
|
||||
}
|
||||
|
||||
/* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
|
||||
* available for OMAP2 and OMAP3
|
||||
*/
|
||||
if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
|
||||
if (def_vrfb && !omap_vrfb_supported()) {
|
||||
def_vrfb = 0;
|
||||
dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
|
||||
"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) {
|
||||
@ -2434,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;
|
||||
@ -2451,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) {
|
||||
@ -2510,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;
|
||||
@ -2525,6 +2589,8 @@ static int __exit omapfb_remove(struct platform_device *pdev)
|
||||
|
||||
omapfb_free_resources(fbdev);
|
||||
|
||||
omapdss_compat_uninit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <linux/omapfb.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <plat/vrfb.h>
|
||||
#include <video/omapvrfb.h>
|
||||
|
||||
#include "omapfb.h"
|
||||
|
||||
@ -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;
|
||||
}
|
@ -26,9 +26,9 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <plat/vrfb.h>
|
||||
#include <plat/sdrc.h>
|
||||
#include <video/omapvrfb.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
|
||||
@ -36,10 +36,10 @@
|
||||
#define DBG(format, ...)
|
||||
#endif
|
||||
|
||||
#define SMS_ROT_VIRT_BASE(context, rot) \
|
||||
(((context >= 4) ? 0xD0000000 : 0x70000000) \
|
||||
+ (0x4000000 * (context)) \
|
||||
+ (0x1000000 * (rot)))
|
||||
#define SMS_ROT_CONTROL(context) (0x0 + 0x10 * context)
|
||||
#define SMS_ROT_SIZE(context) (0x4 + 0x10 * context)
|
||||
#define SMS_ROT_PHYSICAL_BA(context) (0x8 + 0x10 * context)
|
||||
#define SMS_ROT_VIRT_BASE(rot) (0x1000000 * (rot))
|
||||
|
||||
#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
|
||||
|
||||
@ -53,10 +53,16 @@
|
||||
#define SMS_PW_OFFSET 4
|
||||
#define SMS_PS_OFFSET 0
|
||||
|
||||
#define VRFB_NUM_CTXS 12
|
||||
/* bitmap of reserved contexts */
|
||||
static unsigned long ctx_map;
|
||||
|
||||
struct vrfb_ctx {
|
||||
u32 base;
|
||||
u32 physical_ba;
|
||||
u32 control;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(ctx_lock);
|
||||
|
||||
/*
|
||||
@ -65,17 +71,34 @@ static DEFINE_MUTEX(ctx_lock);
|
||||
* we don't need locking, since no drivers will run until after the wake-up
|
||||
* has finished.
|
||||
*/
|
||||
static struct {
|
||||
u32 physical_ba;
|
||||
u32 control;
|
||||
u32 size;
|
||||
} vrfb_hw_context[VRFB_NUM_CTXS];
|
||||
|
||||
static void __iomem *vrfb_base;
|
||||
|
||||
static int num_ctxs;
|
||||
static struct vrfb_ctx *ctxs;
|
||||
|
||||
static bool vrfb_loaded;
|
||||
|
||||
static void omap2_sms_write_rot_control(u32 val, unsigned ctx)
|
||||
{
|
||||
__raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx));
|
||||
}
|
||||
|
||||
static void omap2_sms_write_rot_size(u32 val, unsigned ctx)
|
||||
{
|
||||
__raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx));
|
||||
}
|
||||
|
||||
static void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
|
||||
{
|
||||
__raw_writel(val, vrfb_base + SMS_ROT_PHYSICAL_BA(ctx));
|
||||
}
|
||||
|
||||
static inline void restore_hw_context(int ctx)
|
||||
{
|
||||
omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx);
|
||||
omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx);
|
||||
omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx);
|
||||
omap2_sms_write_rot_control(ctxs[ctx].control, ctx);
|
||||
omap2_sms_write_rot_size(ctxs[ctx].size, ctx);
|
||||
omap2_sms_write_rot_physical_ba(ctxs[ctx].physical_ba, ctx);
|
||||
}
|
||||
|
||||
static u32 get_image_width_roundup(u16 width, u8 bytespp)
|
||||
@ -196,9 +219,9 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
|
||||
control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET;
|
||||
control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
|
||||
|
||||
vrfb_hw_context[ctx].physical_ba = paddr;
|
||||
vrfb_hw_context[ctx].size = size;
|
||||
vrfb_hw_context[ctx].control = control;
|
||||
ctxs[ctx].physical_ba = paddr;
|
||||
ctxs[ctx].size = size;
|
||||
ctxs[ctx].control = control;
|
||||
|
||||
omap2_sms_write_rot_physical_ba(paddr, ctx);
|
||||
omap2_sms_write_rot_size(size, ctx);
|
||||
@ -274,11 +297,11 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
|
||||
|
||||
mutex_lock(&ctx_lock);
|
||||
|
||||
for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
|
||||
for (ctx = 0; ctx < num_ctxs; ++ctx)
|
||||
if ((ctx_map & (1 << ctx)) == 0)
|
||||
break;
|
||||
|
||||
if (ctx == VRFB_NUM_CTXS) {
|
||||
if (ctx == num_ctxs) {
|
||||
pr_err("vrfb: no free contexts\n");
|
||||
r = -EBUSY;
|
||||
goto out;
|
||||
@ -293,7 +316,7 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
|
||||
vrfb->context = ctx;
|
||||
|
||||
for (rot = 0; rot < 4; ++rot) {
|
||||
paddr = SMS_ROT_VIRT_BASE(ctx, rot);
|
||||
paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot);
|
||||
if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
|
||||
pr_err("vrfb: failed to reserve VRFB "
|
||||
"area for ctx %d, rotation %d\n",
|
||||
@ -314,3 +337,80 @@ out:
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_vrfb_request_ctx);
|
||||
|
||||
bool omap_vrfb_supported(void)
|
||||
{
|
||||
return vrfb_loaded;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_vrfb_supported);
|
||||
|
||||
static int __init vrfb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *mem;
|
||||
int i;
|
||||
|
||||
/* first resource is the register res, the rest are vrfb contexts */
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!mem) {
|
||||
dev_err(&pdev->dev, "can't get vrfb base address\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vrfb_base = devm_request_and_ioremap(&pdev->dev, mem);
|
||||
if (!vrfb_base) {
|
||||
dev_err(&pdev->dev, "can't ioremap vrfb memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
num_ctxs = pdev->num_resources - 1;
|
||||
|
||||
ctxs = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct vrfb_ctx) * num_ctxs,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!ctxs)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num_ctxs; ++i) {
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
|
||||
if (!mem) {
|
||||
dev_err(&pdev->dev, "can't get vrfb ctx %d address\n",
|
||||
i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctxs[i].base = mem->start;
|
||||
}
|
||||
|
||||
vrfb_loaded = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit vrfb_remove(struct platform_device *pdev)
|
||||
{
|
||||
vrfb_loaded = false;
|
||||
}
|
||||
|
||||
static struct platform_driver vrfb_driver = {
|
||||
.driver.name = "omapvrfb",
|
||||
.remove = __exit_p(vrfb_remove),
|
||||
};
|
||||
|
||||
static int __init vrfb_init(void)
|
||||
{
|
||||
return platform_driver_probe(&vrfb_driver, &vrfb_probe);
|
||||
}
|
||||
|
||||
static void __exit vrfb_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&vrfb_driver);
|
||||
}
|
||||
|
||||
module_init(vrfb_init);
|
||||
module_exit(vrfb_exit);
|
||||
|
||||
MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
|
||||
MODULE_DESCRIPTION("OMAP VRFB");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -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 {
|
||||
@ -314,6 +315,19 @@ int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel);
|
||||
int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel);
|
||||
void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel);
|
||||
|
||||
enum omapdss_version {
|
||||
OMAPDSS_VER_UNKNOWN = 0,
|
||||
OMAPDSS_VER_OMAP24xx,
|
||||
OMAPDSS_VER_OMAP34xx_ES1, /* OMAP3430 ES1.0, 2.0 */
|
||||
OMAPDSS_VER_OMAP34xx_ES3, /* OMAP3430 ES3.0+ */
|
||||
OMAPDSS_VER_OMAP3630,
|
||||
OMAPDSS_VER_AM35xx,
|
||||
OMAPDSS_VER_OMAP4430_ES1, /* OMAP4430 ES1.0 */
|
||||
OMAPDSS_VER_OMAP4430_ES2, /* OMAP4430 ES2.0, 2.1, 2.2 */
|
||||
OMAPDSS_VER_OMAP4, /* All other OMAP4s */
|
||||
OMAPDSS_VER_OMAP5,
|
||||
};
|
||||
|
||||
/* Board specific data */
|
||||
struct omap_dss_board_info {
|
||||
int (*get_context_loss_count)(struct device *dev);
|
||||
@ -323,6 +337,7 @@ struct omap_dss_board_info {
|
||||
int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask);
|
||||
void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask);
|
||||
int (*set_min_bus_tput)(struct device *dev, unsigned long r);
|
||||
enum omapdss_version version;
|
||||
};
|
||||
|
||||
/* Init with the board info */
|
||||
@ -607,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;
|
||||
@ -672,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,
|
||||
@ -731,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 *);
|
||||
|
||||
@ -740,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);
|
||||
|
||||
@ -765,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)
|
||||
@ -826,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
|
||||
|
@ -36,6 +36,7 @@ struct vrfb {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OMAP2_VRFB
|
||||
extern bool omap_vrfb_supported(void);
|
||||
extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
|
||||
extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
|
||||
extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
|
||||
@ -49,6 +50,7 @@ extern int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot);
|
||||
extern void omap_vrfb_restore_context(void);
|
||||
|
||||
#else
|
||||
static inline bool omap_vrfb_supported(void) { return false; }
|
||||
static inline int omap_vrfb_request_ctx(struct vrfb *vrfb) { return 0; }
|
||||
static inline void omap_vrfb_release_ctx(struct vrfb *vrfb) {}
|
||||
static inline void omap_vrfb_adjust_size(u16 *width, u16 *height,
|
Loading…
Reference in New Issue
Block a user