Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* Re: [PATCH] fbcon: Remove unused 'display *p' variable from fb_flashcursor()
From: Paul Mundt @ 2011-03-29  3:32 UTC (permalink / raw)
  To: Jesse Barnes
  Cc: Sergey Senozhatsky, Andrew Morton, Dave Airlie, linux-fbdev,
	linux-kernel
In-Reply-To: <20110328091846.485dfef0@jbarnes-desktop>

On Mon, Mar 28, 2011 at 09:18:46AM -0700, Jesse Barnes wrote:
> On Thu, 24 Mar 2011 22:50:52 +0200
> Sergey Senozhatsky <sergey.senozhatsky@gmail.com> wrote:
> 
> > fbcon: Remove unused 'display *p' variable from fb_flashcursor()
> > 
> > Signed-of-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
> > 
> 
> Looks fine to me, is Paul the lucky owner of fbdev now?
> 
Seems so. I'll roll the patch in with the next batch of fixes.

^ permalink raw reply

* [RFC][PATCH 0/3] MERAM support for LCDC
From: Damian Hobson-Garcia @ 2011-03-29  3:35 UTC (permalink / raw)
  To: linux-fbdev

This patch series is based on the fbdev tree.  

This series adds support for read-ahead cache access through the ICBs and
MERAM available on SH devices.  The exact ICBs to use are chip specific
and are specified in the platform data. 

Damian Hobson-Garcia (3):
  sh_mobile_meram: MERAM framework for LCDC
  sh_mobile_meram: Add support for NV24 framebuffers
  sh_mobile_meram: MERAM platform data for LCDC

 arch/arm/mach-shmobile/board-ap4evb.c |   69 ++++
 drivers/video/Kconfig                 |   12 +
 drivers/video/Makefile                |    1 +
 drivers/video/sh_mobile_lcdcfb.c      |  104 ++++++-
 drivers/video/sh_mobile_lcdcfb.h      |    1 +
 drivers/video/sh_mobile_meram.c       |  567 +++++++++++++++++++++++++++++++++
 drivers/video/sh_mobile_meram.h       |   41 +++
 include/video/sh_mobile_lcdc.h        |    2 +
 include/video/sh_mobile_meram.h       |   69 ++++
 9 files changed, 857 insertions(+), 9 deletions(-)
 create mode 100644 drivers/video/sh_mobile_meram.c
 create mode 100644 drivers/video/sh_mobile_meram.h
 create mode 100644 include/video/sh_mobile_meram.h


^ permalink raw reply

* [RFC][PATCH 1/3] sh_mobile_meram: MERAM framework for LCDC
From: Damian Hobson-Garcia @ 2011-03-29  3:35 UTC (permalink / raw)
  To: linux-fbdev

Based on the patch by Takanari Hayama <taki@igel.co.jp>

Adds support framework necessary to use Media RAM (MERAM)
caching functionality with the LCDC.  The MERAM is accessed
through up to 4 Interconnect Buffers (ICBs).

ICB numbers and MERAM address ranges to use are specified in
by filling in the .meram_cfg member of the LCDC platform data

Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
---
 drivers/video/Kconfig            |   12 +
 drivers/video/Makefile           |    1 +
 drivers/video/sh_mobile_lcdcfb.c |  100 +++++++-
 drivers/video/sh_mobile_lcdcfb.h |    1 +
 drivers/video/sh_mobile_meram.c  |  553 ++++++++++++++++++++++++++++++++++++++
 drivers/video/sh_mobile_meram.h  |   41 +++
 include/video/sh_mobile_lcdc.h   |    2 +
 include/video/sh_mobile_meram.h  |   68 +++++
 8 files changed, 769 insertions(+), 9 deletions(-)
 create mode 100644 drivers/video/sh_mobile_meram.c
 create mode 100644 drivers/video/sh_mobile_meram.h
 create mode 100644 include/video/sh_mobile_meram.h

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index e6a8d8c..b3f3990 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1975,6 +1975,18 @@ config FB_SH_MOBILE_HDMI
 	---help---
 	  Driver for the on-chip SH-Mobile HDMI controller.
 
+config FB_SH_MOBILE_MERAM
+	tristate "SuperH Mobile MERAM read ahead support for LCDC"
+	depends on FB_SH_MOBILE_LCDC
+	default y
+	---help---
+	  Enable MERAM support for the SH-Mobile LCD controller.
+
+	  This will allow for caching of the framebuffer to provide more
+	  reliable access under heavy main memory bus traffic situations.
+	  Up to 4 memory channels can be configured, allowing 4 RGB or
+	  2 YCbCr framebuffers to be configured.
+
 config FB_TMIO
 	tristate "Toshiba Mobile IO FrameBuffer support"
 	depends on FB && MFD_CORE
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 2ea44b6..8b83129 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -130,6 +130,7 @@ obj-$(CONFIG_FB_UDL)		  += udlfb.o
 obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
 obj-$(CONFIG_SH_MIPI_DSI)	  += sh_mipi_dsi.o
 obj-$(CONFIG_FB_SH_MOBILE_HDMI)	  += sh_mobile_hdmi.o
+obj-$(CONFIG_FB_SH_MOBILE_MERAM)  += sh_mobile_meram.o
 obj-$(CONFIG_FB_SH_MOBILE_LCDC)	  += sh_mobile_lcdcfb.o
 obj-$(CONFIG_FB_OMAP)             += omap/
 obj-y                             += omap2/
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 757665b..92366bd 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -27,6 +27,7 @@
 #include <asm/atomic.h>
 
 #include "sh_mobile_lcdcfb.h"
+#include "sh_mobile_meram.h"
 
 #define SIDE_B_OFFSET 0x1000
 #define MIRROR_OFFSET 0x2000
@@ -564,6 +565,9 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 	}
 
 	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+		unsigned long base_addr_y;
+		unsigned long base_addr_c = 0;
+		int pitch;
 		ch = &priv->ch[k];
 
 		if (!priv->ch[k].enabled)
@@ -598,16 +602,63 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 		}
 		lcdc_write_chan(ch, LDDFR, tmp);
 
+		base_addr_y = ch->info->fix.smem_start;
+		base_addr_c = base_addr_y +
+				ch->info->var.xres *
+				ch->info->var.yres_virtual;
+		pitch = ch->info->fix.line_length;
+
+		/* test if we can enable meram */
+		if (ch->cfg.meram_cfg) {
+			struct sh_mobile_meram_cfg *cfg;
+			struct sh_mobile_meram_info *mdev;
+			unsigned long icb_addr_y, icb_addr_c;
+			int icb_pitch;
+			int pf;
+
+			cfg = ch->cfg.meram_cfg;
+			mdev = cfg->meram_dev;
+			/* we need to de-init configured ICBs before we
+			 * we can re-initialize them.
+			 */
+			if (ch->meram_enabled)
+				mdev->ops->meram_unregister(mdev, cfg);
+
+			ch->meram_enabled = 0;
+
+			if (ch->info->var.nonstd)
+				pf = SH_MOBILE_MERAM_PF_NV;
+			else
+				pf = SH_MOBILE_MERAM_PF_RGB;
+
+			ret = mdev->ops->meram_register(mdev, cfg, pitch,
+						ch->info->var.yres,
+						pf,
+						base_addr_y,
+						base_addr_c,
+						&icb_addr_y,
+						&icb_addr_c,
+						&icb_pitch);
+			if (!ret)  {
+				/* set LDSA1R value */
+				base_addr_y = icb_addr_y;
+				pitch = icb_pitch;
+
+				/* set LDSA2R value if required */
+				if (base_addr_c)
+					base_addr_c = icb_addr_c;
+
+				ch->meram_enabled = 1;
+			}
+		}
+
 		/* point out our frame buffer */
-		lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start);
+		lcdc_write_chan(ch, LDSA1R, base_addr_y);
 		if (ch->info->var.nonstd)
-			lcdc_write_chan(ch, LDSA2R,
-				ch->info->fix.smem_start +
-				ch->info->var.xres *
-				ch->info->var.yres_virtual);
+			lcdc_write_chan(ch, LDSA2R, base_addr_c);
 
 		/* set line size */
-		lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length);
+		lcdc_write_chan(ch, LDMLSR, pitch);
 
 		/* setup deferred io if SYS bus */
 		tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
@@ -692,6 +743,17 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
 			board_cfg->display_off(board_cfg->board_data);
 			module_put(board_cfg->owner);
 		}
+
+		/* disable the meram */
+		if (ch->meram_enabled) {
+			struct sh_mobile_meram_cfg *cfg;
+			struct sh_mobile_meram_info *mdev;
+			cfg = ch->cfg.meram_cfg;
+			mdev = cfg->meram_dev;
+			mdev->ops->meram_unregister(mdev, cfg);
+			ch->meram_enabled = 0;
+		}
+
 	}
 
 	/* stop the lcdc */
@@ -875,9 +937,29 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
 	} else
 		base_addr_c = 0;
 
