aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Marklund <robert.marklund@stericsson.com>2010-08-18 13:22:28 +0200
committerJohn Rigby <john.rigby@linaro.org>2010-09-02 22:45:53 -0600
commita77c874f9b85691ea4af5362e2b5c9fc55a76acc (patch)
tree6e911eef3a565c2ffa8b284210586793ad5c8ce9
parente43925f4db29bd19a8907b0cba1adde455f07a34 (diff)
MCDE Fixes: Added http://gerrit.lud.stericsson.com/gerrit/#change,3792 patchset Added patch set: http://gerrit.lud.stericsson.com/gerrit/#change,3751 Enabled single buffered fb in config.
Change-Id: I59ed2dcd1d45f896177f0f3be425b158f03fd0ee Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/4097 Tested-by: Robert MARKLUND <robert.marklund@stericsson.com> Reviewed-by: Robert ROSENGREN <robert.rosengren@stericsson.com>
-rwxr-xr-xarch/arm/mach-ux500/Kconfig-arch14
-rw-r--r--arch/arm/mach-ux500/board-mop500-mcde.c144
-rw-r--r--drivers/video/av8100/av8100.c14
-rwxr-xr-xdrivers/video/av8100/hdmi.c13
-rw-r--r--drivers/video/mcde/display-ab8500.c1
-rwxr-xr-xdrivers/video/mcde/display-av8100.c2
-rw-r--r--drivers/video/mcde/display-generic_dsi.c17
-rw-r--r--drivers/video/mcde/mcde_display.c6
-rw-r--r--drivers/video/mcde/mcde_fb.c6
-rw-r--r--drivers/video/mcde/mcde_hw.c251
-rw-r--r--include/video/mcde.h35
-rw-r--r--include/video/mcde_fb.h1
-rw-r--r--kernel.spec5
13 files changed, 397 insertions, 112 deletions
diff --git a/arch/arm/mach-ux500/Kconfig-arch b/arch/arm/mach-ux500/Kconfig-arch
index 3e6d35c5c46..8e478c923dd 100755
--- a/arch/arm/mach-ux500/Kconfig-arch
+++ b/arch/arm/mach-ux500/Kconfig-arch
@@ -55,6 +55,13 @@ config DISPLAY_GENERIC_DSI_PRIMARY_VSYNC
help
Say yes to enable v-sync for primary display
+config DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC
+ bool "Enable auto sync for primary display"
+ depends on DISPLAY_GENERIC_DSI_PRIMARY
+ default n
+ help
+ Say yes to enable auto sync for primary display
+
config DISPLAY_GENERIC_DSI_SECONDARY
bool "Sub display support"
depends on MACH_U8500_MOP && FB_MCDE
@@ -70,6 +77,13 @@ config DISPLAY_GENERIC_DSI_SECONDARY_VSYNC
help
Say yes to enable v-sync for secondary display
+config DISPLAY_GENERIC_DSI_SECONDARY_AUTO_SYNC
+ bool "Enable auto sync for secondary display"
+ depends on DISPLAY_GENERIC_DSI_SECONDARY
+ default n
+ help
+ Say yes to enable auto sync for secondary display
+
config DISPLAY_AB8500_TERTIARY
bool "AB8500 TVout display support"
depends on MACH_U8500_MOP && !AV8100_SDTV && FB_MCDE
diff --git a/arch/arm/mach-ux500/board-mop500-mcde.c b/arch/arm/mach-ux500/board-mop500-mcde.c
index eb13cbf9a5e..e8e0acb440b 100644
--- a/arch/arm/mach-ux500/board-mop500-mcde.c
+++ b/arch/arm/mach-ux500/board-mop500-mcde.c
@@ -21,6 +21,10 @@
#define DSI_UNIT_INTERVAL_1 0x9
#define DSI_UNIT_INTERVAL_2 0x6
+#define PRIMARY_DISPLAY_ID 0
+#define SECONDARY_DISPLAY_ID 1
+#define TERTIARY_DISPLAY_ID 2
+
static bool rotate_main = true;
static bool display_initialized_during_boot;
@@ -54,8 +58,13 @@ static struct mcde_port port0 = {
.pixel_format = MCDE_PORTPIXFMT_DSI_24BPP,
.ifc = 1,
.link = 0,
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC
+ .sync_src = MCDE_SYNCSRC_OFF,
+ .update_auto_trig = true,
+#else
.sync_src = MCDE_SYNCSRC_BTA,
.update_auto_trig = false,
+#endif
.phy = {
.dsi = {
.virt_id = 0,
@@ -78,7 +87,7 @@ struct mcde_display_generic_platform_data generic_display0_pdata = {
struct mcde_display_device generic_display0 = {
.name = "mcde_disp_generic",
- .id = 0,
+ .id = PRIMARY_DISPLAY_ID,
.port = &port0,
.chnl_id = MCDE_CHNL_A,
.fifo = MCDE_FIFO_C0,
@@ -106,8 +115,13 @@ static struct mcde_port subdisplay_port = {
.pixel_format = MCDE_PORTPIXFMT_DSI_24BPP,
.ifc = 1,
.link = 1,
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY_AUTO_SYNC
+ .sync_src = MCDE_SYNCSRC_OFF,
+ .update_auto_trig = true,
+#else
.sync_src = MCDE_SYNCSRC_BTA,
.update_auto_trig = false,
+#endif
.phy = {
.dsi = {
.virt_id = 0,
@@ -131,7 +145,7 @@ static struct mcde_display_generic_platform_data generic_subdisplay_pdata = {
static struct mcde_display_device generic_subdisplay = {
.name = "mcde_disp_generic_subdisplay",
- .id = 1,
+ .id = SECONDARY_DISPLAY_ID,
.port = &subdisplay_port,
.chnl_id = MCDE_CHNL_C1,
.fifo = MCDE_FIFO_C1,
@@ -237,7 +251,7 @@ alt_func_failed:
static struct mcde_display_device tvout_ab8500_display = {
.name = "mcde_tv_ab8500",
- .id = 2,
+ .id = TERTIARY_DISPLAY_ID,
.port = &port_tvout1,
.chnl_id = MCDE_CHNL_B,
.fifo = MCDE_FIFO_B,
@@ -347,7 +361,7 @@ alt_func_failed:
static struct mcde_display_device av8100_hdmi = {
.name = "av8100_hdmi",
- .id = 2,
+ .id = TERTIARY_DISPLAY_ID,
.port = &port2,
.chnl_id = MCDE_CHNL_B,
.fifo = MCDE_FIFO_B,
@@ -376,29 +390,40 @@ static int display_registered_callback(struct notifier_block *nb,
{
struct mcde_display_device *ddev = dev;
u16 width, height;
+ u16 virtual_width, virtual_height;
bool rotate;
if (event != MCDE_DSS_EVENT_DISPLAY_REGISTERED)
return 0;
- if (ddev->id < 0 || ddev->id >= ARRAY_SIZE(fbs))
+ if (ddev->id < PRIMARY_DISPLAY_ID || ddev->id >= ARRAY_SIZE(fbs))
return 0;
mcde_dss_get_native_resolution(ddev, &width, &height);
- rotate = (ddev->id == 0 && rotate_main);
- if (rotate) {
- u16 tmp = height;
- height = width;
- width = tmp;
- }
+ rotate = (ddev->id == PRIMARY_DISPLAY_ID && rotate_main);
+ if (rotate)
+ swap(width, height);
+
+ virtual_width = width;
+ virtual_height = height * 2;
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC
+ if (ddev->id == PRIMARY_DISPLAY_ID)
+ virtual_height = height;
+#endif
+
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY_AUTO_SYNC
+ if (ddev->id == SECONDARY_DISPLAY_ID)
+ virtual_height = height;
+#endif
/* Create frame buffer */
fbs[ddev->id] = mcde_fb_create(ddev,
width, height,
- width, height * 2,
+ virtual_width, virtual_height,
ddev->default_pixel_format,
rotate ? FB_ROTATE_CW : FB_ROTATE_UR);
+
if (IS_ERR(fbs[ddev->id]))
pr_warning("Failed to create fb for display %s\n", ddev->name);
else
@@ -411,6 +436,8 @@ static struct notifier_block display_nb = {
.notifier_call = display_registered_callback,
};
+#if defined(CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC) || \
+ defined(CONFIG_DISPLAY_GENERIC_DSI_SECONDARY_AUTO_SYNC)
static int framebuffer_registered_callback(struct notifier_block *nb,
unsigned long event, void *data)
{
@@ -419,28 +446,85 @@ static int framebuffer_registered_callback(struct notifier_block *nb,
struct fb_info *info;
struct fb_var_screeninfo var;
struct fb_fix_screeninfo fix;
+ struct mcde_fb *mfb;
+ u8 *addr;
+ int i;
+
+ if (event != FB_EVENT_FB_REGISTERED)
+ return 0;
+
+ if (!event_data)
+ return 0;
- if (event == FB_EVENT_FB_REGISTERED &&
- !display_initialized_during_boot) {
- if (event_data) {
- u8 *addr;
- info = event_data->info;
- if (!lock_fb_info(info))
- return -ENODEV;
- var = info->var;
- fix = info->fix;
- addr = ioremap(fix.smem_start,
- var.yres_virtual * fix.line_length);
- memset(addr, 0x00,
- var.yres_virtual * fix.line_length);
- var.yoffset = var.yoffset ? 0 : var.yres;
- if (info->fbops->fb_pan_display)
- ret = info->fbops->fb_pan_display(&var, info);
- unlock_fb_info(info);
- }
+ info = event_data->info;
+ mfb = to_mcde_fb(info);
+ var = info->var;
+ fix = info->fix;
+ addr = ioremap(fix.smem_start,
+ var.yres_virtual * fix.line_length);
+ memset(addr, 0x00,
+ var.yres_virtual * fix.line_length);
+ /* Apply overlay info */
+ for (i = 0; i < mfb->num_ovlys; i++) {
+ struct mcde_overlay *ovly = mfb->ovlys[i];
+ struct mcde_overlay_info ovly_info;
+ struct mcde_fb *mfb = to_mcde_fb(info);
+ memset(&ovly_info, 0, sizeof(ovly_info));
+ ovly_info.paddr = fix.smem_start +
+ fix.line_length * var.yoffset;
+ if (ovly_info.paddr + fix.line_length * var.yres
+ > fix.smem_start + fix.smem_len)
+ ovly_info.paddr = fix.smem_start;
+ ovly_info.fmt = mfb->pix_fmt;
+ ovly_info.stride = fix.line_length;
+ ovly_info.w = var.xres;
+ ovly_info.h = var.yres;
+ ovly_info.dirty.w = var.xres;
+ ovly_info.dirty.h = var.yres;
+ (void) mcde_dss_apply_overlay(ovly, &ovly_info);
+ ret = mcde_dss_update_overlay(ovly);
}
+
return ret;
}
+#else
+static int framebuffer_registered_callback(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ int ret = 0;
+ struct fb_event *event_data = data;
+ struct fb_info *info;
+ struct fb_var_screeninfo var;
+ struct fb_fix_screeninfo fix;
+ struct mcde_fb *mfb;
+ u8 *addr;
+
+ if (event != FB_EVENT_FB_REGISTERED)
+ return 0;
+
+ if (!event_data)
+ return 0;
+
+ info = event_data->info;
+ mfb = to_mcde_fb(info);
+ if (mfb->id == 0 && display_initialized_during_boot)
+ goto out;
+
+
+ var = info->var;
+ fix = info->fix;
+ addr = ioremap(fix.smem_start,
+ var.yres_virtual * fix.line_length);
+ memset(addr, 0x00,
+ var.yres_virtual * fix.line_length);
+ var.yoffset = var.yoffset ? 0 : var.yres;
+ if (info->fbops->fb_pan_display)
+ ret = info->fbops->fb_pan_display(&var, info);
+out:
+ return ret;
+}
+#endif
+
static struct notifier_block framebuffer_nb = {
.notifier_call = framebuffer_registered_callback,
diff --git a/drivers/video/av8100/av8100.c b/drivers/video/av8100/av8100.c
index e4df11441a1..47e3c633deb 100644
--- a/drivers/video/av8100/av8100.c
+++ b/drivers/video/av8100/av8100.c
@@ -24,6 +24,7 @@
#include <linux/irq.h>
#include <linux/timer.h>
#include <linux/mutex.h>
+#include <linux/slab.h>
#include "av8100_regs.h"
#include <video/av8100.h>
@@ -80,6 +81,8 @@ DEFINE_MUTEX(av8100_hw_mutex);
#define AV8100_DEBUG_EXTRA
#define AV8100_PLUGIN_DETECT_VIA_TIMER_INTERRUPTS
#define CEC_ADDR_OFFSET 3
+#define AV8100_POWERON_WAITTIME1_MS 1
+#define AV8100_POWERON_WAITTIME2_MS 1
struct av8100_config_t {
struct i2c_client *client;
@@ -210,7 +213,7 @@ struct av8100_cea av8100_all_cea[29] = {
/* cea id
* cea_nr vtot vact vsbpp vslen
* vsfp vpol htot hact hbp hslen hfp freq
- * hpol rld bd uix4 pm pd */
+ * hpol rld bd uix4 pm pd */
{ "0 CUSTOM ",
0, 0, 0, 0, 0,
0, "-", 800, 640, 16, 96, 10, 25200000,
@@ -853,7 +856,7 @@ static int av8100_globals_init(void)
av8100_globals = kzalloc(sizeof(struct av8100_globals_t), GFP_KERNEL);
if (!av8100_globals) {
- dev_err(av8100dev, "%s: Alloc failure \n", __func__);
+ dev_err(av8100dev, "%s: Alloc failure\n", __func__);
return AV8100_FAIL;
}
@@ -1646,6 +1649,10 @@ static int av8100_powerup1(void)
/* Reset av8100 */
gpio_set_value(GPIO_AV8100_RSTN, 1);
+
+ /* Need to wait before proceeding */
+ mdelay(AV8100_POWERON_WAITTIME1_MS);
+
av8100_set_state(AV8100_OPMODE_STANDBY);
/* Get chip version */
@@ -1696,6 +1703,9 @@ static int av8100_powerup2(void)
return -EFAULT;
}
+ /* Need to wait before proceeding */
+ mdelay(AV8100_POWERON_WAITTIME2_MS);
+
av8100_set_state(AV8100_OPMODE_SCAN);
return retval;
diff --git a/drivers/video/av8100/hdmi.c b/drivers/video/av8100/hdmi.c
index 14b15dedbf2..fd4324d5c4b 100755
--- a/drivers/video/av8100/hdmi.c
+++ b/drivers/video/av8100/hdmi.c
@@ -21,6 +21,8 @@
#include <linux/mutex.h>
#include <linux/ctype.h>
#include "hdmi_loc.h"
+#include <linux/slab.h>
+#include <linux/sched.h>
#define SYSFS_EVENT_FILENAME "evread"
@@ -1843,13 +1845,13 @@ int __init hdmi_init(void)
hdmidev = hdmi_miscdev.this_device;
- hdmidev->driver_data =
+ hdmi_driver_data =
kzalloc(sizeof(struct hdmi_driver_data), GFP_KERNEL);
- if (!hdmidev->driver_data)
+ if (!hdmi_driver_data)
return -ENOMEM;
- hdmi_driver_data = dev_get_drvdata(hdmidev);
+ dev_set_drvdata(hdmidev, hdmi_driver_data);
/* Default sysfs file format is hextext */
hdmi_driver_data->store_as_hextext = true;
@@ -1898,6 +1900,8 @@ hdmi_init_out:
void hdmi_exit(void)
{
+ struct hdmi_driver_data *hdmi_driver_data;
+
/* Deregister event callback */
av8100_hdmi_event_cb_set(NULL);
@@ -1918,7 +1922,8 @@ void hdmi_exit(void)
device_remove_file(hdmidev, &dev_attr_evclr);
device_remove_file(hdmidev, &dev_attr_audiocfg);
- kfree(hdmidev->driver_data);
+ hdmi_driver_data = dev_get_drvdata(hdmidev);
+ kfree(hdmi_driver_data);
misc_deregister(&hdmi_miscdev);
}
diff --git a/drivers/video/mcde/display-ab8500.c b/drivers/video/mcde/display-ab8500.c
index 426e23cbf60..cdce3bfa002 100644
--- a/drivers/video/mcde/display-ab8500.c
+++ b/drivers/video/mcde/display-ab8500.c
@@ -300,6 +300,7 @@ static int set_video_mode(
set_power_mode(ddev, MCDE_DISPLAY_PM_STANDBY);
mcde_chnl_set_col_convert(ddev->chnl_state,
&pdata->rgb_2_yCbCr_convert);
+ mcde_chnl_stop_flow(ddev->chnl_state);
res = mcde_chnl_set_video_mode(ddev->chnl_state, &ddev->video_mode);
if (res < 0) {
dev_warn(&ddev->dev, "%s:Failed to set video mode on channel\n",
diff --git a/drivers/video/mcde/display-av8100.c b/drivers/video/mcde/display-av8100.c
index 6de32c3ddf3..96fed0bf8ee 100755
--- a/drivers/video/mcde/display-av8100.c
+++ b/drivers/video/mcde/display-av8100.c
@@ -194,6 +194,8 @@ static int hdmi_set_video_mode(
if (dev->port->pixel_format == MCDE_PORTPIXFMT_DSI_YCBCR422)
mcde_chnl_set_col_convert(dev->chnl_state,
&pdata->rgb_2_yCbCr_convert);
+ mcde_chnl_stop_flow(dev->chnl_state);
+
ret = mcde_chnl_set_video_mode(dev->chnl_state, &dev->video_mode);
if (ret < 0) {
dev_warn(&dev->dev, "Failed to set video mode\n");
diff --git a/drivers/video/mcde/display-generic_dsi.c b/drivers/video/mcde/display-generic_dsi.c
index 15b8ccec59a..d445d806a6a 100644
--- a/drivers/video/mcde/display-generic_dsi.c
+++ b/drivers/video/mcde/display-generic_dsi.c
@@ -13,24 +13,23 @@
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/gpio.h>
+#include <linux/err.h>
#include <video/mcde_display.h>
#include <video/mcde_display-generic_dsi.h>
static int generic_platform_enable(struct mcde_display_device *dev)
{
- int ret = 0;
struct mcde_display_generic_platform_data *pdata =
dev->dev.platform_data;
dev_dbg(&dev->dev, "%s: Reset & power on generic display\n", __func__);
if (pdata->regulator) {
- ret = regulator_enable(pdata->regulator);
- if (ret < 0) {
+ if (regulator_enable(pdata->regulator) < 0) {
dev_err(&dev->dev, "%s:Failed to enable regulator\n"
, __func__);
- goto out;
+ return -EINVAL;
}
}
if (pdata->reset_gpio)
@@ -39,24 +38,24 @@ static int generic_platform_enable(struct mcde_display_device *dev)
if (pdata->reset_gpio)
gpio_set_value(pdata->reset_gpio, !pdata->reset_high);
out:
- return ret;
+ return 0;
}
static int generic_platform_disable(struct mcde_display_device *dev)
{
- int ret = 0;
struct mcde_display_generic_platform_data *pdata =
dev->dev.platform_data;
dev_dbg(&dev->dev, "%s:Reset & power off generic display\n", __func__);
if (pdata->regulator) {
- ret = regulator_disable(pdata->regulator);
- if (ret < 0)
+ if (regulator_disable(pdata->regulator) < 0) {
dev_err(&dev->dev, "%s:Failed to disable regulator\n"
, __func__);
+ return -EINVAL;
+ }
}
- return ret;
+ return 0;
}
static int __devinit generic_probe(struct mcde_display_device *dev)
diff --git a/drivers/video/mcde/mcde_display.c b/drivers/video/mcde/mcde_display.c
index 1537980dcaf..a3aff5021b9 100644
--- a/drivers/video/mcde/mcde_display.c
+++ b/drivers/video/mcde/mcde_display.c
@@ -205,7 +205,7 @@ static int mcde_display_set_synchronized_update_default(
struct mcde_display_device *ddev, bool enable)
{
int ret = 0;
- if (ddev->port->type == MCDE_PORTTYPE_DSI) {
+ if (ddev->port->type == MCDE_PORTTYPE_DSI && enable) {
if (ddev->port->sync_src == MCDE_SYNCSRC_TE0 ||
ddev->port->sync_src == MCDE_SYNCSRC_TE1 ||
ddev->port->sync_src == MCDE_SYNCSRC_BTA) {
@@ -216,7 +216,7 @@ static int mcde_display_set_synchronized_update_default(
ret = -EINVAL;
}
} else {
- ret = -EINVAL;
+ ret = 0;
}
if (ret < 0) {
@@ -253,6 +253,8 @@ static int mcde_display_apply_config_default(struct mcde_display_device *ddev)
}
if (ddev->update_flags) {
+ if (ddev->update_flags & UPDATE_FLAG_VIDEO_MODE)
+ mcde_chnl_stop_flow(ddev->chnl_state);
ret = mcde_chnl_apply(ddev->chnl_state);
if (ret < 0) {
dev_warn(&ddev->dev, "%s:Failed to apply to channel\n",
diff --git a/drivers/video/mcde/mcde_fb.c b/drivers/video/mcde/mcde_fb.c
index f9697d2e9df..b5515b85a18 100644
--- a/drivers/video/mcde/mcde_fb.c
+++ b/drivers/video/mcde/mcde_fb.c
@@ -376,7 +376,7 @@ static int check_var(struct fb_var_screeninfo *var, struct fb_info *fbi,
ret = mcde_dss_try_video_mode(ddev, &vmode);
if (ret < 0) {
dev_vdbg(&(ddev->dev), "check_var failed "
- "mcde_dss_try_video_mode with size = %x \n", ret);
+ "mcde_dss_try_video_mode with size = %x\n", ret);
return ret;
}
vmode_to_var(&vmode, var);
@@ -416,7 +416,7 @@ static int apply_var(struct fb_info *fbi, struct mcde_display_device *ddev)
ret = reallocate_fb_mem(fbi, size);
if (ret) {
dev_vdbg(&(ddev->dev), "apply_var failed with"
- "reallocate mem with size = %d \n", size);
+ "reallocate mem with size = %d\n", size);
return ret;
}
fbi->fix.line_length = line_len;
@@ -579,6 +579,8 @@ struct fb_info *mcde_fb_create(struct mcde_display_device *ddev,
if (ret)
goto ovly_enable_failed;
+ mfb->id = ddev->id;
+
/* Register framebuffer */
ret = register_framebuffer(fbi);
if (ret)
diff --git a/drivers/video/mcde/mcde_hw.c b/drivers/video/mcde/mcde_hw.c
index 3a8f30aa91e..ef3bd0328d3 100644
--- a/drivers/video/mcde/mcde_hw.c
+++ b/drivers/video/mcde/mcde_hw.c
@@ -30,6 +30,7 @@
#include <mach/prcmu-fw-api.h>
static void disable_channel(struct mcde_chnl_state *chnl);
+static void watchdog_auto_sync_timer_function(unsigned long arg);
#define MSEC_TO_JIFFIES(__x) (((__x) * HZ + HZ - 1) / 1000)
@@ -47,13 +48,13 @@ static struct clk *clock_dsi;
static struct clk *clock_mcde;
static struct clk *clock_dsi_lp;
-static inline u32 dsi_rreg(int __i, u32 __reg)
+static inline u32 dsi_rreg(int i, u32 reg)
{
- return readl(dsiio[__i] + __reg);
+ return readl(dsiio[i] + reg);
}
-static inline void dsi_wreg(int __i, u32 __reg, u32 __val)
+static inline void dsi_wreg(int i, u32 reg, u32 val)
{
- writel(__val, dsiio[__i] + __reg);
+ writel(val, dsiio[i] + reg);
}
#define dsi_rfld(__i, __reg, __fld) \
((dsi_rreg(__i, __reg) & __reg##_##__fld##_MASK) >> \
@@ -63,13 +64,13 @@ static inline void dsi_wreg(int __i, u32 __reg, u32 __val)
~__reg##_##__fld##_MASK) | (((__val) << __reg##_##__fld##_SHIFT) & \
__reg##_##__fld##_MASK))
-static inline u32 mcde_rreg(u32 __reg)
+static inline u32 mcde_rreg(u32 reg)
{
- return readl(mcdeio + __reg);
+ return readl(mcdeio + reg);
}
-static inline void mcde_wreg(u32 __reg, u32 __val)
+static inline void mcde_wreg(u32 reg, u32 val)
{
- writel(__val, mcdeio + __reg);
+ writel(val, mcdeio + reg);
}
#define mcde_rfld(__reg, __fld) \
((mcde_rreg(__reg) & __reg##_##__fld##_MASK) >> \
@@ -200,6 +201,8 @@ struct mcde_chnl_state {
u32 transactionid_regs;
u32 transactionid_hw;
wait_queue_head_t waitq_hw; /* Waitq for transactionid_hw */
+ /* Used as watchdog timer for auto sync feature */
+ struct timer_list auto_sync_timer;
enum mcde_display_power_mode power_mode;
@@ -350,7 +353,6 @@ int mcde_chnl_set_video_mode(struct mcde_chnl_state *chnl,
if (chnl == NULL || vmode == NULL)
return -EINVAL;
- disable_channel(chnl);
chnl->vmode = *vmode;
return 0;
@@ -367,7 +369,7 @@ static void tv_video_mode_apply(struct mcde_chnl_state *chnl)
chnl->tv_regs.fsl2 = chnl->vmode.vbp2;
chnl->tv_regs.interlaced_en = chnl->vmode.interlaced;
- if (chnl->port.phy.dpi.num_data_lanes == 4)
+ if (chnl->port.phy.dpi.bus_width == 4)
chnl->tv_regs.tv_mode = MCDE_TVCRA_TVMODE_SDTV_656P_BE;
else
chnl->tv_regs.tv_mode = MCDE_TVCRA_TVMODE_SDTV_656P;
@@ -525,6 +527,8 @@ static irqreturn_t mcde_irq_handler(int irq, void *dev)
{
int i;
u32 irq_status;
+ bool trig = false;
+ struct mcde_chnl_state *chnl;
/* Handle overlay irqs */
irq_status = mcde_rfld(MCDE_RISOVL, OVLFDRIS);
@@ -540,32 +544,81 @@ static irqreturn_t mcde_irq_handler(int irq, void *dev)
/* Handle channel irqs */
irq_status = mcde_rreg(MCDE_RISPP);
if (irq_status & MCDE_RISPP_VCMPARIS_MASK) {
- struct mcde_chnl_state *chnl = &channels[MCDE_CHNL_A];
+ chnl = &channels[MCDE_CHNL_A];
chnl->transactionid_hw = chnl->transactionid_regs;
wake_up(&chnl->waitq_hw);
mcde_wfld(MCDE_RISPP, VCMPARIS, 1);
+ if (chnl->port.update_auto_trig &&
+ chnl->port.sync_src == MCDE_SYNCSRC_OFF &&
+ chnl->port.type == MCDE_PORTTYPE_DSI &&
+ chnl->continous_running) {
+ mcde_wreg(MCDE_CHNL0SYNCHSW +
+ chnl->id * MCDE_CHNL0SYNCHSW_GROUPOFFSET,
+ MCDE_CHNL0SYNCHSW_SW_TRIG(true));
+ mod_timer(&chnl->auto_sync_timer,
+ jiffies +
+ msecs_to_jiffies(MCDE_AUTO_SYNC_WATCHDOG
+ * 1000));
+ }
}
if (irq_status & MCDE_RISPP_VCMPBRIS_MASK) {
- struct mcde_chnl_state *chnl = &channels[MCDE_CHNL_B];
+ chnl = &channels[MCDE_CHNL_B];
chnl->transactionid_hw = chnl->transactionid_regs;
wake_up(&chnl->waitq_hw);
mcde_wfld(MCDE_RISPP, VCMPBRIS, 1);
+ if (chnl->port.update_auto_trig &&
+ chnl->port.sync_src == MCDE_SYNCSRC_OFF &&
+ chnl->port.type == MCDE_PORTTYPE_DSI &&
+ chnl->continous_running) {
+ mcde_wreg(MCDE_CHNL0SYNCHSW +
+ chnl->id * MCDE_CHNL0SYNCHSW_GROUPOFFSET,
+ MCDE_CHNL0SYNCHSW_SW_TRIG(true));
+ mod_timer(&chnl->auto_sync_timer,
+ jiffies +
+ msecs_to_jiffies(MCDE_AUTO_SYNC_WATCHDOG
+ * 1000));
+ }
}
if (irq_status & MCDE_RISPP_VCMPC0RIS_MASK) {
- struct mcde_chnl_state *chnl = &channels[MCDE_CHNL_C0];
+ chnl = &channels[MCDE_CHNL_C0];
chnl->transactionid_hw = chnl->transactionid_regs;
wake_up(&chnl->waitq_hw);
mcde_wfld(MCDE_RISPP, VCMPC0RIS, 1);
+ if (chnl->port.update_auto_trig &&
+ chnl->port.sync_src == MCDE_SYNCSRC_OFF &&
+ chnl->port.type == MCDE_PORTTYPE_DSI &&
+ chnl->continous_running) {
+ mcde_wreg(MCDE_CHNL0SYNCHSW +
+ chnl->id * MCDE_CHNL0SYNCHSW_GROUPOFFSET,
+ MCDE_CHNL0SYNCHSW_SW_TRIG(true));
+ mod_timer(&chnl->auto_sync_timer,
+ jiffies +
+ msecs_to_jiffies(MCDE_AUTO_SYNC_WATCHDOG
+ * 1000));
+ }
}
if (irq_status & MCDE_RISPP_VCMPC1RIS_MASK) {
- struct mcde_chnl_state *chnl = &channels[MCDE_CHNL_C1];
+ chnl = &channels[MCDE_CHNL_C1];
chnl->transactionid_hw = chnl->transactionid_regs;
wake_up(&chnl->waitq_hw);
mcde_wfld(MCDE_RISPP, VCMPC1RIS, 1);
+ if (chnl->port.update_auto_trig &&
+ chnl->port.sync_src == MCDE_SYNCSRC_OFF &&
+ chnl->port.type == MCDE_PORTTYPE_DSI &&
+ chnl->continous_running) {
+ mcde_wreg(MCDE_CHNL0SYNCHSW +
+ chnl->id * MCDE_CHNL0SYNCHSW_GROUPOFFSET,
+ MCDE_CHNL0SYNCHSW_SW_TRIG(true));
+ mod_timer(&chnl->auto_sync_timer,
+ jiffies +
+ msecs_to_jiffies(MCDE_AUTO_SYNC_WATCHDOG
+ * 1000));
+ }
}
for (i = 0; i < num_dsilinks; i++) {
- bool trig = false;
- struct mcde_chnl_state *chnl;
+ struct mcde_chnl_state *chnl_from_dsi;
+
+ trig = false;
irq_status = dsi_rfld(i, DSI_DIRECT_CMD_STS_FLAG,
TE_RECEIVED_FLAG);
if (irq_status) {
@@ -582,13 +635,14 @@ static irqreturn_t mcde_irq_handler(int irq, void *dev)
}
if (!trig)
continue;
- chnl = find_channel_by_dsilink(i);
- if (chnl) {
+ chnl_from_dsi = find_channel_by_dsilink(i);
+ if (chnl_from_dsi) {
mcde_wreg(MCDE_CHNL0SYNCHSW +
- chnl->id * MCDE_CHNL0SYNCHSW_GROUPOFFSET,
+ chnl_from_dsi->id *
+ MCDE_CHNL0SYNCHSW_GROUPOFFSET,
MCDE_CHNL0SYNCHSW_SW_TRIG(true));
dev_vdbg(&mcde_dev->dev, "SW TRIG DSI%d, chnl=%d\n", i,
- chnl->id);
+ chnl_from_dsi->id);
}
}
@@ -797,6 +851,23 @@ static void update_overlay_registers(u8 idx, struct ovly_regs *regs,
#endif /* CONFIG_AV8100_SDTV */
if (regs->reset_buf_id) {
+ u32 sel_mod = MCDE_EXTSRC0CR_SEL_MOD_SOFTWARE_SEL;
+ if (port->update_auto_trig && port->type == MCDE_PORTTYPE_DSI) {
+ switch (port->sync_src) {
+ case MCDE_SYNCSRC_OFF:
+ sel_mod = MCDE_EXTSRC0CR_SEL_MOD_SOFTWARE_SEL;
+ break;
+ case MCDE_SYNCSRC_TE0:
+ case MCDE_SYNCSRC_TE1:
+ default:
+ sel_mod = MCDE_EXTSRC0CR_SEL_MOD_AUTO_TOGGLE;
+ }
+ } else if (port->type == MCDE_PORTTYPE_DPI) {
+ sel_mod = port->update_auto_trig ?
+ MCDE_EXTSRC0CR_SEL_MOD_AUTO_TOGGLE :
+ MCDE_EXTSRC0CR_SEL_MOD_SOFTWARE_SEL;
+ }
+
regs->reset_buf_id = false;
mcde_wreg(MCDE_EXTSRC0CONF + idx * MCDE_EXTSRC0CONF_GROUPOFFSET,
MCDE_EXTSRC0CONF_BUF_ID(0) |
@@ -807,9 +878,7 @@ static void update_overlay_registers(u8 idx, struct ovly_regs *regs,
MCDE_EXTSRC0CONF_BEBO(regs->bebo) |
MCDE_EXTSRC0CONF_BEPO(false));
mcde_wreg(MCDE_EXTSRC0CR + idx * MCDE_EXTSRC0CR_GROUPOFFSET,
- MCDE_EXTSRC0CR_SEL_MOD(port->update_auto_trig ?
- MCDE_EXTSRC0CR_SEL_MOD_AUTO_TOGGLE :
- MCDE_EXTSRC0CR_SEL_MOD_SOFTWARE_SEL) |
+ MCDE_EXTSRC0CR_SEL_MOD(sel_mod) |
MCDE_EXTSRC0CR_MULTIOVL_CTRL_ENUM(PRIMARY) |
MCDE_EXTSRC0CR_FS_DIV_DISABLE(false) |
MCDE_EXTSRC0CR_FORCE_FS_DIV(false));
@@ -951,6 +1020,42 @@ static void enable_channel(struct mcde_chnl_state *chnl)
}
}
+static int is_channel_enabled(struct mcde_chnl_state *chnl)
+{
+ switch (chnl->id) {
+ case MCDE_CHNL_A:
+ return mcde_rfld(MCDE_CRA0, FLOEN);
+ case MCDE_CHNL_B:
+ return mcde_rfld(MCDE_CRB0, FLOEN);
+ case MCDE_CHNL_C0:
+ return mcde_rfld(MCDE_CRC, FLOEN);
+ case MCDE_CHNL_C1:
+ return mcde_rfld(MCDE_CRC, FLOEN);
+ }
+ return 0;
+}
+
+static void watchdog_auto_sync_timer_function(unsigned long arg)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(channels); i++) {
+ struct mcde_chnl_state *chnl = &channels[i];
+ if (chnl->port.update_auto_trig &&
+ chnl->port.sync_src == MCDE_SYNCSRC_OFF &&
+ chnl->port.type == MCDE_PORTTYPE_DSI &&
+ chnl->continous_running) {
+ mcde_wreg(MCDE_CHNL0SYNCHSW +
+ chnl->id
+ * MCDE_CHNL0SYNCHSW_GROUPOFFSET,
+ MCDE_CHNL0SYNCHSW_SW_TRIG(true));
+ mod_timer(&chnl->auto_sync_timer,
+ jiffies +
+ msecs_to_jiffies(MCDE_AUTO_SYNC_WATCHDOG
+ * 1000));
+ }
+ }
+}
+
/* TODO get from register */
#define MCDE_CLK_FREQ_MHZ 160
@@ -960,14 +1065,30 @@ void update_channel_registers(enum mcde_chnl chnl_id, struct chnl_regs *regs,
{
u8 idx = chnl_id;
u32 out_synch_src = MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER;
+ u32 src_synch = MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE;
dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
/* Channel */
- if (port->update_auto_trig && port->type != MCDE_PORTTYPE_DPI) {
- out_synch_src = port->sync_src == MCDE_SYNCSRC_TE0 ?
- MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_VSYNC0 :
- MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_VSYNC1;
+ if (port->update_auto_trig && port->type == MCDE_PORTTYPE_DSI) {
+ switch (port->sync_src) {
+ case MCDE_SYNCSRC_TE0:
+ out_synch_src = MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_VSYNC0;
+ src_synch = MCDE_CHNL0SYNCHMOD_SRC_SYNCH_OUTPUT;
+ break;
+ case MCDE_SYNCSRC_OFF:
+ src_synch = MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE;
+ break;
+ case MCDE_SYNCSRC_TE1:
+ default:
+ out_synch_src = MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_VSYNC1;
+ src_synch = MCDE_CHNL0SYNCHMOD_SRC_SYNCH_OUTPUT;
+ }
+ } else if (port->type == MCDE_PORTTYPE_DPI) {
+ src_synch = port->update_auto_trig ?
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_OUTPUT :
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE;
}
+
mcde_wreg(MCDE_CHNL0CONF + idx * MCDE_CHNL0CONF_GROUPOFFSET,
MCDE_CHNL0CONF_PPL(regs->ppl-1) |
MCDE_CHNL0CONF_LPF(regs->lpf-1));
@@ -976,9 +1097,7 @@ void update_channel_registers(enum mcde_chnl chnl_id, struct chnl_regs *regs,
MCDE_CHNL0STAT_CHNLRD(true));
mcde_wreg(MCDE_CHNL0SYNCHMOD +
idx * MCDE_CHNL0SYNCHMOD_GROUPOFFSET,
- MCDE_CHNL0SYNCHMOD_SRC_SYNCH(port->update_auto_trig ?
- MCDE_CHNL0SYNCHMOD_SRC_SYNCH_OUTPUT :
- MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE) |
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH(src_synch) |
MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC(out_synch_src));
mcde_wreg(MCDE_CHNL0BCKGNDCOL + idx * MCDE_CHNL0BCKGNDCOL_GROUPOFFSET,
MCDE_CHNL0BCKGNDCOL_B(255) | /* TODO: Temp */
@@ -1317,7 +1436,9 @@ int mcde_chnl_set_pixel_format(struct mcde_chnl_state *chnl,
{
if (!chnl->inuse)
return -EINVAL;
+
chnl->pix_fmt = pix_fmt;
+
return 0;
}
@@ -1434,8 +1555,19 @@ static void chnl_update_continous(struct mcde_chnl_state *chnl)
mcde_wfld(MCDE_CRC, SYCEN0, true);
else if (chnl->port.sync_src == MCDE_SYNCSRC_TE1)
mcde_wfld(MCDE_CRC, SYCEN1, true);
-
chnl->continous_running = true;
+ /*
+ * For main and secondary display,
+ * FLOWEN has to be set before a SOFTWARE TRIG
+ * Otherwise not overlay interrupt is triggerd
+ */
+ enable_channel(chnl);
+ if (chnl->port.type == MCDE_PORTTYPE_DSI &&
+ chnl->port.sync_src == MCDE_SYNCSRC_OFF) {
+ mod_timer(&chnl->auto_sync_timer,
+ jiffies +
+ msecs_to_jiffies(MCDE_AUTO_SYNC_WATCHDOG * 1000));
+ }
}
}
@@ -1446,6 +1578,18 @@ static void chnl_update_non_continous(struct mcde_chnl_state *chnl)
if (chnl->transactionid_regs < chnl->transactionid)
chnl_update_registers(chnl);
+ /*
+ * For main and secondary display,
+ * FLOWEN has to be set before a SOFTWARE TRIG
+ * Otherwise not overlay interrupt is triggerd
+ * However FLOWEN must not be triggered before SOFTWARE TRIG
+ * if rotation is enabled
+ */
+ if (chnl->power_mode == MCDE_DISPLAY_PM_STANDBY ||
+ (!is_channel_enabled(chnl) && !chnl->regs.roten))
+ enable_channel(chnl);
+
+
/* TODO: look at port sync source and synched_update */
if (chnl->regs.synchronized_update &&
chnl->power_mode == MCDE_DISPLAY_PM_ON) {
@@ -1463,6 +1607,8 @@ static void chnl_update_non_continous(struct mcde_chnl_state *chnl)
dev_vdbg(&mcde_dev->dev, "Channel update (no sync), chnl=%d\n",
chnl->id);
}
+ if (chnl->power_mode == MCDE_DISPLAY_PM_ON)
+ enable_channel(chnl);
}
static void chnl_update_overlay(struct mcde_chnl_state *chnl,
@@ -1474,10 +1620,9 @@ static void chnl_update_overlay(struct mcde_chnl_state *chnl,
update_overlay_address_registers(ovly->idx, &ovly->regs);
if (ovly->regs.reset_buf_id) {
- if (chnl->continous_running)
- disable_channel(chnl);
- else
+ if (!chnl->continous_running)
wait_for_overlay(ovly);
+
update_overlay_registers(ovly->idx, &ovly->regs, &chnl->port,
chnl->fifo, chnl->regs.x, chnl->regs.y,
chnl->regs.ppl, chnl->regs.lpf, ovly->stride,
@@ -1521,8 +1666,6 @@ int mcde_chnl_update(struct mcde_chnl_state *chnl,
else
chnl_update_non_continous(chnl);
- enable_channel(chnl);
-
dev_vdbg(&mcde_dev->dev, "Channel updated, chnl=%d\n", chnl->id);
return 0;
}
@@ -1539,6 +1682,11 @@ void mcde_chnl_put(struct mcde_chnl_state *chnl)
update_channel_static_registers(chnl);
}
+void mcde_chnl_stop_flow(struct mcde_chnl_state *chnl)
+{
+ disable_channel(chnl);
+}
+
/* MCDE overlays */
struct mcde_ovly_state *mcde_ovly_get(struct mcde_chnl_state *chnl)
{
@@ -1634,7 +1782,7 @@ void mcde_ovly_apply(struct mcde_ovly_state *ovly)
ovly->regs.enabled = ovly->paddr != 0;
ovly->regs.baseaddress0 = ovly->paddr;
ovly->regs.baseaddress1 = ovly->paddr + ovly->stride;
-/*TODO set to true if interlaced *//* REVIEW: Video mode interlaced? */
+ /*TODO set to true if interlaced *//* REVIEW: Video mode interlaced? */
ovly->regs.reset_buf_id = !ovly->chnl->continous_running;
switch (ovly->pix_fmt) {/* REVIEW: Extract to table */
case MCDE_OVLYPIXFMT_RGB565:
@@ -2015,8 +2163,16 @@ out:
return ret;
}
+
static int __devexit mcde_remove(struct platform_device *pdev)
{
+ struct mcde_chnl_state *chnl = &channels[0];
+ for (; chnl < &channels[ARRAY_SIZE(channels)]; chnl++) {
+ if (del_timer(&chnl->auto_sync_timer))
+ dev_vdbg(&mcde_dev->dev,
+ "%s timer could not be stopped\n"
+ , __func__);
+ }
remove_clocks_and_power(pdev);
return 0;
}
@@ -2026,7 +2182,7 @@ static int mcde_resume(struct platform_device *pdev)
{
int ret;
struct mcde_chnl_state *chnl = &channels[0];
- dev_info(&pdev->dev, "Resume is called\n");
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
ret = enable_clocks_and_power(pdev);
if (ret < 0) {
dev_dbg(&pdev->dev, "%s: Enable clocks and power failed\n"
@@ -2067,7 +2223,18 @@ clock_err:
#ifdef CONFIG_PM
static int mcde_suspend(struct platform_device *pdev, pm_message_t state)
{
- dev_info(&pdev->dev, "Suspend is called\n");
+ struct mcde_chnl_state *chnl = &channels[0];
+
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ /* This is added because of the auto sync feature */
+ for (; chnl < &channels[ARRAY_SIZE(channels)]; chnl++) {
+ mcde_chnl_stop_flow(chnl);
+ if (del_timer(&chnl->auto_sync_timer))
+ dev_vdbg(&mcde_dev->dev,
+ "%s timer could not be stopped\n"
+ , __func__);
+ }
return disable_clocks_and_power(pdev);
}
#endif
@@ -2087,8 +2254,7 @@ static struct platform_driver mcde_driver = {
},
};
-/* REVIEW: __init? */
-int mcde_init(void)
+int __init mcde_init(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(channels); i++) {
@@ -2096,6 +2262,9 @@ int mcde_init(void)
if (channels[i].ovly1)
channels[i].ovly1->chnl = &channels[i];
init_waitqueue_head(&channels[i].waitq_hw);
+ init_timer(&channels[i].auto_sync_timer);
+ channels[i].auto_sync_timer.function =
+ watchdog_auto_sync_timer_function;
}
for (i = 0; i < ARRAY_SIZE(overlays); i++)
init_waitqueue_head(&overlays[i].waitq_hw);
diff --git a/include/video/mcde.h b/include/video/mcde.h
index b682200edc7..f8a8fb2a213 100644
--- a/include/video/mcde.h
+++ b/include/video/mcde.h
@@ -11,13 +11,10 @@
#ifndef __MCDE__H__
#define __MCDE__H__
-#include <linux/fb.h> /* REVIEW: Remove */
-
/* Physical interface types */
enum mcde_port_type {
MCDE_PORTTYPE_DSI = 0,
MCDE_PORTTYPE_DPI = 1,
- MCDE_PORTTYPE_DBI = 2, /* REVIEW: Remove */
};
/* Interface mode */
@@ -78,8 +75,6 @@ enum mcde_chnl_path {
MCDE_CHNLPATH_CHNLB_FIFOB_DSI_IFC1_2 = MCDE_CHNLPATH(MCDE_CHNL_B,
MCDE_FIFO_B, MCDE_PORTTYPE_DSI, 1, 2),
/* Channel C0 */
- MCDE_CHNLPATH_CHNLC0_FIFOC0_DBI_0 = MCDE_CHNLPATH(MCDE_CHNL_C0,
- MCDE_FIFO_C0, MCDE_PORTTYPE_DBI, 0, 0),
MCDE_CHNLPATH_CHNLC0_FIFOA_DSI_IFC0_0 = MCDE_CHNLPATH(MCDE_CHNL_C0,
MCDE_FIFO_A, MCDE_PORTTYPE_DSI, 0, 0),
MCDE_CHNLPATH_CHNLC0_FIFOA_DSI_IFC0_1 = MCDE_CHNLPATH(MCDE_CHNL_C0,
@@ -93,8 +88,6 @@ enum mcde_chnl_path {
MCDE_CHNLPATH_CHNLC0_FIFOA_DSI_IFC1_2 = MCDE_CHNLPATH(MCDE_CHNL_C0,
MCDE_FIFO_A, MCDE_PORTTYPE_DSI, 1, 2),
/* Channel C1 */
- MCDE_CHNLPATH_CHNLC1_FIFOC1_DBI_1 = MCDE_CHNLPATH(MCDE_CHNL_C1,
- MCDE_FIFO_C1, MCDE_PORTTYPE_DBI, 0, 1),
MCDE_CHNLPATH_CHNLC1_FIFOB_DSI_IFC0_0 = MCDE_CHNLPATH(MCDE_CHNL_C1,
MCDE_FIFO_B, MCDE_PORTTYPE_DSI, 0, 0),
MCDE_CHNLPATH_CHNLC1_FIFOB_DSI_IFC0_1 = MCDE_CHNLPATH(MCDE_CHNL_C1,
@@ -115,19 +108,15 @@ enum mcde_sync_src {
MCDE_SYNCSRC_TE0 = 1, /* MCDE ext TE0 */
MCDE_SYNCSRC_TE1 = 2, /* MCDE ext TE1 */
MCDE_SYNCSRC_BTA = 3, /* DSI BTA */
- MCDE_SYNCSRC_EXT = 4, /* GPIO, or other outside MCDE control */
-};/* REVIEW: Remove _EXT, not supported */
+};
/* Interface pixel formats (output) */
-/* REVIEW: Define formats */
+/*
+* REVIEW: Define formats
+* Add explanatory comments how the formats are ordered in memory
+*/
enum mcde_port_pix_fmt {
/* MIPI standard formats */
- MCDE_PORTPIXFMT_DBI_3BPP = 0x11,/* REVIEW: Remove */
- MCDE_PORTPIXFMT_DBI_8BPP = 0x12,/* REVIEW: Remove */
- MCDE_PORTPIXFMT_DBI_12BPP = 0x13,/* REVIEW: Remove */
- MCDE_PORTPIXFMT_DBI_16BPP = 0x15,/* REVIEW: Remove */
- MCDE_PORTPIXFMT_DBI_18BPP = 0x16,/* REVIEW: Remove */
- MCDE_PORTPIXFMT_DBI_24BPP = 0x17,/* REVIEW: Remove */
MCDE_PORTPIXFMT_DPI_16BPP_C1 = 0x21,
MCDE_PORTPIXFMT_DPI_16BPP_C2 = 0x22,
@@ -166,8 +155,7 @@ struct mcde_port {
bool clk_cont;
} dsi;
struct {
- bool chip_select;/* REVIEW: Used? Needed? */
- u8 num_data_lanes;/* REVIEW: Rename to bus_width? */
+ u8 bus_width;
} dpi;
} phy;
};
@@ -216,6 +204,9 @@ enum mcde_display_rotation {
#define MCDE_PIXFETCH_MEDIUM_WTRMRKLVL 64
#define MCDE_PIXFETCH_SMALL_WTRMRKLVL 16
+/* In seconds */
+#define MCDE_AUTO_SYNC_WATCHDOG 5
+
/* Video mode descriptor */
struct mcde_video_mode {/* REVIEW: Join 1 & 2 */
u32 xres;
@@ -271,7 +262,7 @@ void mcde_chnl_set_col_convert(struct mcde_chnl_state *chnl,
struct mcde_col_convert *col_convert);
int mcde_chnl_set_video_mode(struct mcde_chnl_state *chnl,
struct mcde_video_mode *vmode);
-/* TODO: Remove rotbuf* parameters */
+/* TODO: Remove rotbuf* parameters when ESRAM allocator is implemented*/
int mcde_chnl_set_rotation(struct mcde_chnl_state *chnl,
enum mcde_display_rotation rotation, u32 rotbuf1, u32 rotbuf2);
int mcde_chnl_enable_synchronized_update(struct mcde_chnl_state *chnl,
@@ -284,6 +275,8 @@ int mcde_chnl_update(struct mcde_chnl_state *chnl,
struct mcde_rectangle *update_area);
void mcde_chnl_put(struct mcde_chnl_state *chnl);
+void mcde_chnl_stop_flow(struct mcde_chnl_state *chnl);
+
/* MCDE overlay */
struct mcde_ovly_state;
@@ -358,7 +351,7 @@ struct mcde_platform_data {
/* DSI */
int num_dsilinks;
- /* DBI/DPI */
+ /* DPI */
u8 outmux[5]; /* MCDE_CONF0.OUTMUXx */
u8 syncmux; /* MCDE_CONF0.SYNCMUXx */
@@ -368,7 +361,7 @@ struct mcde_platform_data {
const char *clock_mcde_id;
};
-int mcde_init(void);
+int __init mcde_init(void);
void mcde_exit(void);
#endif /* __MCDE__H__ */
diff --git a/include/video/mcde_fb.h b/include/video/mcde_fb.h
index 6d05f612184..8aa3d134e74 100644
--- a/include/video/mcde_fb.h
+++ b/include/video/mcde_fb.h
@@ -33,6 +33,7 @@ struct mcde_fb {
struct mcde_overlay *ovlys[MCDE_FB_MAX_NUM_OVERLAYS];
u32 pseudo_palette[17];
enum mcde_ovly_pix_fmt pix_fmt;
+ int id;
};
/* MCDE fbdev API */
diff --git a/kernel.spec b/kernel.spec
index 6f23df05e1c..5e21c8811e9 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -377,7 +377,10 @@ BuildKernel() {
# Set config
make %{?_smp_mflags} mop500$(DEBUG)_power_defconfig
# STE: Disable multibuffer and multitouch.
- scripts/config --file .config --disable FB_MCDE_MULTIBUFFER --disable U8500_TSC_MULTITOUCH
+ scripts/config --file .config --enable DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC --enable DISPLAY_GENERIC_DSI_SECONDARY_AUTO_SYNC
+ # Does not exist in the 34 kernel yet
+ #scripts/config --file .config --disable U8500_TSC_MULTITOUCH
+
# STE: Enable conf for external sd-cards.
scripts/config --file .config --enable LEVELSHIFTER_HREF_V1_PLUS
# STE: Enable g_multi USB gadget with RNDIS, CDC Serial and Storage configuration.