Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* My associate has helped me to send your first payment
From: WESTERN UNION OFFICE @ 2011-07-20 10:30 UTC (permalink / raw)
  To: linux-fbdev




  My associate has helped me to send your first payment
of $7,500 USD to you as instructed by the Malaysian
Government and Mr. David Cameron the United Kingdom
prime minister after the last G20 meeting that was
held in Malaysia, making you one of the beneficiaries.
Here is the information below.

MTCN Numbers: 6096147516
Sender Name Is = Patrick Lee Chun

  I told him to keep sending you $7,500 USD twice a week
until the FULL payment of ($820000.00 United State Dollars)
is completed.

  A certificate will be made to change the Receivers Name
to your name as stated by the Malaysian Government, send
your Full Names and address via Email to: Mr Garry Moore
to proceed.

                         Note:

  You cannot pickup the money until the certificate is
obtained by you.

Regards
Mr. Garry Moore.
Tel: +(60) 136910048.


^ permalink raw reply

* [PATCH v2 0/6] sh_mobile_lcdc cleanup and fixes
From: Laurent Pinchart @ 2011-07-20 11:24 UTC (permalink / raw)
  To: linux-fbdev

Hi everybody,

Here's a second version of my sh_mobile_lcdc cleanup and fixes patch set.
Compared to v1, it adds three new patches that clean the driver's runtime PM
resume handling, and fix a panning issue on resume.

The first three patches have not been modified.

Laurent Pinchart (6):
  fbdev: sh_mobile_lcdc: Replace hardcoded register values with macros
  fbdev: sh_mobile_lcdc: Don't acknowlege interrupts unintentionally
  fbdev: sh_mobile_lcdc: Compute clock pattern using divider
    denominator
  fbdev: sh_mobile_lcdc: Split LCDC start code from
    sh_mobile_lcdc_start
  fbdev: sh_mobile_lcdc: Store the frame buffer base address when
    panning
  fbdev: sh_mobile_lcdc: Restart LCDC in runtime PM resume handler

 drivers/video/sh_mobile_lcdcfb.c |  582 +++++++++++++++++---------------------
 drivers/video/sh_mobile_lcdcfb.h |   12 +-
 include/video/sh_mobile_lcdc.h   |  135 ++++++++--
 3 files changed, 383 insertions(+), 346 deletions(-)

-- 
Regards,

Laurent Pinchart


^ permalink raw reply

* [PATCH v2 1/6] fbdev: sh_mobile_lcdc: Replace hardcoded register values with macros
From: Laurent Pinchart @ 2011-07-20 11:24 UTC (permalink / raw)
  To: linux-fbdev

Instead of hardcoding register values through the driver, define macros
for individual register bits using the register name and the bit name,
and use the macros.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/sh_mobile_lcdcfb.c |  204 +++++++++++++++++---------------------
 include/video/sh_mobile_lcdc.h   |  135 +++++++++++++++++++++----
 2 files changed, 209 insertions(+), 130 deletions(-)

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index e9b80bc..abc2a91 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -32,20 +32,6 @@
 #define SIDE_B_OFFSET 0x1000
 #define MIRROR_OFFSET 0x2000
 
-/* shared registers */
-#define _LDDCKR 0x410
-#define _LDDCKSTPR 0x414
-#define _LDINTR 0x468
-#define _LDSR 0x46c
-#define _LDCNT1R 0x470
-#define _LDCNT2R 0x474
-#define _LDRCNTR 0x478
-#define _LDDDSR 0x47c
-#define _LDDWD0R 0x800
-#define _LDDRDR 0x840
-#define _LDDWAR 0x900
-#define _LDDRAR 0x904
-
 /* shared registers and their order for context save/restore */
 static int lcdc_shared_regs[] = {
 	_LDDCKR,
@@ -98,22 +84,6 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
 	[LDPMR] = 0x63c,
 };
 
-#define START_LCDC	0x00000001
-#define LCDC_RESET	0x00000100
-#define DISPLAY_BEU	0x00000008
-#define LCDC_ENABLE	0x00000001
-#define LDINTR_FE	0x00000400
-#define LDINTR_VSE	0x00000200
-#define LDINTR_VEE	0x00000100
-#define LDINTR_FS	0x00000004
-#define LDINTR_VSS	0x00000002
-#define LDINTR_VES	0x00000001
-#define LDRCNTR_SRS	0x00020000
-#define LDRCNTR_SRC	0x00010000
-#define LDRCNTR_MRS	0x00000002
-#define LDRCNTR_MRC	0x00000001
-#define LDSR_MRS	0x00000100
-
 static const struct fb_videomode default_720p = {
 	.name = "HDMI 720p",
 	.xres = 1280,
@@ -218,33 +188,36 @@ static void lcdc_sys_write_index(void *handle, unsigned long data)
 {
 	struct sh_mobile_lcdc_chan *ch = handle;
 
-	lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000);
-	lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
-	lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
-	lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+	lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT);
+	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
+	lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
+		   (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
 }
 
 static void lcdc_sys_write_data(void *handle, unsigned long data)
 {
 	struct sh_mobile_lcdc_chan *ch = handle;
 
-	lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000);
-	lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
-	lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
-	lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+	lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT | LDDWDxR_RSW);
+	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
+	lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
+		   (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
 }
 
 static unsigned long lcdc_sys_read_data(void *handle)
 {
 	struct sh_mobile_lcdc_chan *ch = handle;
 
-	lcdc_write(ch->lcdc, _LDDRDR, 0x01000000);
-	lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
-	lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+	lcdc_write(ch->lcdc, _LDDRDR, LDDRDR_RSR);
+	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
+	lcdc_write(ch->lcdc, _LDDRAR, LDDRAR_RA |
+		   (lcdc_chan_is_sublcd(ch) ? 2 : 0));
 	udelay(1);
-	lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
 
-	return lcdc_read(ch->lcdc, _LDDRDR) & 0x3ffff;
+	return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK;
 }
 
 struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
@@ -323,13 +296,13 @@ static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
 		if (bcfg->start_transfer)
 			bcfg->start_transfer(bcfg->board_data, ch,
 					     &sh_mobile_lcdc_sys_bus_ops);
-		lcdc_write_chan(ch, LDSM2R, 1);
+		lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
 		dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
 	} else {
 		if (bcfg->start_transfer)
 			bcfg->start_transfer(bcfg->board_data, ch,
 					     &sh_mobile_lcdc_sys_bus_ops);
-		lcdc_write_chan(ch, LDSM2R, 1);
+		lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
 	}
 }
 
@@ -356,11 +329,11 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
 	 * disable further VSYNC End IRQs, preserve all other enabled IRQs,
 	 * write 0 to bits 0-6 to ack all triggered IRQs.
 	 */
-	tmp &= 0xffffff00 & ~LDINTR_VEE;
+	tmp &= ~LDINTR_STATUS_MASK & ~LDINTR_VEE;
 	lcdc_write(priv, _LDINTR, tmp);
 
 	/* figure out if this interrupt is for main or sub lcd */
-	is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0;
+	is_sub = (lcdc_read(priv, _LDSR) & LDSR_MSS) ? 1 : 0;
 
 	/* wake up channel and disable clocks */
 	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
@@ -395,16 +368,17 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
 
 	/* start or stop the lcdc */
 	if (start)
-		lcdc_write(priv, _LDCNT2R, tmp | START_LCDC);
+		lcdc_write(priv, _LDCNT2R, tmp | LDCNT2R_DO);
 	else
-		lcdc_write(priv, _LDCNT2R, tmp & ~START_LCDC);
+		lcdc_write(priv, _LDCNT2R, tmp & ~LDCNT2R_DO);
 
 	/* wait until power is applied/stopped on all channels */
 	for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
 		if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
 			while (1) {
-				tmp = lcdc_read_chan(&priv->ch[k], LDPMR) & 3;
-				if (start && tmp = 3)
+				tmp = lcdc_read_chan(&priv->ch[k], LDPMR)
+				    & LDPMR_LPS;
+				if (start && tmp = LDPMR_LPS)
 					break;
 				if (!start && tmp = 0)
 					break;
@@ -422,13 +396,13 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
 	u32 tmp;
 
 	tmp = ch->ldmt1r_value;
-	tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
-	tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
-	tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
-	tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
-	tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
-	tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
-	tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
+	tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL;
+	tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL;
+	tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0;
+	tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0;
+	tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0;
+	tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0;
+	tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0;
 	lcdc_write_chan(ch, LDMT1R, tmp);
 
 	/* setup SYS bus */
@@ -486,8 +460,8 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 	}
 
 	/* reset */
-	lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET);
-	lcdc_wait_bit(priv, _LDCNT2R, LCDC_RESET, 0);
+	lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR);
+	lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0);
 
 	/* enable LCDC channels */
 	tmp = lcdc_read(priv, _LDCNT2R);
@@ -496,7 +470,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 	lcdc_write(priv, _LDCNT2R, tmp);
 
 	/* read data from external memory, avoid using the BEU for now */
-	lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~DISPLAY_BEU);
+	lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~LDCNT2R_MD);
 
 	/* stop the lcdc first */
 	sh_mobile_lcdc_start_stop(priv, 0);
@@ -514,7 +488,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 			continue;
 
 		if (m = 1)
-			m = 1 << 6;
+			m = LDDCKR_MOSEL;
 		tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
 
 		/* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider denominator */
@@ -554,20 +528,21 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 	/* word and long word swap */
 	ldddsr = lcdc_read(priv, _LDDDSR);
 	if  (priv->ch[0].info->var.nonstd)
-		lcdc_write(priv, _LDDDSR, ldddsr | 7);
+		ldddsr |= LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
 	else {
 		switch (bpp) {
 		case 16:
-			lcdc_write(priv, _LDDDSR, ldddsr | 6);
+			ldddsr |= LDDDSR_LS | LDDDSR_WS;
 			break;
 		case 24:
-			lcdc_write(priv, _LDDDSR, ldddsr | 7);
+			ldddsr |= LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
 			break;
 		case 32:
-			lcdc_write(priv, _LDDDSR, ldddsr | 4);
+			ldddsr |= LDDDSR_LS;
 			break;
 		}
 	}
+	lcdc_write(priv, _LDDDSR, ldddsr);
 
 	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
 		unsigned long base_addr_y;
@@ -580,28 +555,29 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 
 		/* set bpp format in PKF[4:0] */
 		tmp = lcdc_read_chan(ch, LDDFR);
-		tmp &= ~0x0003031f;
+		tmp &= ~(LDDFR_CF0 | LDDFR_CC | LDDFR_YF_MASK | LDDFR_PKF_MASK);
 		if (ch->info->var.nonstd) {
 			tmp |= (ch->info->var.nonstd << 16);
 			switch (ch->info->var.bits_per_pixel) {
 			case 12:
 				break;
 			case 16:
-				tmp |= (0x1 << 8);
+				tmp |= LDDFR_YF_422;
 				break;
 			case 24:
-				tmp |= (0x2 << 8);
+				tmp |= LDDFR_YF_444;
 				break;
 			}
 		} else {
 			switch (ch->info->var.bits_per_pixel) {
 			case 16:
-				tmp |= 0x03;
+				tmp |= LDDFR_PKF_RGB16;
 				break;
 			case 24:
-				tmp |= 0x0b;
+				tmp |= LDDFR_PKF_RGB24;
 				break;
 			case 32:
+				tmp |= LDDFR_PKF_ARGB32;
 				break;
 			}
 		}
@@ -672,14 +648,14 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 
 		/* setup deferred io if SYS bus */
 		tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
-		if (ch->ldmt1r_value & (1 << 12) && tmp) {
+		if (ch->ldmt1r_value & LDMT1R_IFM && tmp) {
 			ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
 			ch->defio.delay = msecs_to_jiffies(tmp);
 			ch->info->fbdefio = &ch->defio;
 			fb_deferred_io_init(ch->info);
 
 			/* one-shot mode */
-			lcdc_write_chan(ch, LDSM1R, 1);
+			lcdc_write_chan(ch, LDSM1R, LDSM1R_OS);
 
 			/* enable "Frame End Interrupt Enable" bit */
 			lcdc_write(priv, _LDINTR, LDINTR_FE);
@@ -691,7 +667,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 	}
 
 	/* display output */
-	lcdc_write(priv, _LDCNT1R, LCDC_ENABLE);
+	lcdc_write(priv, _LDCNT1R, LDCNT1R_DE);
 
 	/* start the lcdc */
 	sh_mobile_lcdc_start_stop(priv, 1);
@@ -780,42 +756,42 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
 
 static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
 {
-	int ifm, miftyp;
-
-	switch (ch->cfg.interface_type) {
-	case RGB8: ifm = 0; miftyp = 0; break;
-	case RGB9: ifm = 0; miftyp = 4; break;
-	case RGB12A: ifm = 0; miftyp = 5; break;
-	case RGB12B: ifm = 0; miftyp = 6; break;
-	case RGB16: ifm = 0; miftyp = 7; break;
-	case RGB18: ifm = 0; miftyp = 10; break;
-	case RGB24: ifm = 0; miftyp = 11; break;
-	case SYS8A: ifm = 1; miftyp = 0; break;
-	case SYS8B: ifm = 1; miftyp = 1; break;
-	case SYS8C: ifm = 1; miftyp = 2; break;
-	case SYS8D: ifm = 1; miftyp = 3; break;
-	case SYS9: ifm = 1; miftyp = 4; break;
-	case SYS12: ifm = 1; miftyp = 5; break;
-	case SYS16A: ifm = 1; miftyp = 7; break;
-	case SYS16B: ifm = 1; miftyp = 8; break;
-	case SYS16C: ifm = 1; miftyp = 9; break;
-	case SYS18: ifm = 1; miftyp = 10; break;
-	case SYS24: ifm = 1; miftyp = 11; break;
-	default: goto bad;
+	int interface_type = ch->cfg.interface_type;
+
+	switch (interface_type) {
+	case RGB8:
+	case RGB9:
+	case RGB12A:
+	case RGB12B:
+	case RGB16:
+	case RGB18:
+	case RGB24:
+	case SYS8A:
+	case SYS8B:
+	case SYS8C:
+	case SYS8D:
+	case SYS9:
+	case SYS12:
+	case SYS16A:
+	case SYS16B:
+	case SYS16C:
+	case SYS18:
+	case SYS24:
+		break;
+	default:
+		return -EINVAL;
 	}
 
 	/* SUBLCD only supports SYS interface */
 	if (lcdc_chan_is_sublcd(ch)) {
-		if (ifm = 0)
-			goto bad;
-		else
-			ifm = 0;
+		if (!(interface_type & LDMT1R_IFM))
+			return -EINVAL;
+
+		interface_type &= ~LDMT1R_IFM;
 	}
 
-	ch->ldmt1r_value = (ifm << 12) | miftyp;
+	ch->ldmt1r_value = interface_type;
 	return 0;
- bad:
-	return -EINVAL;
 }
 
 static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
@@ -823,18 +799,24 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
 				       struct sh_mobile_lcdc_priv *priv)
 {
 	char *str;
-	int icksel;
 
 	switch (clock_source) {
-	case LCDC_CLK_BUS: str = "bus_clk"; icksel = 0; break;
-	case LCDC_CLK_PERIPHERAL: str = "peripheral_clk"; icksel = 1; break;
-	case LCDC_CLK_EXTERNAL: str = NULL; icksel = 2; break;
+	case LCDC_CLK_BUS:
+		str = "bus_clk";
+		priv->lddckr = LDDCKR_ICKSEL_BUS;
+		break;
+	case LCDC_CLK_PERIPHERAL:
+		str = "peripheral_clk";
+		priv->lddckr = LDDCKR_ICKSEL_MIPI;
+		break;
+	case LCDC_CLK_EXTERNAL:
+		str = NULL;
+		priv->lddckr = LDDCKR_ICKSEL_HDMI;
+		break;
 	default:
 		return -EINVAL;
 	}
 
-	priv->lddckr = icksel << 16;
-
 	if (str) {
 		priv->dot_clk = clk_get(&pdev->dev, str);
 		if (IS_ERR(priv->dot_clk)) {
@@ -1476,12 +1458,12 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 
 		switch (pdata->ch[i].chan) {
 		case LCDC_CHAN_MAINLCD:
-			ch->enabled = 1 << 1;
+			ch->enabled = LDCNT2R_ME;
 			ch->reg_offs = lcdc_offs_mainlcd;
 			j++;
 			break;
 		case LCDC_CHAN_SUBLCD:
-			ch->enabled = 1 << 2;
+			ch->enabled = LDCNT2R_SE;
 			ch->reg_offs = lcdc_offs_sublcd;
 			j++;
 			break;
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index d964e68..8101b72 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -4,26 +4,123 @@
 #include <linux/fb.h>
 #include <video/sh_mobile_meram.h>
 
+/* Register definitions */
+#define _LDDCKR			0x410
+#define LDDCKR_ICKSEL_BUS	(0 << 16)
+#define LDDCKR_ICKSEL_MIPI	(1 << 16)
+#define LDDCKR_ICKSEL_HDMI	(2 << 16)
+#define LDDCKR_ICKSEL_EXT	(3 << 16)
+#define LDDCKR_ICKSEL_MASK	(7 << 16)
+#define LDDCKR_MOSEL		(1 << 6)
+#define _LDDCKSTPR		0x414
+#define _LDINTR			0x468
+#define LDINTR_FE		(1 << 10)
+#define LDINTR_VSE		(1 << 9)
+#define LDINTR_VEE		(1 << 8)
+#define LDINTR_FS		(1 << 2)
+#define LDINTR_VSS		(1 << 1)
+#define LDINTR_VES		(1 << 0)
+#define LDINTR_STATUS_MASK	(0xff << 0)
+#define _LDSR			0x46c
+#define LDSR_MSS		(1 << 10)
+#define LDSR_MRS		(1 << 8)
+#define LDSR_AS			(1 << 1)
+#define _LDCNT1R		0x470
+#define LDCNT1R_DE		(1 << 0)
+#define _LDCNT2R		0x474
+#define LDCNT2R_BR		(1 << 8)
+#define LDCNT2R_MD		(1 << 3)
+#define LDCNT2R_SE		(1 << 2)
+#define LDCNT2R_ME		(1 << 1)
+#define LDCNT2R_DO		(1 << 0)
+#define _LDRCNTR		0x478
+#define LDRCNTR_SRS		(1 << 17)
+#define LDRCNTR_SRC		(1 << 16)
+#define LDRCNTR_MRS		(1 << 1)
+#define LDRCNTR_MRC		(1 << 0)
+#define _LDDDSR			0x47c
+#define LDDDSR_LS		(1 << 2)
+#define LDDDSR_WS		(1 << 1)
+#define LDDDSR_BS		(1 << 0)
+
+#define LDMT1R_VPOL		(1 << 28)
+#define LDMT1R_HPOL		(1 << 27)
+#define LDMT1R_DWPOL		(1 << 26)
+#define LDMT1R_DIPOL		(1 << 25)
+#define LDMT1R_DAPOL		(1 << 24)
+#define LDMT1R_HSCNT		(1 << 17)
+#define LDMT1R_DWCNT		(1 << 16)
+#define LDMT1R_IFM		(1 << 12)
+#define LDMT1R_MIFTYP_RGB8	(0x0 << 0)
+#define LDMT1R_MIFTYP_RGB9	(0x4 << 0)
+#define LDMT1R_MIFTYP_RGB12A	(0x5 << 0)
+#define LDMT1R_MIFTYP_RGB12B	(0x6 << 0)
+#define LDMT1R_MIFTYP_RGB16	(0x7 << 0)
+#define LDMT1R_MIFTYP_RGB18	(0xa << 0)
+#define LDMT1R_MIFTYP_RGB24	(0xb << 0)
+#define LDMT1R_MIFTYP_YCBCR	(0xf << 0)
+#define LDMT1R_MIFTYP_SYS8A	(0x0 << 0)
+#define LDMT1R_MIFTYP_SYS8B	(0x1 << 0)
+#define LDMT1R_MIFTYP_SYS8C	(0x2 << 0)
+#define LDMT1R_MIFTYP_SYS8D	(0x3 << 0)
+#define LDMT1R_MIFTYP_SYS9	(0x4 << 0)
+#define LDMT1R_MIFTYP_SYS12	(0x5 << 0)
+#define LDMT1R_MIFTYP_SYS16A	(0x7 << 0)
+#define LDMT1R_MIFTYP_SYS16B	(0x8 << 0)
+#define LDMT1R_MIFTYP_SYS16C	(0x9 << 0)
+#define LDMT1R_MIFTYP_SYS18	(0xa << 0)
+#define LDMT1R_MIFTYP_SYS24	(0xb << 0)
+#define LDMT1R_MIFTYP_MASK	(0xf << 0)
+
+#define LDDFR_CF1		(1 << 18)
+#define LDDFR_CF0		(1 << 17)
+#define LDDFR_CC		(1 << 16)
+#define LDDFR_YF_420		(0 << 8)
+#define LDDFR_YF_422		(1 << 8)
+#define LDDFR_YF_444		(2 << 8)
+#define LDDFR_YF_MASK		(3 << 8)
+#define LDDFR_PKF_ARGB32	(0x00 << 0)
+#define LDDFR_PKF_RGB16		(0x03 << 0)
+#define LDDFR_PKF_RGB24		(0x0b << 0)
+#define LDDFR_PKF_MASK		(0x1f << 0)
+
+#define LDSM1R_OS		(1 << 0)
+
+#define LDSM2R_OSTRG		(1 << 0)
+
+#define LDPMR_LPS		(3 << 0)
+
+#define _LDDWD0R		0x800
+#define LDDWDxR_WDACT		(1 << 28)
+#define LDDWDxR_RSW		(1 << 24)
+#define _LDDRDR			0x840
+#define LDDRDR_RSR		(1 << 24)
+#define LDDRDR_DRD_MASK		(0x3ffff << 0)
+#define _LDDWAR			0x900
+#define LDDWAR_WA		(1 << 0)
+#define _LDDRAR			0x904
+#define LDDRAR_RA		(1 << 0)
+
 enum {
-	RGB8,   /* 24bpp, 8:8:8 */
-	RGB9,   /* 18bpp, 9:9 */
-	RGB12A, /* 24bpp, 12:12 */
-	RGB12B, /* 12bpp */
-	RGB16,  /* 16bpp */
-	RGB18,  /* 18bpp */
-	RGB24,  /* 24bpp */
-	YUV422, /* 16bpp */
-	SYS8A,  /* 24bpp, 8:8:8 */
-	SYS8B,  /* 18bpp, 8:8:2 */
-	SYS8C,  /* 18bpp, 2:8:8 */
-	SYS8D,  /* 16bpp, 8:8 */
-	SYS9,   /* 18bpp, 9:9 */
-	SYS12,  /* 24bpp, 12:12 */
-	SYS16A, /* 16bpp */
-	SYS16B, /* 18bpp, 16:2 */
-	SYS16C, /* 18bpp, 2:16 */
-	SYS18,  /* 18bpp */
-	SYS24,  /* 24bpp */
+	RGB8	= LDMT1R_MIFTYP_RGB8,	/* 24bpp, 8:8:8 */
+	RGB9	= LDMT1R_MIFTYP_RGB9,	/* 18bpp, 9:9 */
+	RGB12A	= LDMT1R_MIFTYP_RGB12A,	/* 24bpp, 12:12 */
+	RGB12B	= LDMT1R_MIFTYP_RGB12B,	/* 12bpp */
+	RGB16	= LDMT1R_MIFTYP_RGB16,	/* 16bpp */
+	RGB18	= LDMT1R_MIFTYP_RGB18,	/* 18bpp */
+	RGB24	= LDMT1R_MIFTYP_RGB24,	/* 24bpp */
+	YUV422	= LDMT1R_MIFTYP_YCBCR,	/* 16bpp */
+	SYS8A	= LDMT1R_IFM | LDMT1R_MIFTYP_SYS8A,	/* 24bpp, 8:8:8 */
+	SYS8B	= LDMT1R_IFM | LDMT1R_MIFTYP_SYS8B,	/* 18bpp, 8:8:2 */
+	SYS8C	= LDMT1R_IFM | LDMT1R_MIFTYP_SYS8C,	/* 18bpp, 2:8:8 */
+	SYS8D	= LDMT1R_IFM | LDMT1R_MIFTYP_SYS8D,	/* 16bpp, 8:8 */
+	SYS9	= LDMT1R_IFM | LDMT1R_MIFTYP_SYS9,	/* 18bpp, 9:9 */
+	SYS12	= LDMT1R_IFM | LDMT1R_MIFTYP_SYS12,	/* 24bpp, 12:12 */
+	SYS16A	= LDMT1R_IFM | LDMT1R_MIFTYP_SYS16A,	/* 16bpp */
+	SYS16B	= LDMT1R_IFM | LDMT1R_MIFTYP_SYS16B,	/* 18bpp, 16:2 */
+	SYS16C	= LDMT1R_IFM | LDMT1R_MIFTYP_SYS16C,	/* 18bpp, 2:16 */
+	SYS18	= LDMT1R_IFM | LDMT1R_MIFTYP_SYS18,	/* 18bpp */
+	SYS24	= LDMT1R_IFM | LDMT1R_MIFTYP_SYS24,	/* 24bpp */
 };
 
 enum { LCDC_CHAN_DISABLED = 0,
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v2 2/6] fbdev: sh_mobile_lcdc: Don't acknowlege interrupts unintentionally
From: Laurent Pinchart @ 2011-07-20 11:24 UTC (permalink / raw)
  To: linux-fbdev

The LDINTR register caries both interrupt enable and interrupt status
bits. When setting or clearing interrupt enable bits, write all status
bits to 1 to avoid acknowledging interrupts by mistake.

When acknowledging interrupts, write 1 to all non-triggered interrupt
bits to avoid losing interrupts.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/sh_mobile_lcdcfb.c |   20 ++++++++------------
 1 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index abc2a91..ba946f4 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -318,19 +318,13 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
 {
 	struct sh_mobile_lcdc_priv *priv = data;
 	struct sh_mobile_lcdc_chan *ch;
-	unsigned long tmp;
 	unsigned long ldintr;
 	int is_sub;
 	int k;
 
-	/* acknowledge interrupt */
-	ldintr = tmp = lcdc_read(priv, _LDINTR);
-	/*
-	 * disable further VSYNC End IRQs, preserve all other enabled IRQs,
-	 * write 0 to bits 0-6 to ack all triggered IRQs.
-	 */
-	tmp &= ~LDINTR_STATUS_MASK & ~LDINTR_VEE;
-	lcdc_write(priv, _LDINTR, tmp);
+	/* Acknowledge interrupts and disable further VSYNC End IRQs. */
+	ldintr = lcdc_read(priv, _LDINTR);
+	lcdc_write(priv, _LDINTR, (ldintr ^ LDINTR_STATUS_MASK) & ~LDINTR_VEE);
 
 	/* figure out if this interrupt is for main or sub lcd */
 	is_sub = (lcdc_read(priv, _LDSR) & LDSR_MSS) ? 1 : 0;
@@ -342,7 +336,7 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
 		if (!ch->enabled)
 			continue;
 
-		/* Frame Start */
+		/* Frame End */
 		if (ldintr & LDINTR_FS) {
 			if (is_sub = lcdc_chan_is_sublcd(ch)) {
 				ch->frame_end = 1;
@@ -971,9 +965,11 @@ static int sh_mobile_wait_for_vsync(struct fb_info *info)
 	unsigned long ldintr;
 	int ret;
 
-	/* Enable VSync End interrupt */
+	/* Enable VSync End interrupt and be careful not to acknowledge any
+	 * pending interrupt.
+	 */
 	ldintr = lcdc_read(ch->lcdc, _LDINTR);
-	ldintr |= LDINTR_VEE;
+	ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK;
 	lcdc_write(ch->lcdc, _LDINTR, ldintr);
 
 	ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v2 3/6] fbdev: sh_mobile_lcdc: Compute clock pattern using divider denominator
From: Laurent Pinchart @ 2011-07-20 11:24 UTC (permalink / raw)
  To: linux-fbdev

The clock divider pattern is computed based on the dot clock register
value which stores the divider denumerator. However, when using a 1:1
divider ratio, the register is programmed with a value that must not be
interpreted as a denominator. This results in a shift left operation
with a value of 32, which produces undefined behaviour.

Compute the clock pattern using the divider denominator, not the dot
clock register value.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/sh_mobile_lcdcfb.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index ba946f4..31aef60 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -481,13 +481,15 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 		if (!m)
 			continue;
 
+		/* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider
+		 * denominator.
+		 */
+		lcdc_write_chan(ch, LDDCKPAT1R, 0);
+		lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
+
 		if (m = 1)
 			m = LDDCKR_MOSEL;
 		tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
-
-		/* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider denominator */
-		lcdc_write_chan(ch, LDDCKPAT1R, 0);
-		lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
 	}
 
 	lcdc_write(priv, _LDDCKR, tmp);
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v2 4/6] fbdev: sh_mobile_lcdc: Split LCDC start code from sh_mobile_lcdc_start
From: Laurent Pinchart @ 2011-07-20 11:24 UTC (permalink / raw)
  To: linux-fbdev

Splitting the LCDC start code from clock, MERAM and panel management
will make the code usable by runtime PM.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/sh_mobile_lcdcfb.c |  313 +++++++++++++++++++-------------------
 drivers/video/sh_mobile_lcdcfb.h |   11 ++
 2 files changed, 164 insertions(+), 160 deletions(-)

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 31aef60..785521e 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -435,48 +435,42 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
 	lcdc_write_chan(ch, LDHAJR, tmp);
 }
 
-static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+/*
+ * __sh_mobile_lcdc_start - Configure and tart the LCDC
+ * @priv: LCDC device
+ *
+ * Configure all enabled channels and start the LCDC device. All external
+ * devices (clocks, MERAM, panels, ...) are not touched by this function.
+ */
+static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 {
 	struct sh_mobile_lcdc_chan *ch;
-	struct sh_mobile_lcdc_board_cfg	*board_cfg;
 	unsigned long tmp;
 	int bpp = 0;
-	unsigned long ldddsr;
-	int k, m, ret;
+	int k, m;
 
-	/* enable clocks before accessing the hardware */
-	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
-		if (priv->ch[k].enabled) {
-			sh_mobile_lcdc_clk_on(priv);
-			if (!bpp)
-				bpp = priv->ch[k].info->var.bits_per_pixel;
-		}
-	}
-
-	/* reset */
-	lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR);
-	lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0);
-
-	/* enable LCDC channels */
-	tmp = lcdc_read(priv, _LDCNT2R);
-	tmp |= priv->ch[0].enabled;
-	tmp |= priv->ch[1].enabled;
-	lcdc_write(priv, _LDCNT2R, tmp);
-
-	/* read data from external memory, avoid using the BEU for now */
-	lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~LDCNT2R_MD);
+	/* Enable LCDC channels. Read data from external memory, avoid using the
+	 * BEU for now.
+	 */
+	lcdc_write(priv, _LDCNT2R, priv->ch[0].enabled | priv->ch[1].enabled);
 
-	/* stop the lcdc first */
+	/* Stop the LCDC first and disable all interrupts. */
 	sh_mobile_lcdc_start_stop(priv, 0);
+	lcdc_write(priv, _LDINTR, 0);
 
-	/* configure clocks */
+	/* Configure power supply, dot clocks and start them. */
 	tmp = priv->lddckr;
 	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
 		ch = &priv->ch[k];
-
-		if (!priv->ch[k].enabled)
+		if (!ch->enabled)
 			continue;
 
+		if (!bpp)
+			bpp = ch->info->var.bits_per_pixel;
+
+		/* Power supply */
+		lcdc_write_chan(ch, LDPMR, 0);
+
 		m = ch->cfg.clock_divider;
 		if (!m)
 			continue;
@@ -493,188 +487,187 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 	}
 
 	lcdc_write(priv, _LDDCKR, tmp);