-	lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
-	if (base_addr_c)
-		lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
+	if (!ch->meram_enabled) {
+		lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
+		if (base_addr_c)
+			lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
+	} else {
+		struct sh_mobile_meram_cfg *cfg;
+		struct sh_mobile_meram_info *mdev;
+		unsigned long icb_addr_y, icb_addr_c;
+		int ret;
+
+		cfg = ch->cfg.meram_cfg;
+		mdev = cfg->meram_dev;
+		ret = mdev->ops->meram_update(mdev, cfg,
+					base_addr_y, base_addr_c,
+					&icb_addr_y, &icb_addr_c);
+		if (ret)
+			return ret;
+
+		lcdc_write_chan_mirror(ch, LDSA1R, icb_addr_y);
+		if (icb_addr_c)
+			lcdc_write_chan_mirror(ch, LDSA2R, icb_addr_c);
+
+	}
 
 	if (lcdc_chan_is_sublcd(ch))
 		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index 4635eed..d6d9f37 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -38,6 +38,7 @@ struct sh_mobile_lcdc_chan {
 	struct fb_var_screeninfo display_var;
 	int use_count;
 	struct mutex open_lock;		/* protects the use counter */
+	int meram_enabled;
 };
 
 #endif
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
new file mode 100644
index 0000000..bd68f3d
--- /dev/null
+++ b/drivers/video/sh_mobile_meram.c
@@ -0,0 +1,553 @@
+/*
+ * SuperH Mobile MERAM Driver for SuperH Mobile LCDC Driver
+ *
+ * Copyright (c) 2011	Damian Hobson-Garcia <dhobsong@igel.co.jp>
+ *                      Takanari Hayama <taki@igel.co.jp>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include "sh_mobile_meram.h"
+
+/* meram registers */
+#define MExxCTL 0x0
+#define MExxBSIZE 0x4
+#define MExxMNCF 0x8
+#define MExxSARA 0x10
+#define MExxSARB 0x14
+#define MExxSBSIZE 0x18
+
+#define MERAM_MExxCTL_VAL(ctl, next_icb, addr)	\
+	((ctl) | (((next_icb) & 0x1f) << 11) | (((addr) & 0x7ff) << 16))
+#define	MERAM_MExxBSIZE_VAL(a, b, c) \
+	(((a) << 28) | ((b) << 16) | (c))
+
+#define MEVCR1 0x4
+#define MEACTS 0x10
+#define MEQSEL1 0x40
+#define MEQSEL2 0x44
+
+/* settings */
+#define MERAM_SEC_LINE 15
+#define MERAM_LINE_WIDTH 2048
+
+/*
+ * MERAM/ICB access functions
+ */
+
+#define MERAM_ICB_OFFSET(base, idx, off)	\
+	((base) + (0x400 + ((idx) * 0x20) + (off)))
+
+static inline void meram_write_icb(void __iomem *base, int idx, int off,
+	unsigned long val)
+{
+	iowrite32(val, MERAM_ICB_OFFSET(base, idx, off));
+}
+
+static inline unsigned long meram_read_icb(void __iomem *base, int idx, int off)
+{
+	return ioread32(MERAM_ICB_OFFSET(base, idx, off));
+}
+
+static inline void meram_write_reg(void __iomem *base, int off,
+		unsigned long val)
+{
+	iowrite32(val, base + off);
+}
+
+static inline unsigned long meram_read_reg(void __iomem *base, int off)
+{
+	return ioread32(base + off);
+}
+
+/*
+ * register ICB
+ */
+
+#define MERAM_CACHE_START(p)	 ((p) >> 16)
+#define MERAM_CACHE_END(p)	 ((p) & 0xffff)
+#define MERAM_CACHE_SET(o, s)	 ((((o) & 0xffff) << 16) | \
+				  (((o) + (s) - 1) & 0xffff))
+
+/*
+ * check if there's no overlaps in MERAM allocation.
+ */
+
+static inline int meram_check_overlap(struct sh_mobile_meram_priv *priv,
+				      struct sh_mobile_meram_icb *new)
+{
+	int i;
+	int used_start, used_end, meram_start, meram_end;
+
+	/* valid ICB? */
+	if (new->marker_icb & ~0x1f || new->cache_icb & ~0x1f)
+		return 1;
+
+	if (test_bit(new->marker_icb, &priv->used_icb) ||
+			test_bit(new->cache_icb,  &priv->used_icb))
+		return  1;
+
+	for (i = 0; i < priv->used_meram_cache_regions; i++) {
+		used_start = MERAM_CACHE_START(priv->used_meram_cache[i]);
+		used_end   = MERAM_CACHE_END(priv->used_meram_cache[i]);
+		meram_start = new->meram_offset;
+		meram_end   = new->meram_offset + new->meram_size;
+
+		if ((meram_start >= used_start && meram_start < used_end) ||
+			(meram_end > used_start && meram_end < used_end))
+			return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * mark the specified ICB as used
+ */
+
+static inline void meram_mark(struct sh_mobile_meram_priv *priv,
+			      struct sh_mobile_meram_icb *new)
+{
+	int n;
+
+	if (new->marker_icb < 0 || new->cache_icb < 0)
+		return;
+
+	__set_bit(new->marker_icb, &priv->used_icb);
+	__set_bit(new->cache_icb, &priv->used_icb);
+
+	n = priv->used_meram_cache_regions;
+
+	priv->used_meram_cache[n] = MERAM_CACHE_SET(new->meram_offset,
+						    new->meram_size);
+
+	priv->used_meram_cache_regions++;
+}
+
+/*
+ * unmark the specified ICB as used
+ */
+
+static inline void meram_unmark(struct sh_mobile_meram_priv *priv,
+				struct sh_mobile_meram_icb *icb)
+{
+	int i;
+	unsigned long pattern;
+
+	if (icb->marker_icb < 0 || icb->cache_icb < 0)
+		return;
+
+	__clear_bit(icb->marker_icb, &priv->used_icb);
+	__clear_bit(icb->cache_icb, &priv->used_icb);
+
+	pattern = MERAM_CACHE_SET(icb->meram_offset, icb->meram_size);
+	for (i = 0; i < priv->used_meram_cache_regions; i++) {
+		if (priv->used_meram_cache[i] = pattern) {
+			while (i < priv->used_meram_cache_regions - 1) {
+				priv->used_meram_cache[i] +					priv->used_meram_cache[i + 1] ;
+				i++;
+			}
+			priv->used_meram_cache[i] = 0;
+			priv->used_meram_cache_regions--;
+			break;
+		}
+	}
+}
+
+
+/*
+ * set the next address to fetch
+ */
+static inline void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
+				       struct sh_mobile_meram_cfg *cfg,
+				       unsigned long base_addr_y,
+				       unsigned long base_addr_c)
+{
+	unsigned long target;
+
+	target = (cfg->current_reg) ? MExxSARA : MExxSARB;
+	cfg->current_reg ^= 1;
+
+	/* set the next address to fetch */
+	meram_write_icb(priv->base, cfg->icb[0].cache_icb,  target,
+			base_addr_y);
+	meram_write_icb(priv->base, cfg->icb[0].marker_icb, target,
+			base_addr_y + cfg->icb[0].cache_unit);
+
+	if (cfg->pixelformat = SH_MOBILE_MERAM_PF_NV) {
+		meram_write_icb(priv->base, cfg->icb[1].cache_icb,  target,
+				base_addr_c);
+		meram_write_icb(priv->base, cfg->icb[1].marker_icb, target,
+				base_addr_c + cfg->icb[1].cache_unit);
+	}
+}
+
+/*
+ * get the next ICB address
+ */
+static inline void meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
+					   struct sh_mobile_meram_cfg *cfg,
+					   unsigned long *icb_addr_y,
+					   unsigned long *icb_addr_c)
+{
+	unsigned long icb_offset;
+
+	if (pdata->addr_mode = SH_MOBILE_MERAM_MODE0)
+		icb_offset = 0x80000000 | (cfg->current_reg << 29);
+	else
+		icb_offset = 0xc0000000 | (cfg->current_reg << 23);
+
+	*icb_addr_y = icb_offset | (cfg->icb[0].marker_icb << 24);
+	if ((*icb_addr_c) && cfg->pixelformat = SH_MOBILE_MERAM_PF_NV)
+		*icb_addr_c = icb_offset | (cfg->icb[1].marker_icb << 24);
+}
+
+#define MERAM_CALC_BYTECOUNT(x, y) \
+	(((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
+
+/*
+ * initialize MERAM
+ */
+
+static int meram_init(struct sh_mobile_meram_priv *priv,
+		      struct sh_mobile_meram_icb *icb,
+		      int xres, int yres, int *out_pitch)
+{
+	unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
+	unsigned long bnm;
+	int lcdc_pitch, xpitch, line_cnt;
+	int save_lines;
+
+	/* adjust pitch to 1024, 2048, 4096 or 8192 */
+	lcdc_pitch = (xres - 1) | 1023;
+	lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 1);
+	lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 2);
+	lcdc_pitch += 1;
+
+	/* derive settings */
+	if (lcdc_pitch = 8192 && yres >= 1024) {
+		lcdc_pitch = xpitch = MERAM_LINE_WIDTH;
+		line_cnt = total_byte_count >> 11;
+		*out_pitch = xres;
+		save_lines = (icb->meram_size / 16 / MERAM_SEC_LINE);
+		save_lines *= MERAM_SEC_LINE;
+	} else {
+		xpitch = xres;
+		line_cnt = yres;
+		*out_pitch = lcdc_pitch;
+		save_lines = icb->meram_size / (lcdc_pitch >> 10) / 2;
+		save_lines &= 0xff;
+	}
+	bnm = (save_lines - 1) << 16;
+
+	/* TODO: we better to check if we have enough MERAM buffer size */
+
+	/* set up ICB */
+	meram_write_icb(priv->base, icb->cache_icb,  MExxBSIZE,
+			MERAM_MExxBSIZE_VAL(0x0, line_cnt - 1, xpitch - 1));
+	meram_write_icb(priv->base, icb->marker_icb, MExxBSIZE,
+			MERAM_MExxBSIZE_VAL(0xf, line_cnt - 1, xpitch - 1));
+
+	meram_write_icb(priv->base, icb->cache_icb,  MExxMNCF, bnm);
+	meram_write_icb(priv->base, icb->marker_icb, MExxMNCF, bnm);
+
+	meram_write_icb(priv->base, icb->cache_icb,  MExxSBSIZE, xpitch);
+	meram_write_icb(priv->base, icb->marker_icb, MExxSBSIZE, xpitch);
+
+	/* save a cache unit size */
+	icb->cache_unit = xres * save_lines;
+
+	/*
+	 * Set MERAM for framebuffer
+	 *
+	 * 0x70f:  WD = 0x3, WS=0x1, CM=0x1, MDû mode
+	 * we also chain the cache_icb and the marker_icb.
+	 * we also split the allocated MERAM buffer between two ICBs.
+	 */
+	meram_write_icb(priv->base, icb->cache_icb, MExxCTL,
+			MERAM_MExxCTL_VAL(0x70f, icb->marker_icb,
+					  icb->meram_offset));
+	meram_write_icb(priv->base, icb->marker_icb, MExxCTL,
+			MERAM_MExxCTL_VAL(0x70f, icb->cache_icb,
+					  icb->meram_offset +
+					  icb->meram_size / 2));
+
+	return 0;
+}
+
+static void meram_deinit(struct sh_mobile_meram_priv *priv,
+			struct sh_mobile_meram_icb *icb)
+{
+	/* disable ICB */
+	meram_write_icb(priv->base, icb->cache_icb,  MExxCTL, 0);
+	meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 0);
+	icb->cache_unit = 0;
+}
+
+/*
+ * register the ICB
+ */
+
+static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
+				    struct sh_mobile_meram_cfg *cfg,
+				    int xres, int yres, int pixelformat,
+				    unsigned long base_addr_y,
+				    unsigned long base_addr_c,
+				    unsigned long *icb_addr_y,
+				    unsigned long *icb_addr_c,
+				    int *pitch)
+{
+	struct platform_device *pdev;
+	struct sh_mobile_meram_priv *priv;
+	int n, out_pitch;
+	int error = 0;
+
+	if (!pdata || !pdata->priv || !pdata->pdev || !cfg)
+		return -EINVAL;
+
+	if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
+	    pixelformat != SH_MOBILE_MERAM_PF_RGB)
+		return -EINVAL;
+
+	priv = pdata->priv;
+	pdev = pdata->pdev;
+
+	dev_dbg(&pdev->dev, "registering %dx%d (%s) (y=%08lx, c=%08lx)",
+		xres, yres, (!pixelformat) ? "yuv" : "rgb",
+		base_addr_y, base_addr_c);
+
+	mutex_lock(&priv->lock);
+
+	/* we can't handle wider than 8192px */
+	if (xres > 8192) {
+		dev_err(&pdev->dev, "width exceeding the limit (> 8192).");
+		error = -EINVAL;
+		goto err;
+	}
+
+	if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) {
+		dev_err(&pdev->dev, "no more ICB available.");
+		error = -EINVAL;
+		goto err;
+	}
+
+	/* do we have at least one ICB config? */
+	if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) {
+		dev_err(&pdev->dev, "at least one ICB is required.");
+		error = -EINVAL;
+		goto err;
+	}
+
+	/* make sure that there's no overlaps */
+	if (meram_check_overlap(priv, &cfg->icb[0])) {
+		dev_err(&pdev->dev, "conflicting config detected.");
+		error = -EINVAL;
+		goto err;
+	}
+	n = 1;
+
+	/* do the same if we have the second ICB set */
+	if (cfg->icb[1].marker_icb >= 0 && cfg->icb[1].cache_icb >= 0) {
+		if (meram_check_overlap(priv, &cfg->icb[1])) {
+			dev_err(&pdev->dev, "conflicting config detected.");
+			error = -EINVAL;
+			goto err;
+		}
+		n = 2;
+	}
+
+	if (pixelformat = SH_MOBILE_MERAM_PF_NV && n != 2) {
+		dev_err(&pdev->dev, "requires two ICB sets for planar Y/C.");
+		error =  -EINVAL;
+		goto err;
+	}
+
+	/* we now register the ICB */
+	cfg->pixelformat = pixelformat;
+	meram_mark(priv, &cfg->icb[0]);
+	if (pixelformat = SH_MOBILE_MERAM_PF_NV)
+		meram_mark(priv, &cfg->icb[1]);
+
+	/* initialize MERAM */
+	meram_init(priv, &cfg->icb[0], xres, yres, &out_pitch);
+	*pitch = out_pitch;
+	if (pixelformat = SH_MOBILE_MERAM_PF_NV)
+		meram_init(priv, &cfg->icb[1], xres, (yres + 1) / 2,
+			&out_pitch);
+
+	cfg->current_reg = 1;
+	meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c);
+	meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c);
+
+	dev_dbg(&pdev->dev, "registered - can access via y=%08lx, c=%08lx",
+		*icb_addr_y, *icb_addr_c);
+
+err:
+	mutex_unlock(&priv->lock);
+	return error;
+}
+
+static int sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata,
+				      struct sh_mobile_meram_cfg *cfg)
+{
+	struct sh_mobile_meram_priv *priv;
+
+	if (!pdata || !pdata->priv || !cfg)
+		return -EINVAL;
+
+	priv = pdata->priv;
+
+	mutex_lock(&priv->lock);
+
+	/* deinit & unmark */
+	if (cfg->pixelformat = SH_MOBILE_MERAM_PF_NV) {
+		meram_deinit(priv, &cfg->icb[1]);
+		meram_unmark(priv, &cfg->icb[1]);
+	}
+	meram_deinit(priv, &cfg->icb[0]);
+	meram_unmark(priv, &cfg->icb[0]);
+
+	mutex_unlock(&priv->lock);
+
+	return 0;
+}
+
+static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata,
+				  struct sh_mobile_meram_cfg *cfg,
+				  unsigned long base_addr_y,
+				  unsigned long base_addr_c,
+				  unsigned long *icb_addr_y,
+				  unsigned long *icb_addr_c)
+{
+	struct sh_mobile_meram_priv *priv;
+
+	if (!pdata || !pdata->priv || !cfg)
+		return -EINVAL;
+
+	priv = pdata->priv;
+
+	mutex_lock(&priv->lock);
+
+	meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c);
+	meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c);
+
+	mutex_unlock(&priv->lock);
+
+	return 0;
+}
+
+static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
+	.module			= THIS_MODULE,
+	.meram_register		= sh_mobile_meram_register,
+	.meram_unregister	= sh_mobile_meram_unregister,
+	.meram_update		= sh_mobile_meram_update,
+};
+
+/*
+ * initialize MERAM
+ */
+
+static int sh_mobile_meram_remove(struct platform_device *pdev);
+
+static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
+{
+	struct sh_mobile_meram_priv *priv;
+	struct sh_mobile_meram_info *pdata = pdev->dev.platform_data;
+	struct resource *res;
+	int error;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform data defined\n");
+		return -EINVAL;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "cannot get platform resources\n");
+		return -ENOENT;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&pdev->dev, "cannot allocate device data\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	/* initialize private data */
+	mutex_init(&priv->lock);
+	priv->base = ioremap_nocache(res->start, resource_size(res));
+	if (!priv->base) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		error = -EFAULT;
+		goto err;
+	}
+	pdata->ops = &sh_mobile_meram_ops;
+	pdata->priv = priv;
+	pdata->pdev = pdev;
+
+	/* initialize ICB addressing mode */
+	if (pdata->addr_mode = SH_MOBILE_MERAM_MODE1)
+		meram_write_reg(priv->base, MEVCR1, 1 << 29);
+
+	dev_info(&pdev->dev, "sh_mobile_meram initialized.");
+
+	return 0;
+
+err:
+	sh_mobile_meram_remove(pdev);
+
+	return error;
+}
+
+
+static int sh_mobile_meram_remove(struct platform_device *pdev)
+{
+	struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
+
+	if (priv->base)
+		iounmap(priv->base);
+
+	mutex_destroy(&priv->lock);
+
+	kfree(priv);
+
+	return 0;
+}
+
+static struct platform_driver sh_mobile_meram_driver = {
+	.driver	= {
+		.name		= "sh_mobile_meram",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= sh_mobile_meram_probe,
+	.remove		= sh_mobile_meram_remove,
+};
+
+static int __init sh_mobile_meram_init(void)
+{
+	return platform_driver_register(&sh_mobile_meram_driver);
+}
+
+static void __exit sh_mobile_meram_exit(void)
+{
+	platform_driver_unregister(&sh_mobile_meram_driver);
+}
+
+module_init(sh_mobile_meram_init);
+module_exit(sh_mobile_meram_exit);
+
+MODULE_DESCRIPTION("SuperH Mobile MERAM driver");
+MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sh_mobile_meram.h b/drivers/video/sh_mobile_meram.h
new file mode 100644
index 0000000..82c54fb
--- /dev/null
+++ b/drivers/video/sh_mobile_meram.h
@@ -0,0 +1,41 @@
+#ifndef __sh_mobile_meram_h__
+#define __sh_mobile_meram_h__
+
+#include <linux/mutex.h>
+#include <video/sh_mobile_meram.h>
+
+/*
+ * MERAM private
+ */
+
+#define MERAM_ICB_Y 0x1
+#define MERAM_ICB_C 0x2
+
+/* MERAM cache size */
+#define SH_MOBILE_MERAM_ICB_NUM		32
+
+#define SH_MOBILE_MERAM_CACHE_OFFSET(p)	((p) >> 16)
+#define SH_MOBILE_MERAM_CACHE_SIZE(p)	((p) & 0xffff)
+
+struct sh_mobile_meram_priv {
+	void __iomem	*base;
+	struct mutex	lock;
+	unsigned long	used_icb;
+	int		used_meram_cache_regions;
+	unsigned long	used_meram_cache[SH_MOBILE_MERAM_ICB_NUM];
+};
+
+int sh_mobile_meram_alloc_icb(const struct sh_mobile_meram_cfg *cfg,
+		   int xres,
+		   int yres,
+		   unsigned int base_addr,
+		   int yuv_mode,
+		   int *marker_icb,
+		   int *out_pitch);
+
+void sh_mobile_meram_free_icb(int marker_icb);
+
+#define SH_MOBILE_MERAM_START(ind, ab) \
+	(0xC0000000 | ((ab & 0x1) << 23) | ((ind & 0x1F) << 24))
+
+#endif /* !__sh_mobile_meram_h__ */
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index 2c8d369..7d07ac8 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -2,6 +2,7 @@
 #define __ASM_SH_MOBILE_LCDC_H__
 
 #include <linux/fb.h>
+#include <video/sh_mobile_meram.h>
 
 enum {
 	RGB8,   /* 24bpp, 8:8:8 */
@@ -87,6 +88,7 @@ struct sh_mobile_lcdc_chan_cfg {
 	struct sh_mobile_lcdc_bl_info bl_info;
 	struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */
 	int nonstd;
+	struct sh_mobile_meram_cfg *meram_cfg;
 };
 
 struct sh_mobile_lcdc_info {
diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
new file mode 100644
index 0000000..e6d2410
--- /dev/null
+++ b/include/video/sh_mobile_meram.h
@@ -0,0 +1,68 @@
+#ifndef __VIDEO_SH_MOBILE_MERAM_H__
+#define __VIDEO_SH_MOBILE_MERAM_H__
+
+/* For sh_mobile_meram_info.addr_mode */
+enum {
+	SH_MOBILE_MERAM_MODE0 = 0,
+	SH_MOBILE_MERAM_MODE1
+};
+
+enum {
+	SH_MOBILE_MERAM_PF_NV = 0,
+	SH_MOBILE_MERAM_PF_RGB
+};
+
+
+struct sh_mobile_meram_priv;
+struct sh_mobile_meram_ops;
+
+struct sh_mobile_meram_info {
+	int				addr_mode;
+	struct sh_mobile_meram_ops	*ops;
+	struct sh_mobile_meram_priv	*priv;
+	struct platform_device		*pdev;
+};
+
+/* icb config */
+struct sh_mobile_meram_icb {
+	int marker_icb;		/* ICB # for Marker ICB */
+	int cache_icb;		/* ICB # for Cache ICB */
+	int meram_offset;	/* MERAM Buffer Offset to use */
+	int meram_size;		/* MERAM Buffer Size to use */
+
+	int cache_unit;		/* bytes to cache per ICB */
+};
+
+struct sh_mobile_meram_cfg {
+	struct sh_mobile_meram_info	*meram_dev;
+	struct sh_mobile_meram_icb	icb[2];
+	int				pixelformat;
+	int				current_reg;
+};
+
+struct module;
+struct sh_mobile_meram_ops {
+	struct module	*module;
+	/* register usage of meram */
+	int (*meram_register)(struct sh_mobile_meram_info *meram_dev,
+			      struct sh_mobile_meram_cfg *cfg,
+			      int xres, int yres, int pixelformat,
+			      unsigned long base_addr_y,
+			      unsigned long base_addr_c,
+			      unsigned long *icb_addr_y,
+			      unsigned long *icb_addr_c, int *pitch);
+
+	/* unregister usage of meram */
+	int (*meram_unregister)(struct sh_mobile_meram_info *meram_dev,
+				struct sh_mobile_meram_cfg *cfg);
+
+	/* update meram settings */
+	int (*meram_update)(struct sh_mobile_meram_info *meram_dev,
+			    struct sh_mobile_meram_cfg *cfg,
+			    unsigned long base_addr_y,
+			    unsigned long base_addr_c,
+			    unsigned long *icb_addr_y,
+			    unsigned long *icb_addr_c);
+};
+
+#endif /* __VIDEO_SH_MOBILE_MERAM_H__  */
-- 
1.7.1


^ permalink raw reply related

* [RFC][PATCH 2/3] sh_mobile_meram: Add support for NV24 framebuffers
From: Damian Hobson-Garcia @ 2011-03-29  3:35 UTC (permalink / raw)
  To: linux-fbdev

Since the NV24 framebuffer has a CbCr plane that is twice as wide
as the Y plane, it needs to be handled as a special case.

Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
---
 drivers/video/sh_mobile_lcdcfb.c |   10 +++++++---
 drivers/video/sh_mobile_meram.c  |   24 +++++++++++++++++++-----
 include/video/sh_mobile_meram.h  |    3 ++-
 3 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 92366bd..6b1db92 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -626,10 +626,14 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 
 			ch->meram_enabled = 0;
 
-			if (ch->info->var.nonstd)
-				pf = SH_MOBILE_MERAM_PF_NV;
-			else
+			if (ch->info->var.nonstd) {
+				if (ch->info->var.bits_per_pixel = 24)
+					pf = SH_MOBILE_MERAM_PF_NV24;
+				else
+					pf = SH_MOBILE_MERAM_PF_NV;
+			} else {
 				pf = SH_MOBILE_MERAM_PF_RGB;
+			}
 
 			ret = mdev->ops->meram_register(mdev, cfg, pitch,
 						ch->info->var.yres,
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index bd68f3d..9170c82 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -164,6 +164,16 @@ static inline void meram_unmark(struct sh_mobile_meram_priv *priv,
 	}
 }
 
+/*
+ * is this a YCbCr(NV12, NV16 or NV24) colorspace
+ */
+static inline int is_nvcolor(int cspace)
+{
+	if (cspace = SH_MOBILE_MERAM_PF_NV ||
+			cspace = SH_MOBILE_MERAM_PF_NV24)
+		return 1;
+	return 0;
+}
 
 /*
  * set the next address to fetch
@@ -184,7 +194,7 @@ static inline void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
 	meram_write_icb(priv->base, cfg->icb[0].marker_icb, target,
 			base_addr_y + cfg->icb[0].cache_unit);
 
-	if (cfg->pixelformat = SH_MOBILE_MERAM_PF_NV) {
+	if (is_nvcolor(cfg->pixelformat)) {
 		meram_write_icb(priv->base, cfg->icb[1].cache_icb,  target,
 				base_addr_c);
 		meram_write_icb(priv->base, cfg->icb[1].marker_icb, target,
@@ -208,7 +218,7 @@ static inline void meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
 		icb_offset = 0xc0000000 | (cfg->current_reg << 23);
 
 	*icb_addr_y = icb_offset | (cfg->icb[0].marker_icb << 24);
-	if ((*icb_addr_c) && cfg->pixelformat = SH_MOBILE_MERAM_PF_NV)
+	if ((*icb_addr_c) && is_nvcolor(cfg->pixelformat))
 		*icb_addr_c = icb_offset | (cfg->icb[1].marker_icb << 24);
 }
 
@@ -316,6 +326,7 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
 		return -EINVAL;
 
 	if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
+	    pixelformat != SH_MOBILE_MERAM_PF_NV24 &&
 	    pixelformat != SH_MOBILE_MERAM_PF_RGB)
 		return -EINVAL;
 
@@ -366,7 +377,7 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
 		n = 2;
 	}
 
-	if (pixelformat = SH_MOBILE_MERAM_PF_NV && n != 2) {
+	if (is_nvcolor(pixelformat) && n != 2) {
 		dev_err(&pdev->dev, "requires two ICB sets for planar Y/C.");
 		error =  -EINVAL;
 		goto err;
@@ -375,7 +386,7 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
 	/* we now register the ICB */
 	cfg->pixelformat = pixelformat;
 	meram_mark(priv, &cfg->icb[0]);
-	if (pixelformat = SH_MOBILE_MERAM_PF_NV)
+	if (is_nvcolor(pixelformat))
 		meram_mark(priv, &cfg->icb[1]);
 
 	/* initialize MERAM */
@@ -384,6 +395,9 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
 	if (pixelformat = SH_MOBILE_MERAM_PF_NV)
 		meram_init(priv, &cfg->icb[1], xres, (yres + 1) / 2,
 			&out_pitch);
+	else if (pixelformat = SH_MOBILE_MERAM_PF_NV24)
+		meram_init(priv, &cfg->icb[1], 2 * xres, (yres + 1) / 2,
+			&out_pitch);
 
 	cfg->current_reg = 1;
 	meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c);
@@ -410,7 +424,7 @@ static int sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata,
 	mutex_lock(&priv->lock);
 
 	/* deinit & unmark */
-	if (cfg->pixelformat = SH_MOBILE_MERAM_PF_NV) {
+	if (is_nvcolor(cfg->pixelformat)) {
 		meram_deinit(priv, &cfg->icb[1]);
 		meram_unmark(priv, &cfg->icb[1]);
 	}
diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
index e6d2410..989eb23 100644
--- a/include/video/sh_mobile_meram.h
+++ b/include/video/sh_mobile_meram.h
@@ -9,7 +9,8 @@ enum {
 
 enum {
 	SH_MOBILE_MERAM_PF_NV = 0,
-	SH_MOBILE_MERAM_PF_RGB
+	SH_MOBILE_MERAM_PF_RGB,
+	SH_MOBILE_MERAM_PF_NV24
 };
 
 
-- 
1.7.1


^ permalink raw reply related

* [RFC][PATCH 3/3] sh_mobile_meram: MERAM platform data for LCDC
From: Damian Hobson-Garcia @ 2011-03-29  3:35 UTC (permalink / raw)
  To: linux-fbdev

Based on the patch by Takanari Hayama <taki@igel.co.jp>

Add the necessary platform data to add MERAM functionality to LCDC

Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
---
 arch/arm/mach-shmobile/board-ap4evb.c |   69 +++++++++++++++++++++++++++++++++
 1 files changed, 69 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index a94f29d..e467696 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -249,6 +249,31 @@ static int slot_cn7_get_cd(struct platform_device *pdev)
 {
 	return !gpio_get_value(GPIO_PORT41);
 }
+#ifdef CONFIG_FB_SH_MOBILE_MERAM
+/* MERAM */
+static struct sh_mobile_meram_info mackerel_meram_info = {
+	.addr_mode      = SH_MOBILE_MERAM_MODE1,
+};
+
+static struct resource meram_resources[] = {
+	[0] = {
+		.name   = "MERAM",
+		.start  = 0xe8000000,
+		.end    = 0xe81fffff,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device meram_device = {
+	.name           = "sh_mobile_meram",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(meram_resources),
+	.resource       = meram_resources,
+	.dev            = {
+		.platform_data = &mackerel_meram_info,
+	},
+};
+#endif
 
 /* SH_MMCIF */
 static struct resource sh_mmcif_resources[] = {
@@ -431,6 +456,23 @@ const static struct fb_videomode ap4evb_lcdc_modes[] = {
 #endif
 	},
 };
+#ifdef CONFIG_FB_SH_MOBILE_MERAM
+static struct sh_mobile_meram_cfg lcd_meram_cfg = {
+	.meram_dev = &mackerel_meram_info,
+	.icb[0] = {
+		.marker_icb     = 28,
+		.cache_icb      = 24,
+		.meram_offset   = 0x0,
+		.meram_size     = 0x40,
+	},
+	.icb[1] = {
+		.marker_icb     = 29,
+		.cache_icb      = 25,
+		.meram_offset   = 0x40,
+		.meram_size     = 0x40,
+	},
+};
+#endif
 
 static struct sh_mobile_lcdc_info lcdc_info = {
 	.ch[0] = {
@@ -438,6 +480,9 @@ static struct sh_mobile_lcdc_info lcdc_info = {
 		.bpp = 16,
 		.lcd_cfg = ap4evb_lcdc_modes,
 		.num_cfg = ARRAY_SIZE(ap4evb_lcdc_modes),
+#ifdef CONFIG_FB_SH_MOBILE_MERAM
+		.meram_cfg = &lcd_meram_cfg,
+#endif
 	}
 };
 
@@ -708,6 +753,23 @@ static struct platform_device fsi_device = {
 static struct platform_device fsi_ak4643_device = {
 	.name		= "sh_fsi2_a_ak4643",
 };
+#ifdef CONFIG_FB_SH_MOBILE_MERAM
+static struct sh_mobile_meram_cfg hdmi_meram_cfg = {
+	.meram_dev = &mackerel_meram_info,
+	.icb[0] = {
+		.marker_icb     = 30,
+		.cache_icb      = 26,
+		.meram_offset   = 0x80,
+		.meram_size     = 0x100,
+	},
+	.icb[1] = {
+		.marker_icb     = 31,
+		.cache_icb      = 27,
+		.meram_offset   = 0x180,
+		.meram_size     = 0x100,
+	},
+};
+#endif
 
 static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
 	.clock_source = LCDC_CLK_EXTERNAL,
@@ -717,6 +779,10 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
 		.interface_type = RGB24,
 		.clock_divider = 1,
 		.flags = LCDC_FLAGS_DWPOL,
+#ifdef CONFIG_FB_SH_MOBILE_MERAM
+		.meram_cfg = &hdmi_meram_cfg,
+#endif
+
 	}
 };
 
@@ -945,6 +1011,9 @@ static struct platform_device *ap4evb_devices[] __initdata = {
 	&csi2_device,
 	&ceu_device,
 	&ap4evb_camera,
+#ifdef CONFIG_FB_SH_MOBILE_MERAM
+	&meram_device,
+#endif
 };
 
 static int __init hdmi_init_pm_clock(void)
-- 
1.7.1


^ permalink raw reply related

* Re: [patch] backlight/ld9040.c: testing the wrong variable in
From: Donghwa Lee @ 2011-03-29  4:37 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <20110329031909.GC9856@bicker>

 On 2011-03-29, Dan Carpenter wrote:
> We should be testing "bd" here instead of "ld".  It's a copy and
> paste bug.
>
> Signed-off-by: Dan Carpenter <error27@gmail.com>
>
> diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
> index 7281b25..9e81d69 100644
> --- a/drivers/video/backlight/ld9040.c
> +++ b/drivers/video/backlight/ld9040.c
> @@ -701,8 +701,8 @@ static int ld9040_probe(struct spi_device *spi)
>  
>  	bd = backlight_device_register("ld9040-bl", &spi->dev,
>  		lcd, &ld9040_backlight_ops, NULL);
> -	if (IS_ERR(ld)) {
> -		ret = PTR_ERR(ld);
> +	if (IS_ERR(bd)) {
> +		ret = PTR_ERR(bd);
>  		goto out_free_lcd;
>  	}
>  
>

Yes, It's my mistake. It has to be changed as you said.

Thank you,


^ permalink raw reply

* Re: [patch] backlight/pcf50633: check for NULL consistently in pcf50633_bl_probe()
From: Lars-Peter Clausen @ 2011-03-29 11:19 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <20110329032020.GD9856@bicker>

On 03/29/2011 05:20 AM, Dan Carpenter wrote:
> We checked "pdata" for NULL at the start of the function so we should
> check it here as well.
> 
> Signed-off-by: Dan Carpenter <error27@gmail.com>

Acked-by: Lars-Peter Clausen <lars@metafoo.de>

> ---
> Compile tested only.  Please review.
> 
> diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
> index ef5628d..0fe934f 100644
> --- a/drivers/video/backlight/pcf50633-backlight.c
> +++ b/drivers/video/backlight/pcf50633-backlight.c
> @@ -136,7 +136,9 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
>  
>  	platform_set_drvdata(pdev, pcf_bl);
>  
> -	pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time);
> +	if (pdata)
> +		pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM,
> +					pdata->ramp_time);
>  
>  	/* Should be different from bl_props.brightness, so we do not exit
>  	 * update_status early the first time it's called */


^ permalink raw reply

* [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
From: Guan Xuetao @ 2011-03-29 14:37 UTC (permalink / raw)
  To: Paul Mundt
  Cc: Arnd Bergmann, 'Guan Xuetao', linux-kernel, linux-fbdev


1. make videomemory kmalloc-ed in fb-puv3.c
2. remove resource reservation for old fixed UNIGFX_MMAP & UVC_MMAP space
3. remove unused PKUNTIY_UNIGFX_MMAP_BASE, PKUNITY_UNIGFX_MMAP_SIZE,
	PKUNITY_UVC_MMAP_BASE, PKUNITY_UVC_MMAP_SIZE and KUSER_UNIGFX_BASE
4. remove unused header linux/vmalloc.h in fb-puv3.c

Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
---
 arch/unicore32/include/mach/PKUnity.h |   10 ----------
 arch/unicore32/include/mach/memory.h  |    1 -
 arch/unicore32/kernel/puv3-core.c     |    5 -----
 arch/unicore32/kernel/setup.c         |   15 ++-------------
 arch/unicore32/mm/mmu.c               |   20 --------------------
 drivers/video/fb-puv3.c               |   27 ++++++++++++++++-----------
 6 files changed, 18 insertions(+), 60 deletions(-)

diff --git a/arch/unicore32/include/mach/PKUnity.h b/arch/unicore32/include/mach/PKUnity.h
index a18bdc3..8040d57 100644
--- a/arch/unicore32/include/mach/PKUnity.h
+++ b/arch/unicore32/include/mach/PKUnity.h
@@ -24,16 +24,6 @@
 #define PKUNITY_MMIO_BASE		0x80000000 /* 0x80000000 - 0xFFFFFFFF 2GB */
 
 /*
- * PKUNITY Memory Map Addresses: 0x0D000000 - 0x0EFFFFFF (32MB)
- *	0x0D000000 - 0x0DFFFFFF 16MB: for UVC
- *	0x0E000000 - 0x0EFFFFFF 16MB: for UNIGFX
- */
-#define PKUNITY_UVC_MMAP_BASE		0x0D000000
-#define PKUNITY_UVC_MMAP_SIZE		0x01000000 /* 16MB */
-#define PKUNITY_UNIGFX_MMAP_BASE        0x0E000000
-#define PKUNITY_UNIGFX_MMAP_SIZE        0x01000000 /* 16MB */
-
-/*
  * PKUNITY System Bus Addresses (PCI): 0x80000000 - 0xBFFFFFFF (1GB)
  * 0x80000000 - 0x8000000B 12B    PCI Configuration regs
  * 0x80010000 - 0x80010250 592B   PCI Bridge Base
diff --git a/arch/unicore32/include/mach/memory.h b/arch/unicore32/include/mach/memory.h
index 0bf21c9..4be72c2 100644
--- a/arch/unicore32/include/mach/memory.h
+++ b/arch/unicore32/include/mach/memory.h
@@ -50,7 +50,6 @@ void puv3_pci_adjust_zones(unsigned long *size, unsigned long *holes);
 
 /* kuser area */
 #define KUSER_VECPAGE_BASE	(KUSER_BASE + UL(0x3fff0000))
-#define KUSER_UNIGFX_BASE	(PAGE_OFFSET + PKUNITY_UNIGFX_MMAP_BASE)
 /* kuser_vecpage (0xbfff0000) is ro, and vectors page (0xffff0000) is rw */
 #define kuser_vecpage_to_vectors(x)	((x) - (KUSER_VECPAGE_BASE)	\
 					+ (VECTORS_BASE))
diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c
index 8b1b6be..1a505a7 100644
--- a/arch/unicore32/kernel/puv3-core.c
+++ b/arch/unicore32/kernel/puv3-core.c
@@ -99,11 +99,6 @@ static struct resource puv3_unigfx_resources[] = {
 		.end	= io_v2p(PKUNITY_UNIGFX_BASE) + 0xfff,
 		.flags	= IORESOURCE_MEM,
 	},
-	[1] = {
-		.start	= PKUNITY_UNIGFX_MMAP_BASE,
-		.end	= PKUNITY_UNIGFX_MMAP_BASE + PKUNITY_UNIGFX_MMAP_SIZE,
-		.flags	= IORESOURCE_MEM,
-	},
 };
 
 static struct resource puv3_rtc_resources[] = {
diff --git a/arch/unicore32/kernel/setup.c b/arch/unicore32/kernel/setup.c
index 1e175a8..471b6bc 100644
--- a/arch/unicore32/kernel/setup.c
+++ b/arch/unicore32/kernel/setup.c
@@ -64,12 +64,6 @@ static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
  */
 static struct resource mem_res[] = {
 	{
-		.name = "Video RAM",
-		.start = 0,
-		.end = 0,
-		.flags = IORESOURCE_MEM
-	},
-	{
 		.name = "Kernel text",
 		.start = 0,
 		.end = 0,
@@ -83,9 +77,8 @@ static struct resource mem_res[] = {
 	}
 };
 
-#define video_ram   mem_res[0]
-#define kernel_code mem_res[1]
-#define kernel_data mem_res[2]
+#define kernel_code mem_res[0]
+#define kernel_data mem_res[1]
 
 /*
  * These functions re-use the assembly code in head.S, which
@@ -224,10 +217,6 @@ request_standard_resources(struct meminfo *mi)
 		    kernel_data.end <= res->end)
 			request_resource(res, &kernel_data);
 	}
-
-	video_ram.start = PKUNITY_UNIGFX_MMAP_BASE;
-	video_ram.end   = PKUNITY_UNIGFX_MMAP_BASE + PKUNITY_UNIGFX_MMAP_SIZE;
-	request_resource(&iomem_resource, &video_ram);
 }
 
 static void (*init_machine)(void) __initdata;
diff --git a/arch/unicore32/mm/mmu.c b/arch/unicore32/mm/mmu.c
index 7bf3d58..db2d334 100644
--- a/arch/unicore32/mm/mmu.c
+++ b/arch/unicore32/mm/mmu.c
@@ -338,15 +338,6 @@ void __init uc32_mm_memblock_reserve(void)
 	 * and can only be in node 0.
 	 */
 	memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t));
-
-#ifdef CONFIG_PUV3_UNIGFX
-	/*
-	 * These should likewise go elsewhere.  They pre-reserve the
-	 * screen/video memory region at the 48M~64M of main system memory.
-	 */
-	memblock_reserve(PKUNITY_UNIGFX_MMAP_BASE, PKUNITY_UNIGFX_MMAP_SIZE);
-	memblock_reserve(PKUNITY_UVC_MMAP_BASE, PKUNITY_UVC_MMAP_SIZE);
-#endif
 }
 
 /*
@@ -371,17 +362,6 @@ static void __init devicemaps_init(void)
 		pmd_clear(pmd_off_k(addr));
 
 	/*
-	 * Create a mapping for UniGFX VRAM
-	 */
-#ifdef CONFIG_PUV3_UNIGFX
-	map.pfn = __phys_to_pfn(PKUNITY_UNIGFX_MMAP_BASE);
-	map.virtual = KUSER_UNIGFX_BASE;
-	map.length = PKUNITY_UNIGFX_MMAP_SIZE;
-	map.type = MT_KUSER;
-	create_mapping(&map);
-#endif
-
-	/*
 	 * Create a mapping for the machine vectors at the high-vectors
 	 * location (0xffff0000).  If we aren't using high-vectors, also
 	 * create a mapping at the low-vectors virtual address.
diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c
index dbd2dc4..286e295 100644
--- a/drivers/video/fb-puv3.c
+++ b/drivers/video/fb-puv3.c
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/vmalloc.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/fb.h>
@@ -531,7 +530,7 @@ static int unifb_set_par(struct fb_info *info)
 		return -EINVAL;
 	}
 
-	writel(PKUNITY_UNIGFX_MMAP_BASE, UDE_FSA);
+	writel(info->fix.smem_start, UDE_FSA);
 	writel(info->var.yres, UDE_LS);
 	writel(get_line_length(info->var.xres,
 			info->var.bits_per_pixel) >> 3, UDE_PS);
@@ -680,13 +679,26 @@ static int unifb_probe(struct platform_device *dev)
 	struct fb_info *info;
 	u32 unifb_regs[UNIFB_REGS_NUM];
 	int retval = -ENOMEM;
-	struct resource *iomem, *mapmem;
+	struct resource *iomem;
+	void *videomemory;
+
+	videomemory = kmalloc(UNIFB_MEMSIZE, GFP_KERNEL);
+	if (!videomemory)
+		goto err;
+
+	memset(videomemory, 0, UNIFB_MEMSIZE);
+
+	unifb_fix.smem_start = virt_to_phys(videomemory);
+	unifb_fix.smem_len = UNIFB_MEMSIZE;
+
+	iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	unifb_fix.mmio_start = iomem->start;
 
 	info = framebuffer_alloc(sizeof(u32)*256, &dev->dev);
 	if (!info)
 		goto err;
 
-	info->screen_base = (char __iomem *)KUSER_UNIGFX_BASE;
+	info->screen_base = (char __iomem *)videomemory;
 	info->fbops = &unifb_ops;
 
 	retval = fb_find_mode(&info->var, info, NULL,
@@ -695,13 +707,6 @@ static int unifb_probe(struct platform_device *dev)
 	if (!retval || (retval = 4))
 		info->var = unifb_default;
 
-	iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	unifb_fix.mmio_start = iomem->start;
-
-	mapmem = platform_get_resource(dev, IORESOURCE_MEM, 1);
-	unifb_fix.smem_start = mapmem->start;
-	unifb_fix.smem_len = UNIFB_MEMSIZE;
-
 	info->fix = unifb_fix;
 	info->pseudo_palette = info->par;
 	info->par = NULL;
-- 
1.6.2.2



^ permalink raw reply related

* Re: [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
From: Arnd Bergmann @ 2011-03-29 14:42 UTC (permalink / raw)
  To: Guan Xuetao; +Cc: Paul Mundt, linux-kernel, linux-fbdev
In-Reply-To: <019701cbee1e$c4e2d260$4ea87720$@mprc.pku.edu.cn>

On Tuesday 29 March 2011, Guan Xuetao wrote:
> 
> 1. make videomemory kmalloc-ed in fb-puv3.c
> 2. remove resource reservation for old fixed UNIGFX_MMAP & UVC_MMAP space
> 3. remove unused PKUNTIY_UNIGFX_MMAP_BASE, PKUNITY_UNIGFX_MMAP_SIZE,
>         PKUNITY_UVC_MMAP_BASE, PKUNITY_UVC_MMAP_SIZE and KUSER_UNIGFX_BASE
> 4. remove unused header linux/vmalloc.h in fb-puv3.c
> 
> Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>

How does this work? UNIFB_MEMSIZE seems to be 4 MB, much more than the
maximum of 128 KB that kmalloc can allocate.

Shouldn't this use get_free_pages() instead of kmalloc?

	Arnd

^ permalink raw reply

* RE: [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
From: Guan Xuetao @ 2011-03-29 14:54 UTC (permalink / raw)
  To: 'Arnd Bergmann'; +Cc: 'Paul Mundt', linux-kernel, linux-fbdev
In-Reply-To: <201103291642.49555.arnd@arndb.de>



> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: Tuesday, March 29, 2011 10:43 PM
> To: Guan Xuetao
> Cc: Paul Mundt; linux-kernel@vger.kernel.org; linux-fbdev@vger.kernel.org
> Subject: Re: [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
> 
> On Tuesday 29 March 2011, Guan Xuetao wrote:
> >
> > 1. make videomemory kmalloc-ed in fb-puv3.c
> > 2. remove resource reservation for old fixed UNIGFX_MMAP & UVC_MMAP space
> > 3. remove unused PKUNTIY_UNIGFX_MMAP_BASE, PKUNITY_UNIGFX_MMAP_SIZE,
> >         PKUNITY_UVC_MMAP_BASE, PKUNITY_UVC_MMAP_SIZE and KUSER_UNIGFX_BASE
> > 4. remove unused header linux/vmalloc.h in fb-puv3.c
> >
> > Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
> 
> How does this work? UNIFB_MEMSIZE seems to be 4 MB, much more than the
> maximum of 128 KB that kmalloc can allocate.
I'm surprised. But kmalloc() returns success with 0xc7000000.

> 
> Shouldn't this use get_free_pages() instead of kmalloc?

I will check and correct it.

> 
> 	Arnd

Thanks.

Guan Xuetao


^ permalink raw reply

* [PATCH] s3fb: fix Virge/GX2
From: Ondrej Zary @ 2011-03-29 19:07 UTC (permalink / raw)
  To: Ondrej Zajicek; +Cc: linux-fbdev, Kernel development list, Paul Mundt

Fix Virge/GX2 support in s3fb:
- fix IDs: 86C357 is GX2, 86C359 is GX2+, 86C356 probably does not exist
- add memory size detection
- drive it the same way as Trio3D/2X

The original IDs most likely came from S3 website which claims that:
- 356 is Virge/GX2 with IDŠ10, driver included in Windows 2K, XP
- 357 is Virge/GX2+ with IDŠ11, driver included in Windows ME
- 359 is Virge/GX2+ with IDŠ12, driver included in Windows ME
but:
- google search for 86C356 only reveals references to Trio3D (probably
because of a typo - Trio3D is 86C365)
- my card is clearly marked as 86C357, Virge/GX2 and has IDŠ10
- there is no driver for IDs 8A11 and 8A12 in Windows ME
- there is a driver for ID 8A10 in Windows ME that says it's GX2 (357)

Tested with #9 Reality 334 (86C357 Virge/GX2, ID=0x8A10).

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>

--- linux-2.6.38-rc4-/drivers/video/s3fb.c	2011-03-29 17:17:48.000000000 +0200
+++ linux-2.6.38-rc4/drivers/video/s3fb.c	2011-03-29 20:25:12.000000000 +0200
@@ -71,9 +71,9 @@ static const int s3_memsizes[] = {4096,
 
 static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Trio64V+",
 			"S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX",
-			"S3 Plato/PX", "S3 Aurora64VP", "S3 Virge",
+			"S3 Plato/PX", "S3 Aurora64V+", "S3 Virge",
 			"S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX",
-			"S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P",
+			"S3 Virge/GX2", "S3 Virge/GX2+", "",
 			"S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X",
 			"S3 Trio3D"};
 
@@ -90,9 +90,8 @@ static const char * const s3_names[] = {
 #define CHIP_988_VIRGE_VX	0x0A
 #define CHIP_375_VIRGE_DX	0x0B
 #define CHIP_385_VIRGE_GX	0x0C
-#define CHIP_356_VIRGE_GX2	0x0D
-#define CHIP_357_VIRGE_GX2P	0x0E
-#define CHIP_359_VIRGE_GX2P	0x0F
+#define CHIP_357_VIRGE_GX2	0x0D
+#define CHIP_359_VIRGE_GX2P	0x0E
 #define CHIP_360_TRIO3D_1X	0x10
 #define CHIP_362_TRIO3D_2X	0x11
 #define CHIP_368_TRIO3D_2X	0x12
@@ -359,7 +358,9 @@ static void s3_set_pixclock(struct fb_in
 	vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
 
 	/* Set S3 clock registers */
-	if (par->chip = CHIP_360_TRIO3D_1X ||
+	if (par->chip = CHIP_357_VIRGE_GX2 ||
+	    par->chip = CHIP_359_VIRGE_GX2P ||
+	    par->chip = CHIP_360_TRIO3D_1X ||
 	    par->chip = CHIP_362_TRIO3D_2X ||
 	    par->chip = CHIP_368_TRIO3D_2X) {
 		vga_wseq(par->state.vgabase, 0x12, (n - 2) | ((r & 3) << 6));	/* n and two bits of r */
@@ -560,7 +561,9 @@ static int s3fb_set_par(struct fb_info *
 	pr_debug("fb%d: offset register       : %d\n", info->node, offset_value);
 	svga_wcrt_multi(par->state.vgabase, s3_offset_regs, offset_value);
 
-	if (par->chip != CHIP_360_TRIO3D_1X &&
+	if (par->chip != CHIP_357_VIRGE_GX2 &&
+	    par->chip != CHIP_359_VIRGE_GX2P &&
+	    par->chip != CHIP_360_TRIO3D_1X &&
 	    par->chip != CHIP_362_TRIO3D_2X &&
 	    par->chip != CHIP_368_TRIO3D_2X) {
 		vga_wcrt(par->state.vgabase, 0x54, 0x18); /* M parameter */
@@ -604,7 +607,9 @@ static int s3fb_set_par(struct fb_info *
 		vga_wcrt(par->state.vgabase, 0x66, 0x90);
 	}
 
-	if (par->chip = CHIP_360_TRIO3D_1X ||
+	if (par->chip = CHIP_357_VIRGE_GX2 ||
+	    par->chip = CHIP_359_VIRGE_GX2P ||
+	    par->chip = CHIP_360_TRIO3D_1X ||
 	    par->chip = CHIP_362_TRIO3D_2X ||
 	    par->chip = CHIP_368_TRIO3D_2X ||
 	    par->chip = CHIP_365_TRIO3D    ||
@@ -617,8 +622,7 @@ static int s3fb_set_par(struct fb_info *
 		vga_wcrt(par->state.vgabase, 0x66, 0x81);
 	}
 
-	if (par->chip = CHIP_356_VIRGE_GX2  ||
-	    par->chip = CHIP_357_VIRGE_GX2P ||
+	if (par->chip = CHIP_357_VIRGE_GX2  ||
 	    par->chip = CHIP_359_VIRGE_GX2P ||
 	    par->chip = CHIP_360_TRIO3D_1X ||
 	    par->chip = CHIP_362_TRIO3D_2X ||
@@ -674,6 +678,8 @@ static int s3fb_set_par(struct fb_info *
 		pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
 		svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
 		if (info->var.pixclock > 20000 ||
+		    par->chip = CHIP_357_VIRGE_GX2 ||
+		    par->chip = CHIP_359_VIRGE_GX2P ||
 		    par->chip = CHIP_360_TRIO3D_1X ||
 		    par->chip = CHIP_362_TRIO3D_2X ||
 		    par->chip = CHIP_368_TRIO3D_2X)
@@ -702,7 +708,9 @@ static int s3fb_set_par(struct fb_info *
 		} else {
 			svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
 			svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0);
-			if (par->chip != CHIP_360_TRIO3D_1X &&
+			if (par->chip != CHIP_357_VIRGE_GX2 &&
+			    par->chip != CHIP_359_VIRGE_GX2P &&
+			    par->chip != CHIP_360_TRIO3D_1X &&
 			    par->chip != CHIP_362_TRIO3D_2X &&
 			    par->chip != CHIP_368_TRIO3D_2X)
 				hmul = 2;
@@ -727,7 +735,9 @@ static int s3fb_set_par(struct fb_info *
 		} else {
 			svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
 			svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0);
-			if (par->chip != CHIP_360_TRIO3D_1X &&
+			if (par->chip != CHIP_357_VIRGE_GX2 &&
+			    par->chip != CHIP_359_VIRGE_GX2P &&
+			    par->chip != CHIP_360_TRIO3D_1X &&
 			    par->chip != CHIP_362_TRIO3D_2X &&
 			    par->chip != CHIP_368_TRIO3D_2X)
 				hmul = 2;
@@ -1069,6 +1079,16 @@ static int __devinit s3_pci_probe(struct
 			info->screen_size = 2 << 20;
 			break;
 		}
+	} else if (par->chip = CHIP_357_VIRGE_GX2 ||
+		   par->chip = CHIP_359_VIRGE_GX2P) {
+		switch ((regval & 0xC0) >> 6) {
+		case 1: /* 4MB */
+			info->screen_size = 4 << 20;
+			break;
+		case 3: /* 2MB */
+			info->screen_size = 2 << 20;
+			break;
+		}
 	} else
 		info->screen_size = s3_memsizes[regval >> 5] << 10;
 	info->fix.smem_len = info->screen_size;
@@ -1275,8 +1295,8 @@ static struct pci_device_id s3_devices[]
 	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE},
 	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX},
 	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_357_VIRGE_GX2},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_359_VIRGE_GX2P},
 	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P},
 	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X},
 	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8904), .driver_data = CHIP_365_TRIO3D},

-- 
Ondrej Zary

^ permalink raw reply

* RE: [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
From: Guan Xuetao @ 2011-03-30  1:39 UTC (permalink / raw)
  To: 'Arnd Bergmann'; +Cc: 'Paul Mundt', linux-kernel, linux-fbdev
In-Reply-To: <201103291642.49555.arnd@arndb.de>



> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: Tuesday, March 29, 2011 10:43 PM
> To: Guan Xuetao
> Cc: Paul Mundt; linux-kernel@vger.kernel.org; linux-fbdev@vger.kernel.org
> Subject: Re: [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
> 
> On Tuesday 29 March 2011, Guan Xuetao wrote:
> >
> > 1. make videomemory kmalloc-ed in fb-puv3.c
> > 2. remove resource reservation for old fixed UNIGFX_MMAP & UVC_MMAP space
> > 3. remove unused PKUNTIY_UNIGFX_MMAP_BASE, PKUNITY_UNIGFX_MMAP_SIZE,
> >         PKUNITY_UVC_MMAP_BASE, PKUNITY_UVC_MMAP_SIZE and KUSER_UNIGFX_BASE
> > 4. remove unused header linux/vmalloc.h in fb-puv3.c
> >
> > Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
> 
> How does this work? UNIFB_MEMSIZE seems to be 4 MB, much more than the
> maximum of 128 KB that kmalloc can allocate.
> 
> Shouldn't this use get_free_pages() instead of kmalloc?
> 
> 	Arnd

When using SLUB allocator, if required memory size  is larger than 2*PAGE_SIZE, kmalloc_large is called,
and eventually __get_free_pages will  be called.
So,  it would be the same as __get_free_pages.



^ permalink raw reply

* Re: [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
From: Arnd Bergmann @ 2011-03-30  6:54 UTC (permalink / raw)
  To: Guan Xuetao; +Cc: 'Paul Mundt', linux-kernel, linux-fbdev
In-Reply-To: <01ca01cbee7b$4f790370$ee6b0a50$@mprc.pku.edu.cn>

On Wednesday 30 March 2011 03:39:26 Guan Xuetao wrote:
> > How does this work? UNIFB_MEMSIZE seems to be 4 MB, much more than the
> > maximum of 128 KB that kmalloc can allocate.
> > 
> > Shouldn't this use get_free_pages() instead of kmalloc?
> > 
> 
> When using SLUB allocator, if required memory size  is larger
> than 2*PAGE_SIZE, kmalloc_large is called,
> and eventually __get_free_pages will  be called.
> So,  it would be the same as __get_free_pages.

Ok, I see. It's probably still better to use __get_free_pages directly,
because it's possible to select a different allocator that does not
do this itself.

	Arnd

^ permalink raw reply

* RE: [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
From: Guan Xuetao @ 2011-03-30  8:43 UTC (permalink / raw)
  To: 'Arnd Bergmann'; +Cc: 'Paul Mundt', linux-kernel, linux-fbdev
In-Reply-To: <201103300854.05366.arnd@arndb.de>



> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: Wednesday, March 30, 2011 2:54 PM
> To: Guan Xuetao
> Cc: 'Paul Mundt'; linux-kernel@vger.kernel.org; linux-fbdev@vger.kernel.org
> Subject: Re: [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
> 
> On Wednesday 30 March 2011 03:39:26 Guan Xuetao wrote:
> > > How does this work? UNIFB_MEMSIZE seems to be 4 MB, much more than the
> > > maximum of 128 KB that kmalloc can allocate.
> > >
> > > Shouldn't this use get_free_pages() instead of kmalloc?
> > >
> >
> > When using SLUB allocator, if required memory size  is larger
> > than 2*PAGE_SIZE, kmalloc_large is called,
> > and eventually __get_free_pages will  be called.
> > So,  it would be the same as __get_free_pages.
> 
> Ok, I see. It's probably still better to use __get_free_pages directly,
> because it's possible to select a different allocator that does not
> do this itself.
> 
> 	Arnd
Is it appropriate to using __get_free_pages in framebuffer driver?
And both SLAB and SLUB allocators support 4MB request.

Thanks & Regards.

Guan Xuetao



^ permalink raw reply

* Re: [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
From: Arnd Bergmann @ 2011-03-30 10:55 UTC (permalink / raw)
  To: Guan Xuetao; +Cc: 'Paul Mundt', linux-kernel, linux-fbdev
In-Reply-To: <01ea01cbeeb6$99bb5240$cd31f6c0$@mprc.pku.edu.cn>

On Wednesday 30 March 2011, Guan Xuetao wrote:
> Is it appropriate to using __get_free_pages in framebuffer driver?

Yes, it is appropriate, and it is also more efficient than using
kmalloc.

> And both SLAB and SLUB allocators support 4MB request.

Ok, I did not know that, but I see now how the maximum size is computed.
The limit was 128 KB for a long time, but has apparently changed.

	Arnd

^ permalink raw reply

* [PATCH] efifb: support AMD Radeon HD 6490
From: Davidlohr Bueso @ 2011-03-31  0:12 UTC (permalink / raw)
  To: Peter Jones, linux-fbdev; +Cc: LKML, zeus

This patch enables the framebuffer for the AMD Radeon 6490 found in the new MacBook Pro 8,2 generation.
The framebuffer's base is located at 0x90010000, the method for obtaining it was found in the same way mentioned in https://patchwork.kernel.org/patch/91704/

Signed-off-by: Davidlohr Bueso <dave@gnu.org>
Signed-off-by: Jonathan Gonzalez <zeus@gnu.org>
---
 drivers/video/efifb.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index 70477c2..a9645b8 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -64,6 +64,7 @@ enum {
 	M_MBP_6_1,	/* MacBook Pro, 6,1th gen */
 	M_MBP_6_2,	/* MacBook Pro, 6,2th gen */
 	M_MBP_7_1,	/* MacBook Pro, 7,1th gen */
+	M_MBP_8_2,	/* MacBook Pro, 8,2nd gen */
 	M_UNKNOWN	/* placeholder */
 };
 
@@ -100,6 +101,7 @@ static struct efifb_dmi_info {
 	[M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 },
 	[M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 },
 	[M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 },
+	[M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900 },
 	[M_UNKNOWN] = { NULL, 0, 0, 0, 0 }
 };
 
@@ -151,6 +153,7 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
 	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1),
 	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2),
 	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro8,2", M_MBP_8_2),
 	{},
 };
 
-- 
1.7.1




^ permalink raw reply related

* Re: [PATCH] s3fb: fix Virge/GX2
From: Paul Mundt @ 2011-03-31  4:52 UTC (permalink / raw)
  To: Ondrej Zary; +Cc: Ondrej Zajicek, linux-fbdev, Kernel development list
In-Reply-To: <201103292107.11969.linux@rainbow-software.org>

On Tue, Mar 29, 2011 at 09:07:08PM +0200, Ondrej Zary wrote:
> Fix Virge/GX2 support in s3fb:
> - fix IDs: 86C357 is GX2, 86C359 is GX2+, 86C356 probably does not exist
> - add memory size detection
> - drive it the same way as Trio3D/2X
> 
> The original IDs most likely came from S3 website which claims that:
> - 356 is Virge/GX2 with IDŠ10, driver included in Windows 2K, XP
> - 357 is Virge/GX2+ with IDŠ11, driver included in Windows ME
> - 359 is Virge/GX2+ with IDŠ12, driver included in Windows ME
> but:
> - google search for 86C356 only reveals references to Trio3D (probably
> because of a typo - Trio3D is 86C365)
> - my card is clearly marked as 86C357, Virge/GX2 and has IDŠ10
> - there is no driver for IDs 8A11 and 8A12 in Windows ME
> - there is a driver for ID 8A10 in Windows ME that says it's GX2 (357)
> 
> Tested with #9 Reality 334 (86C357 Virge/GX2, ID=0x8A10).
> 
> Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
> 
Applied, thanks.

^ permalink raw reply

* Re: [PATCH] efifb: support AMD Radeon HD 6490
From: Paul Mundt @ 2011-03-31  4:54 UTC (permalink / raw)
  To: Davidlohr Bueso; +Cc: Peter Jones, linux-fbdev, LKML, zeus
In-Reply-To: <1301530342.2140.2.camel@offworld>

On Wed, Mar 30, 2011 at 09:12:22PM -0300, Davidlohr Bueso wrote:
> This patch enables the framebuffer for the AMD Radeon 6490 found in the new MacBook Pro 8,2 generation.
> The framebuffer's base is located at 0x90010000, the method for obtaining it was found in the same way mentioned in https://patchwork.kernel.org/patch/91704/
> 
> Signed-off-by: Davidlohr Bueso <dave@gnu.org>
> Signed-off-by: Jonathan Gonzalez <zeus@gnu.org>

Applied, thanks.

^ permalink raw reply

* [PATCH 0/9] Miscellaneous OMAP DSS patches
From: Tomi Valkeinen @ 2011-03-31 10:10 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Some miscellaneous DSS patches. Quite minor fixes/cleanups, except "Remove
implicit display update on unblank" which does have some functional impact. 

Jani Nikula (2):
  OMAP: DSS2: Add method for querying display dimensions from DSS
    drivers
  OMAP: DSS2: OMAPFB: Remove implicit display update on unblank

Tomi Valkeinen (7):
  OMAP: DSS2: move dss device clock configuration
  OMAP: DSS2: remove non-working msleep(40) workaround
  OMAP: DSS2: make 50ms bug-fix sleep optional
  OMAP: DSS2: VENC: make 20ms venc bug-fix sleep optional
  OMAP: DSS2: VENC: Remove sleeps at venc enable/disable
  OMAP: DSS2: OMAPFB: Handle errors when initializing panel
  OMAP: DSS2: VENC: Add missing start/stop_device calls

 arch/arm/mach-omap2/board-4430sdp.c       |   14 +++--
 arch/arm/plat-omap/include/plat/display.h |   30 +++++---
 drivers/video/omap2/dss/Kconfig           |   23 ++++++
 drivers/video/omap2/dss/dsi.c             |   14 ++--
 drivers/video/omap2/dss/dss.c             |    5 ++
 drivers/video/omap2/dss/overlay.c         |   19 +++--
 drivers/video/omap2/dss/venc.c            |   21 ++++--
 drivers/video/omap2/omapfb/omapfb-ioctl.c |   12 +++-
 drivers/video/omap2/omapfb/omapfb-main.c  |  105 +++++++++++++++++++----------
 9 files changed, 168 insertions(+), 75 deletions(-)


^ permalink raw reply

* [PATCH 1/9] OMAP: DSS2: move dss device clock configuration
From: Tomi Valkeinen @ 2011-03-31 10:10 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
In-Reply-To: <1301566266-11187-1-git-send-email-tomi.valkeinen@ti.com>

Clock configuration was defined inside dssdev.phy.dsi struct. The clock
config doesn't really belong there, and so it's moved to dssdev.clock
struct.

Now the explicit clock configuration could also be used for other
interfaces than DSI, although there's no support for it currently.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/board-4430sdp.c       |   14 +++++++++-----
 arch/arm/plat-omap/include/plat/display.h |   28 ++++++++++++++++------------
 drivers/video/omap2/dss/dsi.c             |   14 +++++++-------
 3 files changed, 32 insertions(+), 24 deletions(-)

diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 05288c9..626b16b 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -766,17 +766,21 @@ static struct omap_dss_device sdp4430_lcd_device = {
 		.data1_pol	= 0,
 		.data2_lane	= 3,
 		.data2_pol	= 0,
-		.div		= {
+	},
+
+	.clocks = {
+		.dispc = {
+			.lck_div	= 1,	/* Logic Clock = 172.8 MHz */
+			.pck_div	= 5,	/* Pixel Clock = 34.56 MHz */
+		},
+
+		.dsi = {
 			.regn		= 16,	/* Fint = 2.4 MHz */
 			.regm		= 180,	/* DDR Clock = 216 MHz */
 			.regm_dispc	= 5,	/* PLL1_CLK1 = 172.8 MHz */
 			.regm_dsi	= 5,	/* PLL1_CLK2 = 172.8 MHz */
 
 			.lp_clk_div	= 10,	/* LP Clock = 8.64 MHz */
-
-			.lck_div	= 1,	/* Logic Clock = 172.8 MHz */
-			.pck_div	= 5,	/* Pixel Clock = 34.56 MHz */
-
 		},
 	},
 	.channel		= OMAP_DSS_CHANNEL_LCD,
diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h
index 5e04ddc..e10cfe2 100644
--- a/arch/arm/plat-omap/include/plat/display.h
+++ b/arch/arm/plat-omap/include/plat/display.h
@@ -401,18 +401,6 @@ struct omap_dss_device {
 			u8 data2_lane;
 			u8 data2_pol;
 
-			struct {
-				u16 regn;
-				u16 regm;
-				u16 regm_dispc;
-				u16 regm_dsi;
-
-				u16 lp_clk_div;
-
-				u16 lck_div;
-				u16 pck_div;
-			} div;
-
 			bool ext_te;
 			u8 ext_te_gpio;
 		} dsi;
@@ -424,6 +412,22 @@ struct omap_dss_device {
 	} phy;
 
 	struct {
+		struct {
+			u16 lck_div;
+			u16 pck_div;
+		} dispc;
+
+		struct {
+			u16 regn;
+			u16 regm;
+			u16 regm_dispc;
+			u16 regm_dsi;
+
+			u16 lp_clk_div;
+		} dsi;
+	} clocks;
+
+	struct {
 		struct omap_video_timings timings;
 
 		int acbi;	/* ac-bias pin transitions per interrupt */
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 23d9bbe..7304c87 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1026,7 +1026,7 @@ static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev)
 	unsigned lp_clk_div;
 	unsigned long lp_clk;
 
-	lp_clk_div = dssdev->phy.dsi.div.lp_clk_div;
+	lp_clk_div = dssdev->clocks.dsi.lp_clk_div;
 
 	if (lp_clk_div = 0 || lp_clk_div > dsi.lpdiv_max)
 		return -EINVAL;
@@ -3388,10 +3388,10 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
 
 	/* we always use DSS_CLK_SYSCK as input clock */
 	cinfo.use_sys_clk = true;
-	cinfo.regn  = dssdev->phy.dsi.div.regn;
-	cinfo.regm  = dssdev->phy.dsi.div.regm;
-	cinfo.regm_dispc = dssdev->phy.dsi.div.regm_dispc;
-	cinfo.regm_dsi = dssdev->phy.dsi.div.regm_dsi;
+	cinfo.regn  = dssdev->clocks.dsi.regn;
+	cinfo.regm  = dssdev->clocks.dsi.regm;
+	cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc;
+	cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi;
 	r = dsi_calc_clock_rates(dssdev, &cinfo);
 	if (r) {
 		DSSERR("Failed to calc dsi clocks\n");
@@ -3415,8 +3415,8 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
 
 	fck = dsi_get_pll_hsdiv_dispc_rate();
 
-	dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div;
-	dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div;
+	dispc_cinfo.lck_div = dssdev->clocks.dispc.lck_div;
+	dispc_cinfo.pck_div = dssdev->clocks.dispc.pck_div;
 
 	r = dispc_calc_clock_rates(fck, &dispc_cinfo);
 	if (r) {
-- 
1.7.1


^ permalink raw reply related

* [PATCH 2/9] OMAP: DSS2: remove non-working msleep(40) workaround
From: Tomi Valkeinen @ 2011-03-31 10:10 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
In-Reply-To: <1301566266-11187-1-git-send-email-tomi.valkeinen@ti.com>

The sleep workaround for the problem described in the comment doesn't
really work. This patch removes the workaround, and improves the comment
about the bug, and proposes an userspace workaround.

omap_dss_set_manager() is called 6 times when loading omapdss and
omapfb, which means that 40ms * 6 = 240ms was spent sleeping when
booting up.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/overlay.c |   19 ++++++++++++-------
 1 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index f1aca6d..fcde51b 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -491,13 +491,18 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
 	ovl->manager = mgr;
 
 	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-	/* XXX: on manual update display, in auto update mode, a bug happens
-	 * here. When an overlay is first enabled on LCD, then it's disabled,
-	 * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT
-	 * errors. Waiting before changing the channel_out fixes it. I'm
-	 * guessing that the overlay is still somehow being used for the LCD,
-	 * but I don't understand how or why. */
-	msleep(40);
+	/* XXX: When there is an overlay on a DSI manual update display, and
+	 * the overlay is first disabled, then moved to tv, and enabled, we
+	 * seem to get SYNC_LOST_DIGIT error.
+	 *
+	 * Waiting doesn't seem to help, but updating the manual update display
+	 * after disabling the overlay seems to fix this. This hints that the
+	 * overlay is perhaps somehow tied to the LCD output until the output
+	 * is updated.
+	 *
+	 * Userspace workaround for this is to update the LCD after disabling
+	 * the overlay, but before moving the overlay to TV.
+	 */
 	dispc_set_channel_out(ovl->id, mgr->id);
 	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH 3/9] OMAP: DSS2: make 50ms bug-fix sleep optional
From: Tomi Valkeinen @ 2011-03-31 10:11 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
In-Reply-To: <1301566266-11187-1-git-send-email-tomi.valkeinen@ti.com>

For some unknown reason we may get SYNC_LOST errors from the display
subsystem at initialization time if we don't sleep before resetting the
DSS. See the source (dss.c) for more comments.

However, 50ms is quite long time to sleep, and with some configurations
the SYNC_LOST may never happen, so this patch creates a Kconfig option
to disable the sleep.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/Kconfig |   11 +++++++++++
 drivers/video/omap2/dss/dss.c   |    5 +++++
 2 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index bfc5da0..458cfe1 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -125,4 +125,15 @@ config OMAP2_DSS_MIN_FCK_PER_PCK
 	  Max FCK is 173MHz, so this doesn't work if your PCK
 	  is very high.
 
+config OMAP2_DSS_SLEEP_BEFORE_RESET
+	bool "Sleep 50ms before DSS reset"
+	default y
+	help
+	  For some unknown reason we may get SYNC_LOST errors from the display
+	  subsystem at initialization time if we don't sleep before resetting
+	  the DSS. See the source (dss.c) for more comments.
+
+	  However, 50ms is quite long time to sleep, and with some
+	  configurations the SYNC_LOST may never happen, so the sleep can
+	  be disabled here.
 endif
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 3f1fee6..688947f 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -659,13 +659,18 @@ static int dss_init(void)
 	 * the kernel resets it */
 	omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
 
+#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
 	/* We need to wait here a bit, otherwise we sometimes start to
 	 * get synclost errors, and after that only power cycle will
 	 * restore DSS functionality. I have no idea why this happens.
 	 * And we have to wait _before_ resetting the DSS, but after
 	 * enabling clocks.
+	 *
+	 * This bug was at least present on OMAP3430. It's unknown
+	 * if it happens on OMAP2 or OMAP3630.
 	 */
 	msleep(50);
+#endif
 
 	_omap_dss_reset();
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH 4/9] OMAP: DSS2: VENC: make 20ms venc bug-fix sleep optional
From: Tomi Valkeinen @ 2011-03-31 10:11 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
In-Reply-To: <1301566266-11187-1-git-send-email-tomi.valkeinen@ti.com>

There's a 20ms sleep after VENC reset. It's unknown what bug this
circumvents and on what platforms. Add a Kconfig option to disable the
sleep.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/Kconfig |   12 ++++++++++++
 drivers/video/omap2/dss/venc.c  |    3 +++
 2 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 458cfe1..5b45c0c 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -136,4 +136,16 @@ config OMAP2_DSS_SLEEP_BEFORE_RESET
 	  However, 50ms is quite long time to sleep, and with some
 	  configurations the SYNC_LOST may never happen, so the sleep can
 	  be disabled here.
+
+config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
+	bool "Sleep 20ms after VENC reset"
+	default y
+	help
+	  There is a 20ms sleep after VENC reset which seemed to fix the
+	  reset. The reason for the bug is unclear, and it's also unclear
+	  on what platforms this happens.
+
+	  This option enables the sleep, and is enabled by default. You can
+	  disable the sleep if it doesn't cause problems on your platform.
+
 endif
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 8e35a5b..8c7af90 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -373,8 +373,11 @@ static void venc_reset(void)
 		}
 	}
 
+#ifdef CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET
 	/* the magical sleep that makes things work */
+	/* XXX more info? What bug this circumvents? */
 	msleep(20);
+#endif
 }
 
 static void venc_enable_clocks(int enable)
-- 
1.7.1


^ permalink raw reply related

* [PATCH 5/9] OMAP: DSS2: VENC: Remove sleeps at venc enable/disable
From: Tomi Valkeinen @ 2011-03-31 10:11 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
In-Reply-To: <1301566266-11187-1-git-send-email-tomi.valkeinen@ti.com>

VENC code had 50ms sleep after enabling the output and 100ms sleep after
disabling the output. I don't see any reason for these sleeps.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/venc.c |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 8c7af90..fe18800 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -487,9 +487,6 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
 
 	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
 
-	/* wait couple of vsyncs until enabling the LCD */
-	msleep(50);
-
 err1:
 	mutex_unlock(&venc.venc_lock);
 
@@ -513,9 +510,6 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
 
 	venc_power_off(dssdev);
 
-	/* wait at least 5 vsyncs after disabling the LCD */
-	msleep(100);
-
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 end:
 	mutex_unlock(&venc.venc_lock);
-- 
1.7.1


^ permalink raw reply related

* [PATCH 6/9] OMAP: DSS2: Add method for querying display dimensions from DSS drivers
From: Tomi Valkeinen @ 2011-03-31 10:11 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: Jani Nikula, Tomi Valkeinen
In-Reply-To: <1301566266-11187-1-git-send-email-tomi.valkeinen@ti.com>

From: Jani Nikula <ext-jani.1.nikula@nokia.com>

Add get_dimensions() to struct omap_dss_driver. Use the call, if supported
by the driver, in OMAPFB.

Signed-off-by: Jani Nikula <ext-jani.1.nikula@nokia.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/plat-omap/include/plat/display.h |    2 ++
 drivers/video/omap2/omapfb/omapfb-ioctl.c |   12 ++++++++++--
 drivers/video/omap2/omapfb/omapfb-main.c  |   12 ++++++++++--
 3 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h
index e10cfe2..f6e4b87 100644
--- a/arch/arm/plat-omap/include/plat/display.h
+++ b/arch/arm/plat-omap/include/plat/display.h
@@ -507,6 +507,8 @@ struct omap_dss_driver {
 
 	void (*get_resolution)(struct omap_dss_device *dssdev,
 			u16 *xres, u16 *yres);
+	void (*get_dimensions)(struct omap_dss_device *dssdev,
+			u32 *width, u32 *height);
 	int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
 
 	int (*check_timings)(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 6f43545..b4636b1 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -895,8 +895,16 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 
 		p.display_info.xres = xres;
 		p.display_info.yres = yres;
-		p.display_info.width = 0;
-		p.display_info.height = 0;
+
+		if (display->driver->get_dimensions) {
+			u32 w, h;
+			display->driver->get_dimensions(display, &w, &h);
+			p.display_info.width = w;
+			p.display_info.height = h;
+		} else {
+			p.display_info.width = 0;
+			p.display_info.height = 0;
+		}
 
 		if (copy_to_user((void __user *)arg, &p.display_info,
 					sizeof(p.display_info)))
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 505ec66..163fb8b 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -702,8 +702,16 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
 			var->xres, var->yres,
 			var->xres_virtual, var->yres_virtual);
 
-	var->height             = -1;
-	var->width              = -1;
+	if (display && display->driver->get_dimensions) {
+		u32 w, h;
+		display->driver->get_dimensions(display, &w, &h);
+		var->width = DIV_ROUND_CLOSEST(w, 1000);
+		var->height = DIV_ROUND_CLOSEST(h, 1000);
+	} else {
+		var->height = -1;
+		var->width = -1;
+	}
+
 	var->grayscale          = 0;
 
 	if (display && display->driver->get_timings) {
-- 
1.7.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox