summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWengang Wu <a22350@motorola.com>2014-01-15 11:02:35 -0600
committerJames Wylder <jwylder@motorola.com>2014-03-05 17:47:05 -0600
commit06ef967840e79ae999758d7c7c74b1957e3dbae3 (patch)
treeb96f07e07cdcbeb871dd22fb3372039ff3f64e11
parent97610078a9318e5881b86ff7227d36c11b5de59f (diff)
downloadolio-linux-3.10-06ef967840e79ae999758d7c7c74b1957e3dbae3.tar.xz
olio-linux-3.10-06ef967840e79ae999758d7c7c74b1957e3dbae3.zip
IKXCLOCK-78 Support Solomon+Orise Display Driver
Change-Id: I43a572dec6fc1d469fbf7104cb58359a2b8f87e1 Reviewed-on: http://gerrit.pcs.mot.com/603160 SLTApproved: Slta Waiver <sltawvr@motorola.com> Tested-by: Jira Key <jirakey@motorola.com> Reviewed-by: Jee Su Chang <w20740@motorola.com> Submit-Approved: Jira Key <jirakey@motorola.com>
-rw-r--r--arch/arm/boot/dts/omap3-minnow.dtsi23
-rw-r--r--arch/arm/configs/eng_minnow_defconfig4
-rw-r--r--[-rwxr-xr-x]arch/arm/configs/minnow_defconfig3
-rw-r--r--arch/arm/mach-omap2/display.c65
-rw-r--r--drivers/video/omap2/displays/panel-minnow.c591
-rw-r--r--drivers/video/omap2/dss/Kconfig4
-rw-r--r--drivers/video/omap2/dss/dsi.c2
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c103
8 files changed, 648 insertions, 147 deletions
diff --git a/arch/arm/boot/dts/omap3-minnow.dtsi b/arch/arm/boot/dts/omap3-minnow.dtsi
index 6256a5642a4..3466da5b9b8 100644
--- a/arch/arm/boot/dts/omap3-minnow.dtsi
+++ b/arch/arm/boot/dts/omap3-minnow.dtsi
@@ -15,22 +15,25 @@
compatible = "mot,minnow-panel-dsi-cm";
/* 0: MINNOW_PANEL_CM_220X176
* 1: MINNOW_PANEL_CM_220X220
+ * 2: MINNOW_PANEL_CM_BRIDGE_320X320
*/
- id_panel = <1>;
- gpio_reset = <&gpio1 14 0>; /* RESET gpio-14 */
+ id_panel = <2>;
+ gpio_panel_reset = <&gpio1 14 0>; /* RESET gpio-14 */
+ gpio_bridge_reset = <&gpio1 23 0>; /* RESET gpio-23 */
+ gpio_clk_en = <&gpio6 17 0>; /* RESET gpio-177 */
/* declare it if ext_te enable */
//gpio_te = <&gpio1 0 0>; /* EXT_TE gpio-0 */
- pins = <0 1 2 3>; /* DSI Pin config */
- esd_interval = <0>; /* ESD_INTERVAL */
- pixel_clock = <4608>; /* kHZ = 320*240*60/1000*/
+ //pins = <0 1 2 3>; /* DSI Pin config */
+ //esd_interval = <0>; /* ESD_INTERVAL */
+ //pixel_clock = <4608>; /* kHZ = 320*240*60/1000*/
/* 0: RGB888
* 1: RGB666
* 2: RGB666_PACKED
* 3: RGB565
*/
- pixel_format = <1>;
- hs_clk = <100000000 150000000>; /* min max*/
- lp_clk = <7000000 9000000>; /* min max*/
+ //pixel_format = <1>;
+ //hs_clk = <90000000 150000000>; /* min max*/
+ //lp_clk = <7000000 9000000>; /* min max*/
};
/* FIXME: this dummy regulator is only needed as
@@ -154,6 +157,10 @@
0x08e 0x104 /* GPMC_CLK, MODE4 | INPUT */
0x0a0 0x002 /* GPMC_WAIT2, MODE2 | OUTPUT */
0x0a2 0x102 /* GPMC_WAIT3, MODE2 | INPUT */
+ 0x0ac 0x001 /* DSI_DX0, MODE1 | OUTPUT */
+ 0x0ae 0x001 /* DSI_DY0, MODE1 | OUTPUT */
+ 0x0b0 0x001 /* DSI_DX1, MODE1 | OUTPUT */
+ 0x0b2 0x001 /* DSI_DY1, MODE1 | OUTPUT */
0x0b8 0x104 /* DSS_DATA6, MODE4 | INPUT */
0x0c0 0x004 /* DSS_DATA10, MODE4 | OUTPUT */
0x0c2 0x004 /* DSS_DATA11, MODE4 | OUTPUT */
diff --git a/arch/arm/configs/eng_minnow_defconfig b/arch/arm/configs/eng_minnow_defconfig
index 96ee2200888..c20f4ba972e 100644
--- a/arch/arm/configs/eng_minnow_defconfig
+++ b/arch/arm/configs/eng_minnow_defconfig
@@ -1605,7 +1605,8 @@ CONFIG_FB_MODE_HELPERS=y
CONFIG_OMAP2_VRFB=y
CONFIG_OMAP2_DSS=y
CONFIG_OMAP2_DSS_DEBUG=y
-# CONFIG_OMAP2_DSS_DEBUGFS is not set
+CONFIG_OMAP2_DSS_DEBUGFS=y
+# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set
# CONFIG_OMAP2_DSS_DPI is not set
# CONFIG_OMAP2_DSS_RFBI is not set
# CONFIG_OMAP2_DSS_VENC is not set
@@ -1614,6 +1615,7 @@ CONFIG_OMAP2_DSS_DEBUG=y
CONFIG_OMAP2_DSS_DSI=y
CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y
+CONFIG_OMAP2_DSS_RESET=y
CONFIG_FB_OMAP2=y
CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
CONFIG_FB_OMAP2_NUM_FBS=1
diff --git a/arch/arm/configs/minnow_defconfig b/arch/arm/configs/minnow_defconfig
index a32a9107d8e..83702c51654 100755..100644
--- a/arch/arm/configs/minnow_defconfig
+++ b/arch/arm/configs/minnow_defconfig
@@ -460,7 +460,7 @@ CONFIG_ATAGS=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
# CONFIG_ARM_APPENDED_DTB is not set
-CONFIG_CMDLINE="rootwait earlyprintk console=ttyO2,115200n8 mem=254M@0x80000000 init=/init"
+CONFIG_CMDLINE="rootwait earlyprintk console=ttyO2,115200n8 mem=254M@0x80000000 init=/init omapfb.vram=0:1M"
# CONFIG_CMDLINE_FROM_BOOTLOADER is not set
# CONFIG_CMDLINE_EXTEND is not set
CONFIG_CMDLINE_FORCE=y
@@ -1606,6 +1606,7 @@ CONFIG_OMAP2_DSS_DEBUG=y
CONFIG_OMAP2_DSS_DSI=y
CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y
+CONFIG_OMAP2_DSS_RESET=y
CONFIG_FB_OMAP2=y
CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
CONFIG_FB_OMAP2_NUM_FBS=1
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index ff37be1f6f9..d22833a0f2a 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -320,6 +320,10 @@ static enum omapdss_version __init omap_display_get_version(void)
return OMAPDSS_VER_UNKNOWN;
}
+#ifdef CONFIG_OMAP2_DSS_RESET
+static int reset_omap_dss(void);
+#endif
+
int __init omap_display_init(struct omap_dss_board_info *board_data)
{
int r = 0;
@@ -415,7 +419,9 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
return PTR_ERR(pdev);
}
}
-
+#ifdef CONFIG_OMAP2_DSS_RESET
+ reset_omap_dss();
+#endif
return 0;
}
@@ -564,3 +570,60 @@ int omap_dss_reset(struct omap_hwmod *oh)
return r;
}
+
+#ifdef CONFIG_OMAP2_DSS_RESET
+#define DSS_CLKS 4
+static int reset_omap_dss(void)
+{
+ static const char * const clkstr[DSS_CLKS] = {
+ "dss_ick",
+ "dss1_alwon_fck",
+ "dss2_alwon_fck",
+ "dss_tv_fck"
+ };
+ struct clk *clk[DSS_CLKS];
+ int i, r = 0, c = 0;
+ struct omap_hwmod *oh_dss = omap_hwmod_lookup("dss_core");
+ struct omap_hwmod *oh_dispc = omap_hwmod_lookup("dss_dispc");
+ struct omap_hwmod *oh_dsi = omap_hwmod_lookup("dss_dsi1");
+
+ WARN((!oh_dss || !oh_dispc || !oh_dsi), "Reset lost!");
+
+ for (i = 0; i < DSS_CLKS; i++) {
+ clk[i] = clk_get(NULL, clkstr[i]);
+ if (!IS_ERR(clk[i])) {
+ r = clk_prepare_enable(clk[i]);
+ if (!r)
+ continue;
+ clk_put(clk[i]);
+ }
+ pr_warn("dss_core: failed enable %s\n", clkstr[i]);
+ clk[i] = ERR_PTR(-ENOENT);
+ }
+
+ /*
+ * clear DSS_CONTROL register to switch DSS clock sources to
+ * PRCM clock, if any
+ */
+ omap_hwmod_write(0x0, oh_dss, DSS_CONTROL);
+ dispc_disable_outputs();
+ omap_hwmod_write(0x0, oh_dss, DSS_SDI_CONTROL);
+ omap_hwmod_write(0x0, oh_dss, DSS_PLL_CONTROL);
+
+ omap_hwmod_write(0x02, oh_dss, DSS_SYSCONFIG);
+ omap_test_timeout((omap_hwmod_read(oh_dss, DSS_SYSSTATUS)
+ & SYSS_RESETDONE_MASK),
+ MAX_MODULE_SOFTRESET_WAIT, c);
+ r = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
+ pr_warn("dss_core: reset DSS %s\n", r ? "failed" : "done");
+
+ for (i = 0; i < DSS_CLKS; i++) {
+ if (!IS_ERR(clk[i])) {
+ clk_disable_unprepare(clk[i]);
+ clk_put(clk[i]);
+ }
+ }
+
+ return r;
+}
+#endif
diff --git a/drivers/video/omap2/displays/panel-minnow.c b/drivers/video/omap2/displays/panel-minnow.c
index aa0a380a5da..1ac9125034d 100644
--- a/drivers/video/omap2/displays/panel-minnow.c
+++ b/drivers/video/omap2/displays/panel-minnow.c
@@ -36,6 +36,9 @@
#include <video/omap-panel-data.h>
#include <video/mipi_display.h>
+#include "../dss/dss.h"
+
+
/* DSI Virtual channel. Hardcoded for now. */
#define TCH 0
@@ -48,102 +51,246 @@
#define DCS_GET_ID2 0xdb
#define DCS_GET_ID3 0xdc
+enum minnow_reset_gpios {
+ MINNOW_RESET_PANEL,
+ MINNOW_RESET_BRIDGE,
+ MINNOW_RESET_MAX
+};
+
enum minnow_panel_id {
MINNOW_PANEL_CM_220X176,
MINNOW_PANEL_CM_220X220,
+ MINNOW_PANEL_CM_BRIDGE_320X320,
MINNOW_PANEL_MAX
};
+enum minnow_cmd_type {
+ DCS_WRITE_SYNC,
+ GENERIC_WRITE_SYNC,
+ DCS_WRITE,
+ GENERIC_WRITE,
+ BTA_SYNC,
+ WAIT_MS,
+ CMD_TYPE_MAX
+};
+
+
/* Panel Initialize DSI DCS command buffer description:
* it uses compact DCS command buffer to store all DCS commands, the first
* byte of each command is the command length in byte
*/
static u8 panel_init_220x176[] = {
-/*n, data_0, data_1 ... data_n-1*/
- 3, 0xF0, 0x5A, 0x5A,
- 3, 0xF1, 0x5A, 0x5A,
-18, 0xF2, 0x16, 0xDC, 0x03, 0x28, 0x28, 0x10, 0x00, 0x60, 0xF8, 0x00, 0x07, 0x02, 0x00, 0x00, 0xDC, 0x28, 0x28,
-15, 0xF4, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x7F, 0x07, 0x22, 0x2A, 0x43, 0x07, 0x2A, 0x43, 0x07,
-11, 0xF5, 0x00, 0x50, 0x28, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
-10, 0xF6, 0x07, 0x00, 0x07, 0x00, 0x0B, 0x04, 0x04, 0x04, 0x07,
- 5, 0xF7, 0x00, 0x00, 0x00, 0x00,
- 3, 0xF8, 0x44, 0x08,
- 2, 0xF9, 0x04,
-17, 0xFA, 0x0F, 0x0F, 0x1E, 0x23, 0x26, 0x2D, 0x21, 0x2B, 0x33, 0x32, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00,
-17, 0xFB, 0x0F, 0x0F, 0x1E, 0x23, 0x26, 0x2D, 0x21, 0x2B, 0x33, 0x32, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00,
- 2, 0xF9, 0x02,
-17, 0xFA, 0x00, 0x00, 0x0A, 0x16, 0x1D, 0x27, 0x1C, 0x30, 0x38, 0x37, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
-17, 0xFB, 0x00, 0x00, 0x0A, 0x16, 0x1D, 0x27, 0x1C, 0x30, 0x38, 0x37, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
- 2, 0xF9, 0x01,
-17, 0xFA, 0x00, 0x00, 0x13, 0x14, 0x19, 0x24, 0x1A, 0x31, 0x39, 0x38, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
-17, 0xFB, 0x00, 0x00, 0x13, 0x14, 0x19, 0x24, 0x1A, 0x31, 0x39, 0x38, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
- 3, 0xF0, 0x00, 0x00,
- 3, 0xF1, 0x00, 0x00,
- 2, 0x36, 0xD0,
- 2, 0x3A, 0x06
+/*n, type, data_0, data_1 ... data_n-1*/
+1, DCS_WRITE_SYNC, MIPI_DCS_EXIT_SLEEP_MODE,
+1, WAIT_MS, 5,
+3, DCS_WRITE_SYNC, 0xF0, 0x5A, 0x5A,
+3, DCS_WRITE_SYNC, 0xF1, 0x5A, 0x5A,
+18, DCS_WRITE_SYNC, 0xF2, 0x16, 0xDC, 0x03, 0x28, 0x28, 0x10, 0x00, 0x60, 0xF8,
+ 0x00, 0x07, 0x02, 0x00, 0x00, 0xDC, 0x28, 0x28,
+15, DCS_WRITE_SYNC, 0xF4, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x7F, 0x07, 0x22, 0x2A,
+ 0x43, 0x07, 0x2A, 0x43, 0x07,
+11, DCS_WRITE_SYNC, 0xF5, 0x00, 0x50, 0x28, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x00,
+10, DCS_WRITE_SYNC, 0xF6, 0x07, 0x00, 0x07, 0x00, 0x0B, 0x04, 0x04, 0x04, 0x07,
+5, DCS_WRITE_SYNC, 0xF7, 0x00, 0x00, 0x00, 0x00,
+3, DCS_WRITE_SYNC, 0xF8, 0x44, 0x08,
+2, DCS_WRITE_SYNC, 0xF9, 0x04,
+17, DCS_WRITE_SYNC, 0xFA, 0x0F, 0x0F, 0x1E, 0x23, 0x26, 0x2D, 0x21, 0x2B, 0x33,
+ 0x32, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00,
+17, DCS_WRITE_SYNC, 0xFB, 0x0F, 0x0F, 0x1E, 0x23, 0x26, 0x2D, 0x21, 0x2B, 0x33,
+ 0x32, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00,
+2, DCS_WRITE_SYNC, 0xF9, 0x02,
+17, DCS_WRITE_SYNC, 0xFA, 0x00, 0x00, 0x0A, 0x16, 0x1D, 0x27, 0x1C, 0x30, 0x38,
+ 0x37, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
+17, DCS_WRITE_SYNC, 0xFB, 0x00, 0x00, 0x0A, 0x16, 0x1D, 0x27, 0x1C, 0x30, 0x38,
+ 0x37, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
+2, DCS_WRITE_SYNC, 0xF9, 0x01,
+17, DCS_WRITE_SYNC, 0xFA, 0x00, 0x00, 0x13, 0x14, 0x19, 0x24, 0x1A, 0x31, 0x39,
+ 0x38, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
+17, DCS_WRITE_SYNC, 0xFB, 0x00, 0x00, 0x13, 0x14, 0x19, 0x24, 0x1A, 0x31, 0x39,
+ 0x38, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
+3, DCS_WRITE_SYNC, 0xF0, 0x00, 0x00,
+3, DCS_WRITE_SYNC, 0xF1, 0x00, 0x00,
+2, DCS_WRITE_SYNC, 0x36, 0xD8,
+2, DCS_WRITE_SYNC, 0x3A, 0x06,
+0
};
static u8 panel_init_220x220[] = {
-/*n, data_0, data_1 ... data_n-1*/
- 3, 0xF0, 0x5A, 0x5A,
- 3, 0xF1, 0x5A, 0x5A,
-18, 0xF2, 0x1C, 0xDC, 0x03, 0x28, 0x28, 0x10, 0x00, 0x60, 0xF8, 0x00, 0x07, 0x02, 0x00, 0x00, 0xDC, 0x28, 0x28,
-15, 0xF4, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x7F, 0x07, 0x22, 0x2A, 0x43, 0x07, 0x2A, 0x43, 0x07,
-11, 0xF5, 0x00, 0x50, 0x28, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01, 0x01,
-10, 0xF6, 0x07, 0x00, 0x07, 0x00, 0x0B, 0x04, 0x04, 0x04, 0x07,
- 5, 0xF7, 0x00, 0x00, 0x00, 0x00,
- 3, 0xF8, 0x44, 0x02,
- 2, 0xF9, 0x04,
-17, 0xFA, 0x1E, 0x1E, 0x0D, 0x1D, 0x21, 0x2C, 0x23, 0x28, 0x2C, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
-17, 0xFB, 0x1E, 0x1E, 0x0D, 0x1D, 0x21, 0x2C, 0x23, 0x28, 0x2C, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
- 2, 0xF9, 0x02,
-17, 0xFA, 0x19, 0x18, 0x08, 0x0F, 0x18, 0x26, 0x1E, 0x2C, 0x30, 0x2C, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00,
-17, 0xFB, 0x19, 0x18, 0x08, 0x0F, 0x18, 0x26, 0x1E, 0x2C, 0x30, 0x2C, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00,
- 2, 0xF9, 0x01,
-17, 0xFA, 0x19, 0x19, 0x09, 0x0D, 0x12, 0x21, 0x1B, 0x2E, 0x31, 0x2E, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00,
-17, 0xFB, 0x19, 0x19, 0x09, 0x0D, 0x12, 0x21, 0x1B, 0x2E, 0x31, 0x2E, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00,
- 3, 0xF0, 0x00, 0x00,
- 3, 0xF1, 0x00, 0x00,
- 2, 0x36, 0xD0,
- 2, 0x3A, 0x06
+/*n, type, data_0, data_1 ... data_n-1*/
+1, DCS_WRITE_SYNC, MIPI_DCS_EXIT_SLEEP_MODE,
+1, WAIT_MS, 5,
+3, DCS_WRITE_SYNC, 0xF0, 0x5A, 0x5A,
+3, DCS_WRITE_SYNC, 0xF1, 0x5A, 0x5A,
+18, DCS_WRITE_SYNC, 0xF2, 0x1C, 0xDC, 0x03, 0x28, 0x28, 0x10, 0x00, 0x60, 0xF8,
+ 0x00, 0x07, 0x02, 0x00, 0x00, 0xDC, 0x28, 0x28,
+15, DCS_WRITE_SYNC, 0xF4, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x7F, 0x07, 0x22, 0x2A,
+ 0x43, 0x07, 0x2A, 0x43, 0x07,
+11, DCS_WRITE_SYNC, 0xF5, 0x00, 0x50, 0x28, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01,
+ 0x01,
+10, DCS_WRITE_SYNC, 0xF6, 0x07, 0x00, 0x07, 0x00, 0x0B, 0x04, 0x04, 0x04, 0x07,
+5, DCS_WRITE_SYNC, 0xF7, 0x00, 0x00, 0x00, 0x00,
+3, DCS_WRITE_SYNC, 0xF8, 0x44, 0x02,
+2, DCS_WRITE_SYNC, 0xF9, 0x04,
+17, DCS_WRITE_SYNC, 0xFA, 0x1E, 0x1E, 0x0D, 0x1D, 0x21, 0x2C, 0x23, 0x28, 0x2C,
+ 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
+17, DCS_WRITE_SYNC, 0xFB, 0x1E, 0x1E, 0x0D, 0x1D, 0x21, 0x2C, 0x23, 0x28, 0x2C,
+ 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
+2, DCS_WRITE_SYNC, 0xF9, 0x02,
+17, DCS_WRITE_SYNC, 0xFA, 0x19, 0x18, 0x08, 0x0F, 0x18, 0x26, 0x1E, 0x2C, 0x30,
+ 0x2C, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00,
+17, DCS_WRITE_SYNC, 0xFB, 0x19, 0x18, 0x08, 0x0F, 0x18, 0x26, 0x1E, 0x2C, 0x30,
+ 0x2C, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00,
+2, DCS_WRITE_SYNC, 0xF9, 0x01,
+17, DCS_WRITE_SYNC, 0xFA, 0x19, 0x19, 0x09, 0x0D, 0x12, 0x21, 0x1B, 0x2E, 0x31,
+ 0x2E, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00,
+17, DCS_WRITE_SYNC, 0xFB, 0x19, 0x19, 0x09, 0x0D, 0x12, 0x21, 0x1B, 0x2E, 0x31,
+ 0x2E, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00,
+3, DCS_WRITE_SYNC, 0xF0, 0x00, 0x00,
+3, DCS_WRITE_SYNC, 0xF1, 0x00, 0x00,
+2, DCS_WRITE_SYNC, 0x36, 0xD8,
+2, DCS_WRITE_SYNC, 0x3A, 0x06,
+0
+};
+
+static u8 panel_init_ssd2848_320x320[] = {
+/*n, type, data_0, data_1 ... data_n-1*/
+2, GENERIC_WRITE_SYNC, 0xFF, 0x00,
+6, GENERIC_WRITE_SYNC, 0x00, 0x08, 0x01, 0xF4, 0x04, 0x29,
+6, GENERIC_WRITE_SYNC, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0B,
+6, GENERIC_WRITE_SYNC, 0x00, 0x14, 0x0C, 0x01, 0x80, 0x0F,
+1, DCS_WRITE_SYNC, MIPI_DCS_EXIT_SLEEP_MODE,
+1, WAIT_MS, 1,
+6, GENERIC_WRITE_SYNC, 0x10, 0x08, 0x01, 0x20, 0x01, 0x45,
+6, GENERIC_WRITE_SYNC, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x02,
+6, GENERIC_WRITE_SYNC, 0x20, 0x10, 0x00, 0x1B, 0x00, 0x0C,
+6, GENERIC_WRITE_SYNC, 0x20, 0x14, 0x01, 0x88, 0x00, 0x28,
+6, GENERIC_WRITE_SYNC, 0x20, 0x18, 0x01, 0x4E, 0x00, 0x0A,
+6, GENERIC_WRITE_SYNC, 0x20, 0x20, 0x01, 0x40, 0x01, 0x40,
+6, GENERIC_WRITE_SYNC, 0x20, 0x24, 0x01, 0x40, 0x01, 0x40,
+6, GENERIC_WRITE_SYNC, 0x20, 0x30, 0x00, 0x00, 0x00, 0x15,
+6, GENERIC_WRITE_SYNC, 0x20, 0x34, 0x00, 0x00, 0x00, 0x00,
+6, GENERIC_WRITE_SYNC, 0x20, 0x38, 0x01, 0x3F, 0x01, 0x3F,
+6, GENERIC_WRITE_SYNC, 0x20, 0x3C, 0x01, 0x40, 0x01, 0x40,
+6, GENERIC_WRITE_SYNC, 0x20, 0xA0, 0x00, 0x00, 0x05, 0x00,
+5, DCS_WRITE_SYNC, 0x2A, 0x00, 0x00, 0x01, 0x3F,
+5, DCS_WRITE_SYNC, 0x2B, 0x00, 0x00, 0x01, 0x3F,
+6, GENERIC_WRITE_SYNC, 0x60, 0x08, 0x00, 0x02, 0x00, 0x0A,
+6, GENERIC_WRITE_SYNC, 0x60, 0x0C, 0x0A, 0x2A, 0x02, 0x0A,
+6, GENERIC_WRITE_SYNC, 0x60, 0x10, 0x01, 0x40, 0x02, 0x14,
+6, GENERIC_WRITE_SYNC, 0x60, 0x14, 0x01, 0x00, 0x01, 0x00,
+6, GENERIC_WRITE_SYNC, 0x60, 0x40, 0x3F, 0x0B, 0x23, 0x0A,
+6, GENERIC_WRITE_SYNC, 0x60, 0x44, 0x1F, 0x1F, 0x07, 0x29,
+6, GENERIC_WRITE_SYNC, 0x60, 0x84, 0x00, 0x00, 0x01, 0x40,
+2, GENERIC_WRITE_SYNC, 0xFF, 0x01,
+2, DCS_WRITE_SYNC, 0x36, 0x10,
+3, DCS_WRITE_SYNC, 0xF0, 0x54, 0x47,
+2, DCS_WRITE_SYNC, 0xA0, 0x00,
+4, DCS_WRITE_SYNC, 0xBD, 0x00, 0x11, 0x31,
+2, DCS_WRITE_SYNC, 0xE9, 0x46,
+5, DCS_WRITE_SYNC, 0xBA, 0x07, 0x15, 0x3E, 0x01,
+6, DCS_WRITE_SYNC, 0xB3, 0x02, 0x0A, 0x14, 0x2A, 0x2A,
+5, DCS_WRITE_SYNC, 0xB5, 0x78, 0x78, 0x76, 0xF6,
+18, DCS_WRITE_SYNC, 0xC0, 0x00, 0x03, 0x11, 0x12, 0x17, 0x25, 0x0D, 0x0C, 0x0A,
+ 0x0E, 0x0C, 0x2F, 0x09, 0x0E, 0x3D, 0x3E, 0x3F,
+18, DCS_WRITE_SYNC, 0xC1, 0x00, 0x03, 0x11, 0x12, 0x17, 0x25, 0x0D, 0x0C, 0x0A,
+ 0x0E, 0x0C, 0x2F, 0x09, 0x0E, 0x3D, 0x3E, 0x3F,
+18, DCS_WRITE_SYNC, 0xC2, 0x00, 0x03, 0x11, 0x12, 0x17, 0x25, 0x0D, 0x0C, 0x0A,
+ 0x0E, 0x0C, 0x2F, 0x09, 0x0E, 0x3D, 0x3E, 0x3F,
+18, DCS_WRITE_SYNC, 0xC3, 0x00, 0x03, 0x11, 0x12, 0x17, 0x25, 0x0D, 0x0C, 0x0A,
+ 0x0E, 0x0C, 0x2F, 0x09, 0x0E, 0x3D, 0x3E, 0x3F,
+18, DCS_WRITE_SYNC, 0xC4, 0x00, 0x03, 0x11, 0x12, 0x17, 0x25, 0x0D, 0x0C, 0x0A,
+ 0x0E, 0x0C, 0x2F, 0x09, 0x0E, 0x3D, 0x3E, 0x3F,
+18, DCS_WRITE_SYNC, 0xC5, 0x00, 0x03, 0x11, 0x12, 0x17, 0x25, 0x0D, 0x0C, 0x0A,
+ 0x0E, 0x0C, 0x2F, 0x09, 0x0E, 0x3D, 0x3E, 0x3F,
+1, DCS_WRITE_SYNC, MIPI_DCS_EXIT_SLEEP_MODE,
+1, WAIT_MS, 120,
+1, DCS_WRITE_SYNC, MIPI_DCS_SET_DISPLAY_ON,
+2, GENERIC_WRITE_SYNC, 0xFF, 0x00,
+0
+};
+
+struct minnow_panel_clk_range {
+ int min;
+ int max;
+};
+
+struct minnow_panel_hw_reset {
+ int active;
+ int reset_ms;
+ int wait_ms;
};
struct minnow_panel_attr {
+ int mode;
int xres;
int yres;
- int rate;
+ int pixel_clock;
+ int pixel_format;
int xoffset;
int yoffset;
int init_cmd_count;
u8 *init_cmd;
+ struct minnow_panel_clk_range hs;
+ struct minnow_panel_clk_range lp;
+ struct minnow_panel_hw_reset panel_reset;
+ struct minnow_panel_hw_reset bridge_reset;
};
#define INIT_CMD(buf) .init_cmd_count = sizeof(buf), .init_cmd = (buf)
static struct minnow_panel_attr panel_attr_table[MINNOW_PANEL_MAX] = {
[MINNOW_PANEL_CM_220X176] = {
+ .mode = OMAP_DSS_DSI_CMD_MODE,
.xres = 220,
.yres = 176,
- .rate = 60,
+ .pixel_clock = 4608,
+ .pixel_format = OMAP_DSS_DSI_FMT_RGB666,
.xoffset = 0x32,
.yoffset = 0,
- INIT_CMD(panel_init_220x176)
+ INIT_CMD(panel_init_220x176),
+ .hs = { 100000000, 150000000 },
+ .lp = { 7000000, 9000000 },
+ .panel_reset = { 0, 1, 5 },
+ .bridge_reset = { 0, 0, 0 },
},
[MINNOW_PANEL_CM_220X220] = {
+ .mode = OMAP_DSS_DSI_CMD_MODE,
.xres = 220,
.yres = 220,
- .rate = 60,
+ .pixel_clock = 4608,
+ .pixel_format = OMAP_DSS_DSI_FMT_RGB666,
.xoffset = 0x32,
.yoffset = 0x4,
- INIT_CMD(panel_init_220x220)
+ INIT_CMD(panel_init_220x220),
+ .hs = { 100000000, 150000000 },
+ .lp = { 7000000, 9000000 },
+ .panel_reset = { 0, 1, 5 },
+ .bridge_reset = { 0, 0, 0 },
+ },
+ [MINNOW_PANEL_CM_BRIDGE_320X320] = {
+ .mode = OMAP_DSS_DSI_CMD_MODE,
+ .xres = 320,
+ .yres = 290, /* actual display height is 290 */
+ .pixel_clock = DIV_ROUND_UP(320 * 290 * 60, 1000),
+ .pixel_format = OMAP_DSS_DSI_FMT_RGB888,
+ .xoffset = 0,
+ .yoffset = 0,
+ INIT_CMD(panel_init_ssd2848_320x320),
+ .hs = { 100000000, 150000000 },
+ .lp = { 7000000, 9000000 },
+ .panel_reset = { 0, 5, 10 },
+ .bridge_reset = { 0, 20, 10 }
},
};
+
static irqreturn_t minnow_panel_te_isr(int irq, void *data);
static void minnow_panel_te_timeout_work_callback(struct work_struct *work);
static int _minnow_panel_enable_te(struct omap_dss_device *dssdev, bool enable);
static int minnow_panel_reset(struct omap_dss_device *dssdev);
+
struct minnow_panel_data {
struct mutex lock; /* mutex */
@@ -157,8 +304,11 @@ struct minnow_panel_data {
struct omap_dss_device *dssdev;
/* panel HW configuration from DT or platform data */
- int reset_gpio;
+ int reset_gpio[MINNOW_RESET_MAX];
int ext_te_gpio;
+ int clk_en_gpio;
+ struct minnow_panel_hw_reset hw_reset[MINNOW_RESET_MAX];
+ struct minnow_panel_hw_reset bridge_reset;
bool use_dsi_backlight;
@@ -167,6 +317,7 @@ struct minnow_panel_data {
u8 *init_cmd_data;
int init_cmd_count;
+ int id_panel;
int x_offset;
int y_offset;
@@ -194,6 +345,66 @@ struct minnow_panel_data {
struct delayed_work ulps_work;
};
+#ifdef CONFIG_OMAP2_DSS_DEBUGFS
+static void minnow_panel_dump_regs(struct seq_file *s)
+{
+ static struct {char name[8]; int addr; int endreg; } regs[] = {
+ {"SCM", 0x0000, 0x30},
+ {"MIPIRX", 0x1000, 0x30},
+ {"VTCM", 0x2000, 0xB4},
+ {"VCU", 0x4000, 0x20},
+ {"GPIO", 0x5000, 0x04},
+ {"MIPITX", 0x6000, 0x54},
+ {"TX-DSI0", 0x6080, 0x14},
+ };
+ struct omap_dss_output *out = omap_dss_get_output(OMAP_DSS_OUTPUT_DSI1);
+ struct platform_device *dsidev = out->pdev;
+ struct omap_dss_device *dssdev = out->device;
+ struct minnow_panel_data *mpd = dev_get_drvdata(&dssdev->dev);
+ int i, j, r;
+
+ dsi_bus_lock(dssdev);
+
+ if (dsi_runtime_get(dsidev)) {
+ seq_puts(s, "dsi_runtime_get failed!");
+ goto exit1;
+ }
+
+ if (mpd->dssdev != dssdev) {
+ seq_puts(s, "dssdev mis-matched!");
+ goto exit;
+ }
+
+ if (dsi_vc_set_max_rx_packet_size(dssdev, mpd->channel, 4)) {
+ seq_puts(s, "failed set max rx_packet_size 4");
+ goto exit;
+ }
+
+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) {
+ seq_printf(s, "%s Registers:\n", regs[i].name);
+ for (j = 0; j <= regs[i].endreg; j += 4) {
+ u8 reg[4];
+ u16 addr = j + regs[i].addr;
+ seq_printf(s, " %04X: ", addr);
+ r = dsi_vc_generic_read_2(dssdev, mpd->channel,
+ addr>>8, addr&0xFF, reg, 4);
+ if (r)
+ seq_printf(s, "read failed ret = %d\n", r);
+ else
+ seq_printf(s, "%02X%02X%02X%02X\n",
+ reg[0], reg[1], reg[2], reg[3]);
+ }
+ }
+
+ dsi_vc_set_max_rx_packet_size(dssdev, mpd->channel, 1);
+
+exit:
+ dsi_runtime_put(dsidev);
+exit1:
+ dsi_bus_unlock(dssdev);
+}
+#endif
+
static void minnow_panel_esd_work(struct work_struct *work);
static void minnow_panel_ulps_work(struct work_struct *work);
@@ -278,10 +489,34 @@ static int minnow_panel_sleep_out(struct minnow_panel_data *mpd)
return 0;
}
-static int minnow_panel_get_id(struct minnow_panel_data *mpd, u8 *id1, u8 *id2, u8 *id3)
+static int minnow_panel_get_bridge_rev(struct minnow_panel_data *mpd,
+ u8 *id1, u8 *id2, u8 *id3)
+{
+ int r = dsi_vc_set_max_rx_packet_size(mpd->dssdev, mpd->channel, 4);
+
+ if (!r) {
+ u8 reg[4];
+ r = dsi_vc_generic_read_2(mpd->dssdev,
+ mpd->channel, 0, 0, reg, 4);
+ if (!r) {
+ *id1 = reg[0];
+ *id2 = reg[1];
+ *id3 = reg[3];
+ }
+ }
+ dsi_vc_set_max_rx_packet_size(mpd->dssdev, mpd->channel, 1);
+
+ return r;
+}
+
+static int minnow_panel_get_id(struct minnow_panel_data *mpd,
+ u8 *id1, u8 *id2, u8 *id3)
{
int r;
+ if (mpd->id_panel == MINNOW_PANEL_CM_BRIDGE_320X320)
+ return minnow_panel_get_bridge_rev(mpd, id1, id2, id3);
+
r = minnow_panel_dcs_read_1(mpd, DCS_GET_ID1, id1);
if (r)
return r;
@@ -292,24 +527,67 @@ static int minnow_panel_get_id(struct minnow_panel_data *mpd, u8 *id1, u8 *id2,
if (r)
return r;
+
return 0;
}
static int _minnow_panel_init(struct minnow_panel_data *mpd)
{
+ u8 *data;
int i, r;
- for (i = 0; i < mpd->init_cmd_count; ) {
- u8 *data = mpd->init_cmd_data + i;
- r = *data++;
- i += r + 1;
- if (i > mpd->init_cmd_count) {
- dev_err(&mpd->dssdev->dev, "Invalid init command data selected!\n");
- return -EINVAL;
+
+ for (i = 0, data = mpd->init_cmd_data; *data; ) {
+ i += ((u32)*data + 2);
+ if (i >= mpd->init_cmd_count)
+ break;
+ if (data[1] >= CMD_TYPE_MAX)
+ break;
+ data += (*data + 2);
+ }
+
+ /* Init command data shall end with 0 */
+ if (*data) {
+ dev_err(&mpd->dssdev->dev, "Invalid panel initialize data\n");
+ return -EINVAL;
+ }
+
+ for (i = 0, data = mpd->init_cmd_data; *data; i++) {
+ int len = (u32)*data;
+ u8 cmd = data[1];
+ data += 2;
+ switch (cmd) {
+ case DCS_WRITE_SYNC:
+ r = dsi_vc_dcs_write(mpd->dssdev,
+ mpd->channel, data, len);
+ break;
+ case GENERIC_WRITE_SYNC:
+ r = dsi_vc_generic_write(mpd->dssdev,
+ mpd->channel, data, len);
+ break;
+ case DCS_WRITE:
+ r = dsi_vc_dcs_write_nosync(mpd->dssdev,
+ mpd->channel, data, len);
+ break;
+ case GENERIC_WRITE:
+ r = dsi_vc_generic_write_nosync(mpd->dssdev,
+ mpd->channel, data, len);
+ break;
+ case BTA_SYNC:
+ r = dsi_vc_send_bta_sync(mpd->dssdev, mpd->channel);
+ break;
+ case WAIT_MS:
+ msleep((len == 1 ? (u32)(*data) : *(u16 *)data));
+ break;
}
- r = dsi_vc_dcs_write(mpd->dssdev, mpd->channel, data, r);
- if (r)
+ if (r) {
+ dev_err(&mpd->dssdev->dev, "Failed process initialize"
+ "command[%d] len=%d type=%d ret=%d\n",
+ i, len, cmd, r);
break;
+ }
+ data += len;
}
+
return r;
}
@@ -839,20 +1117,40 @@ static struct attribute_group minnow_panel_attr_group = {
static void minnow_panel_hw_reset(struct omap_dss_device *dssdev)
{
struct minnow_panel_data *mpd = dev_get_drvdata(&dssdev->dev);
+ int i, ms_rst = -1, ms_rel = -1;
- if (!gpio_is_valid(mpd->reset_gpio))
+ for (i = 0; i < MINNOW_RESET_MAX; i++) {
+ if (!gpio_is_valid(mpd->reset_gpio[i]))
+ continue;
+ gpio_set_value(mpd->reset_gpio[i],
+ mpd->hw_reset[i].active ? 0 : 1);
+ if (ms_rst < mpd->hw_reset[i].reset_ms)
+ ms_rst = mpd->hw_reset[i].reset_ms;
+ if (ms_rel < mpd->hw_reset[i].wait_ms)
+ ms_rel = mpd->hw_reset[i].wait_ms;
+ }
+ if (ms_rst == -1)
return;
+ msleep(5);
- gpio_set_value(mpd->reset_gpio, 1);
- udelay(10);
- /* reset the panel */
- gpio_set_value(mpd->reset_gpio, 0);
+ /* reset the device */
+ for (i = 0; i < MINNOW_RESET_MAX; i++) {
+ if (!gpio_is_valid(mpd->reset_gpio[i]))
+ continue;
+ gpio_set_value(mpd->reset_gpio[i],
+ mpd->hw_reset[i].active ? 1 : 0);
+ }
+ /* wait device reset */
+ msleep(ms_rst);
/* assert reset */
- udelay(10);
- gpio_set_value(mpd->reset_gpio, 1);
-
+ for (i = 0; i < MINNOW_RESET_MAX; i++) {
+ if (!gpio_is_valid(mpd->reset_gpio[i]))
+ continue;
+ gpio_set_value(mpd->reset_gpio[i],
+ mpd->hw_reset[i].active ? 0 : 1);
+ }
/* wait after releasing reset */
- msleep(5);
+ msleep(ms_rel);
}
#define DEBUG_DT
@@ -900,30 +1198,40 @@ static int minnow_panel_dt_init(struct minnow_panel_data *mpd)
"Invalid id_panel = %u!\n", value);
return -EINVAL;
}
- DTINFO("id_panel = %d\n", value);
- panel_attr = &panel_attr_table[value];
+ mpd->id_panel = value;
+ DTINFO("id_panel = %d\n", mpd->id_panel);
+
+ panel_attr = &panel_attr_table[mpd->id_panel];
mpd->init_cmd_data = panel_attr->init_cmd;
mpd->init_cmd_count = panel_attr->init_cmd_count;
- mpd->x_offset = panel_attr->xoffset;
- mpd->y_offset = panel_attr->yoffset;
- mpd->dssdev->panel.timings.x_res = panel_attr->xres;
- mpd->dssdev->panel.timings.y_res = panel_attr->yres;
- mpd->dssdev->panel.timings.pixel_clock = DIV_ROUND_UP(panel_attr->xres\
- * panel_attr->yres * panel_attr->rate, 1000);
- mpd->dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
mpd->dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
- mpd->dsi_config.mode = OMAP_DSS_DSI_CMD_MODE;
- mpd->dsi_config.pixel_format = OMAP_DSS_DSI_FMT_RGB888;
- mpd->dsi_config.hs_clk_min = 90000000;
- mpd->dsi_config.hs_clk_max = 150000000;
- mpd->dsi_config.lp_clk_min = 7000000;
- mpd->dsi_config.lp_clk_max = 9000000;
+ mpd->dssdev->panel.timings.x_res = panel_attr->xres;
+ mpd->dssdev->panel.timings.y_res = panel_attr->yres;
+ mpd->dssdev->panel.timings.pixel_clock = panel_attr->pixel_clock;
+ mpd->dssdev->panel.dsi_pix_fmt = panel_attr->pixel_format;
+ mpd->dsi_config.mode = panel_attr->mode;
+ mpd->dsi_config.pixel_format = panel_attr->pixel_format;
+ mpd->dsi_config.hs_clk_min = panel_attr->hs.min;
+ mpd->dsi_config.hs_clk_max = panel_attr->hs.max;
+ mpd->dsi_config.lp_clk_min = panel_attr->lp.min;
+ mpd->dsi_config.lp_clk_max = panel_attr->lp.max;
+ mpd->x_offset = panel_attr->xoffset;
+ mpd->y_offset = panel_attr->yoffset;
- mpd->reset_gpio = of_get_named_gpio(dt_node, "gpio_reset", 0);
- DTINFO("gpio_reset = %d\n", mpd->reset_gpio);
+ mpd->hw_reset[MINNOW_RESET_PANEL] = panel_attr->panel_reset;
+ mpd->hw_reset[MINNOW_RESET_BRIDGE] = panel_attr->bridge_reset;
+ mpd->reset_gpio[MINNOW_RESET_PANEL] =
+ of_get_named_gpio(dt_node, "gpio_panel_reset", 0);
+ DTINFO("gpio_panel_reset = %d\n", mpd->reset_gpio[MINNOW_RESET_PANEL]);
+ mpd->reset_gpio[MINNOW_RESET_BRIDGE] =
+ of_get_named_gpio(dt_node, "gpio_bridge_reset", 0);
+ DTINFO("gpio_bridge_reset = %d\n",
+ mpd->reset_gpio[MINNOW_RESET_BRIDGE]);
mpd->ext_te_gpio = of_get_named_gpio(dt_node, "gpio_te", 0);
- DTINFO("ext_te: gpio_te = %d\n", mpd->ext_te_gpio);
+ DTINFO("gpio_te = %d\n", mpd->ext_te_gpio);
+ mpd->clk_en_gpio = of_get_named_gpio(dt_node, "gpio_clk_en", 0);
+ DTINFO("gpio_clk_en = %d\n", mpd->clk_en_gpio);
mpd->esd_interval = 0;
if (!of_property_read_u32(dt_node, "esd_interval", &value)) {
@@ -1021,7 +1329,7 @@ static int minnow_panel_probe(struct omap_dss_device *dssdev)
struct backlight_properties props;
struct minnow_panel_data *mpd;
struct backlight_device *bldev = NULL;
- int r;
+ int i, r;
dev_dbg(&dssdev->dev, "probe\n");
@@ -1040,11 +1348,28 @@ static int minnow_panel_probe(struct omap_dss_device *dssdev)
atomic_set(&mpd->do_update, 0);
- if (gpio_is_valid(mpd->reset_gpio)) {
- r = devm_gpio_request_one(&dssdev->dev, mpd->reset_gpio,
- GPIOF_OUT_INIT_HIGH, "minnow-panel reset");
+ if (gpio_is_valid(mpd->clk_en_gpio)) {
+ r = devm_gpio_request_one(&dssdev->dev, mpd->clk_en_gpio,
+ GPIOF_OUT_INIT_HIGH, "minnow-panel clk_en");
+ if (r) {
+ dev_err(&dssdev->dev, "failed to request panel clk_en gpio\n");
+ return r;
+ }
+ }
+
+ for (i = 0; i < MINNOW_RESET_MAX; i++) {
+ static const char * const name[MINNOW_RESET_MAX] = {
+ "minnow-panel reset",
+ "minnow-bridge reset"
+ };
+ if (!gpio_is_valid(mpd->reset_gpio[i]))
+ continue;
+ r = devm_gpio_request_one(&dssdev->dev, mpd->reset_gpio[i],
+ mpd->hw_reset[i].active ? GPIOF_OUT_INIT_LOW
+ : GPIOF_OUT_INIT_HIGH, name[i]);
if (r) {
- dev_err(&dssdev->dev, "failed to request reset gpio\n");
+ dev_err(&dssdev->dev,
+ "failed to request %s gpio\n", name[i]);
return r;
}
}
@@ -1053,11 +1378,13 @@ static int minnow_panel_probe(struct omap_dss_device *dssdev)
r = devm_gpio_request_one(&dssdev->dev, mpd->ext_te_gpio,
GPIOF_IN, "minnow-panel irq");
if (r) {
- dev_err(&dssdev->dev, "failed to request ext_te gpio\n");
+ dev_err(&dssdev->dev,
+ "failed to request ext_te gpio\n");
return r;
}
- r = devm_request_irq(&dssdev->dev, gpio_to_irq(mpd->ext_te_gpio),
+ r = devm_request_irq(&dssdev->dev,
+ gpio_to_irq(mpd->ext_te_gpio),
minnow_panel_te_isr,
IRQF_TRIGGER_RISING,
"minnow-panel vsync", dssdev);
@@ -1120,6 +1447,11 @@ static int minnow_panel_probe(struct omap_dss_device *dssdev)
goto err_vc_id;
}
+#ifdef CONFIG_OMAP2_DSS_DEBUGFS
+ if (mpd->id_panel == MINNOW_PANEL_CM_BRIDGE_320X320)
+ dss_debugfs_create_file("panel_regs", minnow_panel_dump_regs);
+#endif
+
return 0;
err_vc_id:
@@ -1182,29 +1514,34 @@ static int minnow_panel_power_on(struct omap_dss_device *dssdev)
goto err0;
}
+#ifdef CONFIG_OMAP2_DSS_RESET
+ minnow_panel_hw_reset(dssdev);
+#else
+ /* Need reset display at first time as it's already enable on boot */
if (mpd->intro_printed)
minnow_panel_hw_reset(dssdev);
+#endif
omapdss_dsi_vc_enable_hs(dssdev, mpd->channel, false);
- r = minnow_panel_sleep_out(mpd);
+ r = _minnow_panel_init(mpd);
if (r)
goto err;
- _minnow_panel_init(mpd);
-
r = minnow_panel_get_id(mpd, &id1, &id2, &id3);
if (r)
goto err;
- r = minnow_panel_dcs_write_0(mpd, MIPI_DCS_SET_DISPLAY_ON);
+ r = _minnow_panel_enable_te(dssdev, mpd->te_enabled);
if (r)
goto err;
- r = _minnow_panel_enable_te(dssdev, mpd->te_enabled);
+ r = minnow_panel_dcs_write_0(mpd, MIPI_DCS_SET_DISPLAY_ON);
if (r)
goto err;
+ omapdss_dsi_vc_enable_hs(dssdev, mpd->channel, true);
+
r = dsi_enable_video_output(dssdev, mpd->channel);
if (r)
goto err;
@@ -1217,8 +1554,6 @@ static int minnow_panel_power_on(struct omap_dss_device *dssdev)
mpd->intro_printed = true;
}
- omapdss_dsi_vc_enable_hs(dssdev, mpd->channel, true);
-
return 0;
err:
dev_err(&dssdev->dev, "error while enabling panel, issuing HW reset\n");
@@ -1343,7 +1678,6 @@ static irqreturn_t minnow_panel_te_isr(int irq, void *data)
if (old) {
cancel_delayed_work(&mpd->te_timeout_work);
-
r = omap_dsi_update(dssdev, mpd->channel, minnow_panel_framedone_cb,
dssdev);
if (r)
@@ -1375,6 +1709,10 @@ static int minnow_panel_update(struct omap_dss_device *dssdev,
struct minnow_panel_data *mpd = dev_get_drvdata(&dssdev->dev);
int r;
+ /* for video mode, do not need manual update */
+ if (mpd->dsi_config.mode == OMAP_DSS_DSI_VIDEO_MODE)
+ return 0;
+
dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
mutex_lock(&mpd->lock);
@@ -1445,9 +1783,6 @@ static int _minnow_panel_enable_te(struct omap_dss_device *dssdev, bool enable)
if (!gpio_is_valid(mpd->ext_te_gpio))
omapdss_dsi_enable_te(dssdev, enable);
- /* possible panel bug */
- msleep(100);
-
return r;
}
@@ -1543,12 +1878,14 @@ static int minnow_panel_memory_read(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h)
{
int r;
- int first = 1;
int plen;
- unsigned buf_used = 0;
+ u32 buf_used = 0;
struct minnow_panel_data *mpd = dev_get_drvdata(&dssdev->dev);
+ u8 dcs_cmd = MIPI_DCS_READ_MEMORY_START;
- if (size < w * h * 3)
+ plen = dsi_get_pixel_size(mpd->dssdev->panel.dsi_pix_fmt);
+ plen = DIV_ROUND_UP(plen, 8);
+ if (size < w * h * plen)
return -ENOMEM;
mutex_lock(&mpd->lock);
@@ -1558,9 +1895,9 @@ static int minnow_panel_memory_read(struct omap_dss_device *dssdev,
goto err1;
}
- size = min(w * h * 3,
+ size = min(w * h * plen,
dssdev->panel.timings.x_res *
- dssdev->panel.timings.y_res * 3);
+ dssdev->panel.timings.y_res * plen);
dsi_bus_lock(dssdev);
@@ -1568,39 +1905,24 @@ static int minnow_panel_memory_read(struct omap_dss_device *dssdev,
if (r)
goto err2;
- /* plen 1 or 2 goes into short packet. until checksum error is fixed,
- * use short packets. plen 32 works, but bigger packets seem to cause
- * an error. */
- if (size % 2)
- plen = 1;
- else
- plen = 2;
-
minnow_panel_set_update_window(mpd, x, y, w, h);
+ /* each read 8 pixel as SSD2848 has minimum read pixels */
+ plen *= 8;
r = dsi_vc_set_max_rx_packet_size(dssdev, mpd->channel, plen);
if (r)
goto err2;
- while (buf_used < size) {
- u8 dcs_cmd = first ? 0x2e : 0x3e;
- first = 0;
-
+ size = size / plen * plen;
+ for (; buf_used < size; dcs_cmd = MIPI_DCS_READ_MEMORY_CONTINUE) {
r = dsi_vc_dcs_read(dssdev, mpd->channel, dcs_cmd,
- buf + buf_used, size - buf_used);
-
- if (r < 0) {
- dev_err(&dssdev->dev, "read error\n");
+ buf + buf_used, plen);
+ if (r) {
+ dev_err(&dssdev->dev,
+ "read failed at %u err=%d\n", buf_used, r);
goto err3;
}
-
- buf_used += r;
-
- if (r < plen) {
- dev_err(&dssdev->dev, "short read\n");
- break;
- }
-
+ buf_used += plen;
if (signal_pending(current)) {
dev_err(&dssdev->dev, "signal pending, "
"aborting memory read\n");
@@ -1608,7 +1930,6 @@ static int minnow_panel_memory_read(struct omap_dss_device *dssdev,
goto err3;
}
}
-
r = buf_used;
err3:
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index cb0f145c707..2bf82e2e15a 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -116,4 +116,8 @@ config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
This option enables the sleep, and is enabled by default. You can
disable the sleep if it doesn't cause problems on your platform.
+config OMAP2_DSS_RESET
+ bool "Reset OMAP Display Subsystem"
+ default n
+
endif
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 749aa38605a..69b44185ed1 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -4594,8 +4594,10 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
dsi_enable_pll_clock(dsidev, 1);
+#ifndef CONFIG_OMAP2_DSS_RESET
dsi_vc_enable(dsidev, 0, 0);
dsi_vc_enable(dsidev, 1, 0);
+#endif
_dsi_initialize_irq(dsidev);
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index f5f57a4e9a2..27579d8f76b 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -29,6 +29,7 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/omapfb.h>
+#include <linux/uaccess.h>
#include <video/omapdss.h>
#include <video/omapvrfb.h>
@@ -906,6 +907,8 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
mirror = ofbi->mirror;
info.paddr = data_start_p;
+ info.p_uv_addr = (u32)omapfb_get_region_vaddr(ofbi) +
+ (data_start_p - (u32)omapfb_get_region_paddr(ofbi));
info.screen_width = screen_width;
info.width = xres;
info.height = yres;
@@ -1048,6 +1051,7 @@ static int omapfb_set_par(struct fb_info *fbi)
static int omapfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *fbi)
{
+ struct omap_dss_device *display = fb2display(fbi);
struct omapfb_info *ofbi = FB2OFB(fbi);
struct fb_var_screeninfo new_var;
int r;
@@ -1070,6 +1074,12 @@ static int omapfb_pan_display(struct fb_var_screeninfo *var,
omapfb_put_mem_region(ofbi->region);
+ if (display && display->driver->update && display->driver->sync) {
+ DBG("sync_update(%d, %d)\n", var->xres, var->yres);
+ display->driver->sync(display);
+ display->driver->update(display, 0, 0, var->xres, var->yres);
+ }
+
return r;
}
@@ -1290,6 +1300,97 @@ ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
}
#endif
+ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct omapfb_info *ofbi = FB2OFB(info);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_dss_device *display = fb2display(info);
+ struct omapfb_display_data *d;
+ struct fb_var_screeninfo *var = &info->var;
+ unsigned long p = *ppos;
+ u8 *buffer, *src;
+ u8 __iomem *dst;
+ int c, cnt, err = 0;
+ unsigned long total_size;
+
+ DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
+
+ total_size = var->xres * var->yres * (var->bits_per_pixel>>3);
+ if (p > total_size)
+ return -EFBIG;
+ if (count > total_size) {
+ err = -EFBIG;
+ count = total_size;
+ }
+ if (count + p > total_size) {
+ if (!err)
+ err = -ENOSPC;
+
+ count = total_size - p;
+ }
+
+ DBG("omapfb_write %d, %lu, %lu\n", count, p, total_size);
+
+ buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
+ GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ dst = (u8 __iomem *)(info->screen_base + p);
+ c = var->bits_per_pixel >> 3;
+ cnt = var->xres_virtual * c;
+ dst += var->yoffset*cnt + var->xoffset*c;
+ DBG("omapfb_write offset = %d, scr_size = %lu\n",
+ (int)(dst) - (int)(info->screen_base + p), info->screen_size);
+
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
+
+ for (cnt = 0; count; ) {
+ c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+ src = buffer;
+
+ if (copy_from_user(src, buf, c)) {
+ err = -EFAULT;
+ break;
+ }
+
+ fb_memcpy_tofb(dst, src, c);
+ dst += c;
+ src += c;
+ *ppos += c;
+ buf += c;
+ cnt += c;
+ count -= c;
+ }
+
+ kfree(buffer);
+
+ if (total_size <= *ppos && display &&
+ display->driver->update && display->driver->sync) {
+ DBG("fb_var_screen info:\n");
+ DBG("\txres = %u\n", var->xres);
+ DBG("\tyres = %u\n", var->yres);
+ DBG("\txres_virtual = %u\n", var->xres_virtual);
+ DBG("\tyres_virtual = %u\n", var->yres_virtual);
+ DBG("\txoffset = %u\n", var->xoffset);
+ DBG("\tyoffset = %u\n", var->yoffset);
+ DBG("\tbits_per_pixel = %u\n", var->bits_per_pixel);
+ omapfb_lock(fbdev);
+ d = get_display_data(fbdev, display);
+ if (d->update_mode == OMAPFB_MANUAL_UPDATE) {
+ DBG("sync_update(%d, %d)\n", var->xres, var->yres);
+ display->driver->sync(display);
+ display->driver->update(display,
+ 0, 0, var->xres, var->yres);
+ }
+ omapfb_unlock(fbdev);
+ }
+
+ return (cnt) ? cnt : err;
+}
+
static struct fb_ops omapfb_ops = {
.owner = THIS_MODULE,
.fb_open = omapfb_open,
@@ -1305,7 +1406,7 @@ static struct fb_ops omapfb_ops = {
.fb_mmap = omapfb_mmap,
.fb_setcolreg = omapfb_setcolreg,
.fb_setcmap = omapfb_setcmap,
- /*.fb_write = omapfb_write,*/
+ .fb_write = omapfb_write,
};
static void omapfb_free_fbmem(struct fb_info *fbi)