-
-	/* start dotclock again */
 	lcdc_write(priv, _LDDCKSTPR, 0);
 	lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
 
-	/* interrupts are disabled to begin with */
-	lcdc_write(priv, _LDINTR, 0);
-
+	/* Setup geometry, format, frame buffer memory and operation mode. */
 	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
 		ch = &priv->ch[k];
-
 		if (!ch->enabled)
 			continue;
 
 		sh_mobile_lcdc_geometry(ch);
 
-		/* power supply */
-		lcdc_write_chan(ch, LDPMR, 0);
-
-		board_cfg = &ch->cfg.board_cfg;
-		if (board_cfg->setup_sys) {
-			ret = board_cfg->setup_sys(board_cfg->board_data,
-						ch, &sh_mobile_lcdc_sys_bus_ops);
-			if (ret)
-				return ret;
-		}
-	}
-
-	/* word and long word swap */
-	ldddsr = lcdc_read(priv, _LDDDSR);
-	if  (priv->ch[0].info->var.nonstd)
-		ldddsr |= LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
-	else {
-		switch (bpp) {
-		case 16:
-			ldddsr |= LDDDSR_LS | LDDDSR_WS;
-			break;
-		case 24:
-			ldddsr |= LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
-			break;
-		case 32:
-			ldddsr |= LDDDSR_LS;
-			break;
-		}
-	}
-	lcdc_write(priv, _LDDDSR, ldddsr);
-
-	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)
-			continue;
-
-		/* set bpp format in PKF[4:0] */
-		tmp = lcdc_read_chan(ch, LDDFR);
-		tmp &= ~(LDDFR_CF0 | LDDFR_CC | LDDFR_YF_MASK | LDDFR_PKF_MASK);
 		if (ch->info->var.nonstd) {
-			tmp |= (ch->info->var.nonstd << 16);
+			tmp = (ch->info->var.nonstd << 16);
 			switch (ch->info->var.bits_per_pixel) {
 			case 12:
+				tmp |= LDDFR_YF_420;
 				break;
 			case 16:
 				tmp |= LDDFR_YF_422;
 				break;
 			case 24:
+			default:
 				tmp |= LDDFR_YF_444;
 				break;
 			}
 		} else {
 			switch (ch->info->var.bits_per_pixel) {
 			case 16:
-				tmp |= LDDFR_PKF_RGB16;
+				tmp = LDDFR_PKF_RGB16;
 				break;
 			case 24:
-				tmp |= LDDFR_PKF_RGB24;
+				tmp = LDDFR_PKF_RGB24;
 				break;
 			case 32:
-				tmp |= LDDFR_PKF_ARGB32;
+			default:
+				tmp = LDDFR_PKF_ARGB32;
 				break;
 			}
 		}
+
 		lcdc_write_chan(ch, LDDFR, tmp);
+		lcdc_write_chan(ch, LDMLSR, ch->pitch);
+		lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
+		if (ch->info->var.nonstd)
+			lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
 
-		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;
+		/* When using deferred I/O mode, configure the LCDC for one-shot
+		 * operation and enable the frame end interrupt. Otherwise use
+		 * continuous read mode.
+		 */
+		if (ch->ldmt1r_value & LDMT1R_IFM &&
+		    ch->cfg.sys_bus_cfg.deferred_io_msec) {
+			lcdc_write_chan(ch, LDSM1R, LDSM1R_OS);
+			lcdc_write(priv, _LDINTR, LDINTR_FE);
+		} else {
+			lcdc_write_chan(ch, LDSM1R, 0);
+		}
+	}
 
-		/* test if we can enable meram */
-		if (ch->cfg.meram_cfg && priv->meram_dev &&
-				priv->meram_dev->ops) {
-			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;
+	/* Word and long word swap. */
+	if  (priv->ch[0].info->var.nonstd)
+		tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
+	else {
+		switch (bpp) {
+		case 16:
+			tmp = LDDDSR_LS | LDDDSR_WS;
+			break;
+		case 24:
+			tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
+			break;
+		case 32:
+		default:
+			tmp = LDDDSR_LS;
+			break;
+		}
+	}
+	lcdc_write(priv, _LDDDSR, tmp);
 
-			cfg = ch->cfg.meram_cfg;
-			mdev = priv->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);
+	/* Enable the display output. */
+	lcdc_write(priv, _LDCNT1R, LDCNT1R_DE);
+	sh_mobile_lcdc_start_stop(priv, 1);
+	priv->started = 1;
+}
 
-			ch->meram_enabled = 0;
+static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+{
+	struct sh_mobile_meram_info *mdev = priv->meram_dev;
+	struct sh_mobile_lcdc_board_cfg	*board_cfg;
+	struct sh_mobile_lcdc_chan *ch;
+	unsigned long tmp;
+	int ret;
+	int k;
 
-			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;
-			}
+	/* enable clocks before accessing the hardware */
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+		if (priv->ch[k].enabled)
+			sh_mobile_lcdc_clk_on(priv);
+	}
 
-			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;
-			}
-		}
+	/* reset */
+	lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR);
+	lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0);
 
-		/* point out our frame buffer */
-		lcdc_write_chan(ch, LDSA1R, base_addr_y);
-		if (ch->info->var.nonstd)
-			lcdc_write_chan(ch, LDSA2R, base_addr_c);
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+		ch = &priv->ch[k];
 
-		/* set line size */
-		lcdc_write_chan(ch, LDMLSR, pitch);
+		if (!ch->enabled)
+			continue;
 
-		/* setup deferred io if SYS bus */
-		tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
-		if (ch->ldmt1r_value & LDMT1R_IFM && tmp) {
-			ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
-			ch->defio.delay = msecs_to_jiffies(tmp);
-			ch->info->fbdefio = &ch->defio;
-			fb_deferred_io_init(ch->info);
+		board_cfg = &ch->cfg.board_cfg;
+		if (board_cfg->setup_sys) {
+			ret = board_cfg->setup_sys(board_cfg->board_data, ch,
+						   &sh_mobile_lcdc_sys_bus_ops);
+			if (ret)
+				return ret;
+		}
+	}
 
-			/* one-shot mode */
-			lcdc_write_chan(ch, LDSM1R, LDSM1R_OS);
+	/* Compute frame buffer base address and pitch for each channel. */
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+		struct sh_mobile_meram_cfg *cfg;
+		int pixelformat;
 
-			/* enable "Frame End Interrupt Enable" bit */
-			lcdc_write(priv, _LDINTR, LDINTR_FE);
+		ch = &priv->ch[k];
+		if (!ch->enabled)
+			continue;
 
-		} else {
-			/* continuous read mode */
-			lcdc_write_chan(ch, LDSM1R, 0);
+		ch->base_addr_y = ch->info->fix.smem_start;
+		ch->base_addr_c = ch->base_addr_y
+				+ ch->info->var.xres
+				* ch->info->var.yres_virtual;
+		ch->pitch = ch->info->fix.line_length;
+
+		/* Enable MERAM if possible. */
+		cfg = ch->cfg.meram_cfg;
+		if (mdev = NULL || mdev->ops = NULL || cfg = NULL)
+			continue;
+
+		/* we need to de-init configured ICBs before we can
+		 * re-initialize them.
+		 */
+		if (ch->meram_enabled) {
+			mdev->ops->meram_unregister(mdev, cfg);
+			ch->meram_enabled = 0;
 		}
-	}
 
-	/* display output */
-	lcdc_write(priv, _LDCNT1R, LDCNT1R_DE);
+		if (!ch->info->var.nonstd)
+			pixelformat = SH_MOBILE_MERAM_PF_RGB;
+		else if (ch->info->var.bits_per_pixel = 24)
+			pixelformat = SH_MOBILE_MERAM_PF_NV24;
+		else
+			pixelformat = SH_MOBILE_MERAM_PF_NV;
+
+		ret = mdev->ops->meram_register(mdev, cfg, ch->pitch,
+					ch->info->var.yres, pixelformat,
+					ch->base_addr_y, ch->base_addr_c,
+					&ch->base_addr_y, &ch->base_addr_c,
+					&ch->pitch);
+		if (!ret)
+			ch->meram_enabled = 1;
+	}
 
-	/* start the lcdc */
-	sh_mobile_lcdc_start_stop(priv, 1);
-	priv->started = 1;
+	/* Start the LCDC. */
+	__sh_mobile_lcdc_start(priv);
 
-	/* tell the board code to enable the panel */
+	/* Setup deferred I/O, tell the board code to enable the panels, and
+	 * turn backlight on.
+	 */
 	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
 		ch = &priv->ch[k];
 		if (!ch->enabled)
 			continue;
 
+		tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
+		if (ch->ldmt1r_value & LDMT1R_IFM && tmp) {
+			ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
+			ch->defio.delay = msecs_to_jiffies(tmp);
+			ch->info->fbdefio = &ch->defio;
+			fb_deferred_io_init(ch->info);
+		}
+
 		board_cfg = &ch->cfg.board_cfg;
 		if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
 			board_cfg->display_on(board_cfg->board_data, ch->info);
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index aeed668..a06219b 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -18,6 +18,13 @@ struct sh_mobile_lcdc_priv;
 struct fb_info;
 struct backlight_device;
 
+/*
+ * struct sh_mobile_lcdc_chan - LCDC display channel
+ *
+ * @base_addr_y: Frame buffer viewport base address (luma component)
+ * @base_addr_c: Frame buffer viewport base address (chroma component)
+ * @pitch: Frame buffer line pitch
+ */
 struct sh_mobile_lcdc_chan {
 	struct sh_mobile_lcdc_priv *lcdc;
 	unsigned long *reg_offs;
@@ -40,6 +47,10 @@ struct sh_mobile_lcdc_chan {
 	int blank_status;
 	struct mutex open_lock;		/* protects the use counter */
 	int meram_enabled;
+
+	unsigned long base_addr_y;
+	unsigned long base_addr_c;
+	unsigned int pitch;
 };
 
 #endif
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v2 5/6] fbdev: sh_mobile_lcdc: Store the frame buffer base address when panning
From: Laurent Pinchart @ 2011-07-20 11:24 UTC (permalink / raw)
  To: linux-fbdev

When the frame buffer base address is changed by a panning operation,
store it in the channel structure. It will be reused when runtime PM
code will use __sh_mobile_lcdc_start().

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/sh_mobile_lcdcfb.c |   22 +++++++++-------------
 1 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 785521e..f0a3d54 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -915,32 +915,28 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
 			base_addr_c += 2 * var->xoffset;
 		else
 			base_addr_c += var->xoffset;
-	} else
-		base_addr_c = 0;
+	}
 
-	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 {
+	if (ch->meram_enabled) {
 		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 = priv->meram_dev;
 		ret = mdev->ops->meram_update(mdev, cfg,
 					base_addr_y, base_addr_c,
-					&icb_addr_y, &icb_addr_c);
+					&base_addr_y, &base_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);
+	ch->base_addr_y = base_addr_y;
+	ch->base_addr_c = base_addr_c;
 
-	}
+	lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
+	if (var->nonstd)
+		lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
 
 	if (lcdc_chan_is_sublcd(ch))
 		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v2 6/6] fbdev: sh_mobile_lcdc: Restart LCDC in runtime PM resume handler
From: Laurent Pinchart @ 2011-07-20 11:24 UTC (permalink / raw)
  To: linux-fbdev

Instead of restoring registers blindly, restart the LCDC by going
through the startup sequence when resuming from runtime PM suspend. All
registers are now correctly initialized in the right order.

As a side effect, this also gets rid fo a possible panning restore issue
caused by always saving the frame buffer base address registers from set
A instead of the currently active set.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/sh_mobile_lcdcfb.c |   49 ++++----------------------------------
 drivers/video/sh_mobile_lcdcfb.h |    1 -
 2 files changed, 5 insertions(+), 45 deletions(-)

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index f0a3d54..d0f768e 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -32,17 +32,6 @@
 #define SIDE_B_OFFSET 0x1000
 #define MIRROR_OFFSET 0x2000
 
-/* shared registers and their order for context save/restore */
-static int lcdc_shared_regs[] = {
-	_LDDCKR,
-	_LDDCKSTPR,
-	_LDINTR,
-	_LDDDSR,
-	_LDCNT1R,
-	_LDCNT2R,
-};
-#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
-
 #define MAX_XRES 1920
 #define MAX_YRES 1080
 
@@ -111,7 +100,6 @@ struct sh_mobile_lcdc_priv {
 	unsigned long lddckr;
 	struct sh_mobile_lcdc_chan ch[2];
 	struct notifier_block notifier;
-	unsigned long saved_shared_regs[NR_SHARED_REGS];
 	int started;
 	int forced_bpp; /* 2 channel LCDC must share bpp setting */
 	struct sh_mobile_meram_info *meram_dev;
@@ -1289,47 +1277,20 @@ static int sh_mobile_lcdc_resume(struct device *dev)
 static int sh_mobile_lcdc_runtime_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev);
-	struct sh_mobile_lcdc_chan *ch;
-	int k, n;
-
-	/* save per-channel registers */
-	for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
-		ch = &p->ch[k];
-		if (!ch->enabled)
-			continue;
-		for (n = 0; n < NR_CH_REGS; n++)
-			ch->saved_ch_regs[n] = lcdc_read_chan(ch, n);
-	}
-
-	/* save shared registers */
-	for (n = 0; n < NR_SHARED_REGS; n++)
-		p->saved_shared_regs[n] = lcdc_read(p, lcdc_shared_regs[n]);
+	struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
 
 	/* turn off LCDC hardware */
-	lcdc_write(p, _LDCNT1R, 0);
+	lcdc_write(priv, _LDCNT1R, 0);
+
 	return 0;
 }
 
 static int sh_mobile_lcdc_runtime_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev);
-	struct sh_mobile_lcdc_chan *ch;
-	int k, n;
-
-	/* restore per-channel registers */
-	for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
-		ch = &p->ch[k];
-		if (!ch->enabled)
-			continue;
-		for (n = 0; n < NR_CH_REGS; n++)
-			lcdc_write_chan(ch, n, ch->saved_ch_regs[n]);
-	}
+	struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
 
-	/* restore shared registers */
-	for (n = 0; n < NR_SHARED_REGS; n++)
-		lcdc_write(p, lcdc_shared_regs[n], p->saved_shared_regs[n]);
+	__sh_mobile_lcdc_start(priv);
 
 	return 0;
 }
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index a06219b..a58a0f3 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -32,7 +32,6 @@ struct sh_mobile_lcdc_chan {
 	unsigned long enabled; /* ME and SE in LDCNT2R */
 	struct sh_mobile_lcdc_chan_cfg cfg;
 	u32 pseudo_palette[PALETTE_NR];
-	unsigned long saved_ch_regs[NR_CH_REGS];
 	struct fb_info *info;
 	struct backlight_device *bl;
 	dma_addr_t dma_handle;
-- 
1.7.3.4


^ permalink raw reply related

* [GIT PULL] viafb updates for 3.1
From: Florian Tobias Schandinat @ 2011-07-20 15:22 UTC (permalink / raw)
  To: linux-fbdev

Hi Paul,

please pull the viafb updates below. It contains only 2 fixes.


Thanks,

Florian Tobias Schandinat


The following changes since commit 8aa4d96fe3e4cda9a6469b22b3f017ed30996b10:
   Daniel Drake (1):
         viafb: Automatic OLPC XO-1.5 configuration

are available in the git repository at:

   git://github.com/schandinat/linux-2.6.git viafb-next

Florian Tobias Schandinat (2):
       viafb: use display information in info not in var for panning
       viafb: improve pitch handling

  drivers/video/via/via_modesetting.h |    5 +++++
  drivers/video/via/viafbdev.c        |   16 +++++++++++-----
  2 files changed, 16 insertions(+), 5 deletions(-)

^ permalink raw reply

* Re: [PATCH] fb: avoid possible deadlock caused by fb_set_suspend
From: Florian Tobias Schandinat @ 2011-07-20 18:16 UTC (permalink / raw)
  To: lethal
  Cc: linux-fbdev, francis.moro, torvalds, bonbons, linux-kernel,
	Herton Ronaldo Krzesinski, stable
In-Reply-To: <1308337359-3480-1-git-send-email-FlorianSchandinat@gmx.de>

Hi Paul,

what are your plans for the patch below? Do you queue it for 3.1?
The only feedback so far was that one driver (sh_mobile_hdmi) would require more 
work with a patch for that proposed. Without any objections to the patch I think 
we should take it as fixing the subsystem is more important than causing 
potential issues with a single driver.


Thanks,

Florian Tobias Schandinat

On 06/17/2011 07:02 PM, Florian Tobias Schandinat wrote:
> From: Herton Ronaldo Krzesinski<herton@mandriva.com.br>
>
> A lock ordering issue can cause deadlocks: in framebuffer/console code,
> all needed struct fb_info locks are taken before acquire_console_sem(),
> in places which need to take console semaphore.
>
> But fb_set_suspend is always called with console semaphore held, and
> inside it we call lock_fb_info which gets the fb_info lock, inverse
> locking order of what the rest of the code does. This causes a real
> deadlock issue, when we write to state fb sysfs attribute (which calls
> fb_set_suspend) while a framebuffer is being unregistered by
> remove_conflicting_framebuffers, as can be shown by following show
> blocked state trace on a test program which loads i915 and runs another
> forked processes writing to state attribute:
>
> Test process with semaphore held and trying to get fb_info lock:
> ..
> fb-test2      D 0000000000000000     0   237    228 0x00000000
>   ffff8800774f3d68 0000000000000082 00000000000135c0 00000000000135c0
>   ffff880000000000 ffff8800774f3fd8 ffff8800774f3fd8 ffff880076ee4530
>   00000000000135c0 ffff8800774f3fd8 ffff8800774f2000 00000000000135c0
> Call Trace:
>   [<ffffffff8141287a>] __mutex_lock_slowpath+0x11a/0x1e0
>   [<ffffffff814142f2>] ? _raw_spin_lock_irq+0x22/0x40
>   [<ffffffff814123d3>] mutex_lock+0x23/0x50
>   [<ffffffff8125dfc5>] lock_fb_info+0x25/0x60
>   [<ffffffff8125e3f0>] fb_set_suspend+0x20/0x80
>   [<ffffffff81263e2f>] store_fbstate+0x4f/0x70
>   [<ffffffff812e7f70>] dev_attr_store+0x20/0x30
>   [<ffffffff811c46b4>] sysfs_write_file+0xd4/0x160
>   [<ffffffff81155a26>] vfs_write+0xc6/0x190
>   [<ffffffff81155d51>] sys_write+0x51/0x90
>   [<ffffffff8100c012>] system_call_fastpath+0x16/0x1b
> ..
> modprobe process stalled because has the fb_info lock (got inside
> unregister_framebuffer) but waiting for the semaphore held by the
> test process which is waiting to get the fb_info lock:
> ..
> modprobe      D 0000000000000000     0   230    218 0x00000000
>   ffff880077a4d618 0000000000000082 0000000000000001 0000000000000001
>   ffff880000000000 ffff880077a4dfd8 ffff880077a4dfd8 ffff8800775a2e20
>   00000000000135c0 ffff880077a4dfd8 ffff880077a4c000 00000000000135c0
> Call Trace:
>   [<ffffffff81411fe5>] schedule_timeout+0x215/0x310
>   [<ffffffff81058051>] ? get_parent_ip+0x11/0x50
>   [<ffffffff814130dd>] __down+0x6d/0xb0
>   [<ffffffff81089f71>] down+0x41/0x50
>   [<ffffffff810629ac>] acquire_console_sem+0x2c/0x50
>   [<ffffffff812ca53d>] unbind_con_driver+0xad/0x2d0
>   [<ffffffff8126f5f7>] fbcon_event_notify+0x457/0x890
>   [<ffffffff814144ff>] ? _raw_spin_unlock_irqrestore+0x1f/0x50
>   [<ffffffff81058051>] ? get_parent_ip+0x11/0x50
>   [<ffffffff8141836d>] notifier_call_chain+0x4d/0x70
>   [<ffffffff8108a3b8>] __blocking_notifier_call_chain+0x58/0x80
>   [<ffffffff8108a3f6>] blocking_notifier_call_chain+0x16/0x20
>   [<ffffffff8125dabb>] fb_notifier_call_chain+0x1b/0x20
>   [<ffffffff8125e6ac>] unregister_framebuffer+0x7c/0x130
>   [<ffffffff8125e8b3>] remove_conflicting_framebuffers+0x153/0x180
>   [<ffffffff8125eef3>] register_framebuffer+0x93/0x2c0
>   [<ffffffffa0331112>] drm_fb_helper_single_fb_probe+0x252/0x2f0 [drm_kms_helper]
>   [<ffffffffa03314a3>] drm_fb_helper_initial_config+0x2f3/0x6d0 [drm_kms_helper]
>   [<ffffffffa03318dd>] ? drm_fb_helper_single_add_all_connectors+0x5d/0x1c0 [drm_kms_helper]
>   [<ffffffffa037b588>] intel_fbdev_init+0xa8/0x160 [i915]
>   [<ffffffffa0343d74>] i915_driver_load+0x854/0x12b0 [i915]
>   [<ffffffffa02f0e7e>] drm_get_pci_dev+0x19e/0x360 [drm]
>   [<ffffffff8141821d>] ? sub_preempt_count+0x9d/0xd0
>   [<ffffffffa0386f91>] i915_pci_probe+0x15/0x17 [i915]
>   [<ffffffff8124481f>] local_pci_probe+0x5f/0xd0
>   [<ffffffff81244f89>] pci_device_probe+0x119/0x120
>   [<ffffffff812eccaa>] ? driver_sysfs_add+0x7a/0xb0
>   [<ffffffff812ed003>] driver_probe_device+0xa3/0x290
>   [<ffffffff812ed1f0>] ? __driver_attach+0x0/0xb0
>   [<ffffffff812ed29b>] __driver_attach+0xab/0xb0
>   [<ffffffff812ed1f0>] ? __driver_attach+0x0/0xb0
>   [<ffffffff812ebd3e>] bus_for_each_dev+0x5e/0x90
>   [<ffffffff812ecc2e>] driver_attach+0x1e/0x20
>   [<ffffffff812ec6f2>] bus_add_driver+0xe2/0x320
>   [<ffffffffa03aa000>] ? i915_init+0x0/0x96 [i915]
>   [<ffffffff812ed536>] driver_register+0x76/0x140
>   [<ffffffffa03aa000>] ? i915_init+0x0/0x96 [i915]
>   [<ffffffff81245216>] __pci_register_driver+0x56/0xd0
>   [<ffffffffa02f1264>] drm_pci_init+0xe4/0xf0 [drm]
>   [<ffffffffa03aa000>] ? i915_init+0x0/0x96 [i915]
>   [<ffffffffa02e84a8>] drm_init+0x58/0x70 [drm]
>   [<ffffffffa03aa094>] i915_init+0x94/0x96 [i915]
>   [<ffffffff81002194>] do_one_initcall+0x44/0x190
>   [<ffffffff810a066b>] sys_init_module+0xcb/0x210
>   [<ffffffff8100c012>] system_call_fastpath+0x16/0x1b
> ..
>
> fb-test2 which reproduces above is available on kernel.org bug #26232.
> To solve this issue, avoid calling lock_fb_info inside fb_set_suspend,
> and move it out to where needed (callers of fb_set_suspend must call
> lock_fb_info before if needed). So far, the only place which needs to
> call lock_fb_info is store_fbstate, all other places which calls
> fb_set_suspend are suspend/resume hooks that should not need the lock as
> they should be run only when processes are already frozen in
> suspend/resume.
>
> References: https://bugzilla.kernel.org/show_bug.cgi?id&232
> Signed-off-by: Herton Ronaldo Krzesinski<herton@mandriva.com.br>
> Signed-off-by: Florian Tobias Schandinat<FlorianSchandinat@gmx.de>
> Cc: stable@kernel.org
> ---
>   drivers/video/fbmem.c   |    3 ---
>   drivers/video/fbsysfs.c |    3 +++
>   2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
> index 5aac00e..ad93629 100644
> --- a/drivers/video/fbmem.c
> +++ b/drivers/video/fbmem.c
> @@ -1738,8 +1738,6 @@ void fb_set_suspend(struct fb_info *info, int state)
>   {
>   	struct fb_event event;
>
> -	if (!lock_fb_info(info))
> -		return;
>   	event.info = info;
>   	if (state) {
>   		fb_notifier_call_chain(FB_EVENT_SUSPEND,&event);
> @@ -1748,7 +1746,6 @@ void fb_set_suspend(struct fb_info *info, int state)
>   		info->state = FBINFO_STATE_RUNNING;
>   		fb_notifier_call_chain(FB_EVENT_RESUME,&event);
>   	}
> -	unlock_fb_info(info);
>   }
>
>   /**
> diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
> index 04251ce..67afa9c 100644
> --- a/drivers/video/fbsysfs.c
> +++ b/drivers/video/fbsysfs.c
> @@ -399,9 +399,12 @@ static ssize_t store_fbstate(struct device *device,
>
>   	state = simple_strtoul(buf,&last, 0);
>
> +	if (!lock_fb_info(fb_info))
> +		return -ENODEV;
>   	console_lock();
>   	fb_set_suspend(fb_info, (int)state);
>   	console_unlock();
> +	unlock_fb_info(fb_info);
>
>   	return count;
>   }


^ permalink raw reply

* [PATCH V8 0/5] ARM: EXYNOS4: Add support EXYNOS4 FIMD
From: Jingoo Han @ 2011-07-20 22:53 UTC (permalink / raw)
  To: Kukjin Kim, Paul Mundt, linux-samsung-soc, linux-fbdev
  Cc: Jonghun Han, Ben Dooks, Jingoo Han

The patches are created against "for-next" branch of Kukjin Kim's tree at:
git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git

This was originally submitted by Jonghun Han <jonghun.han@samsung.com>
http://www.spinics.net/lists/arm-kernel/msg101781.html

This patch adds support FIMD(Fully Interactive Mobile Display) on Exynos4.
The 4th patch is update for s3c-fb and others are for platform data

NOTE: The common part for SMDKV310 will be updated later.

v2: change clock name of exynos4 FIMD: "fimd" -> "lcd"
     use 'has_clksel' variable in order to distinguish FIMD version
     add 'lcd_clk' that can be used for only lcd pixel clock
     add callback 'enable_clk()' to enable parent clock 'sclk_fimd'.
v3: remove the callback from the platform data structure
v4: move clk_enable(sfb->lcd_clk) under the if statement
v5: add clk_enable/disable(sfb->lcd_clk) to s3c_fb_runtime_suspend/resume().
v6: rename dev-fimd-24bpp.c to dev-fimd0.c
     add 'exynos4_fimd0_setup_clock()' to dev-fimd0.c to setup parent clock.
v7: remove parent clock setting from machine directory
     use ¡®gpio_request_one()¡¯ to simply the gpio setting step
v8: updated minor fixes

o To Kukjin Kim
[PATCH V8 1/5] ARM: EXYNOS4: Change clock name for FIMD
[PATCH V8 2/5] ARM: EXYNOS4: Add resource definition for FIMD
[PATCH V8 3/5] ARM: EXYNOS4: Add platform device and helper functions for FIMD
[PATCH V8 5/5] ARM: EXYNOS4: Add platform data for EXYNOS4 FIMD and LTE480WV  platform-lcd on SMDKC210

o To Paul Mundt
[PATCH V8 4/5] video: s3c-fb: Add support EXYNOS4



^ permalink raw reply

* [PATCH V8 1/5] ARM: EXYNOS4: Change clock name for FIMD
From: Jingoo Han @ 2011-07-20 22:54 UTC (permalink / raw)
  To: Kukjin Kim, Paul Mundt, linux-samsung-soc, linux-fbdev
  Cc: Jonghun Han, Ben Dooks, Jingoo Han

This patch changes clock for FIMD from 'fimd' to 'lcd'.
Also, devname for FIMD is changed from 's5pv310-fb' to 'exynos4-fb'.

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
 arch/arm/mach-exynos4/clock.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
index 98b5cc4..778a202 100644
--- a/arch/arm/mach-exynos4/clock.c
+++ b/arch/arm/mach-exynos4/clock.c
@@ -405,13 +405,13 @@ static struct clk init_clocks_off[] = {
 		.enable		= exynos4_clk_ip_cam_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
-		.name		= "fimd",
-		.devname	= "s5pv310-fb.0",
+		.name		= "lcd",
+		.devname	= "exynos4-fb.0",
 		.enable		= exynos4_clk_ip_lcd0_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
-		.name		= "fimd",
-		.devname	= "s5pv310-fb.1",
+		.name		= "lcd",
+		.devname	= "exynos4-fb.1",
 		.enable		= exynos4_clk_ip_lcd1_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
@@ -909,7 +909,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_fimd",
-			.devname	= "s5pv310-fb.0",
+			.devname	= "exynos4-fb.0",
 			.enable		= exynos4_clksrc_mask_lcd0_ctrl,
 			.ctrlbit	= (1 << 0),
 		},
@@ -919,7 +919,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_fimd",
-			.devname	= "s5pv310-fb.1",
+			.devname	= "exynos4-fb.1",
 			.enable		= exynos4_clksrc_mask_lcd1_ctrl,
 			.ctrlbit	= (1 << 0),
 		},
-- 
1.7.1


^ permalink raw reply related

* [PATCH V8 2/5] ARM: EXYNOS4: Add resource definition for FIMD
From: Jingoo Han @ 2011-07-20 22:54 UTC (permalink / raw)
  To: Kukjin Kim, Paul Mundt, linux-samsung-soc, linux-fbdev
  Cc: Jonghun Han, Ben Dooks, Jingoo Han

From: Jonghun Han <jonghun.han@samsung.com>

This patch adds resource definitions for EXYNOS4 FIMD.
IRQ and SFR definitions are added.

Signed-off-by: Jonghun Han <jonghun.han@samsung.com>
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
 arch/arm/mach-exynos4/include/mach/irqs.h |    4 ++++
 arch/arm/mach-exynos4/include/mach/map.h  |    3 +++
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index 250427f..0d315a9 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -137,6 +137,10 @@
 #define IRQ_SYSMMU_MFC_M1_0	COMBINER_IRQ(5, 6)
 #define IRQ_SYSMMU_PCIE_0	COMBINER_IRQ(5, 7)
 
+#define IRQ_FIMD0_FIFO		COMBINER_IRQ(11, 0)
+#define IRQ_FIMD0_VSYNC		COMBINER_IRQ(11, 1)
+#define IRQ_FIMD0_SYSTEM	COMBINER_IRQ(11, 2)
+
 #define MAX_COMBINER_NR		16
 
 #define S5P_IRQ_EINT_BASE	COMBINER_IRQ(MAX_COMBINER_NR, 0)
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
index 3677356..2a5a6f6 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -95,6 +95,8 @@
 #define EXYNOS4_PA_MIPI_CSIS0		0x11880000
 #define EXYNOS4_PA_MIPI_CSIS1		0x11890000
 
+#define EXYNOS4_PA_FIMD0		0x11C00000
+
 #define EXYNOS4_PA_HSMMC(x)		(0x12510000 + ((x) * 0x10000))
 
 #define EXYNOS4_PA_SATA			0x12560000
@@ -142,6 +144,7 @@
 #define S5P_PA_FIMC3			EXYNOS4_PA_FIMC3
 #define S5P_PA_MIPI_CSIS0		EXYNOS4_PA_MIPI_CSIS0
 #define S5P_PA_MIPI_CSIS1		EXYNOS4_PA_MIPI_CSIS1
+#define S5P_PA_FIMD0			EXYNOS4_PA_FIMD0
 #define S5P_PA_ONENAND			EXYNOS4_PA_ONENAND
 #define S5P_PA_ONENAND_DMA		EXYNOS4_PA_ONENAND_DMA
 #define S5P_PA_SDRAM			EXYNOS4_PA_SDRAM
-- 
1.7.1


^ permalink raw reply related

* [PATCH V8 3/5] ARM: EXYNOS4: Add platform device and helper functions for FIMD
From: Jingoo Han @ 2011-07-20 22:54 UTC (permalink / raw)
  To: Kukjin Kim, Paul Mundt, linux-samsung-soc, linux-fbdev
  Cc: Jonghun Han, Ben Dooks, Jingoo Han

From: Jonghun Han <jonghun.han@samsung.com>

This patch adds platform device s5p_device_fimd0 for EXYNOS4 FIMD0.
EXYNOS4 has two FIMDs(FIMD0, FIMD1). FIMD1 will be added later.
Some definitions used to enable EXYNOS4 FIMD0 are added.

Signed-off-by: Jonghun Han <jonghun.han@samsung.com>
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
 arch/arm/mach-exynos4/Kconfig                |    9 ++++
 arch/arm/mach-exynos4/Makefile               |    1 +
 arch/arm/mach-exynos4/cpu.c                  |    3 +
 arch/arm/mach-exynos4/setup-fimd0.c          |   43 ++++++++++++++++
 arch/arm/plat-s5p/Kconfig                    |    5 ++
 arch/arm/plat-s5p/Makefile                   |    1 +
 arch/arm/plat-s5p/dev-fimd0.c                |   67 ++++++++++++++++++++++++++
 arch/arm/plat-samsung/include/plat/devs.h    |    1 +
 arch/arm/plat-samsung/include/plat/fb-core.h |   15 ++++++
 arch/arm/plat-samsung/include/plat/fb.h      |   15 ++++++
 10 files changed, 160 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-exynos4/setup-fimd0.c
 create mode 100644 arch/arm/plat-s5p/dev-fimd0.c

diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index a4fb109..83518b5 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -26,6 +26,11 @@ config EXYNOS4_DEV_AHCI
 	help
 	  Compile in platform device definitions for AHCI
 
+config EXYNOS4_SETUP_FIMD0
+	bool
+	help
+	  Common setup code for FIMD0.
+
 config EXYNOS4_DEV_PD
 	bool
 	help
@@ -104,6 +109,7 @@ menu "EXYNOS4 Machines"
 config MACH_SMDKC210
 	bool "SMDKC210"
 	select CPU_EXYNOS4210
+	select S5P_DEV_FIMD0
 	select S3C_DEV_RTC
 	select S3C_DEV_WDT
 	select S3C_DEV_I2C1
@@ -113,6 +119,7 @@ config MACH_SMDKC210
 	select S3C_DEV_HSMMC3
 	select EXYNOS4_DEV_PD
 	select EXYNOS4_DEV_SYSMMU
+	select EXYNOS4_SETUP_FIMD0
 	select EXYNOS4_SETUP_I2C1
 	select EXYNOS4_SETUP_SDHCI
 	help
@@ -121,6 +128,7 @@ config MACH_SMDKC210
 config MACH_SMDKV310
 	bool "SMDKV310"
 	select CPU_EXYNOS4210
+	select S5P_DEV_FIMD0
 	select S3C_DEV_RTC
 	select S3C_DEV_WDT
 	select S3C_DEV_I2C1
@@ -132,6 +140,7 @@ config MACH_SMDKV310
 	select SAMSUNG_DEV_KEYPAD
 	select EXYNOS4_DEV_PD
 	select EXYNOS4_DEV_SYSMMU
+	select EXYNOS4_SETUP_FIMD0
 	select EXYNOS4_SETUP_I2C1
 	select EXYNOS4_SETUP_KEYPAD
 	select EXYNOS4_SETUP_SDHCI
diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
index c3c70ab..b1077f4 100644
--- a/arch/arm/mach-exynos4/Makefile
+++ b/arch/arm/mach-exynos4/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_EXYNOS4_DEV_PD)		+= dev-pd.o
 obj-$(CONFIG_EXYNOS4_DEV_SYSMMU)	+= dev-sysmmu.o
 
 obj-$(CONFIG_EXYNOS4_SETUP_FIMC)	+= setup-fimc.o
+obj-$(CONFIG_EXYNOS4_SETUP_FIMD0)	+= setup-fimd0.o
 obj-$(CONFIG_EXYNOS4_SETUP_I2C1)	+= setup-i2c1.o
 obj-$(CONFIG_EXYNOS4_SETUP_I2C2)	+= setup-i2c2.o
 obj-$(CONFIG_EXYNOS4_SETUP_I2C3)	+= setup-i2c3.o
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 910ade6..85a0b96 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -23,6 +23,7 @@
 #include <plat/exynos4.h>
 #include <plat/sdhci.h>
 #include <plat/devs.h>
+#include <plat/fb-core.h>
 #include <plat/fimc-core.h>
 #include <plat/iic-core.h>
 
@@ -149,6 +150,8 @@ void __init exynos4_map_io(void)
 	s3c_i2c0_setname("s3c2440-i2c");
 	s3c_i2c1_setname("s3c2440-i2c");
 	s3c_i2c2_setname("s3c2440-i2c");
+
+	s5p_fb_setname(0, "exynos4-fb");
 }
 
 void __init exynos4_init_clocks(int xtal)
diff --git a/arch/arm/mach-exynos4/setup-fimd0.c b/arch/arm/mach-exynos4/setup-fimd0.c
new file mode 100644
index 0000000..ca7ae71
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-fimd0.c
@@ -0,0 +1,43 @@
+/* linux/arch/arm/mach-exynos4/setup-fimd0.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Base Exynos4 FIMD 0 configuration
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/fb.h>
+#include <linux/gpio.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/regs-fb-v4.h>
+
+#include <mach/map.h>
+
+void exynos4_fimd0_gpio_setup_24bpp(void)
+{
+	unsigned int reg;
+
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF0(0), 8, S3C_GPIO_SFN(2));
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF1(0), 8, S3C_GPIO_SFN(2));
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF2(0), 8, S3C_GPIO_SFN(2));
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF3(0), 4, S3C_GPIO_SFN(2));
+
+	/*
+	 * Set DISPLAY_CONTROL register for Display path selection.
+	 *
+	 * DISPLAY_CONTROL[1:0]
+	 * ---------------------
+	 *  00 | MIE
+	 *  01 | MDINE
+	 *  10 | FIMD : selected
+	 *  11 | FIMD
+	 */
+	reg = __raw_readl(S3C_VA_SYS + 0x0210);
+	reg |= (1 << 1);
+	__raw_writel(reg, S3C_VA_SYS + 0x0210);
+}
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index 7f9ff2a..7537ad5 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -71,6 +71,11 @@ config S5P_DEV_FIMC3
 	help
 	  Compile in platform device definitions for FIMC controller 3
 
+config S5P_DEV_FIMD0
+	bool
+	help
+	  Compile in platform device definitions for FIMD controller 0
+
 config S5P_DEV_ONENAND
 	bool
 	help
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index e234cc4..eec7e24 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_S5P_DEV_FIMC0)	+= dev-fimc0.o
 obj-$(CONFIG_S5P_DEV_FIMC1)	+= dev-fimc1.o
 obj-$(CONFIG_S5P_DEV_FIMC2)	+= dev-fimc2.o
 obj-$(CONFIG_S5P_DEV_FIMC3)	+= dev-fimc3.o
+obj-$(CONFIG_S5P_DEV_FIMD0)	+= dev-fimd0.o
 obj-$(CONFIG_S5P_DEV_ONENAND)	+= dev-onenand.o
 obj-$(CONFIG_S5P_DEV_CSIS0)	+= dev-csis0.o
 obj-$(CONFIG_S5P_DEV_CSIS1)	+= dev-csis1.o
diff --git a/arch/arm/plat-s5p/dev-fimd0.c b/arch/arm/plat-s5p/dev-fimd0.c
new file mode 100644
index 0000000..f728bb5
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-fimd0.c
@@ -0,0 +1,67 @@
+/* linux/arch/arm/plat-s5p/dev-fimd0.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Core file for Samsung Display Controller (FIMD) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/gfp.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/fb.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+static struct resource s5p_fimd0_resource[] = {
+	[0] = {
+		.start	= S5P_PA_FIMD0,
+		.end	= S5P_PA_FIMD0 + SZ_32K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_FIMD0_VSYNC,
+		.end	= IRQ_FIMD0_VSYNC,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= IRQ_FIMD0_FIFO,
+		.end	= IRQ_FIMD0_FIFO,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= IRQ_FIMD0_SYSTEM,
+		.end	= IRQ_FIMD0_SYSTEM,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 fimd0_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s5p_device_fimd0 = {
+	.name		= "s5p-fb",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5p_fimd0_resource),
+	.resource	= s5p_fimd0_resource,
+	.dev		= {
+		.dma_mask		= &fimd0_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd)
+{
+	s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
+			&s5p_device_fimd0);
+}
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index e3b31c2..81143b7 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -49,6 +49,7 @@ extern struct platform_device s3c64xx_device_ac97;
 extern struct platform_device s3c_device_ts;
 
 extern struct platform_device s3c_device_fb;
+extern struct platform_device s5p_device_fimd0;
 extern struct platform_device s3c_device_ohci;
 extern struct platform_device s3c_device_lcd;
 extern struct platform_device s3c_device_wdt;
diff --git a/arch/arm/plat-samsung/include/plat/fb-core.h b/arch/arm/plat-samsung/include/plat/fb-core.h
index bca383e..6abcbf1 100644
--- a/arch/arm/plat-samsung/include/plat/fb-core.h
+++ b/arch/arm/plat-samsung/include/plat/fb-core.h
@@ -26,4 +26,19 @@ static inline void s3c_fb_setname(char *name)
 #endif
 }
 
+/* Re-define device name depending on support. */
+static inline void s5p_fb_setname(int id, char *name)
+{
+	switch (id) {
+#ifdef CONFIG_S5P_DEV_FIMD0
+	case 0:
+		s5p_device_fimd0.name = name;
+	break;
+#endif
+	default:
+		printk(KERN_ERR "%s: invalid device id(%d)\n", __func__, id);
+	break;
+	}
+}
+
 #endif /* __ASM_PLAT_FB_CORE_H */
diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h
index cb3ca3a..01f10e4 100644
--- a/arch/arm/plat-samsung/include/plat/fb.h
+++ b/arch/arm/plat-samsung/include/plat/fb.h
@@ -74,6 +74,14 @@ struct s3c_fb_platdata {
 extern void s3c_fb_set_platdata(struct s3c_fb_platdata *pd);
 
 /**
+ * s5p_fimd0_set_platdata() - Setup the FB device with platform data.
+ * @pd: The platform data to set. The data is copied from the passed structure
+ *      so the machine data can mark the data __initdata so that any unused
+ *      machines will end up dumping their data at runtime.
+ */
+extern void s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd);
+
+/**
  * s3c64xx_fb_gpio_setup_24bpp() - S3C64XX setup function for 24bpp LCD
  *
  * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
@@ -94,4 +102,11 @@ extern void s5pc100_fb_gpio_setup_24bpp(void);
  */
 extern void s5pv210_fb_gpio_setup_24bpp(void);
 
+/**
+ * exynos4_fimd0_gpio_setup_24bpp() - Exynos4 setup function for 24bpp LCD0
+ *
+ * Initialise the GPIO for an 24bpp LCD display on the RGB interface 0.
+ */
+extern void exynos4_fimd0_gpio_setup_24bpp(void);
+
 #endif /* __PLAT_S3C_FB_H */
-- 
1.7.1


^ permalink raw reply related

* [PATCH V8 4/5] video: s3c-fb: Add support EXYNOS4 FIMD
From: Jingoo Han @ 2011-07-20 22:54 UTC (permalink / raw)
  To: Kukjin Kim, Paul Mundt, linux-samsung-soc, linux-fbdev
  Cc: Jonghun Han, Ben Dooks, Jingoo Han

This patch adds struct s3c_fb_driverdata s3c_fb_data_exynos4 for EXYNOS4
and adds lcd clock gating support.

FIMD driver needs two clocks for FIMD IP and LCD pixel clock. Previously,
both clocks are provided by using bus clock such as HCLK. However, EXYNOS4
can not select HCLK for LCD pixel clock because the EXYNOS4 FIMD IP does not
have the CLKSEL bit of VIDCON0. So, FIMD driver should provide the lcd clock
using SCLK_FIMD as LCD pixel clock for EXYNOS4.

The driver selects enabling lcd clock according to has_clksel which means
the CLKSEL bit of VIDCON0. If there is has_clksel, the driver will not
enable the lcd clock using SCLK_FIMD because bus clock using HCLK is used
a LCD pixel clock.

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
 drivers/video/Kconfig  |    2 +-
 drivers/video/s3c-fb.c |   88 +++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 85 insertions(+), 5 deletions(-)

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 549b960..963b8b7 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2027,7 +2027,7 @@ config FB_TMIO_ACCELL
 
 config FB_S3C
 	tristate "Samsung S3C framebuffer support"
-	depends on FB && S3C_DEV_FB
+	depends on FB && (S3C_DEV_FB || S5P_DEV_FIMD0)
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 4aecf21..cb0d3ea 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -81,6 +81,7 @@ struct s3c_fb;
  * @palette: Address of palette memory, or 0 if none.
  * @has_prtcon: Set if has PRTCON register.
  * @has_shadowcon: Set if has SHADOWCON register.
+ * @has_clksel: Set if VIDCON0 register has CLKSEL bit.
  */
 struct s3c_fb_variant {
 	unsigned int	is_2443:1;
@@ -98,6 +99,7 @@ struct s3c_fb_variant {
 
 	unsigned int	has_prtcon:1;
 	unsigned int	has_shadowcon:1;
+	unsigned int	has_clksel:1;
 };
 
 /**
@@ -186,6 +188,7 @@ struct s3c_fb_vsync {
  * @dev: The device that we bound to, for printing, etc.
  * @regs_res: The resource we claimed for the IO registers.
  * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
+ * @lcd_clk: The clk (sclk) feeding pixclk.
  * @regs: The mapped hardware registers.
  * @variant: Variant information for this hardware.
  * @enabled: A bitmask of enabled hardware windows.
@@ -200,6 +203,7 @@ struct s3c_fb {
 	struct device		*dev;
 	struct resource		*regs_res;
 	struct clk		*bus_clk;
+	struct clk		*lcd_clk;
 	void __iomem		*regs;
 	struct s3c_fb_variant	 variant;
 
@@ -336,10 +340,15 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
  */
 static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
 {
-	unsigned long clk = clk_get_rate(sfb->bus_clk);
+	unsigned long clk;
 	unsigned long long tmp;
 	unsigned int result;
 
+	if (sfb->variant.has_clksel)
+		clk = clk_get_rate(sfb->bus_clk);
+	else
+		clk = clk_get_rate(sfb->lcd_clk);
+
 	tmp = (unsigned long long)clk;
 	tmp *= pixclk;
 
@@ -1354,13 +1363,24 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
 
 	clk_enable(sfb->bus_clk);
 
+	if (!sfb->variant.has_clksel) {
+		sfb->lcd_clk = clk_get(dev, "sclk_fimd");
+		if (IS_ERR(sfb->lcd_clk)) {
+			dev_err(dev, "failed to get lcd clock\n");
+			ret = PTR_ERR(sfb->lcd_clk);
+			goto err_bus_clk;
+		}
+
+		clk_enable(sfb->lcd_clk);
+	}
+
 	pm_runtime_enable(sfb->dev);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(dev, "failed to find registers\n");
 		ret = -ENOENT;
-		goto err_clk;
+		goto err_lcd_clk;
 	}
 
 	sfb->regs_res = request_mem_region(res->start, resource_size(res),
@@ -1368,7 +1388,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
 	if (!sfb->regs_res) {
 		dev_err(dev, "failed to claim register region\n");
 		ret = -ENOENT;
-		goto err_clk;
+		goto err_lcd_clk;
 	}
 
 	sfb->regs = ioremap(res->start, resource_size(res));
@@ -1450,7 +1470,13 @@ err_ioremap:
 err_req_region:
 	release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
 
-err_clk:
+err_lcd_clk:
+	if (!sfb->variant.has_clksel) {
+		clk_disable(sfb->lcd_clk);
+		clk_put(sfb->lcd_clk);
+	}
+
+err_bus_clk:
 	clk_disable(sfb->bus_clk);
 	clk_put(sfb->bus_clk);
 
@@ -1481,6 +1507,11 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
 
 	iounmap(sfb->regs);
 
+	if (!sfb->variant.has_clksel) {
+		clk_disable(sfb->lcd_clk);
+		clk_put(sfb->lcd_clk);
+	}
+
 	clk_disable(sfb->bus_clk);
 	clk_put(sfb->bus_clk);
 
@@ -1510,6 +1541,9 @@ static int s3c_fb_suspend(struct device *dev)
 		s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
 	}
 
+	if (!sfb->variant.has_clksel)
+		clk_disable(sfb->lcd_clk);
+
 	clk_disable(sfb->bus_clk);
 	return 0;
 }
@@ -1524,6 +1558,9 @@ static int s3c_fb_resume(struct device *dev)
 
 	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);
@@ -1569,6 +1606,9 @@ static int s3c_fb_runtime_suspend(struct device *dev)
 		s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
 	}
 
+	if (!sfb->variant.has_clksel)
+		clk_disable(sfb->lcd_clk);
+
 	clk_disable(sfb->bus_clk);
 	return 0;
 }
@@ -1583,6 +1623,9 @@ static int s3c_fb_runtime_resume(struct device *dev)
 
 	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);
@@ -1755,6 +1798,7 @@ static struct s3c_fb_driverdata s3c_fb_data_64xx = {
 		},
 
 		.has_prtcon	= 1,
+		.has_clksel	= 1,
 	},
 	.win[0]	= &s3c_fb_data_64xx_wins[0],
 	.win[1]	= &s3c_fb_data_64xx_wins[1],
@@ -1785,6 +1829,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
 		},
 
 		.has_prtcon	= 1,
+		.has_clksel	= 1,
 	},
 	.win[0]	= &s3c_fb_data_s5p_wins[0],
 	.win[1]	= &s3c_fb_data_s5p_wins[1],
@@ -1815,6 +1860,37 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
 		},
 
 		.has_shadowcon	= 1,
+		.has_clksel	= 1,
+	},
+	.win[0]	= &s3c_fb_data_s5p_wins[0],
+	.win[1]	= &s3c_fb_data_s5p_wins[1],
+	.win[2]	= &s3c_fb_data_s5p_wins[2],
+	.win[3]	= &s3c_fb_data_s5p_wins[3],
+	.win[4]	= &s3c_fb_data_s5p_wins[4],
+};
+
+static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
+	.variant = {
+		.nr_windows	= 5,
+		.vidtcon	= VIDTCON0,
+		.wincon		= WINCON(0),
+		.winmap		= WINxMAP(0),
+		.keycon		= WKEYCON,
+		.osd		= VIDOSD_BASE,
+		.osd_stride	= 16,
+		.buf_start	= VIDW_BUF_START(0),
+		.buf_size	= VIDW_BUF_SIZE(0),
+		.buf_end	= VIDW_BUF_END(0),
+
+		.palette = {
+			[0] = 0x2400,
+			[1] = 0x2800,
+			[2] = 0x2c00,
+			[3] = 0x3000,
+			[4] = 0x3400,
+		},
+
+		.has_shadowcon	= 1,
 	},
 	.win[0]	= &s3c_fb_data_s5p_wins[0],
 	.win[1]	= &s3c_fb_data_s5p_wins[1],
@@ -1843,6 +1919,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
 			[0] = 0x400,
 			[1] = 0x800,
 		},
+		.has_clksel	= 1,
 	},
 	.win[0] = &(struct s3c_fb_win_variant) {
 		.palette_sz	= 256,
@@ -1870,6 +1947,9 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
 		.name		= "s5pv210-fb",
 		.driver_data	= (unsigned long)&s3c_fb_data_s5pv210,
 	}, {
+		.name		= "exynos4-fb",
+		.driver_data	= (unsigned long)&s3c_fb_data_exynos4,
+	}, {
 		.name		= "s3c2443-fb",
 		.driver_data	= (unsigned long)&s3c_fb_data_s3c2443,
 	},
-- 
1.7.1


^ permalink raw reply related

* [PATCH V8 5/5] ARM: EXYNOS4: Add platform data for EXYNOS4 FIMD and LTE480WV platform-lcd on SMDKC21
From: Jingoo Han @ 2011-07-20 22:54 UTC (permalink / raw)
  To: Kukjin Kim, Paul Mundt, linux-samsung-soc, linux-fbdev
  Cc: Jonghun Han, Ben Dooks, Jingoo Han

This patch adds support EXYNOS4 FIMD0 and LTE480WV LCD pannel
on SMDKC210 board.

Signed-off-by: Jonghun Han <jonghun.han@samsung.com>
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
 arch/arm/mach-exynos4/mach-smdkc210.c |   71 +++++++++++++++++++++++++++++++++
 1 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-exynos4/mach-smdkc210.c b/arch/arm/mach-exynos4/mach-smdkc210.c
index e645f7a..31cfcd6 100644
--- a/arch/arm/mach-exynos4/mach-smdkc210.c
+++ b/arch/arm/mach-exynos4/mach-smdkc210.c
@@ -9,7 +9,9 @@
 */
 
 #include <linux/serial_core.h>
+#include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/lcd.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
 #include <linux/smsc911x.h>
@@ -19,11 +21,15 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
+#include <video/platform_lcd.h>
+
 #include <plat/regs-serial.h>
 #include <plat/regs-srom.h>
+#include <plat/regs-fb-v4.h>
 #include <plat/exynos4.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
+#include <plat/fb.h>
 #include <plat/sdhci.h>
 #include <plat/iic.h>
 #include <plat/pd.h>
@@ -111,6 +117,67 @@ static struct s3c_sdhci_platdata smdkc210_hsmmc3_pdata __initdata = {
 	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
+static void lcd_lte480wv_set_power(struct plat_lcd_data *pd,
+				   unsigned int power)
+{
+	if (power) {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_HIGH, "GPD0");
+		gpio_free(EXYNOS4_GPD0(1));
+#endif
+		/* fire nRESET on power up */
+		gpio_request(EXYNOS4_GPX0(6), "GPX0");
+
+		gpio_direction_output(EXYNOS4_GPX0(6), 1);
+		mdelay(100);
+
+		gpio_set_value(EXYNOS4_GPX0(6), 0);
+		mdelay(10);
+
+		gpio_set_value(EXYNOS4_GPX0(6), 1);
+		mdelay(10);
+
+		gpio_free(EXYNOS4_GPX0(6));
+	} else {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_LOW, "GPD0");
+		gpio_free(EXYNOS4_GPD0(1));
+#endif
+	}
+}
+
+static struct plat_lcd_data smdkc210_lcd_lte480wv_data = {
+	.set_power		= lcd_lte480wv_set_power,
+};
+
+static struct platform_device smdkc210_lcd_lte480wv = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s5p_device_fimd0.dev,
+	.dev.platform_data	= &smdkc210_lcd_lte480wv_data,
+};
+
+static struct s3c_fb_pd_win smdkc210_fb_win0 = {
+	.win_mode = {
+		.left_margin	= 13,
+		.right_margin	= 8,
+		.upper_margin	= 7,
+		.lower_margin	= 5,
+		.hsync_len	= 3,
+		.vsync_len	= 1,
+		.xres		= 800,
+		.yres		= 480,
+	},
+	.max_bpp		= 32,
+	.default_bpp		= 24,
+};
+
+static struct s3c_fb_platdata smdkc210_lcd0_pdata __initdata = {
+	.win[0]		= &smdkc210_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
+};
+
 static struct resource smdkc210_smsc911x_resources[] = {
 	[0] = {
 		.start	= EXYNOS4_PA_SROM_BANK(1),
@@ -165,6 +232,8 @@ static struct platform_device *smdkc210_devices[] __initdata = {
 	&exynos4_device_pd[PD_GPS],
 	&exynos4_device_sysmmu,
 	&samsung_asoc_dma,
+	&s5p_device_fimd0,
+	&smdkc210_lcd_lte480wv,
 	&smdkc210_smsc911x,
 };
 
@@ -210,6 +279,8 @@ static void __init smdkc210_machine_init(void)
 	s3c_sdhci2_set_platdata(&smdkc210_hsmmc2_pdata);
 	s3c_sdhci3_set_platdata(&smdkc210_hsmmc3_pdata);
 
+	s5p_fimd0_set_platdata(&smdkc210_lcd0_pdata);
+
 	platform_add_devices(smdkc210_devices, ARRAY_SIZE(smdkc210_devices));
 }
 
-- 
1.7.1


^ permalink raw reply related

* Re: [GIT PULL] viafb updates for 3.1
From: Paul Mundt @ 2011-07-21  6:22 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <4E26F2D1.5040205@gmx.de>

On Wed, Jul 20, 2011 at 03:22:57PM +0000, Florian Tobias Schandinat wrote:
> please pull the viafb updates below. It contains only 2 fixes.
> 
Pulled, thanks.

^ permalink raw reply

* RE: [PATCH V8 1/5] ARM: EXYNOS4: Change clock name for FIMD
From: Kukjin Kim @ 2011-07-21  7:16 UTC (permalink / raw)
  To: 'Jingoo Han', 'Paul Mundt', linux-samsung-soc,
	linux-fbdev
  Cc: 'Jonghun Han', 'Ben Dooks'
In-Reply-To: <1311202444-18137-1-git-send-email-jg1.han@samsung.com>

Jingoo Han wrote:
> 
> This patch changes clock for FIMD from 'fimd' to 'lcd'.
> Also, devname for FIMD is changed from 's5pv310-fb' to 'exynos4-fb'.
> 
> Signed-off-by: Jingoo Han <jg1.han@samsung.com>
> ---
>  arch/arm/mach-exynos4/clock.c |   12 ++++++------
>  1 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
> index 98b5cc4..778a202 100644
> --- a/arch/arm/mach-exynos4/clock.c
> +++ b/arch/arm/mach-exynos4/clock.c
> @@ -405,13 +405,13 @@ static struct clk init_clocks_off[] = {
>  		.enable		= exynos4_clk_ip_cam_ctrl,
>  		.ctrlbit	= (1 << 3),
>  	}, {
> -		.name		= "fimd",
> -		.devname	= "s5pv310-fb.0",
> +		.name		= "lcd",
> +		.devname	= "exynos4-fb.0",
>  		.enable		= exynos4_clk_ip_lcd0_ctrl,
>  		.ctrlbit	= (1 << 0),
>  	}, {
> -		.name		= "fimd",
> -		.devname	= "s5pv310-fb.1",
> +		.name		= "lcd",

As I remember, some guys discussed about the clock name before.

Please refer to the following diagram. Before EXYNOS4210 clk 'lcd' was used
for FIMD IP core clock and source of the LCD pixel clock. But the mux used
to select source of LCD pixel clock is removed. So 'lcd' clock is only used
for core clock of FIMD IP. It isn't used for LCD pixel clock.

As a result clock name was changed from lcd to fimd in the EXYNOS4210
datasheet.

Before EXYNOS4
           ------------------------------------
                      dsys bus
           ----------------+-------------------
                           |
                           |1.clk 'lcd'
                           |
                           | FIMD block
                       +---+-----------+
4.mout_mpll |\         |   |           |
    --------|m|        | +-+-+ +----+  |
            |u|-+      | |   +-+core|  |
            |x| |      | |     +----+  |
            |/  |      | | |\          |
                |      | +-|m|  +---+  |
                |      |   |u|--+div|  |
                +------+---|x|  +---+  |
           2.SCLK_FIMD |   |/     |    |
                       |          |    |
                       +----------+----+
                                  |
           inside of SoC          |
           -----------------------+--------------------------
           outside of SoC         |
                                  | 3.LCD pixel clock
                                  |
                          +--------------+
                          | LCD module   |
                          +--------------+


EXYNOS4210
           ------------------------------------
                      dsys bus
           ----------------+-------------------
                           |
                           |1.clk 'fimd'
                           |
                           | FIMD block
                       +---+-----------+
4.mout_mpll |\         |   |           |
    --------|m|        |   |   +----+  |
            |u|-+      |   +---+core|  |
            |x| |      |       +----+  |
            |/  |      |               |
                |      |        +---+  |
                |      |     +--+div|  |
                +------+-----+  +---+  |
           2.SCLK_FIMD |          |    |
                       |          |    |
                       +----------+----+
                                  |
           inside of SoC          |
           -----------------------+--------------------------
           outside of SoC         |
                                  | 3.LCD pixel clock
                                  |
                          +--------------+
                          | LCD module   |
                          +--------------+

To change devname is ok to me. So will apply only it.

If any problems, please let me know :)

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.


> +		.devname	= "exynos4-fb.1",
>  		.enable		= exynos4_clk_ip_lcd1_ctrl,
>  		.ctrlbit	= (1 << 0),
>  	}, {
> @@ -909,7 +909,7 @@ static struct clksrc_clk clksrcs[] = {
>  	}, {
>  		.clk		= {
>  			.name		= "sclk_fimd",
> -			.devname	= "s5pv310-fb.0",
> +			.devname	= "exynos4-fb.0",
>  			.enable		= exynos4_clksrc_mask_lcd0_ctrl,
>  			.ctrlbit	= (1 << 0),
>  		},
> @@ -919,7 +919,7 @@ static struct clksrc_clk clksrcs[] = {
>  	}, {
>  		.clk		= {
>  			.name		= "sclk_fimd",
> -			.devname	= "s5pv310-fb.1",
> +			.devname	= "exynos4-fb.1",
>  			.enable		= exynos4_clksrc_mask_lcd1_ctrl,
>  			.ctrlbit	= (1 << 0),
>  		},
> --
> 1.7.1


^ permalink raw reply

* RE: [PATCH V8 0/5] ARM: EXYNOS4: Add support EXYNOS4 FIMD
From: Kukjin Kim @ 2011-07-21  7:53 UTC (permalink / raw)
  To: 'Jingoo Han', 'Paul Mundt', linux-samsung-soc,
	linux-fbdev
  Cc: 'Jonghun Han', 'Ben Dooks'
In-Reply-To: <1311202438-18105-1-git-send-email-jg1.han@samsung.com>

Jingoo Han wrote:
> 
> The patches are created against "for-next" branch of Kukjin Kim's tree at:
> git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
> 
> This was originally submitted by Jonghun Han <jonghun.han@samsung.com>
> http://www.spinics.net/lists/arm-kernel/msg101781.html
> 
> This patch adds support FIMD(Fully Interactive Mobile Display) on Exynos4.
> The 4th patch is update for s3c-fb and others are for platform data
> 
> NOTE: The common part for SMDKV310 will be updated later.
> 
> v2: change clock name of exynos4 FIMD: "fimd" -> "lcd"
>      use 'has_clksel' variable in order to distinguish FIMD version
>      add 'lcd_clk' that can be used for only lcd pixel clock
>      add callback 'enable_clk()' to enable parent clock 'sclk_fimd'.
> v3: remove the callback from the platform data structure
> v4: move clk_enable(sfb->lcd_clk) under the if statement
> v5: add clk_enable/disable(sfb->lcd_clk) to
s3c_fb_runtime_suspend/resume().
> v6: rename dev-fimd-24bpp.c to dev-fimd0.c
>      add 'exynos4_fimd0_setup_clock()' to dev-fimd0.c to setup parent
clock.
> v7: remove parent clock setting from machine directory
>      use 'gpio_request_one()' to simply the gpio setting step
> v8: updated minor fixes
> 
> o To Kukjin Kim
> [PATCH V8 1/5] ARM: EXYNOS4: Change clock name for FIMD
> [PATCH V8 2/5] ARM: EXYNOS4: Add resource definition for FIMD
> [PATCH V8 3/5] ARM: EXYNOS4: Add platform device and helper functions for
> FIMD
> [PATCH V8 5/5] ARM: EXYNOS4: Add platform data for EXYNOS4 FIMD and
> LTE480WV  platform-lcd on SMDKC210
> 
Hi Jingoo,

As I replied in your 1st patch, will fix it when I apply this series.
Others, looks ok to me.

As you said, we need to implement handling of common part on each boards
next time :)

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

> o To Paul Mundt
> [PATCH V8 4/5] video: s3c-fb: Add support EXYNOS4


^ permalink raw reply

* RE: [PATCH V8 4/5] video: s3c-fb: Add support EXYNOS4 FIMD
From: JinGoo Han @ 2011-07-22  1:06 UTC (permalink / raw)
  To: Paul Mundt
  Cc: Kukjin Kim, linux-samsung-soc@vger.kernel.org,
	linux-fbdev@vger.kernel.org, Jong-Hun Han, Ben Dooks, JinGoo Han
In-Reply-To: <1311202461-18235-1-git-send-email-jg1.han@samsung.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1254", Size: 8342 bytes --]

Hi  Paul,

Other patches were commited to 'linux-arm-soc.git'.
Please, commit this patch '[PATCH V8 4/5] video: s3c-fb: Add support EXYNOS4 FIMD' to 'fbdev-2.6'.

Thanks,
Jingoo Han

Jingoo Han wrote:
> -----Original Message-----
> Subject: [PATCH V8 4/5] video: s3c-fb: Add support EXYNOS4 FIMD
> 
> This patch adds struct s3c_fb_driverdata s3c_fb_data_exynos4 for EXYNOS4
> and adds lcd clock gating support.
> 
> FIMD driver needs two clocks for FIMD IP and LCD pixel clock. Previously,
> both clocks are provided by using bus clock such as HCLK. However, EXYNOS4
> can not select HCLK for LCD pixel clock because the EXYNOS4 FIMD IP does
> not
> have the CLKSEL bit of VIDCON0. So, FIMD driver should provide the lcd
> clock
> using SCLK_FIMD as LCD pixel clock for EXYNOS4.
> 
> The driver selects enabling lcd clock according to has_clksel which means
> the CLKSEL bit of VIDCON0. If there is has_clksel, the driver will not
> enable the lcd clock using SCLK_FIMD because bus clock using HCLK is used
> a LCD pixel clock.
> 
> Signed-off-by: Jingoo Han <jg1.han@samsung.com>
> ---
>  drivers/video/Kconfig  |    2 +-
>  drivers/video/s3c-fb.c |   88
> +++++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 85 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> index 549b960..963b8b7 100644
> --- a/drivers/video/Kconfig
> +++ b/drivers/video/Kconfig
> @@ -2027,7 +2027,7 @@ config FB_TMIO_ACCELL
> 
>  config FB_S3C
>  	tristate "Samsung S3C framebuffer support"
> -	depends on FB && S3C_DEV_FB
> +	depends on FB && (S3C_DEV_FB || S5P_DEV_FIMD0)
>  	select FB_CFB_FILLRECT
>  	select FB_CFB_COPYAREA
>  	select FB_CFB_IMAGEBLIT
> diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
> index 4aecf21..cb0d3ea 100644
> --- a/drivers/video/s3c-fb.c
> +++ b/drivers/video/s3c-fb.c
> @@ -81,6 +81,7 @@ struct s3c_fb;
>   * @palette: Address of palette memory, or 0 if none.
>   * @has_prtcon: Set if has PRTCON register.
>   * @has_shadowcon: Set if has SHADOWCON register.
> + * @has_clksel: Set if VIDCON0 register has CLKSEL bit.
>   */
>  struct s3c_fb_variant {
>  	unsigned int	is_2443:1;
> @@ -98,6 +99,7 @@ struct s3c_fb_variant {
> 
>  	unsigned int	has_prtcon:1;
>  	unsigned int	has_shadowcon:1;
> +	unsigned int	has_clksel:1;
>  };
> 
>  /**
> @@ -186,6 +188,7 @@ struct s3c_fb_vsync {
>   * @dev: The device that we bound to, for printing, etc.
>   * @regs_res: The resource we claimed for the IO registers.
>   * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
> + * @lcd_clk: The clk (sclk) feeding pixclk.
>   * @regs: The mapped hardware registers.
>   * @variant: Variant information for this hardware.
>   * @enabled: A bitmask of enabled hardware windows.
> @@ -200,6 +203,7 @@ struct s3c_fb {
>  	struct device		*dev;
>  	struct resource		*regs_res;
>  	struct clk		*bus_clk;
> +	struct clk		*lcd_clk;
>  	void __iomem		*regs;
>  	struct s3c_fb_variant	 variant;
> 
> @@ -336,10 +340,15 @@ static int s3c_fb_check_var(struct fb_var_screeninfo
> *var,
>   */
>  static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
>  {
> -	unsigned long clk = clk_get_rate(sfb->bus_clk);
> +	unsigned long clk;
>  	unsigned long long tmp;
>  	unsigned int result;
> 
> +	if (sfb->variant.has_clksel)
> +		clk = clk_get_rate(sfb->bus_clk);
> +	else
> +		clk = clk_get_rate(sfb->lcd_clk);
> +
>  	tmp = (unsigned long long)clk;
>  	tmp *= pixclk;
> 
> @@ -1354,13 +1363,24 @@ static int __devinit s3c_fb_probe(struct
> platform_device *pdev)
> 
>  	clk_enable(sfb->bus_clk);
> 
> +	if (!sfb->variant.has_clksel) {
> +		sfb->lcd_clk = clk_get(dev, "sclk_fimd");
> +		if (IS_ERR(sfb->lcd_clk)) {
> +			dev_err(dev, "failed to get lcd clock\n");
> +			ret = PTR_ERR(sfb->lcd_clk);
> +			goto err_bus_clk;
> +		}
> +
> +		clk_enable(sfb->lcd_clk);
> +	}
> +
>  	pm_runtime_enable(sfb->dev);
> 
>  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  	if (!res) {
>  		dev_err(dev, "failed to find registers\n");
>  		ret = -ENOENT;
> -		goto err_clk;
> +		goto err_lcd_clk;
>  	}
> 
>  	sfb->regs_res = request_mem_region(res->start, resource_size(res),
> @@ -1368,7 +1388,7 @@ static int __devinit s3c_fb_probe(struct
> platform_device *pdev)
>  	if (!sfb->regs_res) {
>  		dev_err(dev, "failed to claim register region\n");
>  		ret = -ENOENT;
> -		goto err_clk;
> +		goto err_lcd_clk;
>  	}
> 
>  	sfb->regs = ioremap(res->start, resource_size(res));
> @@ -1450,7 +1470,13 @@ err_ioremap:
>  err_req_region:
>  	release_mem_region(sfb->regs_res->start, resource_size(sfb-
> >regs_res));
> 
> -err_clk:
> +err_lcd_clk:
> +	if (!sfb->variant.has_clksel) {
> +		clk_disable(sfb->lcd_clk);
> +		clk_put(sfb->lcd_clk);
> +	}
> +
> +err_bus_clk:
>  	clk_disable(sfb->bus_clk);
>  	clk_put(sfb->bus_clk);
> 
> @@ -1481,6 +1507,11 @@ static int __devexit s3c_fb_remove(struct
> platform_device *pdev)
> 
>  	iounmap(sfb->regs);
> 
> +	if (!sfb->variant.has_clksel) {
> +		clk_disable(sfb->lcd_clk);
> +		clk_put(sfb->lcd_clk);
> +	}
> +
>  	clk_disable(sfb->bus_clk);
>  	clk_put(sfb->bus_clk);
> 
> @@ -1510,6 +1541,9 @@ static int s3c_fb_suspend(struct device *dev)
>  		s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
>  	}
> 
> +	if (!sfb->variant.has_clksel)
> +		clk_disable(sfb->lcd_clk);
> +
>  	clk_disable(sfb->bus_clk);
>  	return 0;
>  }
> @@ -1524,6 +1558,9 @@ static int s3c_fb_resume(struct device *dev)
> 
>  	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);
> @@ -1569,6 +1606,9 @@ static int s3c_fb_runtime_suspend(struct device *dev)
>  		s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
>  	}
> 
> +	if (!sfb->variant.has_clksel)
> +		clk_disable(sfb->lcd_clk);
> +
>  	clk_disable(sfb->bus_clk);
>  	return 0;
>  }
> @@ -1583,6 +1623,9 @@ static int s3c_fb_runtime_resume(struct device *dev)
> 
>  	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);
> @@ -1755,6 +1798,7 @@ static struct s3c_fb_driverdata s3c_fb_data_64xx = {
>  		},
> 
>  		.has_prtcon	= 1,
> +		.has_clksel	= 1,
>  	},
>  	.win[0]	= &s3c_fb_data_64xx_wins[0],
>  	.win[1]	= &s3c_fb_data_64xx_wins[1],
> @@ -1785,6 +1829,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100
> = {
>  		},
> 
>  		.has_prtcon	= 1,
> +		.has_clksel	= 1,
>  	},
>  	.win[0]	= &s3c_fb_data_s5p_wins[0],
>  	.win[1]	= &s3c_fb_data_s5p_wins[1],
> @@ -1815,6 +1860,37 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210
> = {
>  		},
> 
>  		.has_shadowcon	= 1,
> +		.has_clksel	= 1,
> +	},
> +	.win[0]	= &s3c_fb_data_s5p_wins[0],
> +	.win[1]	= &s3c_fb_data_s5p_wins[1],
> +	.win[2]	= &s3c_fb_data_s5p_wins[2],
> +	.win[3]	= &s3c_fb_data_s5p_wins[3],
> +	.win[4]	= &s3c_fb_data_s5p_wins[4],
> +};
> +
> +static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
> +	.variant = {
> +		.nr_windows	= 5,
> +		.vidtcon	= VIDTCON0,
> +		.wincon		= WINCON(0),
> +		.winmap		= WINxMAP(0),
> +		.keycon		= WKEYCON,
> +		.osd		= VIDOSD_BASE,
> +		.osd_stride	= 16,
> +		.buf_start	= VIDW_BUF_START(0),
> +		.buf_size	= VIDW_BUF_SIZE(0),
> +		.buf_end	= VIDW_BUF_END(0),
> +
> +		.palette = {
> +			[0] = 0x2400,
> +			[1] = 0x2800,
> +			[2] = 0x2c00,
> +			[3] = 0x3000,
> +			[4] = 0x3400,
> +		},
> +
> +		.has_shadowcon	= 1,
>  	},
>  	.win[0]	= &s3c_fb_data_s5p_wins[0],
>  	.win[1]	= &s3c_fb_data_s5p_wins[1],
> @@ -1843,6 +1919,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s3c2443
> = {
>  			[0] = 0x400,
>  			[1] = 0x800,
>  		},
> +		.has_clksel	= 1,
>  	},
>  	.win[0] = &(struct s3c_fb_win_variant) {
>  		.palette_sz	= 256,
> @@ -1870,6 +1947,9 @@ static struct platform_device_id s3c_fb_driver_ids[]
> = {
>  		.name		= "s5pv210-fb",
>  		.driver_data	= (unsigned long)&s3c_fb_data_s5pv210,
>  	}, {
> +		.name		= "exynos4-fb",
> +		.driver_data	= (unsigned long)&s3c_fb_data_exynos4,
> +	}, {
>  		.name		= "s3c2443-fb",
>  		.driver_data	= (unsigned long)&s3c_fb_data_s3c2443,
>  	},
> --
> 1.7.1


ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±ýöÝzÿâžØ^n‡r¡ö¦zË\x1aëh™¨è­Ú&£ûàz¿äz¹Þ—ú+€Ê+zf£¢·hšˆ§~†­†Ûiÿÿïêÿ‘êçz_è®\x0fæj:+v‰¨þ)ߣøm

