* [PATCH] grvga: fix section mismatch warnings
From: Sam Ravnborg @ 2011-12-27 21:57 UTC (permalink / raw)
To: linux-fbdev
From 7368b53b755a66c69b2b5ede30e2effe960ad59a Mon Sep 17 00:00:00 2001
From: Sam Ravnborg <sam@ravnborg.org>
Date: Tue, 27 Dec 2011 22:55:49 +0100
Subject: [PATCH] grvga: fix section mismatch warnings
Fix following section mismatch warnings:
WARNING: drivers/video/built-in.o(.devinit.text+0x110): Section mismatch in reference from the function grvga_probe() to the function .init.text:grvga_parse_custom()
The function __devinit grvga_probe() references
a function __init grvga_parse_custom().
If grvga_parse_custom is only used by grvga_probe then
annotate grvga_parse_custom with a matching annotation.
WARNING: drivers/video/built-in.o(.devinit.text+0x1f8): Section mismatch in reference from the function grvga_probe() to the variable .init.data:grvga_fix
The function __devinit grvga_probe() references
a variable __initdata grvga_fix.
If grvga_fix is only used by grvga_probe then
annotate grvga_fix with a matching annotation.
WARNING: drivers/video/built-in.o(.devinit.text+0x204): Section mismatch in reference from the function grvga_probe() to the variable .init.data:grvga_fix
The function __devinit grvga_probe() references
a variable __initdata grvga_fix.
If grvga_fix is only used by grvga_probe then
annotate grvga_fix with a matching annotation.
grvga_fix is used in a function annotated __devinit - so
match this using a __devinitdata annotation on grvga_fix.
grvga_parse_custom() is used in a function annotated
__devinit - so match this by annotating grvga_parse_custom()
with __devinit too.
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Cc: Kristoffer Glembo <kristoffer@gaisler.com>
Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
drivers/video/grvga.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c
index f37e025..da066c2 100644
--- a/drivers/video/grvga.c
+++ b/drivers/video/grvga.c
@@ -70,7 +70,7 @@ static const struct fb_videomode grvga_modedb[] = {
}
};
-static struct fb_fix_screeninfo grvga_fix __initdata = {
+static struct fb_fix_screeninfo grvga_fix __devinitdata = {
.id = "AG SVGACTRL",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
@@ -267,7 +267,7 @@ static struct fb_ops grvga_ops = {
.fb_imageblit = cfb_imageblit
};
-static int __init grvga_parse_custom(char *options,
+static int __devinit grvga_parse_custom(char *options,
struct fb_var_screeninfo *screendata)
{
char *this_opt;
--
1.6.0.6
^ permalink raw reply related
* [PATCH 6/6] video: s3c-fb: Don't keep device runtime active when open
From: Mark Brown @ 2011-12-27 14:16 UTC (permalink / raw)
To: Jingoo Han, Florian Tobias Schandinat
Cc: linux-fbdev, linux-kernel, Mark Brown
In-Reply-To: <1324995372-3410-1-git-send-email-broonie@opensource.wolfsonmicro.com>
Allow the controller to be runtime suspended when the screen is blanked
by not taking a runtime reference while the device is open. This allows
greater system wide power savings when used with a standard application
layer and ensures that the screen does not blank unless requested.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
drivers/video/s3c-fb.c | 22 ----------------------
1 files changed, 0 insertions(+), 22 deletions(-)
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 84cf631..0c63b69 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -1070,30 +1070,8 @@ static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
return ret;
}
-static int s3c_fb_open(struct fb_info *info, int user)
-{
- struct s3c_fb_win *win = info->par;
- struct s3c_fb *sfb = win->parent;
-
- pm_runtime_get_sync(sfb->dev);
-
- return 0;
-}
-
-static int s3c_fb_release(struct fb_info *info, int user)
-{
- struct s3c_fb_win *win = info->par;
- struct s3c_fb *sfb = win->parent;
-
- pm_runtime_put_sync(sfb->dev);
-
- return 0;
-}
-
static struct fb_ops s3c_fb_ops = {
.owner = THIS_MODULE,
- .fb_open = s3c_fb_open,
- .fb_release = s3c_fb_release,
.fb_check_var = s3c_fb_check_var,
.fb_set_par = s3c_fb_set_par,
.fb_blank = s3c_fb_blank,
--
1.7.7.3
^ permalink raw reply related
* [PATCH 5/6] video: s3c-fb: Hold runtime PM references when touching registers
From: Mark Brown @ 2011-12-27 14:16 UTC (permalink / raw)
To: Jingoo Han, Florian Tobias Schandinat
Cc: linux-fbdev, linux-kernel, Mark Brown
In-Reply-To: <1324995372-3410-1-git-send-email-broonie@opensource.wolfsonmicro.com>
Take a runtime PM reference whenever updating registers in preparation
for suspending the device when the framebuffer is blanked.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
drivers/video/s3c-fb.c | 22 ++++++++++++++++++++++
1 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 688b9d8..84cf631 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -496,6 +496,8 @@ static int s3c_fb_set_par(struct fb_info *info)
dev_dbg(sfb->dev, "setting framebuffer parameters\n");
+ pm_runtime_get_sync(sfb->dev);
+
shadow_protect_win(win, 1);
switch (var->bits_per_pixel) {
@@ -692,6 +694,8 @@ static int s3c_fb_set_par(struct fb_info *info)
shadow_protect_win(win, 0);
+ pm_runtime_put_sync(sfb->dev);
+
return 0;
}
@@ -763,6 +767,8 @@ static int s3c_fb_setcolreg(unsigned regno,
dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n",
__func__, win->index, regno, red, green, blue);
+ pm_runtime_get_sync(sfb->dev);
+
switch (info->fix.visual) {
case FB_VISUAL_TRUECOLOR:
/* true-colour, use pseudo-palette */
@@ -790,9 +796,11 @@ static int s3c_fb_setcolreg(unsigned regno,
break;
default:
+ pm_runtime_put_sync(sfb->dev);
return 1; /* unknown type */
}
+ pm_runtime_put_sync(sfb->dev);
return 0;
}
@@ -812,6 +820,8 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
dev_dbg(sfb->dev, "blank mode %d\n", blank_mode);
+ pm_runtime_get_sync(sfb->dev);
+
wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4));
switch (blank_mode) {
@@ -839,6 +849,7 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
case FB_BLANK_VSYNC_SUSPEND:
case FB_BLANK_HSYNC_SUSPEND:
default:
+ pm_runtime_put_sync(sfb->dev);
return 1;
}
@@ -869,6 +880,8 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
shadow_protect_win(win, 0);
}
+ pm_runtime_put_sync(sfb->dev);
+
return 0;
}
@@ -891,6 +904,8 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
void __iomem *buf = sfb->regs + win->index * 8;
unsigned int start_boff, end_boff;
+ pm_runtime_get_sync(sfb->dev);
+
/* Offset in bytes to the start of the displayed area */
start_boff = var->yoffset * info->fix.line_length;
/* X offset depends on the current bpp */
@@ -909,6 +924,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
break;
default:
dev_err(sfb->dev, "invalid bpp\n");
+ pm_runtime_put_sync(sfb->dev);
return -EINVAL;
}
}
@@ -924,6 +940,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
shadow_protect_win(win, 0);
+ pm_runtime_put_sync(sfb->dev);
return 0;
}
@@ -1013,11 +1030,16 @@ static int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc)
if (crtc != 0)
return -ENODEV;
+ pm_runtime_get_sync(sfb->dev);
+
count = sfb->vsync_info.count;
s3c_fb_enable_irq(sfb);
ret = wait_event_interruptible_timeout(sfb->vsync_info.wait,
count != sfb->vsync_info.count,
msecs_to_jiffies(VSYNC_TIMEOUT_MSEC));
+
+ pm_runtime_put_sync(sfb->dev);
+
if (ret = 0)
return -ETIMEDOUT;
--
1.7.7.3
^ permalink raw reply related
* [PATCH 4/6] video: s3c-fb: Take a runtime PM reference when unblanked
From: Mark Brown @ 2011-12-27 14:16 UTC (permalink / raw)
To: Jingoo Han, Florian Tobias Schandinat
Cc: linux-fbdev, linux-kernel, Mark Brown
In-Reply-To: <1324995372-3410-1-git-send-email-broonie@opensource.wolfsonmicro.com>
When the framebuffer is unblanked hold a runtime PM reference. This
prevents us powering down when userspace has left an image on the
framebuffer and prepares the way for being able to power down the hardware
when an application still has the device open.
Since we now hold a runtime PM reference whenever the display is unblanked
there is no need for the runtime power management to disable and enable
the display, and doing so would lead to runtime PM trying to recurse into
itself when called from the blanking code, so split the runtime PM into
separate functions which only deal with the clocks. The PM core will
runtime resume the device prior to system suspend.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
drivers/video/s3c-fb.c | 66 +++++++++++++++++++++++++++++++++++++++--------
1 files changed, 54 insertions(+), 12 deletions(-)
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 2e0eef0..688b9d8 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -192,6 +192,7 @@ struct s3c_fb_vsync {
* @regs: The mapped hardware registers.
* @variant: Variant information for this hardware.
* @enabled: A bitmask of enabled hardware windows.
+ * @output_on: Flag if the physical output is enabled.
* @pdata: The platform configuration data passed with the device.
* @windows: The hardware windows that have been claimed.
* @irq_no: IRQ line number
@@ -208,6 +209,7 @@ struct s3c_fb {
struct s3c_fb_variant variant;
unsigned char enabled;
+ bool output_on;
struct s3c_fb_platdata *pdata;
struct s3c_fb_win *windows[S3C_FB_MAX_WIN];
@@ -449,21 +451,28 @@ static void s3c_fb_enable(struct s3c_fb *sfb, int enable)
{
u32 vidcon0 = readl(sfb->regs + VIDCON0);
- if (enable)
+ if (enable && !sfb->output_on)
+ pm_runtime_get_sync(sfb->dev);
+
+ if (enable) {
vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
- else {
+ } else {
/* see the note in the framebuffer datasheet about
* why you cannot take both of these bits down at the
* same time. */
- if (!(vidcon0 & VIDCON0_ENVID))
- return;
-
- vidcon0 |= VIDCON0_ENVID;
- vidcon0 &= ~VIDCON0_ENVID_F;
+ if (vidcon0 & VIDCON0_ENVID) {
+ vidcon0 |= VIDCON0_ENVID;
+ vidcon0 &= ~VIDCON0_ENVID_F;
+ }
}
writel(vidcon0, sfb->regs + VIDCON0);
+
+ if (!enable && sfb->output_on)
+ pm_runtime_put_sync(sfb->dev);
+
+ sfb->output_on = enable;
}
/**
@@ -1539,7 +1548,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int s3c_fb_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -1609,11 +1618,40 @@ static int s3c_fb_resume(struct device *dev)
return 0;
}
-#else
-#define s3c_fb_suspend NULL
-#define s3c_fb_resume NULL
#endif
+#ifdef CONFIG_PM_RUNTIME
+static int s3c_fb_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct s3c_fb *sfb = platform_get_drvdata(pdev);
+
+ if (!sfb->variant.has_clksel)
+ clk_disable(sfb->lcd_clk);
+
+ clk_disable(sfb->bus_clk);
+
+ return 0;
+}
+
+static int s3c_fb_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct s3c_fb *sfb = platform_get_drvdata(pdev);
+ struct s3c_fb_platdata *pd = sfb->pdata;
+
+ clk_enable(sfb->bus_clk);
+
+ if (!sfb->variant.has_clksel)
+ clk_enable(sfb->lcd_clk);
+
+ /* setup gpio and output polarity controls */
+ pd->setup_gpio();
+ writel(pd->vidcon1, sfb->regs + VIDCON1);
+
+ return 0;
+}
+#endif
#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
@@ -1936,7 +1974,11 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
};
MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
-static UNIVERSAL_DEV_PM_OPS(s3cfb_pm_ops, s3c_fb_suspend, s3c_fb_resume, NULL);
+static const struct dev_pm_ops s3cfb_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(s3c_fb_suspend, s3c_fb_resume)
+ SET_RUNTIME_PM_OPS(s3c_fb_runtime_suspend, s3c_fb_runtime_resume,
+ NULL)
+};
static struct platform_driver s3c_fb_driver = {
.probe = s3c_fb_probe,
--
1.7.7.3
^ permalink raw reply related
* [PATCH 3/6] video: s3c-fb: Disable runtime PM in error paths from probe
From: Mark Brown @ 2011-12-27 14:16 UTC (permalink / raw)
To: Jingoo Han, Florian Tobias Schandinat
Cc: linux-fbdev, linux-kernel, Mark Brown
In-Reply-To: <1324995372-3410-1-git-send-email-broonie@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
drivers/video/s3c-fb.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index be4c218..2e0eef0 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -1464,7 +1464,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
dev_err(dev, "failed to create window %d\n", win);
for (; win >= 0; win--)
s3c_fb_release_win(sfb, sfb->windows[win]);
- goto err_irq;
+ goto err_pm_runtime;
}
}
@@ -1473,7 +1473,8 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
return 0;
-err_irq:
+err_pm_runtime:
+ pm_runtime_put_sync(sfb->dev);
free_irq(sfb->irq_no, sfb);
err_ioremap:
@@ -1483,6 +1484,8 @@ err_req_region:
release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
err_lcd_clk:
+ pm_runtime_disable(sfb->dev);
+
if (!sfb->variant.has_clksel) {
clk_disable(sfb->lcd_clk);
clk_put(sfb->lcd_clk);
--
1.7.7.3
^ permalink raw reply related
* [PATCH 2/6] video: s3c-fb: Use s3c_fb_enable() to enable the framebuffer
From: Mark Brown @ 2011-12-27 14:16 UTC (permalink / raw)
To: Jingoo Han, Florian Tobias Schandinat
Cc: linux-fbdev, linux-kernel, Mark Brown
In-Reply-To: <1324995372-3410-1-git-send-email-broonie@opensource.wolfsonmicro.com>
The s3c-fb driver has a function called s3c_fb_enable() which turns on
and off the physical output. However it is only actually used in paths
which disable the screen, the enabling just writes to the register. Make
the code less confusing by ensuring that the enable also goes through
the same path.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Jingoo Han <jg1.han@samsung.com>
---
drivers/video/s3c-fb.c | 55 ++++++++++++++++++++++++-----------------------
1 files changed, 28 insertions(+), 27 deletions(-)
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index b1a75a0..be4c218 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -441,6 +441,32 @@ static void shadow_protect_win(struct s3c_fb_win *win, bool protect)
}
/**
+ * s3c_fb_enable() - Set the state of the main LCD output
+ * @sfb: The main framebuffer state.
+ * @enable: The state to set.
+ */
+static void s3c_fb_enable(struct s3c_fb *sfb, int enable)
+{
+ u32 vidcon0 = readl(sfb->regs + VIDCON0);
+
+ if (enable)
+ vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
+ else {
+ /* see the note in the framebuffer datasheet about
+ * why you cannot take both of these bits down at the
+ * same time. */
+
+ if (!(vidcon0 & VIDCON0_ENVID))
+ return;
+
+ vidcon0 |= VIDCON0_ENVID;
+ vidcon0 &= ~VIDCON0_ENVID_F;
+ }
+
+ writel(vidcon0, sfb->regs + VIDCON0);
+}
+
+/**
* s3c_fb_set_par() - framebuffer request to set new framebuffer state.
* @info: The framebuffer to change.
*
@@ -510,9 +536,10 @@ static int s3c_fb_set_par(struct fb_info *info)
if (sfb->variant.is_2443)
data |= (1 << 5);
- data |= VIDCON0_ENVID | VIDCON0_ENVID_F;
writel(data, regs + VIDCON0);
+ s3c_fb_enable(sfb, 1);
+
data = VIDTCON0_VBPD(var->upper_margin - 1) |
VIDTCON0_VFPD(var->lower_margin - 1) |
VIDTCON0_VSPW(var->vsync_len - 1);
@@ -761,32 +788,6 @@ static int s3c_fb_setcolreg(unsigned regno,
}
/**
- * s3c_fb_enable() - Set the state of the main LCD output
- * @sfb: The main framebuffer state.
- * @enable: The state to set.
- */
-static void s3c_fb_enable(struct s3c_fb *sfb, int enable)
-{
- u32 vidcon0 = readl(sfb->regs + VIDCON0);
-
- if (enable)
- vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
- else {
- /* see the note in the framebuffer datasheet about
- * why you cannot take both of these bits down at the
- * same time. */
-
- if (!(vidcon0 & VIDCON0_ENVID))
- return;
-
- vidcon0 |= VIDCON0_ENVID;
- vidcon0 &= ~VIDCON0_ENVID_F;
- }
-
- writel(vidcon0, sfb->regs + VIDCON0);
-}
-
-/**
* s3c_fb_blank() - blank or unblank the given window
* @blank_mode: The blank state from FB_BLANK_*
* @info: The framebuffer to blank.
--
1.7.7.3
^ permalink raw reply related
* [PATCH 1/6] video: s3c-fb: Make runtime PM functional again
From: Mark Brown @ 2011-12-27 14:16 UTC (permalink / raw)
To: Jingoo Han, Florian Tobias Schandinat
Cc: linux-fbdev, linux-kernel, Mark Brown
In-Reply-To: <20111227141550.GA3331@opensource.wolfsonmicro.com>
The change in "video: s3c-fb: modify runtime pm functions" (commit
35784b) renders the runtime power management for the device completely
ineffectual as while it leaves runtime power management notionally
enabled a runtime power reference is held for the entire time the device
is registered meaning it will never actually do anything.
A further issue is introduced as runtime power management is added
during the system suspend path which is not something which drivers are
supposed to do and would interact poorly if there were any operations
done in the runtime power management callbacks.
While this does make things simpler (the main motivation for the
original change) it will not only cause us to use more power in the
framebuffer controller but will also prevent us entering lower power
domain and SoC wide states as we can never power down the domain
containing the device. Since neither of these things is desirable
revert the change.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
drivers/video/s3c-fb.c | 51 +++++++++++++++++++++++++++++------------------
1 files changed, 31 insertions(+), 20 deletions(-)
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index a0b3fd6..b1a75a0 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -1038,8 +1038,30 @@ static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
return ret;
}
+static int s3c_fb_open(struct fb_info *info, int user)
+{
+ struct s3c_fb_win *win = info->par;
+ struct s3c_fb *sfb = win->parent;
+
+ pm_runtime_get_sync(sfb->dev);
+
+ return 0;
+}
+
+static int s3c_fb_release(struct fb_info *info, int user)
+{
+ struct s3c_fb_win *win = info->par;
+ struct s3c_fb *sfb = win->parent;
+
+ pm_runtime_put_sync(sfb->dev);
+
+ return 0;
+}
+
static struct fb_ops s3c_fb_ops = {
.owner = THIS_MODULE,
+ .fb_open = s3c_fb_open,
+ .fb_release = s3c_fb_release,
.fb_check_var = s3c_fb_check_var,
.fb_set_par = s3c_fb_set_par,
.fb_blank = s3c_fb_blank,
@@ -1446,6 +1468,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, sfb);
+ pm_runtime_put_sync(sfb->dev);
return 0;
@@ -1485,6 +1508,8 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
struct s3c_fb *sfb = platform_get_drvdata(pdev);
int win;
+ pm_runtime_get_sync(sfb->dev);
+
for (win = 0; win < S3C_FB_MAX_WIN; win++)
if (sfb->windows[win])
s3c_fb_release_win(sfb, sfb->windows[win]);
@@ -1510,7 +1535,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
static int s3c_fb_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -1531,8 +1556,6 @@ static int s3c_fb_suspend(struct device *dev)
clk_disable(sfb->lcd_clk);
clk_disable(sfb->bus_clk);
- pm_runtime_put_sync(sfb->dev);
-
return 0;
}
@@ -1544,7 +1567,6 @@ static int s3c_fb_resume(struct device *dev)
struct s3c_fb_win *win;
int win_no;
- pm_runtime_get_sync(sfb->dev);
clk_enable(sfb->bus_clk);
if (!sfb->variant.has_clksel)
@@ -1583,19 +1605,11 @@ static int s3c_fb_resume(struct device *dev)
return 0;
}
+#else
+#define s3c_fb_suspend NULL
+#define s3c_fb_resume NULL
#endif
-#ifdef CONFIG_PM_RUNTIME
-static int s3c_fb_runtime_suspend(struct device *dev)
-{
- return 0;
-}
-
-static int s3c_fb_runtime_resume(struct device *dev)
-{
- return 0;
-}
-#endif
#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
@@ -1918,10 +1932,7 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
};
MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
-static const struct dev_pm_ops s3c_fb_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(s3c_fb_suspend, s3c_fb_resume)
- SET_RUNTIME_PM_OPS(s3c_fb_runtime_suspend, s3c_fb_runtime_resume, NULL)
-};
+static UNIVERSAL_DEV_PM_OPS(s3cfb_pm_ops, s3c_fb_suspend, s3c_fb_resume, NULL);
static struct platform_driver s3c_fb_driver = {
.probe = s3c_fb_probe,
@@ -1930,7 +1941,7 @@ static struct platform_driver s3c_fb_driver = {
.driver = {
.name = "s3c-fb",
.owner = THIS_MODULE,
- .pm = &s3c_fb_pm_ops,
+ .pm = &s3cfb_pm_ops,
},
};
--
1.7.7.3
^ permalink raw reply related
* [PATCH 0/6] video: s3c-fb: Use runtime suspend while blanked
From: Mark Brown @ 2011-12-27 14:15 UTC (permalink / raw)
To: Jingoo Han, 'Florian Tobias Schandinat'; +Cc: linux-kernel, linux-fbdev
This patch series (the first two of which I posted the other day)
improves the runtime power management in the s3c-fb driver by moving it
to keeping the device runtime suspended when the screen is powered down
by userspace. This saves a trivial amount of power in the framebuffer
controller and allows the SoC core code to enter system wide idle
states which offer much more substantial gains.
Currently it's only lightly tested but it certainly seems to the right
thing for me.
Mark Brown (6):
video: s3c-fb: Make runtime PM functional again
video: s3c-fb: Use s3c_fb_enable() to enable the framebuffer
video: s3c-fb: Disable runtime PM in error paths from probe
video: s3c-fb: Take a runtime PM reference when unblanked
video: s3c-fb: Hold runtime PM references when touching registers
video: s3c-fb: Don't keep device runtime active when open
drivers/video/s3c-fb.c | 127 ++++++++++++++++++++++++++++++++++-------------
1 files changed, 92 insertions(+), 35 deletions(-)
^ permalink raw reply
* [RFC PATCH 29/29] OMAPDSS: FEATURES: Allow WB panels to attach to managers
From: Archit Taneja @ 2011-12-27 12:49 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Add WB panel type in supported displays for all managers of OMAP4. A manager can
now use set/unset ops on the dummy writeback panel.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/dss_features.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 9478ed8..dbde3b9 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -132,14 +132,16 @@ static const enum omap_display_type omap3630_dss_supported_displays[] = {
static const enum omap_display_type omap4_dss_supported_displays[] = {
/* OMAP_DSS_CHANNEL_LCD */
- OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI,
+ OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI |
+ OMAP_DISPLAY_TYPE_WB,
/* OMAP_DSS_CHANNEL_DIGIT */
OMAP_DISPLAY_TYPE_VENC | OMAP_DISPLAY_TYPE_HDMI,
+ OMAP_DISPLAY_TYPE_WB,
/* OMAP_DSS_CHANNEL_LCD2 */
OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
- OMAP_DISPLAY_TYPE_DSI,
+ OMAP_DISPLAY_TYPE_DSI | OMAP_DISPLAY_TYPE_WB,
};
static const enum omap_color_mode omap2_dss_supported_color_modes[] = {
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 28/29] OMAPDSS: MANAGER: Add writeback as a sysfs attribute
From: Archit Taneja @ 2011-12-27 12:49 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Add writeback as a sysfs attribute. This can be used to show and store the dummy
writeback panel that the manager can connect to.
Add checks so that in the store functions so that a display store cant set a
writeback device and vice versa.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/manager.c | 38 +++++++++++++++++++++++++++++++++++++
1 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index fb7c1e6..a064656 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -129,6 +129,41 @@ static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
if (r)
return r;
+ if (dssdev->wbdev) {
+ r = -EINVAL;
+ return r;
+ }
+
+ r = dss_mgr_set_output(mgr, dssdev);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static ssize_t manager_writeback_show(struct omap_overlay_manager *mgr, char *buf)
+{
+ struct omap_dss_device *wb_device = mgr->get_writeback(mgr);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", wb_device ?
+ wb_device->name : "<none>");
+}
+
+static ssize_t manager_writeback_store(struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+{
+ int r;
+ struct omap_dss_device *dssdev;
+
+ r = dss_find_device_buf(&dssdev, buf, size);
+ if (r)
+ return r;
+
+ if (!dssdev->wbdev) {
+ r = -EINVAL;
+ return r;
+ }
+
r = dss_mgr_set_output(mgr, dssdev);
if (r)
return r;
@@ -452,6 +487,8 @@ struct manager_attribute {
static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
manager_display_show, manager_display_store);
+static MANAGER_ATTR(writeback, S_IRUGO|S_IWUSR,
+ manager_writeback_show, manager_writeback_store);
static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
manager_default_color_show, manager_default_color_store);
static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
@@ -475,6 +512,7 @@ static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
static struct attribute *manager_sysfs_attrs[] = {
&manager_attr_name.attr,
&manager_attr_display.attr,
+ &manager_attr_writeback.attr,
&manager_attr_default_color.attr,
&manager_attr_trans_key_type.attr,
&manager_attr_trans_key_value.attr,
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 27/29] OMAPDSS: MANAGER: Split manager_display_store into smaller functions
From: Archit Taneja @ 2011-12-27 12:49 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Split manager_display_store() into two function, the first function finds a
device with the same name. The second unsets the current output attached and
sets the one we had searched for.
This is done so that there can be re use between display store and writeback
store sysfs ops.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/manager.c | 46 ++++++++++++++++++++++++++++++------
1 files changed, 38 insertions(+), 8 deletions(-)
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index f4fd3d8..fb7c1e6 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -49,13 +49,11 @@ static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
dssdev->name : "<none>");
}
-static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
+static int dss_find_device_buf(struct omap_dss_device **pdssdev,
const char *buf, size_t size)
{
- int r = 0;
size_t len = size;
struct omap_dss_device *dssdev = NULL;
- struct omap_dss_device *curr_display;
int match(struct omap_dss_device *dssdev, void *data)
{
@@ -73,12 +71,25 @@ static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
return -EINVAL;
if (dssdev)
- DSSDBG("display %s found\n", dssdev->name);
+ DSSDBG("device %s found\n", dssdev->name);
+
+ *pdssdev = dssdev;
+
+ return 0;
+}
+static int dss_mgr_set_output(struct omap_overlay_manager *mgr,
+ struct omap_dss_device *dssdev)
+{
+ int r;
+ struct omap_dss_device *curr_dssdev;
- curr_display = mgr->get_display(mgr);
+ if (dssdev->wbdev)
+ curr_dssdev = mgr->get_writeback(mgr);
+ else
+ curr_dssdev = mgr->get_display(mgr);
- if (curr_display) {
- r = mgr->unset_device(mgr, curr_display);
+ if (curr_dssdev) {
+ r = mgr->unset_device(mgr, curr_dssdev);
if (r) {
DSSERR("failed to unset display\n");
goto put_device;
@@ -99,11 +110,30 @@ static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
}
}
+ return 0;
+
put_device:
if (dssdev)
omap_dss_put_device(dssdev);
- return r ? r : size;
+ return r;
+}
+
+static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+{
+ int r;
+ struct omap_dss_device *dssdev;
+
+ r = dss_find_device_buf(&dssdev, buf, size);
+ if (r)
+ return r;
+
+ r = dss_mgr_set_output(mgr, dssdev);
+ if (r)
+ return r;
+
+ return size;
}
static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 26/29] OMAPDSS: DISPLAY: Add a manager apply to sysfs store attributes for writeback
From: Archit Taneja @ 2011-12-27 12:49 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Writeback driver ops don't apply the writeback attribute changes, they just set
the writeback info parameters. Add manager apply calls in sysfs store ops for
timings, rotation and mirroring when its the writeback panel.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/display.c | 18 ++++++++++++++++++
1 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 03d7fb0..71ef0d7 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -144,6 +144,12 @@ static ssize_t display_timings_store(struct device *dev,
dssdev->driver->set_timings(dssdev, &t);
+ if (dssdev->wbdev && dssdev->manager) {
+ r = dssdev->manager->apply(dssdev->manager);
+ if (r)
+ return r;
+ }
+
return size;
}
@@ -175,6 +181,12 @@ static ssize_t display_rotate_store(struct device *dev,
if (r)
return r;
+ if (dssdev->wbdev && dssdev->manager) {
+ r = dssdev->manager->apply(dssdev->manager);
+ if (r)
+ return r;
+ }
+
return size;
}
@@ -207,6 +219,12 @@ static ssize_t display_mirror_store(struct device *dev,
if (r)
return r;
+ if (dssdev->wbdev && dssdev->manager) {
+ r = dssdev->manager->apply(dssdev->manager);
+ if (r)
+ return r;
+ }
+
return size;
}
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 25/29] OMAPDSS: Writeback: Add sysfs attributes to writeback panel
From: Archit Taneja @ 2011-12-27 12:49 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Add the following sysfs attributes to the writeback panel driver:
- paddr
- p_uv_addr
- rotation_type
- color_mode
- pre_mult_alpha
- capture_rate
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/writeback.c | 210 +++++++++++++++++++++++++++++++++++
1 files changed, 210 insertions(+), 0 deletions(-)
diff --git a/drivers/video/omap2/dss/writeback.c b/drivers/video/omap2/dss/writeback.c
index 215958e..c6450e7 100644
--- a/drivers/video/omap2/dss/writeback.c
+++ b/drivers/video/omap2/dss/writeback.c
@@ -214,8 +214,218 @@ int dss_wb_simple_check(struct omap_dss_writeback *wb,
/* Dummy Writeback Panel driver */
+static ssize_t writeback_panel_paddr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_writeback_info info;
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+
+ wb->get_wb_info(wb, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%x\n", info.paddr);
+}
+
+static ssize_t writeback_panel_p_uv_addr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_writeback_info info;
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+
+ wb->get_wb_info(wb, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%x\n", info.p_uv_addr);
+}
+
+static ssize_t writeback_panel_rotation_type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_writeback_info info;
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+
+ wb->get_wb_info(wb, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", info.rotation_type);
+}
+
+static ssize_t writeback_panel_color_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_writeback_info info;
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+
+ wb->get_wb_info(wb, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", info.color_mode);
+}
+
+static ssize_t writeback_panel_color_mode_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ int r;
+ int color_mode;
+ struct omap_dss_writeback_info info;
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+
+ r = kstrtoint(buf, 0, &color_mode);
+ if (r)
+ return r;
+
+ wb->get_wb_info(wb, &info);
+
+ info.color_mode = color_mode;
+
+ r = wb->set_wb_info(wb, &info);
+ if (r) {
+ dev_err(&dssdev->dev, "failed to set color mode %d\n",
+ color_mode);
+ return r;
+ }
+
+ if (dssdev->manager) {
+ r = dssdev->manager->apply(dssdev->manager);
+ if (r)
+ return r;
+ }
+
+ return size;
+}
+
+static ssize_t writeback_panel_pre_mult_alpha_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_writeback_info info;
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+
+ wb->get_wb_info(wb, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", info.pre_mult_alpha);
+}
+
+static ssize_t writeback_panel_pre_mult_alpha_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ int r;
+ u8 pre_mult_alpha;
+ struct omap_dss_writeback_info info;
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+
+ r = kstrtou8(buf, 0, &pre_mult_alpha);
+ if (r)
+ return r;
+
+ wb->get_wb_info(wb, &info);
+
+ info.pre_mult_alpha = pre_mult_alpha;
+
+ r = wb->set_wb_info(wb, &info);
+ if (r) {
+ dev_err(&dssdev->dev, "failed to set pre_mult_alpha %d\n",
+ pre_mult_alpha);
+ return r;
+ }
+
+ if (dssdev->manager) {
+ r = dssdev->manager->apply(dssdev->manager);
+ if (r)
+ return r;
+ }
+
+ return size;
+}
+
+static ssize_t writeback_panel_capture_rate_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_writeback_info info;
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+
+ wb->get_wb_info(wb, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", info.capture_rate);
+}
+
+static ssize_t writeback_panel_capture_rate_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ int r;
+ int capture_rate;
+ struct omap_dss_writeback_info info;
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+
+ r = kstrtoint(buf, 0, &capture_rate);
+ if (r)
+ return r;
+
+ wb->get_wb_info(wb, &info);
+
+ info.capture_rate = capture_rate;
+
+ r = wb->set_wb_info(wb, &info);
+ if (r) {
+ dev_err(&dssdev->dev, "failed to set capture_rate %d\n",
+ capture_rate);
+ return r;
+ }
+
+ if (dssdev->manager) {
+ r = dssdev->manager->apply(dssdev->manager);
+ if (r)
+ return r;
+ }
+
+ return size;
+}
+
+static DEVICE_ATTR(paddr, S_IRUGO, writeback_panel_paddr_show, NULL);
+static DEVICE_ATTR(p_uv_addr, S_IRUGO, writeback_panel_p_uv_addr_show, NULL);
+static DEVICE_ATTR(rotation_type, S_IRUGO, writeback_panel_rotation_type_show,
+ NULL);
+static DEVICE_ATTR(color_mode, S_IRUGO | S_IWUSR,
+ writeback_panel_color_mode_show,
+ writeback_panel_color_mode_store);
+static DEVICE_ATTR(pre_mult_alpha, S_IRUGO | S_IWUSR,
+ writeback_panel_pre_mult_alpha_show,
+ writeback_panel_pre_mult_alpha_store);
+static DEVICE_ATTR(capture_rate, S_IRUGO | S_IWUSR,
+ writeback_panel_capture_rate_show,
+ writeback_panel_capture_rate_store);
+
+static struct attribute *writeback_attrs[] = {
+ &dev_attr_paddr.attr,
+ &dev_attr_p_uv_addr.attr,
+ &dev_attr_rotation_type.attr,
+ &dev_attr_color_mode.attr,
+ &dev_attr_pre_mult_alpha.attr,
+ &dev_attr_capture_rate.attr,
+ NULL,
+};
+
+static struct attribute_group writeback_attr_group = {
+ .attrs = writeback_attrs,
+};
+
static int writeback_panel_probe(struct omap_dss_device *dssdev)
{
+ int r;
+
+ r = sysfs_create_group(&dssdev->dev.kobj, &writeback_attr_group);
+ if (r) {
+ dev_err(&dssdev->dev, "failed to create sysfs files\n");
+ return r;
+ }
+
return 0;
}
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 24/29] OMAPDSS: Writeback: Use panel driver ops to configure mirroring rotation and buffe
From: Archit Taneja @ 2011-12-27 12:49 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Add rotation and mirroring ops to writeback panel driver. Use these ops to
get/set wb info.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/writeback.c | 79 +++++++++++++++++++++++++++++++++++
1 files changed, 79 insertions(+), 0 deletions(-)
diff --git a/drivers/video/omap2/dss/writeback.c b/drivers/video/omap2/dss/writeback.c
index 82d601c..215958e 100644
--- a/drivers/video/omap2/dss/writeback.c
+++ b/drivers/video/omap2/dss/writeback.c
@@ -287,9 +287,83 @@ static int writeback_panel_resume(struct omap_dss_device *dssdev)
return 0;
}
+static int writeback_panel_rotate(struct omap_dss_device *dssdev, u8 rotate)
+{
+ int r;
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+ struct omap_dss_writeback_info info;
+
+ wb->get_wb_info(wb, &info);
+
+ info.rotation = rotate;
+
+ r = wb->set_wb_info(wb, &info);
+ if (r) {
+ dev_err(&dssdev->dev, "failed to set rotation %d\n", rotate);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static u8 writeback_panel_get_rotate(struct omap_dss_device *dssdev)
+{
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+ struct omap_dss_writeback_info info;
+
+ wb->get_wb_info(wb, &info);
+
+ return info.rotation;
+}
+
+static int writeback_panel_mirror(struct omap_dss_device *dssdev, bool mirror)
+{
+ int r;
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+ struct omap_dss_writeback_info info;
+
+ wb->get_wb_info(wb, &info);
+
+ info.mirror = mirror;
+
+ r = wb->set_wb_info(wb, &info);
+ if (r) {
+ dev_err(&dssdev->dev, "failed to set mirror %d\n", mirror);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static bool writeback_panel_get_mirror(struct omap_dss_device *dssdev)
+{
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+ struct omap_dss_writeback_info info;
+
+ wb->get_wb_info(wb, &info);
+
+ return info.mirror;
+}
+
static void writeback_panel_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
+ int r;
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+ struct omap_dss_writeback_info info;
+
+ wb->get_wb_info(wb, &info);
+
+ info.buf_width = timings->x_res;
+ info.buf_height = timings->y_res;
+
+ r = wb->set_wb_info(wb, &info);
+ if (r) {
+ dev_err(&dssdev->dev, "failed to set timings %d, %d\n",
+ timings->x_res, timings->y_res);
+ return;
+ }
+
dssdev->panel.timings.x_res = timings->x_res;
dssdev->panel.timings.y_res = timings->y_res;
}
@@ -315,6 +389,11 @@ static struct omap_dss_driver writeback_panel_driver = {
.suspend = writeback_panel_suspend,
.resume = writeback_panel_resume,
+ .set_rotate = writeback_panel_rotate,
+ .get_rotate = writeback_panel_get_rotate,
+ .set_mirror = writeback_panel_mirror,
+ .get_mirror = writeback_panel_get_mirror,
+
.set_timings = writeback_panel_set_timings,
.get_timings = writeback_panel_get_timings,
.check_timings = writeback_panel_check_timings,
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 23/29] OMAPDSS: Writeback: Configure writeback specific parameters
From: Archit Taneja @ 2011-12-27 12:49 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Calculate writeback specific parameters capture mode, truncation and delay count
in dss_wb_calc_params(). The writeback parameters calculated are:
truncation: This is needs to be set if the color depth input to writeback is more
than the color depth of the color mode we want to store in memory.
writeback mode: This configures whether we want to use writeback in mem to mem
or capture mode. A helper function called wb_manual_update() is created, it
returns true if we are in mem to mem mode. It will be used later again when mem
to mem support is added.
delay_count: This specifies the time(in lines) when the HW flushes writeback
FIFOs and takes in new register configurations after the VSYNC is generated by
the manager to which writeback is connected.
Pass these parameters to dispc_wb_setup() so that they can be written in
writeback registers.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/apply.c | 15 +++++++++++++--
drivers/video/omap2/dss/dispc.c | 28 +++++++++++++++++++++-------
drivers/video/omap2/dss/dss.h | 5 +++--
drivers/video/omap2/dss/writeback.c | 31 +++++++++++++++++++++++++++----
4 files changed, 64 insertions(+), 15 deletions(-)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 57b061f..b941d95 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -208,6 +208,13 @@ static bool mgr_manual_update(struct omap_overlay_manager *mgr)
return dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
}
+static bool wb_manual_update(struct omap_dss_writeback *wb)
+{
+ struct omap_overlay_manager *mgr = wb->dssdev->manager;
+
+ return mgr->get_display(mgr) ? false : true;
+}
+
static int dss_check_settings_low(struct omap_overlay_manager *mgr,
struct omap_dss_device *dssdev, bool applying)
{
@@ -662,6 +669,8 @@ static void dss_wb_write_regs(struct omap_dss_writeback *wb)
struct wb_priv_data *wp = get_wb_priv(wb);
struct omap_dss_writeback_info *wi;
u16 in_width, in_height;
+ bool truncation;
+ int delay_count;
int r;
if (!wp->enabled || !wp->info_dirty)
@@ -671,9 +680,11 @@ static void dss_wb_write_regs(struct omap_dss_writeback *wb)
wi = &wp->info;
- dss_wb_calc_params(wb, wi, &in_width, &in_height);
+ dss_wb_calc_params(wb, wi, &in_width, &in_height, &truncation,
+ &delay_count);
- r = dispc_wb_setup(wb->id, wi, in_width, in_height);
+ r = dispc_wb_setup(wb->id, wi, in_width, in_height,
+ wb_manual_update(wb), truncation, delay_count);
if (r) {
DSSERR("dispc_wb_setup failed\n");
return;
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index cbce120..73ba7cd 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1965,29 +1965,43 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
}
int dispc_wb_setup(int id, struct omap_dss_writeback_info *wi,
- u16 in_width, u16 in_height)
+ u16 in_width, u16 in_height, bool mem_to_mem_mode,
+ bool truncation, int delay_count)
{
int r;
struct omap_dss_writeback *wb = omap_dss_get_writeback(id);
+ enum omap_plane plane = wb->plane_id;
const int pos_x = 0, pos_y = 0;
const u8 zorder = 0, global_alpha = 0;
const bool chroma_upscale = false, ilace = false, replication = false;
enum omap_channel channel;
+ u32 l;
- channel = dispc_wb_get_channel_in(wb->plane_id);
+ channel = dispc_wb_get_channel_in(plane);
DSSDBG("dispc_wb_setup %d, pa %x, pa_uv %x, %d,%d -> %dx%d, cmode %x, "
- "rot %d, mir %d, chan %d\n",
- wb->id, wi->paddr, wi->p_uv_addr, in_width, in_height,
- wi->buf_width, wi->buf_height, wi->color_mode, wi->rotation,
- wi->mirror, channel);
+ "rot %d, mir %d, chan %d, wb_mode %d, trunc %d, "
+ "delay_count %d\n", wb->id, wi->paddr, wi->p_uv_addr, in_width,
+ in_height, wi->buf_width, wi->buf_height, wi->color_mode,
+ wi->rotation, wi->mirror, channel, mem_to_mem_mode, truncation,
+ delay_count);
- r = dispc_plane_setup(wb->plane_id, channel, wb->caps, wi->paddr,
+ r = dispc_plane_setup(plane, channel, wb->caps, wi->paddr,
wi->p_uv_addr, in_width, pos_x, pos_y, in_width, in_height,
wi->buf_width, wi->buf_height, wi->color_mode, wi->rotation,
wi->mirror, zorder, wi->pre_mult_alpha, global_alpha,
wi->rotation_type, chroma_upscale, ilace, replication);
+ /* setup extra DISPC_WB_ATTRIBUTES */
+ l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
+ l = FLD_MOD(l, truncation, 10, 10); /* TRUNCATIONENABLE */
+ l = FLD_MOD(l, mem_to_mem_mode, 19, 19); /* WRITEBACKMODE */
+ l = FLD_MOD(l, wi->capture_rate, 26, 24); /* CAPTUREMODE */
+ dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
+
+ /* setup DISPC_WB_ATTRIBUTES2 */
+ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), delay_count, 7, 0);
+
return r;
}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index c05658b..c656aed 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -251,7 +251,7 @@ int writeback_init_display(struct omap_dss_device *dssdev);
enum dss_writeback_channel_in dss_wb_calc_channel_in(struct omap_dss_writeback *wb);
void dss_wb_calc_params(struct omap_dss_writeback *wb,
struct omap_dss_writeback_info *wi, u16 *in_width,
- u16 *in_height);
+ u16 *in_height, bool *truncation, int *delay_count);
int dss_wb_simple_check(struct omap_dss_writeback *wb,
const struct omap_dss_writeback_info *info);
@@ -496,7 +496,8 @@ void dispc_mgr_setup(enum omap_channel channel,
bool dispc_wb_go_busy(int id);
void dispc_wb_go(int id);
int dispc_wb_setup(int id, struct omap_dss_writeback_info *wi,
- u16 in_width, u16 in_height);
+ u16 in_width, u16 in_height, bool mem_to_mem_mode,
+ bool truncation, int delay_count);
void dispc_wb_enable(int id, bool enable);
void dispc_wb_set_channel_in(int plane, enum dss_writeback_channel_in ch_in);
diff --git a/drivers/video/omap2/dss/writeback.c b/drivers/video/omap2/dss/writeback.c
index 7c4e9c0..82d601c 100644
--- a/drivers/video/omap2/dss/writeback.c
+++ b/drivers/video/omap2/dss/writeback.c
@@ -143,7 +143,7 @@ enum dss_writeback_channel_in dss_wb_calc_channel_in(struct omap_dss_writeback *
void dss_wb_calc_params(struct omap_dss_writeback *wb,
struct omap_dss_writeback_info *wi, u16 *in_width,
- u16 *in_height)
+ u16 *in_height, bool *truncation, int *delay_count)
{
struct omap_video_timings timings;
struct omap_dss_device *dssdev;
@@ -152,10 +152,33 @@ void dss_wb_calc_params(struct omap_dss_writeback *wb,
mgr = wb->dssdev->manager;
dssdev = mgr->get_display(mgr);
- dssdev->driver->get_timings(dssdev, &timings);
+ if (dssdev) {
+ /* we are in capture mode */
+ dssdev->driver->get_timings(dssdev, &timings);
- *in_width = timings.x_res;
- *in_height = timings.y_res;
+ *in_width = timings.x_res;
+ *in_height = timings.y_res;
+
+ /* TODO: Find more optimal values of delay_count */
+ *delay_count = timings.vsw + timings.vbp + timings.vfp - 1;
+ *delay_count = *delay_count < 255 ? : 255;
+ }
+
+ switch (wi->color_mode) {
+ case OMAP_DSS_COLOR_RGB16:
+ case OMAP_DSS_COLOR_RGB24P:
+ case OMAP_DSS_COLOR_ARGB16:
+ case OMAP_DSS_COLOR_RGBA16:
+ case OMAP_DSS_COLOR_RGB12U:
+ case OMAP_DSS_COLOR_ARGB16_1555:
+ case OMAP_DSS_COLOR_XRGB16_1555:
+ case OMAP_DSS_COLOR_RGBX16:
+ *truncation = true;
+ break;
+ default:
+ *truncation = false;
+ break;
+ }
}
int dss_wb_simple_check(struct omap_dss_writeback *wb,
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 22/29] OMAPDSS: DISPC: Setup writeback go, enable and channel_in functions
From: Archit Taneja @ 2011-12-27 12:49 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Fill up dispc_wb_go(), dispc_wb_go_busy(), dispc_wb_enable() and
dispc_wb_get_channel_in()/set_channel_in() with writeback register writes. Make
a minor modification in dss_wb_write_regs_extra() to pass the plane_id instead
of the writeback id when calling dispc_wb_set_channel_in().
Setup dispc_wb_enable() as dispc_enable_lcd_out() function and wait for the
FRAMEDONEWB interrupt while disabling writeback.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/apply.c | 2 +-
drivers/video/omap2/dss/dispc.c | 68 +++++++++++++++++++++++++++++++++++----
drivers/video/omap2/dss/dss.h | 2 +-
3 files changed, 63 insertions(+), 9 deletions(-)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index dd1fd419..57b061f 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -690,7 +690,7 @@ static void dss_wb_write_regs_extra(struct omap_dss_writeback *wb)
if (!wp->extra_info_dirty)
return;
- dispc_wb_set_channel_in(wb->id, wp->channel_in);
+ dispc_wb_set_channel_in(wb->plane_id, wp->channel_in);
dispc_ovl_set_fifo_threshold(wb->plane_id, wp->fifo_low, wp->fifo_high);
wp->extra_info_dirty = false;
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index c7de56d..cbce120 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -510,12 +510,26 @@ void dispc_mgr_go(enum omap_channel channel)
bool dispc_wb_go_busy(int id)
{
- return false;
+ return REG_GET(DISPC_CONTROL2, 6, 6) = 1;
}
void dispc_wb_go(int id)
{
- return;
+ struct omap_dss_writeback *wb = omap_dss_get_writeback(id);
+ bool enable, go;
+
+ enable = REG_GET(DISPC_OVL_ATTRIBUTES(wb->plane_id), 0, 0) = 1;
+
+ if (!enable)
+ return;
+
+ go = REG_GET(DISPC_CONTROL2, 6, 6) = 1;
+ if (go) {
+ DSSERR("GO bit not down for WB\n");
+ return;
+ }
+
+ REG_FLD_MOD(DISPC_CONTROL2, 1, 6, 6);
}
static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value)
@@ -903,16 +917,24 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
return channel;
}
-void dispc_wb_set_channel_in(int id, enum dss_writeback_channel_in ch_in)
+void dispc_wb_set_channel_in(int plane, enum dss_writeback_channel_in ch_in)
{
- return;
+ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), ch_in, 18, 16);
}
static enum omap_channel dispc_wb_get_channel_in(int plane)
{
- /* Return LCD channel for now */
+ int channel_in = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 18, 16);
- return OMAP_DSS_CHANNEL_LCD;
+ switch (channel_in) {
+ case OMAP_DSS_WB_LCD2_MGR:
+ return OMAP_DSS_CHANNEL_LCD2;
+ case OMAP_DSS_WB_TV_MGR:
+ return OMAP_DSS_CHANNEL_DIGIT;
+ case OMAP_DSS_WB_LCD1_MGR:
+ default:
+ return OMAP_DSS_CHANNEL_LCD;
+ };
}
static void dispc_ovl_set_burst_size(enum omap_plane plane,
@@ -2138,7 +2160,39 @@ void dispc_mgr_enable(enum omap_channel channel, bool enable)
void dispc_wb_enable(int id, bool enable)
{
- return;
+ struct omap_dss_writeback *wb = omap_dss_get_writeback(id);
+ enum omap_plane plane = wb->plane_id;
+ struct completion frame_done_completion;
+ bool is_on;
+ int r;
+ u32 irq;
+
+ is_on = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
+ irq = DISPC_IRQ_FRAMEDONEWB;
+
+ if (!enable && is_on) {
+ init_completion(&frame_done_completion);
+
+ r = omap_dispc_register_isr(dispc_disable_isr,
+ &frame_done_completion, irq);
+
+ if (r)
+ DSSERR("failed to register FRAMEDONEWB isr\n");
+ }
+
+ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
+
+ if (!enable && is_on) {
+ if (!wait_for_completion_timeout(&frame_done_completion,
+ msecs_to_jiffies(100)))
+ DSSERR("timeout waiting for FRAMEDONEWB\n");
+
+ r = omap_dispc_unregister_isr(dispc_disable_isr,
+ &frame_done_completion, irq);
+
+ if (r)
+ DSSERR("failed to unregister FRAMEDONEWB isr\n");
+ }
}
void dispc_lcd_enable_signal_polarity(bool act_high)
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 69b4793..c05658b 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -498,7 +498,7 @@ void dispc_wb_go(int id);
int dispc_wb_setup(int id, struct omap_dss_writeback_info *wi,
u16 in_width, u16 in_height);
void dispc_wb_enable(int id, bool enable);
-void dispc_wb_set_channel_in(int id, enum dss_writeback_channel_in ch_in);
+void dispc_wb_set_channel_in(int plane, enum dss_writeback_channel_in ch_in);
/* VENC */
#ifdef CONFIG_OMAP2_DSS_VENC
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 21/29] OMAPDSS: DISPC: Configure overlay-like parameters in dispc_wb_setup
From: Archit Taneja @ 2011-12-27 12:49 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Call dispc_plane_setup() through dispc_wb_setup() to configure overlay-like
parameters. Create a helper function in writeback.c called dss_wb_calc_params()
which for now calculates the input width and height which goes to writeback.
Create a dummy dispc function which returns the channel of the manager to which
the writeback pipeline is connected.
The parameters in dispc_plane_setup() which do not hold for writeback are filled
passed as zeroes or false, dispc_plane_setup() takes care of not configuring
them if the plane is writeback.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/apply.c | 5 ++++-
drivers/video/omap2/dss/dispc.c | 33 +++++++++++++++++++++++++++++++--
drivers/video/omap2/dss/dss.h | 6 +++++-
drivers/video/omap2/dss/writeback.c | 17 +++++++++++++++++
4 files changed, 57 insertions(+), 4 deletions(-)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index a17cc47..dd1fd419 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -661,6 +661,7 @@ static void dss_wb_write_regs(struct omap_dss_writeback *wb)
{
struct wb_priv_data *wp = get_wb_priv(wb);
struct omap_dss_writeback_info *wi;
+ u16 in_width, in_height;
int r;
if (!wp->enabled || !wp->info_dirty)
@@ -670,7 +671,9 @@ static void dss_wb_write_regs(struct omap_dss_writeback *wb)
wi = &wp->info;
- r = dispc_wb_setup(wb->id, wi);
+ dss_wb_calc_params(wb, wi, &in_width, &in_height);
+
+ r = dispc_wb_setup(wb->id, wi, in_width, in_height);
if (r) {
DSSERR("dispc_wb_setup failed\n");
return;
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 3a40f8e..c7de56d 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -908,6 +908,13 @@ void dispc_wb_set_channel_in(int id, enum dss_writeback_channel_in ch_in)
return;
}
+static enum omap_channel dispc_wb_get_channel_in(int plane)
+{
+ /* Return LCD channel for now */
+
+ return OMAP_DSS_CHANNEL_LCD;
+}
+
static void dispc_ovl_set_burst_size(enum omap_plane plane,
enum omap_burst_size burst_size)
{
@@ -1935,9 +1942,31 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
return r;
}
-int dispc_wb_setup(int id, struct omap_dss_writeback_info *wi)
+int dispc_wb_setup(int id, struct omap_dss_writeback_info *wi,
+ u16 in_width, u16 in_height)
{
- return 0;
+ int r;
+ struct omap_dss_writeback *wb = omap_dss_get_writeback(id);
+ const int pos_x = 0, pos_y = 0;
+ const u8 zorder = 0, global_alpha = 0;
+ const bool chroma_upscale = false, ilace = false, replication = false;
+ enum omap_channel channel;
+
+ channel = dispc_wb_get_channel_in(wb->plane_id);
+
+ DSSDBG("dispc_wb_setup %d, pa %x, pa_uv %x, %d,%d -> %dx%d, cmode %x, "
+ "rot %d, mir %d, chan %d\n",
+ wb->id, wi->paddr, wi->p_uv_addr, in_width, in_height,
+ wi->buf_width, wi->buf_height, wi->color_mode, wi->rotation,
+ wi->mirror, channel);
+
+ r = dispc_plane_setup(wb->plane_id, channel, wb->caps, wi->paddr,
+ wi->p_uv_addr, in_width, pos_x, pos_y, in_width, in_height,
+ wi->buf_width, wi->buf_height, wi->color_mode, wi->rotation,
+ wi->mirror, zorder, wi->pre_mult_alpha, global_alpha,
+ wi->rotation_type, chroma_upscale, ilace, replication);
+
+ return r;
}
int dispc_ovl_enable(enum omap_plane plane, bool enable)
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 1b128f1..69b4793 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -249,6 +249,9 @@ void dss_init_writeback(void);
void dss_uninit_writeback(void);
int writeback_init_display(struct omap_dss_device *dssdev);
enum dss_writeback_channel_in dss_wb_calc_channel_in(struct omap_dss_writeback *wb);
+void dss_wb_calc_params(struct omap_dss_writeback *wb,
+ struct omap_dss_writeback_info *wi, u16 *in_width,
+ u16 *in_height);
int dss_wb_simple_check(struct omap_dss_writeback *wb,
const struct omap_dss_writeback_info *info);
@@ -492,7 +495,8 @@ void dispc_mgr_setup(enum omap_channel channel,
bool dispc_wb_go_busy(int id);
void dispc_wb_go(int id);
-int dispc_wb_setup(int id, struct omap_dss_writeback_info *wi);
+int dispc_wb_setup(int id, struct omap_dss_writeback_info *wi,
+ u16 in_width, u16 in_height);
void dispc_wb_enable(int id, bool enable);
void dispc_wb_set_channel_in(int id, enum dss_writeback_channel_in ch_in);
diff --git a/drivers/video/omap2/dss/writeback.c b/drivers/video/omap2/dss/writeback.c
index 14103bf..7c4e9c0 100644
--- a/drivers/video/omap2/dss/writeback.c
+++ b/drivers/video/omap2/dss/writeback.c
@@ -141,6 +141,23 @@ enum dss_writeback_channel_in dss_wb_calc_channel_in(struct omap_dss_writeback *
}
}
+void dss_wb_calc_params(struct omap_dss_writeback *wb,
+ struct omap_dss_writeback_info *wi, u16 *in_width,
+ u16 *in_height)
+{
+ struct omap_video_timings timings;
+ struct omap_dss_device *dssdev;
+ struct omap_overlay_manager *mgr;
+
+ mgr = wb->dssdev->manager;
+ dssdev = mgr->get_display(mgr);
+
+ dssdev->driver->get_timings(dssdev, &timings);
+
+ *in_width = timings.x_res;
+ *in_height = timings.y_res;
+}
+
int dss_wb_simple_check(struct omap_dss_writeback *wb,
const struct omap_dss_writeback_info *info)
{
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 20/29] OMAPDSS: Writeback: Add writeback capabilities
From: Archit Taneja @ 2011-12-27 12:49 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Add a capabilities parameter of type omap_overlay_caps to omap_dss_writeback.
These caps let us reuse some of the DISPC overlay functions. Set the
capabilities so the writeback supports scaling and pre multiplied alpha.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/writeback.c | 3 +++
include/video/omapdss.h | 3 +++
2 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/drivers/video/omap2/dss/writeback.c b/drivers/video/omap2/dss/writeback.c
index 540e61d..14103bf 100644
--- a/drivers/video/omap2/dss/writeback.c
+++ b/drivers/video/omap2/dss/writeback.c
@@ -90,6 +90,9 @@ void dss_init_writeback(void)
wb->id = i;
wb->plane_id = OMAP_DSS_WB + i;
+ wb->caps = OMAP_DSS_OVL_CAP_SCALE |
+ OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA;
+
wb->set_wb_info = &dss_wb_set_info;
wb->get_wb_info = &dss_wb_get_info;
}
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 49e3ccb..291457c 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -493,6 +493,9 @@ struct omap_dss_writeback {
int id;
int plane_id;
+ /* overlay-like capabilities writeback supports */
+ enum omap_overlay_caps caps;
+
/* dummy panel we are connected to */
struct omap_dss_device *dssdev;
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 19/29] OMAPDSS: DISPC: Don't set chroma resampling bit for writeback
From: Archit Taneja @ 2011-12-27 12:49 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
The bit YUVCHROMARESAMPLING isn't there for writeback in DISPC_WB_ATTRIBUTES2.
Ignore this bit in dispc_ovl_set_scaling_uv() if the plane is OMAP_DSS_WB.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/dispc.c | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 21d6286..3a40f8e 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1238,7 +1238,8 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
color_mode != OMAP_DSS_COLOR_UYVY &&
color_mode != OMAP_DSS_COLOR_NV12)) {
/* reset chroma resampling for RGB formats */
- REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
+ if (plane != OMAP_DSS_WB)
+ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
return;
}
switch (color_mode) {
@@ -1277,8 +1278,10 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
out_width, out_height, five_taps,
rotation, DISPC_COLOR_COMPONENT_UV);
- REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
- (scale_x || scale_y) ? 1 : 0, 8, 8);
+ if (plane != OMAP_DSS_WB)
+ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
+ (scale_x || scale_y) ? 1 : 0, 8, 8);
+
/* set H scaling */
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
/* set V scaling */
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 18/29] OMAPDSS: DISPC: Make chroma_upscale an argument to dispc_plane_setup
From: Archit Taneja @ 2011-12-27 12:49 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Pass chroma_upscale boolean parameter to dispc_plane_setup(), this will be set
to true when dispc_plane_setup() is called from dispc_ovl_setup() and false when
called from dispc_wb_setup().
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/dispc.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index eca6157..21d6286 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1789,7 +1789,7 @@ static int dispc_plane_setup(enum omap_plane plane, enum omap_channel channel,
u16 out_width, u16 out_height, enum omap_color_mode color_mode,
u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
u8 global_alpha, enum omap_dss_rotation_type rotation_type,
- bool ilace, bool replication)
+ bool chroma_upscale, bool ilace, bool replication)
{
bool five_taps = true;
bool fieldmode = 0;
@@ -1887,10 +1887,9 @@ static int dispc_plane_setup(enum omap_plane plane, enum omap_channel channel,
dispc_ovl_set_pic_size(plane, width, height);
if (caps & OMAP_DSS_OVL_CAP_SCALE) {
- dispc_ovl_set_scaling(plane, width, height,
- outw, outh,
- ilace, five_taps, fieldmode,
- color_mode, rotation, true);
+ dispc_ovl_set_scaling(plane, width, height, outw, outh,
+ ilace, five_taps, fieldmode, color_mode,
+ rotation, chroma_upscale);
dispc_ovl_set_vid_size(plane, outw, outh);
dispc_ovl_set_vid_color_conv(plane, cconv);
}
@@ -1911,6 +1910,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
{
int r;
struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+ const bool chroma_upscale = true;
enum omap_channel channel;
channel = dispc_ovl_get_channel_out(plane);
@@ -1927,7 +1927,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
oi->width, oi->height, oi->out_width, oi->out_height,
oi->color_mode, oi->rotation, oi->mirror, oi->zorder,
oi->pre_mult_alpha, oi->global_alpha, oi->rotation_type,
- ilace, replication);
+ chroma_upscale, ilace, replication);
return r;
}
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 17/29] OMAPDSS: DISPC: Make dispc_ovl_setup call dispc_plane_setup
From: Archit Taneja @ 2011-12-27 12:49 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Add a new static function called dispc_plane_setup(). This function is used by
dispc_ovl_setup() to configure the overlay registers.
This split is done so that dispc_wb_setup() can reuse the common overlay related
registers configured in dispc_plane_setup().
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/dispc.c | 126 ++++++++++++++++++++++-----------------
1 files changed, 71 insertions(+), 55 deletions(-)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 58de7d7..eca6157 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1783,63 +1783,54 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
return 0;
}
-int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
+static int dispc_plane_setup(enum omap_plane plane, enum omap_channel channel,
+ enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
+ u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
+ u16 out_width, u16 out_height, enum omap_color_mode color_mode,
+ u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
+ u8 global_alpha, enum omap_dss_rotation_type rotation_type,
bool ilace, bool replication)
{
- struct omap_overlay *ovl = omap_dss_get_overlay(plane);
- enum omap_overlay_caps caps = ovl->caps;
bool five_taps = true;
bool fieldmode = 0;
int r, cconv = 0;
unsigned offset0, offset1;
s32 row_inc;
s32 pix_inc;
- u16 frame_height = oi->height;
+ u16 frame_height = height;
unsigned int field_offset = 0;
u16 outw, outh;
- enum omap_channel channel;
-
- channel = dispc_ovl_get_channel_out(plane);
- DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
- "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d\n",
- plane, oi->paddr, oi->p_uv_addr,
- oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
- oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
- oi->mirror, ilace, channel, replication);
-
- if (oi->paddr = 0)
+ if (paddr = 0)
return -EINVAL;
- outw = oi->out_width = 0 ? oi->width : oi->out_width;
- outh = oi->out_height = 0 ? oi->height : oi->out_height;
+ outw = out_width = 0 ? width : out_width;
+ outh = out_height = 0 ? height : out_height;
- if (ilace && oi->height = outh)
+ if (ilace && height = outh)
fieldmode = 1;
if (ilace) {
if (fieldmode)
- oi->height /= 2;
- oi->pos_y /= 2;
+ height /= 2;
+ pos_y /= 2;
outh /= 2;
DSSDBG("adjusting for ilace: height %d, pos_y %d, "
- "out_height %d\n",
- oi->height, oi->pos_y, outh);
+ "out_height %d\n", height, pos_y, outh);
}
- if (!dss_feat_color_mode_supported(plane, oi->color_mode))
+ if (!dss_feat_color_mode_supported(plane, color_mode))
return -EINVAL;
- r = dispc_ovl_calc_scaling(plane, channel, caps, oi->width, oi->height,
- outw, outh, oi->color_mode,
- &five_taps);
+ r = dispc_ovl_calc_scaling(plane, channel, caps, width, height,
+ outw, outh, color_mode, &five_taps);
if (r)
return r;
- if (oi->color_mode = OMAP_DSS_COLOR_YUV2 ||
- oi->color_mode = OMAP_DSS_COLOR_UYVY ||
- oi->color_mode = OMAP_DSS_COLOR_NV12)
+ if (color_mode = OMAP_DSS_COLOR_YUV2 ||
+ color_mode = OMAP_DSS_COLOR_UYVY ||
+ color_mode = OMAP_DSS_COLOR_NV12)
cconv = 1;
if (ilace && !fieldmode) {
@@ -1850,72 +1841,97 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
* so the integer part must be added to the base address of the
* bottom field.
*/
- if (!oi->height || oi->height = outh)
+ if (!height || height = outh)
field_offset = 0;
else
- field_offset = oi->height / outh / 2;
+ field_offset = height / outh / 2;
}
/* Fields are independent but interleaved in memory. */
if (fieldmode)
field_offset = 1;
- if (oi->rotation_type = OMAP_DSS_ROT_DMA)
- calc_dma_rotation_offset(oi->rotation, oi->mirror,
- oi->screen_width, oi->width, frame_height,
- oi->color_mode, fieldmode, field_offset,
+ if (rotation_type = OMAP_DSS_ROT_DMA)
+ calc_dma_rotation_offset(rotation, mirror,
+ screen_width, width, frame_height,
+ color_mode, fieldmode, field_offset,
&offset0, &offset1, &row_inc, &pix_inc);
else
- calc_vrfb_rotation_offset(oi->rotation, oi->mirror,
- oi->screen_width, oi->width, frame_height,
- oi->color_mode, fieldmode, field_offset,
+ calc_vrfb_rotation_offset(rotation, mirror,
+ screen_width, width, frame_height,
+ color_mode, fieldmode, field_offset,
&offset0, &offset1, &row_inc, &pix_inc);
DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
offset0, offset1, row_inc, pix_inc);
- dispc_ovl_set_color_mode(plane, oi->color_mode);
+ dispc_ovl_set_color_mode(plane, color_mode);
- dispc_ovl_set_ba0(plane, oi->paddr + offset0);
- dispc_ovl_set_ba1(plane, oi->paddr + offset1);
+ dispc_ovl_set_ba0(plane, paddr + offset0);
+ dispc_ovl_set_ba1(plane, paddr + offset1);
- if (OMAP_DSS_COLOR_NV12 = oi->color_mode) {
- dispc_ovl_set_ba0_uv(plane, oi->p_uv_addr + offset0);
- dispc_ovl_set_ba1_uv(plane, oi->p_uv_addr + offset1);
+ if (OMAP_DSS_COLOR_NV12 = color_mode) {
+ dispc_ovl_set_ba0_uv(plane, p_uv_addr + offset0);
+ dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1);
}
dispc_ovl_set_row_inc(plane, row_inc);
dispc_ovl_set_pix_inc(plane, pix_inc);
- DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width,
- oi->height, outw, outh);
+ DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height,
+ outw, outh);
- dispc_ovl_set_pos(plane, caps, oi->pos_x, oi->pos_y);
+ dispc_ovl_set_pos(plane, caps, pos_x, pos_y);
- dispc_ovl_set_pic_size(plane, oi->width, oi->height);
+ dispc_ovl_set_pic_size(plane, width, height);
if (caps & OMAP_DSS_OVL_CAP_SCALE) {
- dispc_ovl_set_scaling(plane, oi->width, oi->height,
+ dispc_ovl_set_scaling(plane, width, height,
outw, outh,
ilace, five_taps, fieldmode,
- oi->color_mode, oi->rotation, true);
+ color_mode, rotation, true);
dispc_ovl_set_vid_size(plane, outw, outh);
dispc_ovl_set_vid_color_conv(plane, cconv);
}
- dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror,
- oi->color_mode);
+ dispc_ovl_set_rotation_attrs(plane, rotation, mirror, color_mode);
- dispc_ovl_set_zorder(plane, caps, oi->zorder);
- dispc_ovl_set_pre_mult_alpha(plane, caps, oi->pre_mult_alpha);
- dispc_ovl_setup_global_alpha(plane, caps, oi->global_alpha);
+ dispc_ovl_set_zorder(plane, caps, zorder);
+ dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha);
+ dispc_ovl_setup_global_alpha(plane, caps, global_alpha);
dispc_ovl_enable_replication(plane, caps, replication);
return 0;
}
+int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
+ bool ilace, bool replication)
+{
+ int r;
+ struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+ enum omap_channel channel;
+
+ channel = dispc_ovl_get_channel_out(plane);
+
+ DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
+ "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d\n",
+ plane, oi->paddr, oi->p_uv_addr,
+ oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
+ oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
+ oi->mirror, ilace, channel, replication);
+
+ r = dispc_plane_setup(plane, channel, ovl->caps, oi->paddr,
+ oi->p_uv_addr, oi->screen_width, oi->pos_x, oi->pos_y,
+ oi->width, oi->height, oi->out_width, oi->out_height,
+ oi->color_mode, oi->rotation, oi->mirror, oi->zorder,
+ oi->pre_mult_alpha, oi->global_alpha, oi->rotation_type,
+ ilace, replication);
+
+ return r;
+}
+
int dispc_wb_setup(int id, struct omap_dss_writeback_info *wi)
{
return 0;
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 16/29] OMAPDSS: OVERLAY: Add position and replication as overlay caps
From: Archit Taneja @ 2011-12-27 12:48 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Add position and replication as overlay caps. Pass overlay caps as an argument
to the corresponding functions.
These caps will be set for all overlays, but not for writeback. This is done
so writeback can reuse dispc_ovl_setup() to the maximum.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/dispc.c | 20 +++++++++++++++-----
drivers/video/omap2/dss/overlay.c | 6 ++++++
include/video/omapdss.h | 2 ++
3 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index d9e04f0..58de7d7 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -656,9 +656,15 @@ static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr)
dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
}
-static void dispc_ovl_set_pos(enum omap_plane plane, int x, int y)
+static void dispc_ovl_set_pos(enum omap_plane plane,
+ enum omap_overlay_caps caps, int x, int y)
{
- u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
+ u32 val;
+
+ if ((caps & OMAP_DSS_OVL_CAP_POS) = 0)
+ return;
+
+ val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
dispc_write_reg(DISPC_OVL_POSITION(plane), val);
}
@@ -988,11 +994,15 @@ static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)
dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
}
-static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable)
+static void dispc_ovl_enable_replication(enum omap_plane plane,
+ enum omap_overlay_caps caps, bool enable)
{
static const unsigned shifts[] = { 5, 10, 10, 10 };
int shift;
+ if ((caps & OMAP_DSS_OVL_CAP_REPLICATION) = 0)
+ return;
+
shift = shifts[plane];
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
}
@@ -1881,7 +1891,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width,
oi->height, outw, outh);
- dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y);
+ dispc_ovl_set_pos(plane, caps, oi->pos_x, oi->pos_y);
dispc_ovl_set_pic_size(plane, oi->width, oi->height);
@@ -1901,7 +1911,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
dispc_ovl_set_pre_mult_alpha(plane, caps, oi->pre_mult_alpha);
dispc_ovl_setup_global_alpha(plane, caps, oi->global_alpha);
- dispc_ovl_enable_replication(plane, replication);
+ dispc_ovl_enable_replication(plane, caps, replication);
return 0;
}
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index dc0cc52..cb548c0 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -509,6 +509,12 @@ void dss_init_overlays(struct platform_device *pdev)
ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
ovl->caps = dss_feat_get_overlay_caps(ovl->id);
+
+ /* these caps are common to all ovelays across all OMAPs, they
+ * are used to differentiate between an overlay and writeback */
+ ovl->caps |= OMAP_DSS_OVL_CAP_POS |
+ OMAP_DSS_OVL_CAP_REPLICATION;
+
ovl->supported_modes dss_feat_get_supported_color_modes(ovl->id);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 6bf84b2..49e3ccb 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -185,6 +185,8 @@ enum omap_overlay_caps {
OMAP_DSS_OVL_CAP_GLOBAL_ALPHA = 1 << 1,
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA = 1 << 2,
OMAP_DSS_OVL_CAP_ZORDER = 1 << 3,
+ OMAP_DSS_OVL_CAP_POS = 1 << 4,
+ OMAP_DSS_OVL_CAP_REPLICATION = 1 << 5,
};
enum omap_overlay_manager_caps {
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 15/29] OMAPDSS: DISPC: Pass overlay caps as a parameter to DISPC overlay related function
From: Archit Taneja @ 2011-12-27 12:48 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Currently, the functions below take the omap_plane parameter and derive the
overlay caps within them. Pass the overlay caps as a parameter to the function
to allow writeback functions to use them too.
- dispc_ovl_set_zorder()
- dispc_ovl_set_pre_mult_alpha()
- dispc_ovl_setup_global_alpha()
- dispc_ovl_calc_scaling()
- dispc_ovl_setup()
These functions will be used for writeback later, and the caps will help in
deciding if they are to be used for writeback or not. This allows reuse of
overlay caps for writeback.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/dispc.c | 38 ++++++++++++++++++--------------------
1 files changed, 18 insertions(+), 20 deletions(-)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index dfbb39b..d9e04f0 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -684,11 +684,10 @@ static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height)
dispc_write_reg(DISPC_OVL_SIZE(plane), val);
}
-static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder)
+static void dispc_ovl_set_zorder(enum omap_plane plane,
+ enum omap_overlay_caps caps, u8 zorder)
{
- struct omap_overlay *ovl = omap_dss_get_overlay(plane);
-
- if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) = 0)
+ if ((caps & OMAP_DSS_OVL_CAP_ZORDER) = 0)
return;
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
@@ -705,23 +704,22 @@ static void dispc_ovl_enable_zorder_planes(void)
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
}
-static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable)
+static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane,
+ enum omap_overlay_caps caps, bool enable)
{
- struct omap_overlay *ovl = omap_dss_get_overlay(plane);
-
- if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) = 0)
+ if ((caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) = 0)
return;
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
}
-static void dispc_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
+static void dispc_ovl_setup_global_alpha(enum omap_plane plane,
+ enum omap_overlay_caps caps, u8 global_alpha)
{
static const unsigned shifts[] = { 0, 8, 16, 24, };
int shift;
- struct omap_overlay *ovl = omap_dss_get_overlay(plane);
- if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) = 0)
+ if ((caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) = 0)
return;
shift = shifts[plane];
@@ -1704,11 +1702,10 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
}
static int dispc_ovl_calc_scaling(enum omap_plane plane,
- enum omap_channel channel, u16 width, u16 height,
- u16 out_width, u16 out_height,
+ enum omap_channel channel, enum omap_overlay_caps caps,
+ u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps)
{
- struct omap_overlay *ovl = omap_dss_get_overlay(plane);
const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
const int maxsinglelinewidth dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
@@ -1717,7 +1714,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
if (width = out_width && height = out_height)
return 0;
- if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) = 0)
+ if ((caps & OMAP_DSS_OVL_CAP_SCALE) = 0)
return -EINVAL;
if (out_width < width / maxdownscale ||
@@ -1780,6 +1777,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
bool ilace, bool replication)
{
struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+ enum omap_overlay_caps caps = ovl->caps;
bool five_taps = true;
bool fieldmode = 0;
int r, cconv = 0;
@@ -1823,7 +1821,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
if (!dss_feat_color_mode_supported(plane, oi->color_mode))
return -EINVAL;
- r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height,
+ r = dispc_ovl_calc_scaling(plane, channel, caps, oi->width, oi->height,
outw, outh, oi->color_mode,
&five_taps);
if (r)
@@ -1887,7 +1885,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
dispc_ovl_set_pic_size(plane, oi->width, oi->height);
- if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) {
+ if (caps & OMAP_DSS_OVL_CAP_SCALE) {
dispc_ovl_set_scaling(plane, oi->width, oi->height,
outw, outh,
ilace, five_taps, fieldmode,
@@ -1899,9 +1897,9 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror,
oi->color_mode);
- dispc_ovl_set_zorder(plane, oi->zorder);
- dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha);
- dispc_ovl_setup_global_alpha(plane, oi->global_alpha);
+ dispc_ovl_set_zorder(plane, caps, oi->zorder);
+ dispc_ovl_set_pre_mult_alpha(plane, caps, oi->pre_mult_alpha);
+ dispc_ovl_setup_global_alpha(plane, caps, oi->global_alpha);
dispc_ovl_enable_replication(plane, replication);
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 14/29] OMAPDSS: DISPC: Allow both upscaling and downscaling of chroma
From: Archit Taneja @ 2011-12-27 12:48 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Make the function dispc_ovl_set_scaling_uv() take a boolean argument which tells
if we want to upscale or downscale the chroma plane.
Downscaling of chroma is required by writeback pipeline for converting the input
YUV444 color format to YUV422 or NV12.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/dispc.c | 17 ++++++++++-------
1 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 231369a..dfbb39b 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1219,7 +1219,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
u16 out_width, u16 out_height,
bool ilace, bool five_taps,
bool fieldmode, enum omap_color_mode color_mode,
- u8 rotation)
+ u8 rotation, bool chroma_upscale)
{
int scale_x = out_width != orig_width;
int scale_y = out_height != orig_height;
@@ -1236,9 +1236,11 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
switch (color_mode) {
case OMAP_DSS_COLOR_NV12:
/* UV is subsampled by 2 vertically*/
- orig_height >>= 1;
+ orig_height = chroma_upscale ?
+ orig_height >> 1 : orig_height << 1;
/* UV is subsampled by 2 horz.*/
- orig_width >>= 1;
+ orig_width = chroma_upscale ?
+ orig_width >> 1 : orig_width << 1;
break;
case OMAP_DSS_COLOR_YUV2:
case OMAP_DSS_COLOR_UYVY:
@@ -1248,7 +1250,8 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
if (rotation = OMAP_DSS_ROT_0 ||
rotation = OMAP_DSS_ROT_180)
/* UV is subsampled by 2 hrz*/
- orig_width >>= 1;
+ orig_width = chroma_upscale ?
+ orig_width >> 1 : orig_width << 1;
/* must use FIR for YUV422 if rotated */
if (rotation != OMAP_DSS_ROT_0)
scale_x = scale_y = true;
@@ -1282,7 +1285,7 @@ static void dispc_ovl_set_scaling(enum omap_plane plane,
u16 out_width, u16 out_height,
bool ilace, bool five_taps,
bool fieldmode, enum omap_color_mode color_mode,
- u8 rotation)
+ u8 rotation, bool chroma_upscale)
{
BUG_ON(plane = OMAP_DSS_GFX);
@@ -1298,7 +1301,7 @@ static void dispc_ovl_set_scaling(enum omap_plane plane,
out_width, out_height,
ilace, five_taps,
fieldmode, color_mode,
- rotation);
+ rotation, chroma_upscale);
}
static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,
@@ -1888,7 +1891,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
dispc_ovl_set_scaling(plane, oi->width, oi->height,
outw, outh,
ilace, five_taps, fieldmode,
- oi->color_mode, oi->rotation);
+ oi->color_mode, oi->rotation, true);
dispc_ovl_set_vid_size(plane, outw, outh);
dispc_ovl_set_vid_color_conv(plane, cconv);
}
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 13/29] OMAPDSS: APPLY: Configure writeback FIFOs
From: Archit Taneja @ 2011-12-27 12:48 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: rohitkc, linux-omap, linux-fbdev, Archit Taneja
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>
Add writeback FIFO thresholds as extra_info parameters. Modify function
dss_ovl_fifo_setup() so that it can also also configure writeback pipeline
FIFOs. Extend the DISPC fifo functions to also configure the writeback
registers.
Signed-off-by: Archit Taneja <archit@ti.com>
---
drivers/video/omap2/dss/apply.c | 70 +++++++++++++++++++++++++++++++++-----
drivers/video/omap2/dss/dispc.c | 8 +++--
2 files changed, 65 insertions(+), 13 deletions(-)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 9f3c174..a17cc47 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -115,6 +115,7 @@ struct wb_priv_data {
bool shadow_extra_info_dirty;
enum dss_writeback_channel_in channel_in;
+ u32 fifo_low, fifo_high;
/* If true, GO bit is up and shadow registers cannot be written.
* Never true for writeback in memory to memory mode */
@@ -687,6 +688,7 @@ static void dss_wb_write_regs_extra(struct omap_dss_writeback *wb)
return;
dispc_wb_set_channel_in(wb->id, wp->channel_in);
+ dispc_ovl_set_fifo_threshold(wb->plane_id, wp->fifo_low, wp->fifo_high);
wp->extra_info_dirty = false;
wp->shadow_extra_info_dirty = true;
@@ -1102,21 +1104,59 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
op->extra_info_dirty = true;
}
-static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
+static void dss_apply_wb_fifo_thresholds(struct omap_dss_writeback *wb,
+ u32 fifo_low, u32 fifo_high)
{
- struct ovl_priv_data *op = get_ovl_priv(ovl);
+ struct wb_priv_data *wp = get_wb_priv(wb);
+
+ if (wp->fifo_low = fifo_low && wp->fifo_high = fifo_high)
+ return;
+
+ wp->fifo_low = fifo_low;
+ wp->fifo_high = fifo_high;
+ wp->extra_info_dirty = true;
+}
+
+static void dss_plane_setup_fifo(struct omap_overlay *ovl,
+ struct omap_dss_writeback *wb)
+{
+ enum omap_plane plane;
+ struct omap_overlay_manager *mgr;
struct omap_dss_device *dssdev;
+ bool enabled, enabling;
u32 size, burst_size;
u32 fifo_low, fifo_high;
- if (!op->enabled && !op->enabling)
+ if (ovl) {
+ struct ovl_priv_data *op;
+
+ mgr = ovl->manager;
+ op = get_ovl_priv(ovl);
+
+ enabled = op->enabled;
+ enabling = op->enabling;
+
+ plane = ovl->id;
+ } else {
+ struct wb_priv_data *wp;
+
+ mgr = wb->dssdev->manager;
+ wp = get_wb_priv(wb);
+
+ enabled = wp->enabled;
+ enabling = false;
+
+ plane = wb->plane_id;
+ }
+
+ if (!enabled && !enabling)
return;
- dssdev = ovl->manager->get_output(ovl->manager);
+ dssdev = mgr->get_output(mgr);
- size = dispc_ovl_get_fifo_size(ovl->id);
+ size = dispc_ovl_get_fifo_size(plane);
- burst_size = dispc_ovl_get_burst_size(ovl->id);
+ burst_size = dispc_ovl_get_burst_size(plane);
switch (dssdev->type) {
case OMAP_DISPLAY_TYPE_DPI:
@@ -1124,12 +1164,12 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
case OMAP_DISPLAY_TYPE_SDI:
case OMAP_DISPLAY_TYPE_VENC:
case OMAP_DISPLAY_TYPE_HDMI:
- default_get_overlay_fifo_thresholds(ovl->id, size,
+ default_get_overlay_fifo_thresholds(plane, size,
burst_size, &fifo_low, &fifo_high);
break;
#ifdef CONFIG_OMAP2_DSS_DSI
case OMAP_DISPLAY_TYPE_DSI:
- dsi_get_overlay_fifo_thresholds(ovl->id, size,
+ dsi_get_overlay_fifo_thresholds(plane, size,
burst_size, &fifo_low, &fifo_high);
break;
#endif
@@ -1137,13 +1177,17 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
BUG();
}
- dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
+ if (ovl)
+ dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
+ else
+ dss_apply_wb_fifo_thresholds(wb, fifo_low, fifo_high);
}
static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
{
struct omap_overlay *ovl;
struct mgr_priv_data *mp;
+ struct omap_dss_device *dssdev;
mp = get_mgr_priv(mgr);
@@ -1151,7 +1195,13 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
return;
list_for_each_entry(ovl, &mgr->overlays, list)
- dss_ovl_setup_fifo(ovl);
+ dss_plane_setup_fifo(ovl, NULL);
+
+ dssdev = mgr->get_writeback(mgr);
+ if (dssdev) {
+ struct omap_dss_writeback *wb = dssdev->wbdev;
+ dss_plane_setup_fifo(NULL, wb);
+ }
}
static void dss_setup_fifos(void)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index a4d5504..231369a 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -91,7 +91,7 @@ static struct {
int irq;
struct clk *dss_clk;
- u32 fifo_size[MAX_DSS_OVERLAYS];
+ u32 fifo_size[MAX_DSS_OVERLAYS + MAX_DSS_WB];
spinlock_t irq_lock;
u32 irq_error_mask;
@@ -907,7 +907,7 @@ void dispc_wb_set_channel_in(int id, enum dss_writeback_channel_in ch_in)
static void dispc_ovl_set_burst_size(enum omap_plane plane,
enum omap_burst_size burst_size)
{
- static const unsigned shifts[] = { 6, 14, 14, 14, };
+ static const unsigned shifts[] = { 6, 14, 14, 14, 14, };
int shift;
shift = shifts[plane];
@@ -1021,12 +1021,14 @@ static void dispc_read_plane_fifo_sizes(void)
int plane;
u8 start, end;
u32 unit;
+ int num_ovl = dss_feat_get_num_ovls();
+ int num_wb = dss_feat_get_num_wb();
unit = dss_feat_get_buffer_size_unit();
dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
- for (plane = 0; plane < dss_feat_get_num_ovls(); ++plane) {
+ for (plane = 0; plane < num_ovl + num_wb; ++plane) {
size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end);
size *= unit;
dispc.fifo_size[plane] = size;
--
1.7.4.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox