All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/6] pxa: support pxa168 LCD controller SPI operation
@ 2009-11-03  6:45 ` Jun Nie
  0 siblings, 0 replies; 8+ messages in thread
From: Jun Nie @ 2009-11-03  6:45 UTC (permalink / raw)
  To: linux-arm-kernel, linux-fbdev-devel

pxa: support pxa168 LCD controller SPI operation

Signed-off-by: Jun Nie <njun@marvell.com>
---
 arch/arm/mach-mmp/include/mach/pxa168fb.h |   29 +++++++++
 drivers/video/pxa168fb.c                  |   92 +++++++++++++++++++++++++++++
 drivers/video/pxa168fb.h                  |   24 +-------
 include/video/pxa168fb.h                  |   18 ++++++
 4 files changed, 140 insertions(+), 23 deletions(-)
 create mode 100644 arch/arm/mach-mmp/include/mach/pxa168fb.h

diff --git a/arch/arm/mach-mmp/include/mach/pxa168fb.h
b/arch/arm/mach-mmp/include/mach/pxa168fb.h
new file mode 100644
index 0000000..897cc3e
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/pxa168fb.h
@@ -0,0 +1,29 @@
+#ifndef __PXA168FBSPI_H__
+#define __PXA168FBSPI_H__
+
+/* SPI Control Register. */
+#define LCD_SPU_SPI_CTRL			0x0180
+#define     CFG_SCLKCNT(div)			((div) << 24)  /* 0xFF~0x2 */
+#define     CFG_SCLKCNT_MASK			0xFF000000
+#define     CFG_RXBITS(rx)			((rx - 1) << 16)   /* 0x1F~0x1, 0x1:
2bits ... 0x1F: 32bits */
+#define     CFG_RXBITS_MASK			0x00FF0000
+#define     CFG_TXBITS(tx)                      ((tx - 1) << 8)    /*
0x1F~0x1, 0x1: 2bits ... 0x1F: 32bits */
+#define     CFG_TXBITS_MASK			0x0000FF00
+#define     CFG_CLKINV(clk)			((clk) << 7)
+#define     CFG_CLKINV_MASK			0x00000080
+#define     CFG_KEEPXFER(transfer)		((transfer) << 6)
+#define     CFG_KEEPXFER_MASK			0x00000040
+#define     CFG_RXBITSTO0(rx)			((rx) << 5)
+#define     CFG_RXBITSTO0_MASK			0x00000020
+#define     CFG_TXBITSTO0(tx)			((tx) << 4)
+#define     CFG_TXBITSTO0_MASK			0x00000010
+#define     CFG_SPI_ENA(spi)			((spi) << 3)
+#define     CFG_SPI_ENA_MASK			0x00000008
+#define     CFG_SPI_SEL(spi)			((spi) << 2)	/* 1: port1; 0: port0 */
+#define     CFG_SPI_SEL_MASK			0x00000004
+#define     CFG_SPI_3W4WB(wire)                 ((wire)<<1)  /* 1:
3-wire; 0: 4-wire */
+#define     CFG_SPI_3W4WB_MASK			0x00000002
+#define     CFG_SPI_START(start)		(start)
+#define     CFG_SPI_START_MASK			0x00000001
+
+#endif /* __PXA168FBSPI_H__ */
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index 84d8327..27bdf2b 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -29,10 +29,91 @@
 #include <linux/uaccess.h>
 #include <video/pxa168fb.h>

+#include <mach/pxa168fb.h>
+#include <mach/gpio.h>
 #include "pxa168fb.h"

 #define DEFAULT_REFRESH		60	/* Hz */

+static inline void spi_gpio_assert_set(int spi_gpio_cs, int val)
+{
+	       if (gpio_is_valid(spi_gpio_cs))
+		                      gpio_set_value(spi_gpio_cs, val);
+}
+
+int pxa168fb_spi_send(struct pxa168fb_info *fbi, void *value, int count,
+		unsigned int spi_gpio_cs, unsigned int interval_us)
+{
+	u32 x, spi_byte_len;
+	u8 *cmd = (u8 *)value;
+	int i, err, isr, iopad, ret = 0;
+
+	if (gpio_is_valid(spi_gpio_cs)) {
+		err = gpio_request(spi_gpio_cs, "LCD_SPI_CS");
+		if (err) {
+			dev_err(fbi->dev, "failed to request GPIO for LCD CS\n");
+			return -1;
+		}
+		gpio_direction_output(spi_gpio_cs, 1);
+	}
+	spi_byte_len = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
+	spi_byte_len = (spi_byte_len >> 8) & 0xff;
+	/* Alignment should be (spi_byte_len + 7) >> 3, but
+	 * spi controller request set one less than bit length */
+	spi_byte_len = (spi_byte_len + 8) >> 3;
+	/* spi command provided by platform should be 1, 2, or 4 byte aligned */
+	if(3 == spi_byte_len)
+		spi_byte_len = 4;
+
+	iopad = readl(fbi->reg_base + SPU_IOPAD_CONTROL);
+	if ((iopad & CFG_IOPADMODE_MASK) != PIN_MODE_DUMB_18_SPI)
+		writel(PIN_MODE_DUMB_18_SPI, fbi->reg_base + SPU_IOPAD_CONTROL);
+	isr = readl(fbi->reg_base + SPU_IRQ_ISR);
+	writel((isr & ~SPI_IRQ_ENA_MASK), fbi->reg_base + SPU_IRQ_ISR);
+	for (i = 0; i < count; i++) {
+		spi_gpio_assert_set(spi_gpio_cs, 0);
+		udelay(interval_us);
+		switch (spi_byte_len){
+		case 1:
+			writel(*cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
+			break;
+		case 2:
+			writel(*(u16*)cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
+			break;
+		case 4:
+			writel(*(u32*)cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
+			break;
+		default:
+			dev_err(fbi->dev, "Wrong spi bit length\n");
+			spi_gpio_assert_set(spi_gpio_cs, 1);
+			ret = -1;
+			goto spi_exit;
+		}
+		cmd += spi_byte_len;
+		x = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
+		x |= 0x1;
+		writel(x, fbi->reg_base + LCD_SPU_SPI_CTRL);
+		isr = readl(fbi->reg_base + SPU_IRQ_ISR);
+		while(!(isr & SPI_IRQ_ENA_MASK)) {
+			udelay(1);
+			isr = readl(fbi->reg_base + SPU_IRQ_ISR);
+		}
+		x = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
+		x &= ~0x1;
+		writel(x, fbi->reg_base + LCD_SPU_SPI_CTRL);
+		spi_gpio_assert_set(spi_gpio_cs, 1);
+	}
+
+spi_exit:
+	if (gpio_is_valid(spi_gpio_cs))
+		gpio_free(spi_gpio_cs);
+	if ((iopad & CFG_IOPADMODE_MASK) != PIN_MODE_DUMB_18_SPI)
+		writel(iopad, fbi->reg_base + SPU_IOPAD_CONTROL);
+
+	return ret;
+}
+EXPORT_SYMBOL(pxa168fb_spi_send);
+
 static int determine_best_pix_fmt(struct fb_var_screeninfo *var)
 {
 	/*
@@ -687,6 +768,7 @@ static int __init pxa168fb_probe(struct
platform_device *pdev)
 	}

 	info->fix.smem_start = (unsigned long)fbi->fb_start_dma;
+	set_graphics_start(info, 0, 0);

 	/*
 	 * Set video mode according to platform data.
@@ -728,6 +810,9 @@ static int __init pxa168fb_probe(struct
platform_device *pdev)
 	writel(0, fbi->reg_base + LCD_SPU_SRAM_PARA0);
 	writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1),
 		fbi->reg_base + LCD_SPU_SRAM_PARA1);
+	if ((mi->spi_ctrl != -1) && (mi->spi_ctrl & CFG_SPI_ENA_MASK))
+		writel(mi->spi_ctrl, fbi->reg_base + LCD_SPU_SPI_CTRL);
+

 	/*
 	 * Allocate color map.
@@ -764,6 +849,13 @@ static int __init pxa168fb_probe(struct
platform_device *pdev)
 	}

 	platform_set_drvdata(pdev, fbi);
+	if (mi->pxa168fb_lcd_power){
+		if(mi->pxa168fb_lcd_power(fbi, mi->spi_gpio_cs, mi->spi_gpio_reset, 1)){
+			dev_err(&pdev->dev, "Failed to power up pxa168-fb\n");
+			goto failed_free_irq;
+		}
+	}
+	dev_info(fbi->dev, "frame buffer detected\n");
 	return 0;

 failed_free_irq:
diff --git a/drivers/video/pxa168fb.h b/drivers/video/pxa168fb.h
index eee0927..1e4859e 100644
--- a/drivers/video/pxa168fb.h
+++ b/drivers/video/pxa168fb.h
@@ -170,29 +170,7 @@
 #define     DMA_FRAME_CNT_MASK			0x00000003  /* Video */

 /* SPI Control Register. */
-#define LCD_SPU_SPI_CTRL			0x0180
-#define     CFG_SCLKCNT(div)			((div) << 24)  /* 0xFF~0x2 */
-#define     CFG_SCLKCNT_MASK			0xFF000000
-#define     CFG_RXBITS(rx)			((rx) << 16)   /* 0x1F~0x1 */
-#define     CFG_RXBITS_MASK			0x00FF0000
-#define     CFG_TXBITS(tx)			((tx) << 8)    /* 0x1F~0x1 */
-#define     CFG_TXBITS_MASK			0x0000FF00
-#define     CFG_CLKINV(clk)			((clk) << 7)
-#define     CFG_CLKINV_MASK			0x00000080
-#define     CFG_KEEPXFER(transfer)		((transfer) << 6)
-#define     CFG_KEEPXFER_MASK			0x00000040
-#define     CFG_RXBITSTO0(rx)			((rx) << 5)
-#define     CFG_RXBITSTO0_MASK			0x00000020
-#define     CFG_TXBITSTO0(tx)			((tx) << 4)
-#define     CFG_TXBITSTO0_MASK			0x00000010
-#define     CFG_SPI_ENA(spi)			((spi) << 3)
-#define     CFG_SPI_ENA_MASK			0x00000008
-#define     CFG_SPI_SEL(spi)			((spi) << 2)
-#define     CFG_SPI_SEL_MASK			0x00000004
-#define     CFG_SPI_3W4WB(wire)			((wire) << 1)
-#define     CFG_SPI_3W4WB_MASK			0x00000002
-#define     CFG_SPI_START(start)		(start)
-#define     CFG_SPI_START_MASK			0x00000001
+/* For SPI register, please refer to
arch/arm/mach-mmp/include/mach/pxa168fb.h */

 /* SPI Tx Data Register */
 #define LCD_SPU_SPI_TXDATA			0x0184
diff --git a/include/video/pxa168fb.h b/include/video/pxa168fb.h
index b5cc72f..f0497ae 100644
--- a/include/video/pxa168fb.h
+++ b/include/video/pxa168fb.h
@@ -122,6 +122,24 @@ struct pxa168fb_mach_info {
 	unsigned	panel_rbswap:1;
 	unsigned	active:1;
 	unsigned	enable_lcd:1;
+	/*
+	 * SPI control
+	 */
+	unsigned int	spi_ctrl;
+	unsigned int	spi_gpio_cs;
+	unsigned int 	spi_gpio_reset;
+	/*
+	 * power on/off function.
+	 */
+	int (*pxa168fb_lcd_power)(struct pxa168fb_info *, unsigned int,
unsigned int, int);
 };

+/* SPI utility for configure panel SPI command.
+ * value: command array, element should be 1, 2 or 4 byte aligned.
+ * count: command array length
+ * spi_gpio_cs: gpio number for spi chip select
+ * interval_us: time interval between two commands, us as unit */
+int pxa168fb_spi_send(struct pxa168fb_info *fbi, void *value, int count,
+		unsigned int spi_gpio_cs, unsigned int interval_us);
+
 #endif /* __ASM_MACH_PXA168FB_H */
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 1/6] pxa: support pxa168 LCD controller SPI operation
@ 2009-11-03  6:45 ` Jun Nie
  0 siblings, 0 replies; 8+ messages in thread