^ permalink raw reply

* Congratulation!!!
From: BBC NATIONAL PROMO @ 2011-07-22  1:19 UTC (permalink / raw)
  To: linux-fbdev



BBC E-MAIL PROMOTION WINNERS NOTICE,
WINNING NOTIFICATION !!!
BBC NATIONAL LOTTERY PROMO
UK HEAD OFFICE.
SUITES 23-30,LION TOWERS
CENTRAL LONDON
ENGLAND
http://www.bbc.co.uk/lottery/

Your Email Address was selected thereby Winning for you,500,000 pounds in the
British Broadcasting corporation (BBC) Online Promo Held on this month of July
2011, and you are to acknowledge the receipt of this mail with the
details below to.
CLAIMS DIRECTOR BBC ONLINE PROMOTION.

1.Full name:
2.Tel:
3.Country :

Sincerely,
Mr. Scott Carson

----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.

^ permalink raw reply

* Congratulation!!!
From: BBC NATIONAL PROMO @ 2011-07-22  1:22 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1311297573.4e28d0251878b@www.bitsnet.com.br>



BBC E-MAIL PROMOTION WINNERS NOTICE,
WINNING NOTIFICATION !!!
BBC NATIONAL LOTTERY PROMO
UK HEAD OFFICE.
SUITES 23-30,LION TOWERS
CENTRAL LONDON
ENGLAND
http://www.bbc.co.uk/lottery/

Your Email Address was selected thereby Winning for you,500,000 pounds in the
British Broadcasting corporation (BBC) Online Promo Held on this month of July
2011, and you are to acknowledge the receipt of this mail with the
details below to.
CLAIMS DIRECTOR BBC ONLINE PROMOTION.

1.Full name:
2.Tel:
3.Country :

Sincerely,
Mr. Scott Carson

----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.

^ permalink raw reply

* [PATCH] drivers:video:remove the dup include file prefetch.h
From: Wanlong Gao @ 2011-07-24  4:18 UTC (permalink / raw)
  To: linux-fbdev

linux/prefetch.h has been incuded more than once.

Signed-off-by: Wanlong Gao <gaowanlong@cn.fujitsu.com>
---
 drivers/video/udlfb.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index 816a4fd..087fc99 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -29,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/prefetch.h>
 #include <linux/delay.h>
-#include <linux/prefetch.h>
 #include <video/udlfb.h>
 #include "edid.h"
 
-- 
1.7.4.1


^ permalink raw reply related

* Re: [PATCH/RFC] fbdev: Add FOURCC-based format configuration API
From: Laurent Pinchart @ 2011-07-25 10:30 UTC (permalink / raw)
  To: dri-devel
  Cc: Florian Tobias Schandinat, linux-fbdev, Paul Mundt,
	Geert Uytterhoeven, linux-media
In-Reply-To: <201107111732.52156.laurent.pinchart@ideasonboard.com>

Ping ?

As stated in my previous mail, I'd like to reach an agreement on the API, and 
implement it. I'm fine with either grayscale or nonstd to store the FOURCC 
(with a slight preference for grayscale), and with either a vmode flag or 
using the most significant byte of the grayscale/nonstd field to detect FOURCC 
mode. I believe FB_CAP_FOURCC (or something similar) is needed.

Paul, Geert, Florian, what are your opinions ?

On Monday 11 July 2011 17:32:51 Laurent Pinchart wrote:
> On Friday 24 June 2011 21:45:57 Florian Tobias Schandinat wrote:
> > On 06/24/2011 06:55 PM, Geert Uytterhoeven wrote:
> > > On Fri, Jun 24, 2011 at 08:19, Paul Mundt wrote:
> > >> On Thu, Jun 23, 2011 at 06:08:03PM +0200, Geert Uytterhoeven wrote:
> > >>> On Wed, Jun 22, 2011 at 07:45, Florian Tobias Schandinat wrote:
> > >>>> On 06/21/2011 10:31 PM, Laurent Pinchart wrote:
> > >>>>> On Tuesday 21 June 2011 22:49:14 Geert Uytterhoeven wrote:
> > >>>>>> As FOURCC values are always 4 ASCII characters (hence all 4 bytes
> > >>>>>> must be non-zero), I don't think there are any conflicts with
> > >>>>>> existing values of
> > >>>>>> nonstd. To make it even safer and easier to parse, you could set
> > >>>>>> bit 31 of
> > >>>>>> nonstd as a FOURCC indicator.
> > >>>>> 
> > >>>>> I would then create a union between nonstd and fourcc, and document
> > >>>>> nonstd as
> > >>>>> being used for the legacy API only. Most existing drivers use a
> > >>>>> couple of nonstd bits only. The driver that (ab)uses nonstd the
> > >>>>> most is pxafb and uses
> > >>>>> bits 22:0. Bits 31:24 are never used as far as I can tell, so
> > >>>>> nonstd& 0xff000000 != 0 could be used as a FOURCC mode test.
> > >>>>> 
> > >>>>> This assumes that FOURCCs will never have their last character set
> > >>>>> to '\0'. Is
> > >>>>> that a safe assumption for the future ?
> > >>>> 
> > >>>> Yes, I think. The information I found indicates that space should be
> > >>>> used for padding, so a \0 shouldn't exist.
> > >>>> I think using only the nonstd field and requiring applications to
> > >>>> check the capabilities would be possible, although not fool proof ;)
> > >>> 
> > >>> So we can declare the 8 msb bits of nonstd reserved, and assume
> > >>> FOURCC if any of them is set.
> > >>> 
> > >>> Nicely backwards compatible, as sane drivers should reject nonstd
> > >>> values they don't support (apps _will_ start filling in FOURCC values
> > >>> ignoring capabilities, won't they?).
> > >> 
> > >> That seems like a reasonable case, but if we're going to do that then
> > >> certainly the nonstd bit encoding needs to be documented and treated
> > >> as a hard ABI.
> > >> 
> > >> I'm not so sure about the if any bit in the upper byte is set assume
> > >> FOURCC case though, there will presumably be other users in the future
> > >> that will want bits for themselves, too. What exactly was the issue
> > >> with having a FOURCC capability bit in the upper byte?
> > > 
> > > That indeed gives less issues (as long as you don't stuff 8-bit ASCII
> > > in the MSB) and more bits for tradiditional nonstd users.
> > 
> > The only disadvantage I can see is that it requires adding this bit in
> > the application and stripping it when interpreting it. But I think the
> > 24 lower bits should be enough for driver specific behavior (as the
> > current values really can only be interpreted per driver).
> 
> I'm also not keen on adding/stripping the MSB. It would be easier for
> applications to use FOURCCs directly.
> 
> > > BTW, after giving it some more thought: what does the FB_CAP_FOURCC
> > > buys us? It's not like all drivers will support whatever random FOURCC
> > > mode you give them, so you have to check whether it's supported by
> > > doing a set_var first.
> > 
> > Because any solution purely based on the nonstd field is insane. The
> > abuse of that field is just too widespread. Drivers that use nonstd
> > usually only check whether it is zero or nonzero and others will just
> > interpret parts of nonstd and ignore the rest. They will happily accept
> > FOURCC values in the nonstd and just doing the wrong thing. Even if we
> > would fix those the problems applications will run into with older
> > kernels will remain.
> 
> I agree with Florian here. Many drivers currently check whether nonstd !> 0. Who knows what kind of values applications feed them ?
> 
> I'd like to reach an agreement on the API, and implement it. I'm fine with
> either grayscale or nonstd to store the FOURCC (with a slight preference
> for grayscale), and with either a vmode flag or using the most significant
> byte of the grayscale/nonstd field to detect FOURCC mode. I believe
> FB_CAP_FOURCC (or something similar) is needed.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* [PATCH RESEND 1/7] video: s3c-fb: Add S5P64X0 specific
From: Ajay Kumar @ 2011-07-25 14:11 UTC (permalink / raw)
  To: linux-fbdev

This patch:
Adds s3c_fb_driverdata for S5P64X0, which supports 3 windows.
Also, register "s5p64x0-fb" type driver_data.
Existing s3c_fb_driverdata definitions in s3c-fb.c
supports 5 or 2 windows.

Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com>
acked-by: Jingoo Han <jg1.han@samsung.com>
---
 drivers/video/s3c-fb.c |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 4aecf21..0fda252 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -1859,6 +1859,30 @@ static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
 	},
 };
 
+static struct s3c_fb_driverdata s3c_fb_data_s5p64x0 = {
+	.variant = {
+		.nr_windows	= 3,
+		.vidtcon	= VIDTCON0,
+		.wincon		= WINCON(0),
+		.winmap		= WINxMAP(0),
+		.keycon		= WKEYCON,
+		.osd		= VIDOSD_BASE,
+		.osd_stride	= 16,
+		.buf_start	= VIDW_BUF_START(0),
+		.buf_size	= VIDW_BUF_SIZE(0),
+		.buf_end	= VIDW_BUF_END(0),
+
+		.palette = {
+			[0] = 0x2400,
+			[1] = 0x2800,
+			[2] = 0x2c00,
+		},
+	},
+	.win[0] = &s3c_fb_data_s5p_wins[0],
+	.win[1] = &s3c_fb_data_s5p_wins[1],
+	.win[2] = &s3c_fb_data_s5p_wins[2],
+};
+
 static struct platform_device_id s3c_fb_driver_ids[] = {
 	{
 		.name		= "s3c-fb",
@@ -1872,6 +1896,9 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
 	}, {
 		.name		= "s3c2443-fb",
 		.driver_data	= (unsigned long)&s3c_fb_data_s3c2443,
+	}, {
+		.name		= "s5p64x0-fb",
+		.driver_data	= (unsigned long)&s3c_fb_data_s5p64x0,
 	},
 	{},
 };
-- 
1.7.0.4


^ 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