From: Jun Nie @ 2009-11-03  6:45 UTC (permalink / raw)
  To: linux-arm-kernel

pxa: support pxa168 LCD controller SPI operation

Signed-off-by: Jun Nie <njun@marvell.com>
---
 arch/arm/mach-mmp/include/mach/pxa168fb.h |   29 +++++++++
 drivers/video/pxa168fb.c                  |   92 +++++++++++++++++++++++++++++
 drivers/video/pxa168fb.h                  |   24 +-------
 include/video/pxa168fb.h                  |   18 ++++++
 4 files changed, 140 insertions(+), 23 deletions(-)
 create mode 100644 arch/arm/mach-mmp/include/mach/pxa168fb.h

diff --git a/arch/arm/mach-mmp/include/mach/pxa168fb.h
b/arch/arm/mach-mmp/include/mach/pxa168fb.h
new file mode 100644
index 0000000..897cc3e
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/pxa168fb.h
@@ -0,0 +1,29 @@
+#ifndef __PXA168FBSPI_H__
+#define __PXA168FBSPI_H__
+
+/* SPI Control Register. */
+#define LCD_SPU_SPI_CTRL			0x0180
+#define     CFG_SCLKCNT(div)			((div) << 24)  /* 0xFF~0x2 */
+#define     CFG_SCLKCNT_MASK			0xFF000000
+#define     CFG_RXBITS(rx)			((rx - 1) << 16)   /* 0x1F~0x1, 0x1:
2bits ... 0x1F: 32bits */
+#define     CFG_RXBITS_MASK			0x00FF0000
+#define     CFG_TXBITS(tx)                      ((tx - 1) << 8)    /*
0x1F~0x1, 0x1: 2bits ... 0x1F: 32bits */
+#define     CFG_TXBITS_MASK			0x0000FF00
+#define     CFG_CLKINV(clk)			((clk) << 7)
+#define     CFG_CLKINV_MASK			0x00000080
+#define     CFG_KEEPXFER(transfer)		((transfer) << 6)
+#define     CFG_KEEPXFER_MASK			0x00000040
+#define     CFG_RXBITSTO0(rx)			((rx) << 5)
+#define     CFG_RXBITSTO0_MASK			0x00000020
+#define     CFG_TXBITSTO0(tx)			((tx) << 4)
+#define     CFG_TXBITSTO0_MASK			0x00000010
+#define     CFG_SPI_ENA(spi)			((spi) << 3)
+#define     CFG_SPI_ENA_MASK			0x00000008
+#define     CFG_SPI_SEL(spi)			((spi) << 2)	/* 1: port1; 0: port0 */
+#define     CFG_SPI_SEL_MASK			0x00000004
+#define     CFG_SPI_3W4WB(wire)                 ((wire)<<1)  /* 1:
3-wire; 0: 4-wire */
+#define     CFG_SPI_3W4WB_MASK			0x00000002
+#define     CFG_SPI_START(start)		(start)
+#define     CFG_SPI_START_MASK			0x00000001
+
+#endif /* __PXA168FBSPI_H__ */
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index 84d8327..27bdf2b 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -29,10 +29,91 @@
 #include <linux/uaccess.h>
 #include <video/pxa168fb.h>

+#include <mach/pxa168fb.h>
+#include <mach/gpio.h>
 #include "pxa168fb.h"

 #define DEFAULT_REFRESH		60	/* Hz */

+static inline void spi_gpio_assert_set(int spi_gpio_cs, int val)
+{
+	       if (gpio_is_valid(spi_gpio_cs))
+		                      gpio_set_value(spi_gpio_cs, val);
+}
+
+int pxa168fb_spi_send(struct pxa168fb_info *fbi, void *value, int count,
+		unsigned int spi_gpio_cs, unsigned int interval_us)
+{
+	u32 x, spi_byte_len;
+	u8 *cmd = (u8 *)value;
+	int i, err, isr, iopad, ret = 0;
+
+	if (gpio_is_valid(spi_gpio_cs)) {
+		err = gpio_request(spi_gpio_cs, "LCD_SPI_CS");
+		if (err) {
+			dev_err(fbi->dev, "failed to request GPIO for LCD CS\n");
+			return -1;
+		}
+		gpio_direction_output(spi_gpio_cs, 1);
+	}
+	spi_byte_len = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
+	spi_byte_len = (spi_byte_len >> 8) & 0xff;
+	/* Alignment should be (spi_byte_len + 7) >> 3, but
+	 * spi controller request set one less than bit length */
+	spi_byte_len = (spi_byte_len + 8) >> 3;
+	/* spi command provided by platform should be 1, 2, or 4 byte aligned */
+	if(3 == spi_byte_len)
+		spi_byte_len = 4;
+
+	iopad = readl(fbi->reg_base + SPU_IOPAD_CONTROL);
+	if ((iopad & CFG_IOPADMODE_MASK) != PIN_MODE_DUMB_18_SPI)
+		writel(PIN_MODE_DUMB_18_SPI, fbi->reg_base + SPU_IOPAD_CONTROL);
+	isr = readl(fbi->reg_base + SPU_IRQ_ISR);
+	writel((isr & ~SPI_IRQ_ENA_MASK), fbi->reg_base + SPU_IRQ_ISR);
+	for (i = 0; i < count; i++) {
+		spi_gpio_assert_set(spi_gpio_cs, 0);
+		udelay(interval_us);
+		switch (spi_byte_len){
+		case 1:
+			writel(*cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
+			break;
+		case 2:
+			writel(*(u16*)cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
+			break;
+		case 4:
+			writel(*(u32*)cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
+			break;
+		default:
+			dev_err(fbi->dev, "Wrong spi bit length\n");
+			spi_gpio_assert_set(spi_gpio_cs, 1);
+			ret = -1;
+			goto spi_exit;
+		}
+		cmd += spi_byte_len;
+		x = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
+		x |= 0x1;
+		writel(x, fbi->reg_base + LCD_SPU_SPI_CTRL);
+		isr = readl(fbi->reg_base + SPU_IRQ_ISR);
+		while(!(isr & SPI_IRQ_ENA_MASK)) {
+			udelay(1);
+			isr = readl(fbi->reg_base + SPU_IRQ_ISR);
+		}
+		x = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
+		x &= ~0x1;
+		writel(x, fbi->reg_base + LCD_SPU_SPI_CTRL);
+		spi_gpio_assert_set(spi_gpio_cs, 1);
+	}
+
+spi_exit:
+	if (gpio_is_valid(spi_gpio_cs))
+		gpio_free(spi_gpio_cs);
+	if ((iopad & CFG_IOPADMODE_MASK) != PIN_MODE_DUMB_18_SPI)
+		writel(iopad, fbi->reg_base + SPU_IOPAD_CONTROL);
+
+	return ret;
+}
+EXPORT_SYMBOL(pxa168fb_spi_send);
+
 static int determine_best_pix_fmt(struct fb_var_screeninfo *var)
 {
 	/*
@@ -687,6 +768,7 @@ static int __init pxa168fb_probe(struct
platform_device *pdev)
 	}

 	info->fix.smem_start = (unsigned long)fbi->fb_start_dma;
+	set_graphics_start(info, 0, 0);

 	/*
 	 * Set video mode according to platform data.
@@ -728,6 +810,9 @@ static int __init pxa168fb_probe(struct
platform_device *pdev)
 	writel(0, fbi->reg_base + LCD_SPU_SRAM_PARA0);
 	writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1),
 		fbi->reg_base + LCD_SPU_SRAM_PARA1);
+	if ((mi->spi_ctrl != -1) && (mi->spi_ctrl & CFG_SPI_ENA_MASK))
+		writel(mi->spi_ctrl, fbi->reg_base + LCD_SPU_SPI_CTRL);
+

 	/*
 	 * Allocate color map.
@@ -764,6 +849,13 @@ static int __init pxa168fb_probe(struct
platform_device *pdev)
 	}

 	platform_set_drvdata(pdev, fbi);
+	if (mi->pxa168fb_lcd_power){
+		if(mi->pxa168fb_lcd_power(fbi, mi->spi_gpio_cs, mi->spi_gpio_reset, 1)){
+			dev_err(&pdev->dev, "Failed to power up pxa168-fb\n");
+			goto failed_free_irq;
+		}
+	}
+	dev_info(fbi->dev, "frame buffer detected\n");
 	return 0;

 failed_free_irq:
diff --git a/drivers/video/pxa168fb.h b/drivers/video/pxa168fb.h
index eee0927..1e4859e 100644
--- a/drivers/video/pxa168fb.h
+++ b/drivers/video/pxa168fb.h
@@ -170,29 +170,7 @@
 #define     DMA_FRAME_CNT_MASK			0x00000003  /* Video */

 /* SPI Control Register. */
-#define LCD_SPU_SPI_CTRL			0x0180
-#define     CFG_SCLKCNT(div)			((div) << 24)  /* 0xFF~0x2 */
-#define     CFG_SCLKCNT_MASK			0xFF000000
-#define     CFG_RXBITS(rx)			((rx) << 16)   /* 0x1F~0x1 */
-#define     CFG_RXBITS_MASK			0x00FF0000
-#define     CFG_TXBITS(tx)			((tx) << 8)    /* 0x1F~0x1 */
-#define     CFG_TXBITS_MASK			0x0000FF00
-#define     CFG_CLKINV(clk)			((clk) << 7)
-#define     CFG_CLKINV_MASK			0x00000080
-#define     CFG_KEEPXFER(transfer)		((transfer) << 6)
-#define     CFG_KEEPXFER_MASK			0x00000040
-#define     CFG_RXBITSTO0(rx)			((rx) << 5)
-#define     CFG_RXBITSTO0_MASK			0x00000020
-#define     CFG_TXBITSTO0(tx)			((tx) << 4)
-#define     CFG_TXBITSTO0_MASK			0x00000010
-#define     CFG_SPI_ENA(spi)			((spi) << 3)
-#define     CFG_SPI_ENA_MASK			0x00000008
-#define     CFG_SPI_SEL(spi)			((spi) << 2)
-#define     CFG_SPI_SEL_MASK			0x00000004
-#define     CFG_SPI_3W4WB(wire)			((wire) << 1)
-#define     CFG_SPI_3W4WB_MASK			0x00000002
-#define     CFG_SPI_START(start)		(start)
-#define     CFG_SPI_START_MASK			0x00000001
+/* For SPI register, please refer to
arch/arm/mach-mmp/include/mach/pxa168fb.h */

 /* SPI Tx Data Register */
 #define LCD_SPU_SPI_TXDATA			0x0184
diff --git a/include/video/pxa168fb.h b/include/video/pxa168fb.h
index b5cc72f..f0497ae 100644
--- a/include/video/pxa168fb.h
+++ b/include/video/pxa168fb.h
@@ -122,6 +122,24 @@ struct pxa168fb_mach_info {
 	unsigned	panel_rbswap:1;
 	unsigned	active:1;
 	unsigned	enable_lcd:1;
+	/*
+	 * SPI control
+	 */
+	unsigned int	spi_ctrl;
+	unsigned int	spi_gpio_cs;
+	unsigned int 	spi_gpio_reset;
+	/*
+	 * power on/off function.
+	 */
+	int (*pxa168fb_lcd_power)(struct pxa168fb_info *, unsigned int,
unsigned int, int);
 };

+/* SPI utility for configure panel SPI command.
+ * value: command array, element should be 1, 2 or 4 byte aligned.
+ * count: command array length
+ * spi_gpio_cs: gpio number for spi chip select
+ * interval_us: time interval between two commands, us as unit */
+int pxa168fb_spi_send(struct pxa168fb_info *fbi, void *value, int count,
+		unsigned int spi_gpio_cs, unsigned int interval_us);
+
 #endif /* __ASM_MACH_PXA168FB_H */
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/6] pxa: support pxa168 LCD controller SPI operation
  2009-11-03  6:45 ` Jun Nie
@ 2009-11-03  7:28   ` Jun Nie
  -1 siblings, 0 replies; 8+ messages in thread
From: Jun Nie @ 2009-11-03  7:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-fbdev-devel, linux-fbdev

2009/11/3 Jun Nie <niej0001@gmail.com>:
> pxa: support pxa168 LCD controller SPI operation
>
> Signed-off-by: Jun Nie <njun@marvell.com>
> ---
>  arch/arm/mach-mmp/include/mach/pxa168fb.h |   29 +++++++++
>  drivers/video/pxa168fb.c                  |   92 +++++++++++++++++++++++++++++
>  drivers/video/pxa168fb.h                  |   24 +-------
>  include/video/pxa168fb.h                  |   18 ++++++
>  4 files changed, 140 insertions(+), 23 deletions(-)
>  create mode 100644 arch/arm/mach-mmp/include/mach/pxa168fb.h
>
> diff --git a/arch/arm/mach-mmp/include/mach/pxa168fb.h
> b/arch/arm/mach-mmp/include/mach/pxa168fb.h
> new file mode 100644
> index 0000000..897cc3e
> --- /dev/null
> +++ b/arch/arm/mach-mmp/include/mach/pxa168fb.h
> @@ -0,0 +1,29 @@
> +#ifndef __PXA168FBSPI_H__
> +#define __PXA168FBSPI_H__
> +
> +/* SPI Control Register. */
> +#define LCD_SPU_SPI_CTRL                       0x0180
> +#define     CFG_SCLKCNT(div)                   ((div) << 24)  /* 0xFF~0x2 */
> +#define     CFG_SCLKCNT_MASK                   0xFF000000
> +#define     CFG_RXBITS(rx)                     ((rx - 1) << 16)   /* 0x1F~0x1, 0x1:
> 2bits ... 0x1F: 32bits */
> +#define     CFG_RXBITS_MASK                    0x00FF0000
> +#define     CFG_TXBITS(tx)                      ((tx - 1) << 8)    /*
> 0x1F~0x1, 0x1: 2bits ... 0x1F: 32bits */
> +#define     CFG_TXBITS_MASK                    0x0000FF00
> +#define     CFG_CLKINV(clk)                    ((clk) << 7)
> +#define     CFG_CLKINV_MASK                    0x00000080
> +#define     CFG_KEEPXFER(transfer)             ((transfer) << 6)
> +#define     CFG_KEEPXFER_MASK                  0x00000040
> +#define     CFG_RXBITSTO0(rx)                  ((rx) << 5)
> +#define     CFG_RXBITSTO0_MASK                 0x00000020
> +#define     CFG_TXBITSTO0(tx)                  ((tx) << 4)
> +#define     CFG_TXBITSTO0_MASK                 0x00000010
> +#define     CFG_SPI_ENA(spi)                   ((spi) << 3)
> +#define     CFG_SPI_ENA_MASK                   0x00000008
> +#define     CFG_SPI_SEL(spi)                   ((spi) << 2)    /* 1: port1; 0: port0 */
> +#define     CFG_SPI_SEL_MASK                   0x00000004
> +#define     CFG_SPI_3W4WB(wire)                 ((wire)<<1)  /* 1:
> 3-wire; 0: 4-wire */
> +#define     CFG_SPI_3W4WB_MASK                 0x00000002
> +#define     CFG_SPI_START(start)               (start)
> +#define     CFG_SPI_START_MASK                 0x00000001
> +
> +#endif /* __PXA168FBSPI_H__ */
> diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
> index 84d8327..27bdf2b 100644
> --- a/drivers/video/pxa168fb.c
> +++ b/drivers/video/pxa168fb.c
> @@ -29,10 +29,91 @@
>  #include <linux/uaccess.h>
>  #include <video/pxa168fb.h>
>
> +#include <mach/pxa168fb.h>
> +#include <mach/gpio.h>
>  #include "pxa168fb.h"
>
>  #define DEFAULT_REFRESH                60      /* Hz */
>
> +static inline void spi_gpio_assert_set(int spi_gpio_cs, int val)
> +{
> +              if (gpio_is_valid(spi_gpio_cs))
> +                                     gpio_set_value(spi_gpio_cs, val);
> +}
> +
> +int pxa168fb_spi_send(struct pxa168fb_info *fbi, void *value, int count,
> +               unsigned int spi_gpio_cs, unsigned int interval_us)
> +{
> +       u32 x, spi_byte_len;
> +       u8 *cmd = (u8 *)value;
> +       int i, err, isr, iopad, ret = 0;
> +
> +       if (gpio_is_valid(spi_gpio_cs)) {
> +               err = gpio_request(spi_gpio_cs, "LCD_SPI_CS");
> +               if (err) {
> +                       dev_err(fbi->dev, "failed to request GPIO for LCD CS\n");
> +                       return -1;
> +               }
> +               gpio_direction_output(spi_gpio_cs, 1);
> +       }
> +       spi_byte_len = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
> +       spi_byte_len = (spi_byte_len >> 8) & 0xff;
> +       /* Alignment should be (spi_byte_len + 7) >> 3, but
> +        * spi controller request set one less than bit length */
> +       spi_byte_len = (spi_byte_len + 8) >> 3;
> +       /* spi command provided by platform should be 1, 2, or 4 byte aligned */
> +       if(3 == spi_byte_len)
> +               spi_byte_len = 4;
> +
> +       iopad = readl(fbi->reg_base + SPU_IOPAD_CONTROL);
> +       if ((iopad & CFG_IOPADMODE_MASK) != PIN_MODE_DUMB_18_SPI)
> +               writel(PIN_MODE_DUMB_18_SPI, fbi->reg_base + SPU_IOPAD_CONTROL);
> +       isr = readl(fbi->reg_base + SPU_IRQ_ISR);
> +       writel((isr & ~SPI_IRQ_ENA_MASK), fbi->reg_base + SPU_IRQ_ISR);
> +       for (i = 0; i < count; i++) {
> +               spi_gpio_assert_set(spi_gpio_cs, 0);
> +               udelay(interval_us);
> +               switch (spi_byte_len){
> +               case 1:
> +                       writel(*cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
> +                       break;
> +               case 2:
> +                       writel(*(u16*)cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
> +                       break;
> +               case 4:
> +                       writel(*(u32*)cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
> +                       break;
> +               default:
> +                       dev_err(fbi->dev, "Wrong spi bit length\n");
> +                       spi_gpio_assert_set(spi_gpio_cs, 1);
> +                       ret = -1;
> +                       goto spi_exit;
> +               }
> +               cmd += spi_byte_len;
> +               x = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
> +               x |= 0x1;
> +               writel(x, fbi->reg_base + LCD_SPU_SPI_CTRL);
> +               isr = readl(fbi->reg_base + SPU_IRQ_ISR);
> +               while(!(isr & SPI_IRQ_ENA_MASK)) {
> +                       udelay(1);
> +                       isr = readl(fbi->reg_base + SPU_IRQ_ISR);
> +               }
> +               x = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
> +               x &= ~0x1;
> +               writel(x, fbi->reg_base + LCD_SPU_SPI_CTRL);
> +               spi_gpio_assert_set(spi_gpio_cs, 1);
> +       }
> +
> +spi_exit:
> +       if (gpio_is_valid(spi_gpio_cs))
> +               gpio_free(spi_gpio_cs);
> +       if ((iopad & CFG_IOPADMODE_MASK) != PIN_MODE_DUMB_18_SPI)
> +               writel(iopad, fbi->reg_base + SPU_IOPAD_CONTROL);
> +
> +       return ret;
> +}
> +EXPORT_SYMBOL(pxa168fb_spi_send);
> +
>  static int determine_best_pix_fmt(struct fb_var_screeninfo *var)
>  {
>        /*
> @@ -687,6 +768,7 @@ static int __init pxa168fb_probe(struct
> platform_device *pdev)
>        }
>
>        info->fix.smem_start = (unsigned long)fbi->fb_start_dma;
> +       set_graphics_start(info, 0, 0);
>
>        /*
>         * Set video mode according to platform data.
> @@ -728,6 +810,9 @@ static int __init pxa168fb_probe(struct
> platform_device *pdev)
>        writel(0, fbi->reg_base + LCD_SPU_SRAM_PARA0);
>        writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1),
>                fbi->reg_base + LCD_SPU_SRAM_PARA1);
> +       if ((mi->spi_ctrl != -1) && (mi->spi_ctrl & CFG_SPI_ENA_MASK))
> +               writel(mi->spi_ctrl, fbi->reg_base + LCD_SPU_SPI_CTRL);
> +
>
>        /*
>         * Allocate color map.
> @@ -764,6 +849,13 @@ static int __init pxa168fb_probe(struct
> platform_device *pdev)
>        }
>
>        platform_set_drvdata(pdev, fbi);
> +       if (mi->pxa168fb_lcd_power){
> +               if(mi->pxa168fb_lcd_power(fbi, mi->spi_gpio_cs, mi->spi_gpio_reset, 1)){
> +                       dev_err(&pdev->dev, "Failed to power up pxa168-fb\n");
> +                       goto failed_free_irq;
> +               }
> +       }
> +       dev_info(fbi->dev, "frame buffer detected\n");
>        return 0;
>
>  failed_free_irq:
> diff --git a/drivers/video/pxa168fb.h b/drivers/video/pxa168fb.h
> index eee0927..1e4859e 100644
> --- a/drivers/video/pxa168fb.h
> +++ b/drivers/video/pxa168fb.h
> @@ -170,29 +170,7 @@
>  #define     DMA_FRAME_CNT_MASK                 0x00000003  /* Video */
>
>  /* SPI Control Register. */
> -#define LCD_SPU_SPI_CTRL                       0x0180
> -#define     CFG_SCLKCNT(div)                   ((div) << 24)  /* 0xFF~0x2 */
> -#define     CFG_SCLKCNT_MASK                   0xFF000000
> -#define     CFG_RXBITS(rx)                     ((rx) << 16)   /* 0x1F~0x1 */
> -#define     CFG_RXBITS_MASK                    0x00FF0000
> -#define     CFG_TXBITS(tx)                     ((tx) << 8)    /* 0x1F~0x1 */
> -#define     CFG_TXBITS_MASK                    0x0000FF00
> -#define     CFG_CLKINV(clk)                    ((clk) << 7)
> -#define     CFG_CLKINV_MASK                    0x00000080
> -#define     CFG_KEEPXFER(transfer)             ((transfer) << 6)
> -#define     CFG_KEEPXFER_MASK                  0x00000040
> -#define     CFG_RXBITSTO0(rx)                  ((rx) << 5)
> -#define     CFG_RXBITSTO0_MASK                 0x00000020
> -#define     CFG_TXBITSTO0(tx)                  ((tx) << 4)
> -#define     CFG_TXBITSTO0_MASK                 0x00000010
> -#define     CFG_SPI_ENA(spi)                   ((spi) << 3)
> -#define     CFG_SPI_ENA_MASK                   0x00000008
> -#define     CFG_SPI_SEL(spi)                   ((spi) << 2)
> -#define     CFG_SPI_SEL_MASK                   0x00000004
> -#define     CFG_SPI_3W4WB(wire)                        ((wire) << 1)
> -#define     CFG_SPI_3W4WB_MASK                 0x00000002
> -#define     CFG_SPI_START(start)               (start)
> -#define     CFG_SPI_START_MASK                 0x00000001
> +/* For SPI register, please refer to
> arch/arm/mach-mmp/include/mach/pxa168fb.h */
>
>  /* SPI Tx Data Register */
>  #define LCD_SPU_SPI_TXDATA                     0x0184
> diff --git a/include/video/pxa168fb.h b/include/video/pxa168fb.h
> index b5cc72f..f0497ae 100644
> --- a/include/video/pxa168fb.h
> +++ b/include/video/pxa168fb.h
> @@ -122,6 +122,24 @@ struct pxa168fb_mach_info {
>        unsigned        panel_rbswap:1;
>        unsigned        active:1;
>        unsigned        enable_lcd:1;
> +       /*
> +        * SPI control
> +        */
> +       unsigned int    spi_ctrl;
> +       unsigned int    spi_gpio_cs;
> +       unsigned int    spi_gpio_reset;
> +       /*
> +        * power on/off function.
> +        */
> +       int (*pxa168fb_lcd_power)(struct pxa168fb_info *, unsigned int,
> unsigned int, int);
>  };
>
> +/* SPI utility for configure panel SPI command.
> + * value: command array, element should be 1, 2 or 4 byte aligned.
> + * count: command array length
> + * spi_gpio_cs: gpio number for spi chip select
> + * interval_us: time interval between two commands, us as unit */
> +int pxa168fb_spi_send(struct pxa168fb_info *fbi, void *value, int count,
> +               unsigned int spi_gpio_cs, unsigned int interval_us);
> +
>  #endif /* __ASM_MACH_PXA168FB_H */
> --
> 1.5.4.3
>

add linux-fbdev@vger.kernel.org

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/6] pxa: support pxa168 LCD controller SPI operation
@ 2009-11-03  7:28   ` Jun Nie
  0 siblings, 0 replies; 8+ messages in thread
From: Jun Nie @ 2009-11-03  7:28 UTC (permalink / raw)
  To: linux-arm-kernel

2009/11/3 Jun Nie <niej0001@gmail.com>:
> pxa: support pxa168 LCD controller SPI operation
>
> Signed-off-by: Jun Nie <njun@marvell.com>
> ---
> ?arch/arm/mach-mmp/include/mach/pxa168fb.h | ? 29 +++++++++
> ?drivers/video/pxa168fb.c ? ? ? ? ? ? ? ? ?| ? 92 +++++++++++++++++++++++++++++
> ?drivers/video/pxa168fb.h ? ? ? ? ? ? ? ? ?| ? 24 +-------
> ?include/video/pxa168fb.h ? ? ? ? ? ? ? ? ?| ? 18 ++++++
> ?4 files changed, 140 insertions(+), 23 deletions(-)
> ?create mode 100644 arch/arm/mach-mmp/include/mach/pxa168fb.h
>
> diff --git a/arch/arm/mach-mmp/include/mach/pxa168fb.h
> b/arch/arm/mach-mmp/include/mach/pxa168fb.h
> new file mode 100644
> index 0000000..897cc3e
> --- /dev/null
> +++ b/arch/arm/mach-mmp/include/mach/pxa168fb.h
> @@ -0,0 +1,29 @@
> +#ifndef __PXA168FBSPI_H__
> +#define __PXA168FBSPI_H__
> +
> +/* SPI Control Register. */
> +#define LCD_SPU_SPI_CTRL ? ? ? ? ? ? ? ? ? ? ? 0x0180
> +#define ? ? CFG_SCLKCNT(div) ? ? ? ? ? ? ? ? ? ((div) << 24) ?/* 0xFF~0x2 */
> +#define ? ? CFG_SCLKCNT_MASK ? ? ? ? ? ? ? ? ? 0xFF000000
> +#define ? ? CFG_RXBITS(rx) ? ? ? ? ? ? ? ? ? ? ((rx - 1) << 16) ? /* 0x1F~0x1, 0x1:
> 2bits ... 0x1F: 32bits */
> +#define ? ? CFG_RXBITS_MASK ? ? ? ? ? ? ? ? ? ?0x00FF0000
> +#define ? ? CFG_TXBITS(tx) ? ? ? ? ? ? ? ? ? ? ?((tx - 1) << 8) ? ?/*
> 0x1F~0x1, 0x1: 2bits ... 0x1F: 32bits */
> +#define ? ? CFG_TXBITS_MASK ? ? ? ? ? ? ? ? ? ?0x0000FF00
> +#define ? ? CFG_CLKINV(clk) ? ? ? ? ? ? ? ? ? ?((clk) << 7)
> +#define ? ? CFG_CLKINV_MASK ? ? ? ? ? ? ? ? ? ?0x00000080
> +#define ? ? CFG_KEEPXFER(transfer) ? ? ? ? ? ? ((transfer) << 6)
> +#define ? ? CFG_KEEPXFER_MASK ? ? ? ? ? ? ? ? ?0x00000040
> +#define ? ? CFG_RXBITSTO0(rx) ? ? ? ? ? ? ? ? ?((rx) << 5)
> +#define ? ? CFG_RXBITSTO0_MASK ? ? ? ? ? ? ? ? 0x00000020
> +#define ? ? CFG_TXBITSTO0(tx) ? ? ? ? ? ? ? ? ?((tx) << 4)
> +#define ? ? CFG_TXBITSTO0_MASK ? ? ? ? ? ? ? ? 0x00000010
> +#define ? ? CFG_SPI_ENA(spi) ? ? ? ? ? ? ? ? ? ((spi) << 3)
> +#define ? ? CFG_SPI_ENA_MASK ? ? ? ? ? ? ? ? ? 0x00000008
> +#define ? ? CFG_SPI_SEL(spi) ? ? ? ? ? ? ? ? ? ((spi) << 2) ? ?/* 1: port1; 0: port0 */
> +#define ? ? CFG_SPI_SEL_MASK ? ? ? ? ? ? ? ? ? 0x00000004
> +#define ? ? CFG_SPI_3W4WB(wire) ? ? ? ? ? ? ? ? ((wire)<<1) ?/* 1:
> 3-wire; 0: 4-wire */
> +#define ? ? CFG_SPI_3W4WB_MASK ? ? ? ? ? ? ? ? 0x00000002
> +#define ? ? CFG_SPI_START(start) ? ? ? ? ? ? ? (start)
> +#define ? ? CFG_SPI_START_MASK ? ? ? ? ? ? ? ? 0x00000001
> +
> +#endif /* __PXA168FBSPI_H__ */
> diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
> index 84d8327..27bdf2b 100644
> --- a/drivers/video/pxa168fb.c
> +++ b/drivers/video/pxa168fb.c
> @@ -29,10 +29,91 @@
> ?#include <linux/uaccess.h>
> ?#include <video/pxa168fb.h>
>
> +#include <mach/pxa168fb.h>
> +#include <mach/gpio.h>
> ?#include "pxa168fb.h"
>
> ?#define DEFAULT_REFRESH ? ? ? ? ? ? ? ?60 ? ? ?/* Hz */
>
> +static inline void spi_gpio_assert_set(int spi_gpio_cs, int val)
> +{
> + ? ? ? ? ? ? ?if (gpio_is_valid(spi_gpio_cs))
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? gpio_set_value(spi_gpio_cs, val);
> +}
> +
> +int pxa168fb_spi_send(struct pxa168fb_info *fbi, void *value, int count,
> + ? ? ? ? ? ? ? unsigned int spi_gpio_cs, unsigned int interval_us)
> +{
> + ? ? ? u32 x, spi_byte_len;
> + ? ? ? u8 *cmd = (u8 *)value;
> + ? ? ? int i, err, isr, iopad, ret = 0;
> +
> + ? ? ? if (gpio_is_valid(spi_gpio_cs)) {
> + ? ? ? ? ? ? ? err = gpio_request(spi_gpio_cs, "LCD_SPI_CS");
> + ? ? ? ? ? ? ? if (err) {
> + ? ? ? ? ? ? ? ? ? ? ? dev_err(fbi->dev, "failed to request GPIO for LCD CS\n");
> + ? ? ? ? ? ? ? ? ? ? ? return -1;
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? gpio_direction_output(spi_gpio_cs, 1);
> + ? ? ? }
> + ? ? ? spi_byte_len = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
> + ? ? ? spi_byte_len = (spi_byte_len >> 8) & 0xff;
> + ? ? ? /* Alignment should be (spi_byte_len + 7) >> 3, but
> + ? ? ? ?* spi controller request set one less than bit length */
> + ? ? ? spi_byte_len = (spi_byte_len + 8) >> 3;
> + ? ? ? /* spi command provided by platform should be 1, 2, or 4 byte aligned */
> + ? ? ? if(3 == spi_byte_len)
> + ? ? ? ? ? ? ? spi_byte_len = 4;
> +
> + ? ? ? iopad = readl(fbi->reg_base + SPU_IOPAD_CONTROL);
> + ? ? ? if ((iopad & CFG_IOPADMODE_MASK) != PIN_MODE_DUMB_18_SPI)
> + ? ? ? ? ? ? ? writel(PIN_MODE_DUMB_18_SPI, fbi->reg_base + SPU_IOPAD_CONTROL);
> + ? ? ? isr = readl(fbi->reg_base + SPU_IRQ_ISR);
> + ? ? ? writel((isr & ~SPI_IRQ_ENA_MASK), fbi->reg_base + SPU_IRQ_ISR);
> + ? ? ? for (i = 0; i < count; i++) {
> + ? ? ? ? ? ? ? spi_gpio_assert_set(spi_gpio_cs, 0);
> + ? ? ? ? ? ? ? udelay(interval_us);
> + ? ? ? ? ? ? ? switch (spi_byte_len){
> + ? ? ? ? ? ? ? case 1:
> + ? ? ? ? ? ? ? ? ? ? ? writel(*cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? case 2:
> + ? ? ? ? ? ? ? ? ? ? ? writel(*(u16*)cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? case 4:
> + ? ? ? ? ? ? ? ? ? ? ? writel(*(u32*)cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? default:
> + ? ? ? ? ? ? ? ? ? ? ? dev_err(fbi->dev, "Wrong spi bit length\n");
> + ? ? ? ? ? ? ? ? ? ? ? spi_gpio_assert_set(spi_gpio_cs, 1);
> + ? ? ? ? ? ? ? ? ? ? ? ret = -1;
> + ? ? ? ? ? ? ? ? ? ? ? goto spi_exit;
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? cmd += spi_byte_len;
> + ? ? ? ? ? ? ? x = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
> + ? ? ? ? ? ? ? x |= 0x1;
> + ? ? ? ? ? ? ? writel(x, fbi->reg_base + LCD_SPU_SPI_CTRL);
> + ? ? ? ? ? ? ? isr = readl(fbi->reg_base + SPU_IRQ_ISR);
> + ? ? ? ? ? ? ? while(!(isr & SPI_IRQ_ENA_MASK)) {
> + ? ? ? ? ? ? ? ? ? ? ? udelay(1);
> + ? ? ? ? ? ? ? ? ? ? ? isr = readl(fbi->reg_base + SPU_IRQ_ISR);
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? x = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
> + ? ? ? ? ? ? ? x &= ~0x1;
> + ? ? ? ? ? ? ? writel(x, fbi->reg_base + LCD_SPU_SPI_CTRL);
> + ? ? ? ? ? ? ? spi_gpio_assert_set(spi_gpio_cs, 1);
> + ? ? ? }
> +
> +spi_exit:
> + ? ? ? if (gpio_is_valid(spi_gpio_cs))
> + ? ? ? ? ? ? ? gpio_free(spi_gpio_cs);
> + ? ? ? if ((iopad & CFG_IOPADMODE_MASK) != PIN_MODE_DUMB_18_SPI)
> + ? ? ? ? ? ? ? writel(iopad, fbi->reg_base + SPU_IOPAD_CONTROL);
> +
> + ? ? ? return ret;
> +}
> +EXPORT_SYMBOL(pxa168fb_spi_send);
> +
> ?static int determine_best_pix_fmt(struct fb_var_screeninfo *var)
> ?{
> ? ? ? ?/*
> @@ -687,6 +768,7 @@ static int __init pxa168fb_probe(struct
> platform_device *pdev)
> ? ? ? ?}
>
> ? ? ? ?info->fix.smem_start = (unsigned long)fbi->fb_start_dma;
> + ? ? ? set_graphics_start(info, 0, 0);
>
> ? ? ? ?/*
> ? ? ? ? * Set video mode according to platform data.
> @@ -728,6 +810,9 @@ static int __init pxa168fb_probe(struct
> platform_device *pdev)
> ? ? ? ?writel(0, fbi->reg_base + LCD_SPU_SRAM_PARA0);
> ? ? ? ?writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1),
> ? ? ? ? ? ? ? ?fbi->reg_base + LCD_SPU_SRAM_PARA1);
> + ? ? ? if ((mi->spi_ctrl != -1) && (mi->spi_ctrl & CFG_SPI_ENA_MASK))
> + ? ? ? ? ? ? ? writel(mi->spi_ctrl, fbi->reg_base + LCD_SPU_SPI_CTRL);
> +
>
> ? ? ? ?/*
> ? ? ? ? * Allocate color map.
> @@ -764,6 +849,13 @@ static int __init pxa168fb_probe(struct
> platform_device *pdev)
> ? ? ? ?}
>
> ? ? ? ?platform_set_drvdata(pdev, fbi);
> + ? ? ? if (mi->pxa168fb_lcd_power){
> + ? ? ? ? ? ? ? if(mi->pxa168fb_lcd_power(fbi, mi->spi_gpio_cs, mi->spi_gpio_reset, 1)){
> + ? ? ? ? ? ? ? ? ? ? ? dev_err(&pdev->dev, "Failed to power up pxa168-fb\n");
> + ? ? ? ? ? ? ? ? ? ? ? goto failed_free_irq;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> + ? ? ? dev_info(fbi->dev, "frame buffer detected\n");
> ? ? ? ?return 0;
>
> ?failed_free_irq:
> diff --git a/drivers/video/pxa168fb.h b/drivers/video/pxa168fb.h
> index eee0927..1e4859e 100644
> --- a/drivers/video/pxa168fb.h
> +++ b/drivers/video/pxa168fb.h
> @@ -170,29 +170,7 @@
> ?#define ? ? DMA_FRAME_CNT_MASK ? ? ? ? ? ? ? ? 0x00000003 ?/* Video */
>
> ?/* SPI Control Register. */
> -#define LCD_SPU_SPI_CTRL ? ? ? ? ? ? ? ? ? ? ? 0x0180
> -#define ? ? CFG_SCLKCNT(div) ? ? ? ? ? ? ? ? ? ((div) << 24) ?/* 0xFF~0x2 */
> -#define ? ? CFG_SCLKCNT_MASK ? ? ? ? ? ? ? ? ? 0xFF000000
> -#define ? ? CFG_RXBITS(rx) ? ? ? ? ? ? ? ? ? ? ((rx) << 16) ? /* 0x1F~0x1 */
> -#define ? ? CFG_RXBITS_MASK ? ? ? ? ? ? ? ? ? ?0x00FF0000
> -#define ? ? CFG_TXBITS(tx) ? ? ? ? ? ? ? ? ? ? ((tx) << 8) ? ?/* 0x1F~0x1 */
> -#define ? ? CFG_TXBITS_MASK ? ? ? ? ? ? ? ? ? ?0x0000FF00
> -#define ? ? CFG_CLKINV(clk) ? ? ? ? ? ? ? ? ? ?((clk) << 7)
> -#define ? ? CFG_CLKINV_MASK ? ? ? ? ? ? ? ? ? ?0x00000080
> -#define ? ? CFG_KEEPXFER(transfer) ? ? ? ? ? ? ((transfer) << 6)
> -#define ? ? CFG_KEEPXFER_MASK ? ? ? ? ? ? ? ? ?0x00000040
> -#define ? ? CFG_RXBITSTO0(rx) ? ? ? ? ? ? ? ? ?((rx) << 5)
> -#define ? ? CFG_RXBITSTO0_MASK ? ? ? ? ? ? ? ? 0x00000020
> -#define ? ? CFG_TXBITSTO0(tx) ? ? ? ? ? ? ? ? ?((tx) << 4)
> -#define ? ? CFG_TXBITSTO0_MASK ? ? ? ? ? ? ? ? 0x00000010
> -#define ? ? CFG_SPI_ENA(spi) ? ? ? ? ? ? ? ? ? ((spi) << 3)
> -#define ? ? CFG_SPI_ENA_MASK ? ? ? ? ? ? ? ? ? 0x00000008
> -#define ? ? CFG_SPI_SEL(spi) ? ? ? ? ? ? ? ? ? ((spi) << 2)
> -#define ? ? CFG_SPI_SEL_MASK ? ? ? ? ? ? ? ? ? 0x00000004
> -#define ? ? CFG_SPI_3W4WB(wire) ? ? ? ? ? ? ? ? ? ? ? ?((wire) << 1)
> -#define ? ? CFG_SPI_3W4WB_MASK ? ? ? ? ? ? ? ? 0x00000002
> -#define ? ? CFG_SPI_START(start) ? ? ? ? ? ? ? (start)
> -#define ? ? CFG_SPI_START_MASK ? ? ? ? ? ? ? ? 0x00000001
> +/* For SPI register, please refer to
> arch/arm/mach-mmp/include/mach/pxa168fb.h */
>
> ?/* SPI Tx Data Register */
> ?#define LCD_SPU_SPI_TXDATA ? ? ? ? ? ? ? ? ? ? 0x0184
> diff --git a/include/video/pxa168fb.h b/include/video/pxa168fb.h
> index b5cc72f..f0497ae 100644
> --- a/include/video/pxa168fb.h
> +++ b/include/video/pxa168fb.h
> @@ -122,6 +122,24 @@ struct pxa168fb_mach_info {
> ? ? ? ?unsigned ? ? ? ?panel_rbswap:1;
> ? ? ? ?unsigned ? ? ? ?active:1;
> ? ? ? ?unsigned ? ? ? ?enable_lcd:1;
> + ? ? ? /*
> + ? ? ? ?* SPI control
> + ? ? ? ?*/
> + ? ? ? unsigned int ? ?spi_ctrl;
> + ? ? ? unsigned int ? ?spi_gpio_cs;
> + ? ? ? unsigned int ? ?spi_gpio_reset;
> + ? ? ? /*
> + ? ? ? ?* power on/off function.
> + ? ? ? ?*/
> + ? ? ? int (*pxa168fb_lcd_power)(struct pxa168fb_info *, unsigned int,
> unsigned int, int);
> ?};
>
> +/* SPI utility for configure panel SPI command.
> + * value: command array, element should be 1, 2 or 4 byte aligned.
> + * count: command array length
> + * spi_gpio_cs: gpio number for spi chip select
> + * interval_us: time interval between two commands, us as unit */
> +int pxa168fb_spi_send(struct pxa168fb_info *fbi, void *value, int count,
> + ? ? ? ? ? ? ? unsigned int spi_gpio_cs, unsigned int interval_us);
> +
> ?#endif /* __ASM_MACH_PXA168FB_H */
> --
> 1.5.4.3
>

add linux-fbdev at vger.kernel.org

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/6] pxa: support pxa168 LCD controller SPI operation
  2009-11-03  6:45 ` Jun Nie
@ 2009-11-03  8:32   ` Eric Miao
  -1 siblings, 0 replies; 8+ messages in thread
From: Eric Miao @ 2009-11-03  8:32 UTC (permalink / raw)
  To: Jun Nie; +Cc: linux-fbdev-devel, linux-arm-kernel

On Tue, Nov 3, 2009 at 2:45 PM, Jun Nie <niej0001@gmail.com> wrote:
> pxa: support pxa168 LCD controller SPI operation
>
> Signed-off-by: Jun Nie <njun@marvell.com>
> ---
>  arch/arm/mach-mmp/include/mach/pxa168fb.h |   29 +++++++++
>  drivers/video/pxa168fb.c                  |   92 +++++++++++++++++++++++++++++
>  drivers/video/pxa168fb.h                  |   24 +-------
>  include/video/pxa168fb.h                  |   18 ++++++
>  4 files changed, 140 insertions(+), 23 deletions(-)
>  create mode 100644 arch/arm/mach-mmp/include/mach/pxa168fb.h
>
> diff --git a/arch/arm/mach-mmp/include/mach/pxa168fb.h
> b/arch/arm/mach-mmp/include/mach/pxa168fb.h
> new file mode 100644
> index 0000000..897cc3e
> --- /dev/null
> +++ b/arch/arm/mach-mmp/include/mach/pxa168fb.h
> @@ -0,0 +1,29 @@
> +#ifndef __PXA168FBSPI_H__
> +#define __PXA168FBSPI_H__
> +
> +/* SPI Control Register. */
> +#define LCD_SPU_SPI_CTRL                       0x0180
> +#define     CFG_SCLKCNT(div)                   ((div) << 24)  /* 0xFF~0x2 */
> +#define     CFG_SCLKCNT_MASK                   0xFF000000
> +#define     CFG_RXBITS(rx)                     ((rx - 1) << 16)   /* 0x1F~0x1, 0x1:
> 2bits ... 0x1F: 32bits */
> +#define     CFG_RXBITS_MASK                    0x00FF0000
> +#define     CFG_TXBITS(tx)                      ((tx - 1) << 8)    /*
> 0x1F~0x1, 0x1: 2bits ... 0x1F: 32bits */
> +#define     CFG_TXBITS_MASK                    0x0000FF00
> +#define     CFG_CLKINV(clk)                    ((clk) << 7)
> +#define     CFG_CLKINV_MASK                    0x00000080
> +#define     CFG_KEEPXFER(transfer)             ((transfer) << 6)
> +#define     CFG_KEEPXFER_MASK                  0x00000040
> +#define     CFG_RXBITSTO0(rx)                  ((rx) << 5)
> +#define     CFG_RXBITSTO0_MASK                 0x00000020
> +#define     CFG_TXBITSTO0(tx)                  ((tx) << 4)
> +#define     CFG_TXBITSTO0_MASK                 0x00000010
> +#define     CFG_SPI_ENA(spi)                   ((spi) << 3)
> +#define     CFG_SPI_ENA_MASK                   0x00000008
> +#define     CFG_SPI_SEL(spi)                   ((spi) << 2)    /* 1: port1; 0: port0 */
> +#define     CFG_SPI_SEL_MASK                   0x00000004
> +#define     CFG_SPI_3W4WB(wire)                 ((wire)<<1)  /* 1:
> 3-wire; 0: 4-wire */
> +#define     CFG_SPI_3W4WB_MASK                 0x00000002
> +#define     CFG_SPI_START(start)               (start)
> +#define     CFG_SPI_START_MASK                 0x00000001
> +
> +#endif /* __PXA168FBSPI_H__ */

Shouldn't these be defined in drivers/video/pxa168fb.h? Or if
some of the definitions are to be used by platform code, move
them to include/video/pxa168fb.h.

> diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
> index 84d8327..27bdf2b 100644
> --- a/drivers/video/pxa168fb.c
> +++ b/drivers/video/pxa168fb.c
> @@ -29,10 +29,91 @@
>  #include <linux/uaccess.h>
>  #include <video/pxa168fb.h>
>
> +#include <mach/pxa168fb.h>
> +#include <mach/gpio.h>
>  #include "pxa168fb.h"
>
>  #define DEFAULT_REFRESH                60      /* Hz */
>
> +static inline void spi_gpio_assert_set(int spi_gpio_cs, int val)
> +{
> +              if (gpio_is_valid(spi_gpio_cs))
> +                                     gpio_set_value(spi_gpio_cs, val);
> +}

Mmm.... two points:

1. spi_gpio_assert() sounds enough to me, no "_set" suffix necessary
2. is it possible that in some cases that this GPIO CS signal is inverted?

> +int pxa168fb_spi_send(struct pxa168fb_info *fbi, void *value, int count,
> +               unsigned int spi_gpio_cs, unsigned int interval_us)
> +{
> +       u32 x, spi_byte_len;
> +       u8 *cmd = (u8 *)value;
> +       int i, err, isr, iopad, ret = 0;
> +
> +       if (gpio_is_valid(spi_gpio_cs)) {
> +               err = gpio_request(spi_gpio_cs, "LCD_SPI_CS");
> +               if (err) {
> +                       dev_err(fbi->dev, "failed to request GPIO for LCD CS\n");
> +                       return -1;
> +               }
> +               gpio_direction_output(spi_gpio_cs, 1);
> +       }

Is this possible this been done at some initialization stage and do only once?

> +       spi_byte_len = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
> +       spi_byte_len = (spi_byte_len >> 8) & 0xff;
> +       /* Alignment should be (spi_byte_len + 7) >> 3, but
> +        * spi controller request set one less than bit length */
> +       spi_byte_len = (spi_byte_len + 8) >> 3;
> +       /* spi command provided by platform should be 1, 2, or 4 byte aligned */
> +       if(3 == spi_byte_len)
> +               spi_byte_len = 4;
> +
> +       iopad = readl(fbi->reg_base + SPU_IOPAD_CONTROL);
> +       if ((iopad & CFG_IOPADMODE_MASK) != PIN_MODE_DUMB_18_SPI)
> +               writel(PIN_MODE_DUMB_18_SPI, fbi->reg_base + SPU_IOPAD_CONTROL);
> +       isr = readl(fbi->reg_base + SPU_IRQ_ISR);
> +       writel((isr & ~SPI_IRQ_ENA_MASK), fbi->reg_base + SPU_IRQ_ISR);
> +       for (i = 0; i < count; i++) {
> +               spi_gpio_assert_set(spi_gpio_cs, 0);
> +               udelay(interval_us);
> +               switch (spi_byte_len){
> +               case 1:
> +                       writel(*cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
> +                       break;
> +               case 2:
> +                       writel(*(u16*)cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
> +                       break;
> +               case 4:
> +                       writel(*(u32*)cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
> +                       break;
> +               default:
> +                       dev_err(fbi->dev, "Wrong spi bit length\n");
> +                       spi_gpio_assert_set(spi_gpio_cs, 1);
> +                       ret = -1;
> +                       goto spi_exit;
> +               }
> +               cmd += spi_byte_len;
> +               x = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
> +               x |= 0x1;
> +               writel(x, fbi->reg_base + LCD_SPU_SPI_CTRL);
> +               isr = readl(fbi->reg_base + SPU_IRQ_ISR);
> +               while(!(isr & SPI_IRQ_ENA_MASK)) {
> +                       udelay(1);
> +                       isr = readl(fbi->reg_base + SPU_IRQ_ISR);
> +               }
> +               x = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
> +               x &= ~0x1;
> +               writel(x, fbi->reg_base + LCD_SPU_SPI_CTRL);
> +               spi_gpio_assert_set(spi_gpio_cs, 1);
> +       }

So after this loop, the 'spi_gpio_cs' is left asserted, which isn't good.

> +
> +spi_exit:
> +       if (gpio_is_valid(spi_gpio_cs))
> +               gpio_free(spi_gpio_cs);
> +       if ((iopad & CFG_IOPADMODE_MASK) != PIN_MODE_DUMB_18_SPI)
> +               writel(iopad, fbi->reg_base + SPU_IOPAD_CONTROL);
> +
> +       return ret;
> +}
> +EXPORT_SYMBOL(pxa168fb_spi_send);
> +
>  static int determine_best_pix_fmt(struct fb_var_screeninfo *var)
>  {
>        /*
> @@ -687,6 +768,7 @@ static int __init pxa168fb_probe(struct
> platform_device *pdev)
>        }
>
>        info->fix.smem_start = (unsigned long)fbi->fb_start_dma;
> +       set_graphics_start(info, 0, 0);

This need a separate patch.

>
>        /*
>         * Set video mode according to platform data.
> @@ -728,6 +810,9 @@ static int __init pxa168fb_probe(struct
> platform_device *pdev)
>        writel(0, fbi->reg_base + LCD_SPU_SRAM_PARA0);
>        writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1),
>                fbi->reg_base + LCD_SPU_SRAM_PARA1);
> +       if ((mi->spi_ctrl != -1) && (mi->spi_ctrl & CFG_SPI_ENA_MASK))
> +               writel(mi->spi_ctrl, fbi->reg_base + LCD_SPU_SPI_CTRL);
> +
>
>        /*
>         * Allocate color map.
> @@ -764,6 +849,13 @@ static int __init pxa168fb_probe(struct
> platform_device *pdev)
>        }
>
>        platform_set_drvdata(pdev, fbi);
> +       if (mi->pxa168fb_lcd_power){
> +               if(mi->pxa168fb_lcd_power(fbi, mi->spi_gpio_cs, mi->spi_gpio_reset, 1)){
> +                       dev_err(&pdev->dev, "Failed to power up pxa168-fb\n");
> +                       goto failed_free_irq;
> +               }
> +       }
> +       dev_info(fbi->dev, "frame buffer detected\n");

Need another patch for this as well?

>        return 0;
>
>  failed_free_irq:
> diff --git a/drivers/video/pxa168fb.h b/drivers/video/pxa168fb.h
> index eee0927..1e4859e 100644
> --- a/drivers/video/pxa168fb.h
> +++ b/drivers/video/pxa168fb.h
> @@ -170,29 +170,7 @@
>  #define     DMA_FRAME_CNT_MASK                 0x00000003  /* Video */
>
>  /* SPI Control Register. */
> -#define LCD_SPU_SPI_CTRL                       0x0180
> -#define     CFG_SCLKCNT(div)                   ((div) << 24)  /* 0xFF~0x2 */
> -#define     CFG_SCLKCNT_MASK                   0xFF000000
> -#define     CFG_RXBITS(rx)                     ((rx) << 16)   /* 0x1F~0x1 */
> -#define     CFG_RXBITS_MASK                    0x00FF0000
> -#define     CFG_TXBITS(tx)                     ((tx) << 8)    /* 0x1F~0x1 */
> -#define     CFG_TXBITS_MASK                    0x0000FF00
> -#define     CFG_CLKINV(clk)                    ((clk) << 7)
> -#define     CFG_CLKINV_MASK                    0x00000080
> -#define     CFG_KEEPXFER(transfer)             ((transfer) << 6)
> -#define     CFG_KEEPXFER_MASK                  0x00000040
> -#define     CFG_RXBITSTO0(rx)                  ((rx) << 5)
> -#define     CFG_RXBITSTO0_MASK                 0x00000020
> -#define     CFG_TXBITSTO0(tx)                  ((tx) << 4)
> -#define     CFG_TXBITSTO0_MASK                 0x00000010
> -#define     CFG_SPI_ENA(spi)                   ((spi) << 3)
> -#define     CFG_SPI_ENA_MASK                   0x00000008
> -#define     CFG_SPI_SEL(spi)                   ((spi) << 2)
> -#define     CFG_SPI_SEL_MASK                   0x00000004
> -#define     CFG_SPI_3W4WB(wire)                        ((wire) << 1)
> -#define     CFG_SPI_3W4WB_MASK                 0x00000002
> -#define     CFG_SPI_START(start)               (start)
> -#define     CFG_SPI_START_MASK                 0x00000001
> +/* For SPI register, please refer to
> arch/arm/mach-mmp/include/mach/pxa168fb.h */
>
>  /* SPI Tx Data Register */
>  #define LCD_SPU_SPI_TXDATA                     0x0184
> diff --git a/include/video/pxa168fb.h b/include/video/pxa168fb.h
> index b5cc72f..f0497ae 100644
> --- a/include/video/pxa168fb.h
> +++ b/include/video/pxa168fb.h
> @@ -122,6 +122,24 @@ struct pxa168fb_mach_info {
>        unsigned        panel_rbswap:1;
>        unsigned        active:1;
>        unsigned        enable_lcd:1;
> +       /*
> +        * SPI control
> +        */
> +       unsigned int    spi_ctrl;
> +       unsigned int    spi_gpio_cs;
> +       unsigned int    spi_gpio_reset;
> +       /*
> +        * power on/off function.
> +        */
> +       int (*pxa168fb_lcd_power)(struct pxa168fb_info *, unsigned int,
> unsigned int, int);
>  };
>
> +/* SPI utility for configure panel SPI command.
> + * value: command array, element should be 1, 2 or 4 byte aligned.
> + * count: command array length
> + * spi_gpio_cs: gpio number for spi chip select
> + * interval_us: time interval between two commands, us as unit */
> +int pxa168fb_spi_send(struct pxa168fb_info *fbi, void *value, int count,
> +               unsigned int spi_gpio_cs, unsigned int interval_us);
> +
>  #endif /* __ASM_MACH_PXA168FB_H */
> --
> 1.5.4.3
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Linux-fbdev-devel mailing list
Linux-fbdev-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/6] pxa: support pxa168 LCD controller SPI operation
@ 2009-11-03  8:32   ` Eric Miao
  0 siblings, 0 replies; 8+ messages in thread
From: Eric Miao @ 2009-11-03  8:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Nov 3, 2009 at 2:45 PM, Jun Nie <niej0001@gmail.com> wrote:
> pxa: support pxa168 LCD controller SPI operation
>
> Signed-off-by: Jun Nie <njun@marvell.com>
> ---
> ?arch/arm/mach-mmp/include/mach/pxa168fb.h | ? 29 +++++++++
> ?drivers/video/pxa168fb.c ? ? ? ? ? ? ? ? ?| ? 92 +++++++++++++++++++++++++++++
> ?drivers/video/pxa168fb.h ? ? ? ? ? ? ? ? ?| ? 24 +-------
> ?include/video/pxa168fb.h ? ? ? ? ? ? ? ? ?| ? 18 ++++++
> ?4 files changed, 140 insertions(+), 23 deletions(-)
> ?create mode 100644 arch/arm/mach-mmp/include/mach/pxa168fb.h
>
> diff --git a/arch/arm/mach-mmp/include/mach/pxa168fb.h
> b/arch/arm/mach-mmp/include/mach/pxa168fb.h
> new file mode 100644
> index 0000000..897cc3e
> --- /dev/null
> +++ b/arch/arm/mach-mmp/include/mach/pxa168fb.h
> @@ -0,0 +1,29 @@
> +#ifndef __PXA168FBSPI_H__
> +#define __PXA168FBSPI_H__
> +
> +/* SPI Control Register. */
> +#define LCD_SPU_SPI_CTRL ? ? ? ? ? ? ? ? ? ? ? 0x0180
> +#define ? ? CFG_SCLKCNT(div) ? ? ? ? ? ? ? ? ? ((div) << 24) ?/* 0xFF~0x2 */
> +#define ? ? CFG_SCLKCNT_MASK ? ? ? ? ? ? ? ? ? 0xFF000000
> +#define ? ? CFG_RXBITS(rx) ? ? ? ? ? ? ? ? ? ? ((rx - 1) << 16) ? /* 0x1F~0x1, 0x1:
> 2bits ... 0x1F: 32bits */
> +#define ? ? CFG_RXBITS_MASK ? ? ? ? ? ? ? ? ? ?0x00FF0000
> +#define ? ? CFG_TXBITS(tx) ? ? ? ? ? ? ? ? ? ? ?((tx - 1) << 8) ? ?/*
> 0x1F~0x1, 0x1: 2bits ... 0x1F: 32bits */
> +#define ? ? CFG_TXBITS_MASK ? ? ? ? ? ? ? ? ? ?0x0000FF00
> +#define ? ? CFG_CLKINV(clk) ? ? ? ? ? ? ? ? ? ?((clk) << 7)
> +#define ? ? CFG_CLKINV_MASK ? ? ? ? ? ? ? ? ? ?0x00000080
> +#define ? ? CFG_KEEPXFER(transfer) ? ? ? ? ? ? ((transfer) << 6)
> +#define ? ? CFG_KEEPXFER_MASK ? ? ? ? ? ? ? ? ?0x00000040
> +#define ? ? CFG_RXBITSTO0(rx) ? ? ? ? ? ? ? ? ?((rx) << 5)
> +#define ? ? CFG_RXBITSTO0_MASK ? ? ? ? ? ? ? ? 0x00000020
> +#define ? ? CFG_TXBITSTO0(tx) ? ? ? ? ? ? ? ? ?((tx) << 4)
> +#define ? ? CFG_TXBITSTO0_MASK ? ? ? ? ? ? ? ? 0x00000010
> +#define ? ? CFG_SPI_ENA(spi) ? ? ? ? ? ? ? ? ? ((spi) << 3)
> +#define ? ? CFG_SPI_ENA_MASK ? ? ? ? ? ? ? ? ? 0x00000008
> +#define ? ? CFG_SPI_SEL(spi) ? ? ? ? ? ? ? ? ? ((spi) << 2) ? ?/* 1: port1; 0: port0 */
> +#define ? ? CFG_SPI_SEL_MASK ? ? ? ? ? ? ? ? ? 0x00000004
> +#define ? ? CFG_SPI_3W4WB(wire) ? ? ? ? ? ? ? ? ((wire)<<1) ?/* 1:
> 3-wire; 0: 4-wire */
> +#define ? ? CFG_SPI_3W4WB_MASK ? ? ? ? ? ? ? ? 0x00000002
> +#define ? ? CFG_SPI_START(start) ? ? ? ? ? ? ? (start)
> +#define ? ? CFG_SPI_START_MASK ? ? ? ? ? ? ? ? 0x00000001
> +
> +#endif /* __PXA168FBSPI_H__ */

Shouldn't these be defined in drivers/video/pxa168fb.h? Or if
some of the definitions are to be used by platform code, move
them to include/video/pxa168fb.h.

> diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
> index 84d8327..27bdf2b 100644
> --- a/drivers/video/pxa168fb.c
> +++ b/drivers/video/pxa168fb.c
> @@ -29,10 +29,91 @@
> ?#include <linux/uaccess.h>
> ?#include <video/pxa168fb.h>
>
> +#include <mach/pxa168fb.h>
> +#include <mach/gpio.h>
> ?#include "pxa168fb.h"
>
> ?#define DEFAULT_REFRESH ? ? ? ? ? ? ? ?60 ? ? ?/* Hz */
>
> +static inline void spi_gpio_assert_set(int spi_gpio_cs, int val)
> +{
> + ? ? ? ? ? ? ?if (gpio_is_valid(spi_gpio_cs))
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? gpio_set_value(spi_gpio_cs, val);
> +}

Mmm.... two points:

1. spi_gpio_assert() sounds enough to me, no "_set" suffix necessary
2. is it possible that in some cases that this GPIO CS signal is inverted?

> +int pxa168fb_spi_send(struct pxa168fb_info *fbi, void *value, int count,
> + ? ? ? ? ? ? ? unsigned int spi_gpio_cs, unsigned int interval_us)
> +{
> + ? ? ? u32 x, spi_byte_len;
> + ? ? ? u8 *cmd = (u8 *)value;
> + ? ? ? int i, err, isr, iopad, ret = 0;
> +
> + ? ? ? if (gpio_is_valid(spi_gpio_cs)) {
> + ? ? ? ? ? ? ? err = gpio_request(spi_gpio_cs, "LCD_SPI_CS");
> + ? ? ? ? ? ? ? if (err) {
> + ? ? ? ? ? ? ? ? ? ? ? dev_err(fbi->dev, "failed to request GPIO for LCD CS\n");
> + ? ? ? ? ? ? ? ? ? ? ? return -1;
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? gpio_direction_output(spi_gpio_cs, 1);
> + ? ? ? }

Is this possible this been done at some initialization stage and do only once?

> + ? ? ? spi_byte_len = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
> + ? ? ? spi_byte_len = (spi_byte_len >> 8) & 0xff;
> + ? ? ? /* Alignment should be (spi_byte_len + 7) >> 3, but
> + ? ? ? ?* spi controller request set one less than bit length */
> + ? ? ? spi_byte_len = (spi_byte_len + 8) >> 3;
> + ? ? ? /* spi command provided by platform should be 1, 2, or 4 byte aligned */
> + ? ? ? if(3 == spi_byte_len)
> + ? ? ? ? ? ? ? spi_byte_len = 4;
> +
> + ? ? ? iopad = readl(fbi->reg_base + SPU_IOPAD_CONTROL);
> + ? ? ? if ((iopad & CFG_IOPADMODE_MASK) != PIN_MODE_DUMB_18_SPI)
> + ? ? ? ? ? ? ? writel(PIN_MODE_DUMB_18_SPI, fbi->reg_base + SPU_IOPAD_CONTROL);
> + ? ? ? isr = readl(fbi->reg_base + SPU_IRQ_ISR);
> + ? ? ? writel((isr & ~SPI_IRQ_ENA_MASK), fbi->reg_base + SPU_IRQ_ISR);
> + ? ? ? for (i = 0; i < count; i++) {
> + ? ? ? ? ? ? ? spi_gpio_assert_set(spi_gpio_cs, 0);
> + ? ? ? ? ? ? ? udelay(interval_us);
> + ? ? ? ? ? ? ? switch (spi_byte_len){
> + ? ? ? ? ? ? ? case 1:
> + ? ? ? ? ? ? ? ? ? ? ? writel(*cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? case 2:
> + ? ? ? ? ? ? ? ? ? ? ? writel(*(u16*)cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? case 4:
> + ? ? ? ? ? ? ? ? ? ? ? writel(*(u32*)cmd, fbi->reg_base + LCD_SPU_SPI_TXDATA);
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? default:
> + ? ? ? ? ? ? ? ? ? ? ? dev_err(fbi->dev, "Wrong spi bit length\n");
> + ? ? ? ? ? ? ? ? ? ? ? spi_gpio_assert_set(spi_gpio_cs, 1);
> + ? ? ? ? ? ? ? ? ? ? ? ret = -1;
> + ? ? ? ? ? ? ? ? ? ? ? goto spi_exit;
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? cmd += spi_byte_len;
> + ? ? ? ? ? ? ? x = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
> + ? ? ? ? ? ? ? x |= 0x1;
> + ? ? ? ? ? ? ? writel(x, fbi->reg_base + LCD_SPU_SPI_CTRL);
> + ? ? ? ? ? ? ? isr = readl(fbi->reg_base + SPU_IRQ_ISR);
> + ? ? ? ? ? ? ? while(!(isr & SPI_IRQ_ENA_MASK)) {
> + ? ? ? ? ? ? ? ? ? ? ? udelay(1);
> + ? ? ? ? ? ? ? ? ? ? ? isr = readl(fbi->reg_base + SPU_IRQ_ISR);
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? x = readl(fbi->reg_base + LCD_SPU_SPI_CTRL);
> + ? ? ? ? ? ? ? x &= ~0x1;
> + ? ? ? ? ? ? ? writel(x, fbi->reg_base + LCD_SPU_SPI_CTRL);
> + ? ? ? ? ? ? ? spi_gpio_assert_set(spi_gpio_cs, 1);
> + ? ? ? }

So after this loop, the 'spi_gpio_cs' is left asserted, which isn't good.

> +
> +spi_exit:
> + ? ? ? if (gpio_is_valid(spi_gpio_cs))
> + ? ? ? ? ? ? ? gpio_free(spi_gpio_cs);
> + ? ? ? if ((iopad & CFG_IOPADMODE_MASK) != PIN_MODE_DUMB_18_SPI)
> + ? ? ? ? ? ? ? writel(iopad, fbi->reg_base + SPU_IOPAD_CONTROL);
> +
> + ? ? ? return ret;
> +}
> +EXPORT_SYMBOL(pxa168fb_spi_send);
> +
> ?static int determine_best_pix_fmt(struct fb_var_screeninfo *var)
> ?{
> ? ? ? ?/*
> @@ -687,6 +768,7 @@ static int __init pxa168fb_probe(struct
> platform_device *pdev)
> ? ? ? ?}
>
> ? ? ? ?info->fix.smem_start = (unsigned long)fbi->fb_start_dma;
> + ? ? ? set_graphics_start(info, 0, 0);

This need a separate patch.

>
> ? ? ? ?/*
> ? ? ? ? * Set video mode according to platform data.
> @@ -728,6 +810,9 @@ static int __init pxa168fb_probe(struct
> platform_device *pdev)
> ? ? ? ?writel(0, fbi->reg_base + LCD_SPU_SRAM_PARA0);
> ? ? ? ?writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1),
> ? ? ? ? ? ? ? ?fbi->reg_base + LCD_SPU_SRAM_PARA1);
> + ? ? ? if ((mi->spi_ctrl != -1) && (mi->spi_ctrl & CFG_SPI_ENA_MASK))
> + ? ? ? ? ? ? ? writel(mi->spi_ctrl, fbi->reg_base + LCD_SPU_SPI_CTRL);
> +
>
> ? ? ? ?/*
> ? ? ? ? * Allocate color map.
> @@ -764,6 +849,13 @@ static int __init pxa168fb_probe(struct
> platform_device *pdev)
> ? ? ? ?}
>
> ? ? ? ?platform_set_drvdata(pdev, fbi);
> + ? ? ? if (mi->pxa168fb_lcd_power){
> + ? ? ? ? ? ? ? if(mi->pxa168fb_lcd_power(fbi, mi->spi_gpio_cs, mi->spi_gpio_reset, 1)){
> + ? ? ? ? ? ? ? ? ? ? ? dev_err(&pdev->dev, "Failed to power up pxa168-fb\n");
> + ? ? ? ? ? ? ? ? ? ? ? goto failed_free_irq;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> + ? ? ? dev_info(fbi->dev, "frame buffer detected\n");

Need another patch for this as well?

> ? ? ? ?return 0;
>
> ?failed_free_irq:
> diff --git a/drivers/video/pxa168fb.h b/drivers/video/pxa168fb.h
> index eee0927..1e4859e 100644
> --- a/drivers/video/pxa168fb.h
> +++ b/drivers/video/pxa168fb.h
> @@ -170,29 +170,7 @@
> ?#define ? ? DMA_FRAME_CNT_MASK ? ? ? ? ? ? ? ? 0x00000003 ?/* Video */
>
> ?/* SPI Control Register. */
> -#define LCD_SPU_SPI_CTRL ? ? ? ? ? ? ? ? ? ? ? 0x0180
> -#define ? ? CFG_SCLKCNT(div) ? ? ? ? ? ? ? ? ? ((div) << 24) ?/* 0xFF~0x2 */
> -#define ? ? CFG_SCLKCNT_MASK ? ? ? ? ? ? ? ? ? 0xFF000000
> -#define ? ? CFG_RXBITS(rx) ? ? ? ? ? ? ? ? ? ? ((rx) << 16) ? /* 0x1F~0x1 */
> -#define ? ? CFG_RXBITS_MASK ? ? ? ? ? ? ? ? ? ?0x00FF0000
> -#define ? ? CFG_TXBITS(tx) ? ? ? ? ? ? ? ? ? ? ((tx) << 8) ? ?/* 0x1F~0x1 */
> -#define ? ? CFG_TXBITS_MASK ? ? ? ? ? ? ? ? ? ?0x0000FF00
> -#define ? ? CFG_CLKINV(clk) ? ? ? ? ? ? ? ? ? ?((clk) << 7)
> -#define ? ? CFG_CLKINV_MASK ? ? ? ? ? ? ? ? ? ?0x00000080
> -#define ? ? CFG_KEEPXFER(transfer) ? ? ? ? ? ? ((transfer) << 6)
> -#define ? ? CFG_KEEPXFER_MASK ? ? ? ? ? ? ? ? ?0x00000040
> -#define ? ? CFG_RXBITSTO0(rx) ? ? ? ? ? ? ? ? ?((rx) << 5)
> -#define ? ? CFG_RXBITSTO0_MASK ? ? ? ? ? ? ? ? 0x00000020
> -#define ? ? CFG_TXBITSTO0(tx) ? ? ? ? ? ? ? ? ?((tx) << 4)
> -#define ? ? CFG_TXBITSTO0_MASK ? ? ? ? ? ? ? ? 0x00000010
> -#define ? ? CFG_SPI_ENA(spi) ? ? ? ? ? ? ? ? ? ((spi) << 3)
> -#define ? ? CFG_SPI_ENA_MASK ? ? ? ? ? ? ? ? ? 0x00000008
> -#define ? ? CFG_SPI_SEL(spi) ? ? ? ? ? ? ? ? ? ((spi) << 2)
> -#define ? ? CFG_SPI_SEL_MASK ? ? ? ? ? ? ? ? ? 0x00000004
> -#define ? ? CFG_SPI_3W4WB(wire) ? ? ? ? ? ? ? ? ? ? ? ?((wire) << 1)
> -#define ? ? CFG_SPI_3W4WB_MASK ? ? ? ? ? ? ? ? 0x00000002
> -#define ? ? CFG_SPI_START(start) ? ? ? ? ? ? ? (start)
> -#define ? ? CFG_SPI_START_MASK ? ? ? ? ? ? ? ? 0x00000001
> +/* For SPI register, please refer to
> arch/arm/mach-mmp/include/mach/pxa168fb.h */
>
> ?/* SPI Tx Data Register */
> ?#define LCD_SPU_SPI_TXDATA ? ? ? ? ? ? ? ? ? ? 0x0184
> diff --git a/include/video/pxa168fb.h b/include/video/pxa168fb.h
> index b5cc72f..f0497ae 100644
> --- a/include/video/pxa168fb.h
> +++ b/include/video/pxa168fb.h
> @@ -122,6 +122,24 @@ struct pxa168fb_mach_info {
> ? ? ? ?unsigned ? ? ? ?panel_rbswap:1;
> ? ? ? ?unsigned ? ? ? ?active:1;
> ? ? ? ?unsigned ? ? ? ?enable_lcd:1;
> + ? ? ? /*
> + ? ? ? ?* SPI control
> + ? ? ? ?*/
> + ? ? ? unsigned int ? ?spi_ctrl;
> + ? ? ? unsigned int ? ?spi_gpio_cs;
> + ? ? ? unsigned int ? ?spi_gpio_reset;
> + ? ? ? /*
> + ? ? ? ?* power on/off function.
> + ? ? ? ?*/
> + ? ? ? int (*pxa168fb_lcd_power)(struct pxa168fb_info *, unsigned int,
> unsigned int, int);
> ?};
>
> +/* SPI utility for configure panel SPI command.
> + * value: command array, element should be 1, 2 or 4 byte aligned.
> + * count: command array length
> + * spi_gpio_cs: gpio number for spi chip select
> + * interval_us: time interval between two commands, us as unit */
> +int pxa168fb_spi_send(struct pxa168fb_info *fbi, void *value, int count,
> + ? ? ? ? ? ? ? unsigned int spi_gpio_cs, unsigned int interval_us);
> +
> ?#endif /* __ASM_MACH_PXA168FB_H */
> --
> 1.5.4.3
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/6] pxa: support pxa168 LCD controller SPI operation
  2009-11-03  6:45 ` Jun Nie
@ 2009-11-08 16:53   ` Russell King - ARM Linux
  -1 siblings, 0 replies; 8+ messages in thread
From: Russell King - ARM Linux @ 2009-11-08 16:53 UTC (permalink / raw)
  To: Jun Nie; +Cc: linux-fbdev-devel, linux-arm-kernel

On Tue, Nov 03, 2009 at 02:45:20PM +0800, Jun Nie wrote:
> diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
> index 84d8327..27bdf2b 100644
> --- a/drivers/video/pxa168fb.c
> +++ b/drivers/video/pxa168fb.c
> @@ -29,10 +29,91 @@
>  #include <linux/uaccess.h>
>  #include <video/pxa168fb.h>
> 
> +#include <mach/pxa168fb.h>
> +#include <mach/gpio.h>

linux/gpio.h

> +int pxa168fb_spi_send(struct pxa168fb_info *fbi, void *value, int count,
> +		unsigned int spi_gpio_cs, unsigned int interval_us)
> +{
> +	u32 x, spi_byte_len;
> +	u8 *cmd = (u8 *)value;
> +	int i, err, isr, iopad, ret = 0;
> +
> +	if (gpio_is_valid(spi_gpio_cs)) {
> +		err = gpio_request(spi_gpio_cs, "LCD_SPI_CS");
> +		if (err) {
> +			dev_err(fbi->dev, "failed to request GPIO for LCD CS\n");
> +			return -1;

Please stop using '-1' as a general error return value.  It has a specific
meaning, translating as "operation not permitted" or "permission denied".
This is not what this error is.  Always propagate error codes back when
you have them.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/6] pxa: support pxa168 LCD controller SPI operation
@ 2009-11-08 16:53   ` Russell King - ARM Linux
  0 siblings, 0 replies; 8+ messages in thread
From: Russell King - ARM Linux @ 2009-11-08 16:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Nov 03, 2009 at 02:45:20PM +0800, Jun Nie wrote:
> diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
> index 84d8327..27bdf2b 100644
> --- a/drivers/video/pxa168fb.c
> +++ b/drivers/video/pxa168fb.c
> @@ -29,10 +29,91 @@
>  #include <linux/uaccess.h>
>  #include <video/pxa168fb.h>
> 
> +#include <mach/pxa168fb.h>
> +#include <mach/gpio.h>

linux/gpio.h

> +int pxa168fb_spi_send(struct pxa168fb_info *fbi, void *value, int count,
> +		unsigned int spi_gpio_cs, unsigned int interval_us)
> +{
> +	u32 x, spi_byte_len;
> +	u8 *cmd = (u8 *)value;
> +	int i, err, isr, iopad, ret = 0;
> +
> +	if (gpio_is_valid(spi_gpio_cs)) {
> +		err = gpio_request(spi_gpio_cs, "LCD_SPI_CS");
> +		if (err) {
> +			dev_err(fbi->dev, "failed to request GPIO for LCD CS\n");
> +			return -1;

Please stop using '-1' as a general error return value.  It has a specific
meaning, translating as "operation not permitted" or "permission denied".
This is not what this error is.  Always propagate error codes back when
you have them.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2009-11-08 16:53 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-03  6:45 [PATCH 1/6] pxa: support pxa168 LCD controller SPI operation Jun Nie
2009-11-03  6:45 ` Jun Nie
2009-11-03  7:28 ` Jun Nie
2009-11-03  7:28   ` Jun Nie
2009-11-03  8:32 ` Eric Miao
2009-11-03  8:32   ` Eric Miao
2009-11-08 16:53 ` Russell King - ARM Linux
2009-11-08 16:53   ` Russell King - ARM Linux

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.