summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWengang Wu <wgw@motorola.com>2014-05-15 12:09:23 -0500
committerWengang Wu <wgw@motorola.com>2014-05-20 00:50:02 +0000
commit7cb6941f44acdf142aed3c0feb7e28a9b712ac91 (patch)
tree4e85fab1e2d7fdd4ae5538a43728d5bf710416d6
parent2f31b672dbf04ca02af624db49b873b5cee47348 (diff)
downloadolio-linux-3.10-7cb6941f44acdf142aed3c0feb7e28a9b712ac91.tar.xz
olio-linux-3.10-7cb6941f44acdf142aed3c0feb7e28a9b712ac91.zip
IKXCLOCK-1342 Display: support new cut 2.1 panel and new timing for bluetooth defense
1. support panel determination to apply different settings 2. apply new timing settings for bluetooth defense, current MIPI TX HS CLK setting are: OMAP = 104 MHz, SOLOMON = 108.3 MHz 3. sync initial setting data for both boot-loader and kernel, and pass panel type from boot-loader Change-Id: Iff9dacb738829a0739373b85ee913cd214d4bd50
-rw-r--r--drivers/gpu/pvr/Makefile3
-rw-r--r--drivers/gpu/pvr/services4/3rdparty/dc_omapfb3_linux/omaplfb_linux.c10
-rw-r--r--drivers/video/omap2/displays/panel-minnow-common.h175
-rw-r--r--drivers/video/omap2/displays/panel-minnow.c664
4 files changed, 539 insertions, 313 deletions
diff --git a/drivers/gpu/pvr/Makefile b/drivers/gpu/pvr/Makefile
index a848a8c79ec..11f512373f8 100644
--- a/drivers/gpu/pvr/Makefile
+++ b/drivers/gpu/pvr/Makefile
@@ -52,7 +52,8 @@ ccflags-y = -Idrivers/video/omap2 \
ccflags-$(CONFIG_SGX_OMAP3630) += \
-Idrivers/gpu/pvr/services4/system/omap3630 \
-DSGX530 -DSUPPORT_SGX530 -DSGXCORE=530 \
- -DSGX_CORE_REV=125
+ -DSGX_CORE_REV=125 \
+ -DSKIP_FIRST_FLIP_BUFS=4
ccflags-$(CONFIG_SGX_BUILD_RELEASE) += \
-DPVR_BUILD_TYPE="\"release\"" \
diff --git a/drivers/gpu/pvr/services4/3rdparty/dc_omapfb3_linux/omaplfb_linux.c b/drivers/gpu/pvr/services4/3rdparty/dc_omapfb3_linux/omaplfb_linux.c
index 9525688ab40..ce3c8cbd38f 100644
--- a/drivers/gpu/pvr/services4/3rdparty/dc_omapfb3_linux/omaplfb_linux.c
+++ b/drivers/gpu/pvr/services4/3rdparty/dc_omapfb3_linux/omaplfb_linux.c
@@ -334,6 +334,16 @@ void OMAPLFBFlip(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_BUFFER *psBuffer)
struct fb_var_screeninfo sFBVar;
int res;
unsigned long ulYResVirtual;
+#ifdef SKIP_FIRST_FLIP_BUFS
+ /* Skip first n numbers of flip buffers to avoid draw blank screen
+ * that occurred flicker at first time booting up
+ */
+ static unsigned int skip_flips = SKIP_FIRST_FLIP_BUFS;
+ if (skip_flips) {
+ --skip_flips;
+ return;
+ }
+#endif
OMAPLFB_CONSOLE_LOCK();
diff --git a/drivers/video/omap2/displays/panel-minnow-common.h b/drivers/video/omap2/displays/panel-minnow-common.h
new file mode 100644
index 00000000000..e4b142daf8e
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-minnow-common.h
@@ -0,0 +1,175 @@
+/*
+ * Minnow DSI command mode panel - common initialization data header
+ *
+ * Copyright (C) 2013-2014 Motorola Mobility LLC.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MINNOW_PANEL_COMMON_HEADER_
+
+/* This header file is used to sync Bootloader and Kernel Display Initialize
+ * Structure/Data, please make sure sync it for both Bootloader/Kernel when
+ * it changes some settings for Solomon/Orise
+ */
+#ifndef u8
+typedef unsigned char u8;
+#endif
+
+enum minnow_panel_type {
+ PANEL_INIT = -1, /* Not Initialize */
+ PANEL_DUMMY, /* None panel detected */
+ OTM3201_1_0, /* Initial Orise Panel 1.0, it's not stable */
+ OTM3201_2_0, /* Orise Panel 2.0, only for test purpose */
+ OTM3201_2_1, /* Orise Panel 2.1 */
+};
+
+/* Panel initialize command type description:
+ * DCS_WRITE_SYNC, DCS_WRITE:
+ * standard DCS type command with/without BTA sync
+ * GENERIC_WRITE_SYNC, GENERIC_WRITE:
+ * standard Generic type command with/without BTA sync
+ * BTA_SYNC:
+ * standard BTA sync command
+ * WAIT_MS:
+ * sleep for given milliseconds
+ * SSD2848_CMD:
+ * special command for SSD2848 bridge register, it has fixed 6 bytes format,
+ * the fist 2 bytes is the register address, the last is 32 bits register
+ * OTM3201_CMD:
+ * special command for OTM3201 register, it has flexible register length,
+ * the fist byte is the register address
+ * SWITCH_TO_PANEL:
+ * turn on/off bridge retransmission mode by follow 1 byte
+ * this is a indicator that separate initialize sequence for bridge and panel.
+ *
+ * There's different requirement for bridge and panel initialization,
+ * for bridge, it needs initialize first and it should verify all registers
+ * only after write all the registers. when the verification is failed,
+ * it must reset hardware to retry initialize.
+ * for panel, it needs initialize after bridge, and it should verify each
+ * register after each write. when the verify is failed, it could retry to
+ * re-write the failed register.
+ */
+enum minnow_cmd_type {
+ DCS_WRITE_SYNC,
+ GENERIC_WRITE_SYNC,
+ DCS_WRITE,
+ GENERIC_WRITE,
+ BTA_SYNC,
+ WAIT_MS,
+ SSD2848_CMD,
+ OTM3201_CMD,
+ SWITCH_TO_PANEL,
+ CMD_TYPE_MAX
+};
+/* Special register id to indicate the verification is needed */
+#define CMD_VERIFY_REG 0xFF
+
+/* Panel initialize command buffer description:
+ * it uses compact buffer to store all initialize commands, the first
+ * byte of each command is the command length in byte
+ */
+static u8 panel_init_ssd2848_320x320[] = {
+/*n, type, data_0, data_1 ... data_n-1*/
+1, SWITCH_TO_PANEL, 0,
+6, SSD2848_CMD, 0x00, 0x08, 0x01, 0xF4, 0x05, 0x32,
+6, SSD2848_CMD, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0B,
+6, SSD2848_CMD, 0x00, 0x14, 0x0C, 0x07, 0x80, 0x0F,
+1, DCS_WRITE_SYNC, MIPI_DCS_EXIT_SLEEP_MODE,
+1, WAIT_MS, 1,
+6, SSD2848_CMD, 0x10, 0x08, 0x01, 0x20, 0x01, 0x45,
+6, SSD2848_CMD, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x02,
+6, SSD2848_CMD, 0x20, 0x10, 0x00, 0xF7, 0x00, 0x6C,
+6, SSD2848_CMD, 0x20, 0x14, 0x01, 0x88, 0x00, 0x2A,
+6, SSD2848_CMD, 0x20, 0x18, 0x01, 0x4E, 0x00, 0x0A,
+6, SSD2848_CMD, 0x20, 0x20, 0x01, 0x40, 0x01, 0x40,
+6, SSD2848_CMD, 0x20, 0x24, 0x01, 0x40, 0x01, 0x40,
+6, SSD2848_CMD, 0x20, 0x30, 0x00, 0x00, 0x00, 0x15,
+6, SSD2848_CMD, 0x20, 0x34, 0x00, 0x00, 0x00, 0x00,
+6, SSD2848_CMD, 0x20, 0x38, 0x01, 0x3F, 0x01, 0x3F,
+6, SSD2848_CMD, 0x20, 0x3C, 0x01, 0x40, 0x01, 0x40,
+6, SSD2848_CMD, 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, SSD2848_CMD, 0x60, 0x08, 0x00, 0x02, 0x00, 0x0A,
+6, SSD2848_CMD, 0x60, 0x0C, 0x0A, 0x2A, 0x02, 0x0A,
+6, SSD2848_CMD, 0x60, 0x10, 0x01, 0x40, 0x02, 0x14,
+6, SSD2848_CMD, 0x60, 0x14, 0x01, 0x00, 0x01, 0x00,
+6, SSD2848_CMD, 0x60, 0x40, 0x13, 0x01, 0x0A, 0x01,
+6, SSD2848_CMD, 0x60, 0x44, 0x05, 0x05, 0x04, 0x0A,
+6, SSD2848_CMD, 0x60, 0x84, 0x00, 0x00, 0x01, 0x40,
+1, SSD2848_CMD, CMD_VERIFY_REG, /* command for verify ssd2848 registers */
+1, SWITCH_TO_PANEL, 1,
+3, OTM3201_CMD, 0xF0, 0x54, 0x47,
+2, OTM3201_CMD, 0xA0, 0x00,
+4, OTM3201_CMD, 0xBD, 0x00, 0x11, 0x31,
+2, OTM3201_CMD, 0xE9, 0x46,
+2, OTM3201_CMD, 0xB1, 0x12,
+2, OTM3201_CMD, 0xE2, 0xF0,
+5, OTM3201_CMD, 0xBA, 0x06, 0x15, 0x2B, 0x01,
+6, OTM3201_CMD, 0xB3, 0x02, 0x0A, 0x14, 0x2A, 0x2A,
+5, OTM3201_CMD, 0xB5, 0x78, 0x78, 0x76, 0xF6,
+18, OTM3201_CMD, 0xC0, 0x00, 0x06, 0x17, 0x11, 0x16, 0x25, 0x0E,
+ 0x0C, 0x0C, 0x0E, 0x0C, 0x2F, 0x07, 0x0A, 0x3F, 0x3F, 0x3F,
+18, OTM3201_CMD, 0xC1, 0x00, 0x06, 0x17, 0x11, 0x16, 0x25, 0x0E,
+ 0x0C, 0x0C, 0x0E, 0x0C, 0x2F, 0x07, 0x0A, 0x3F, 0x3F, 0x3F,
+18, OTM3201_CMD, 0xC2, 0x00, 0x06, 0x17, 0x11, 0x16, 0x25, 0x0E,
+ 0x0C, 0x0C, 0x0E, 0x0C, 0x2F, 0x07, 0x0A, 0x3F, 0x3F, 0x3F,
+18, OTM3201_CMD, 0xC3, 0x00, 0x06, 0x17, 0x11, 0x16, 0x25, 0x0E,
+ 0x0C, 0x0C, 0x0E, 0x0C, 0x2F, 0x07, 0x0A, 0x3F, 0x3F, 0x3F,
+18, OTM3201_CMD, 0xC4, 0x00, 0x06, 0x17, 0x11, 0x16, 0x25, 0x0E,
+ 0x0C, 0x0C, 0x0E, 0x0C, 0x2F, 0x07, 0x0A, 0x3F, 0x3F, 0x3F,
+18, OTM3201_CMD, 0xC5, 0x00, 0x06, 0x17, 0x11, 0x16, 0x25, 0x0E,
+ 0x0C, 0x0C, 0x0E, 0x0C, 0x2F, 0x07, 0x0A, 0x3F, 0x3F, 0x3F,
+1, OTM3201_CMD, CMD_VERIFY_REG, /* command for verify otm3201 registers */
+2, OTM3201_CMD, 0xA0, 0x80,
+3, OTM3201_CMD, 0xF0, 0x00, 0x00,
+1, DCS_WRITE_SYNC, MIPI_DCS_EXIT_SLEEP_MODE,
+1, WAIT_MS, 120,
+1, DCS_WRITE_SYNC, MIPI_DCS_SET_DISPLAY_ON,
+1, SWITCH_TO_PANEL, 0,
+0
+};
+
+/* Special settings for OTM3201 PANEL revision 1.0
+ * Orise panel 1.0 has known issue that don't meet MIPI timing requirement
+ * it needs the different timing setting that apply for panel 2.0 or above
+ */
+static u8 panel_init_ssd2848_320x320_1[] = {
+6, SSD2848_CMD, 0x60, 0x44, 0x0A, 0x0A, 0x04, 0x16,
+0
+};
+
+static u8 panel_off_ssd2848_320x320[] = {
+/*n, type, data_0, data_1 ... data_n-1*/
+1, SWITCH_TO_PANEL, 1,
+1, DCS_WRITE_SYNC, MIPI_DCS_SET_DISPLAY_OFF,
+1, DCS_WRITE, MIPI_DCS_ENTER_SLEEP_MODE,
+1, SWITCH_TO_PANEL, 0,
+1, DCS_WRITE_SYNC, MIPI_DCS_SET_DISPLAY_OFF,
+1, WAIT_MS, 50,
+1, DCS_WRITE, MIPI_DCS_ENTER_SLEEP_MODE,
+1, WAIT_MS, 20,
+6, GENERIC_WRITE, 0x10, 0x28, 0x00, 0x00, 0x00, 0x01, /*power cut enabled*/
+1, WAIT_MS, 5,
+0
+};
+
+/* Special code to process Orise internal register */
+static u8 otm3201_eng_mode[] = { 0xF0, 0x54, 0x47 };
+static u8 otm3201_write_mode[] = { 0xA0, 0x00 };
+static u8 otm3201_read_mode[] = { 0xA0, 0x80 };
+
+#define _MINNOW_PANEL_COMMON_HEADER_
+#endif
diff --git a/drivers/video/omap2/displays/panel-minnow.c b/drivers/video/omap2/displays/panel-minnow.c
index 8819bac9509..b88c5184607 100644
--- a/drivers/video/omap2/displays/panel-minnow.c
+++ b/drivers/video/omap2/displays/panel-minnow.c
@@ -41,9 +41,7 @@
#include "../dss/dss.h"
-/* panel parameter to indicate if it needs skip first time initialize */
-static bool def_skip_first_init;
-module_param_named(skip_first_init, def_skip_first_init, bool, 0);
+#include "panel-minnow-common.h"
/* DSI Virtual channel. Hardcoded for now. */
#define TCH 0
@@ -70,43 +68,6 @@ enum minnow_panel_id {
MINNOW_PANEL_MAX
};
-/* Panel initialize command type description:
- * DCS_WRITE_SYNC, DCS_WRITE:
- * standard DCS type command with/without BTA sync
- * GENERIC_WRITE_SYNC, GENERIC_WRITE:
- * standard Generic type command with/without BTA sync
- * BTA_SYNC:
- * standard BTA sync command
- * WAIT_MS:
- * sleep for given milliseconds
- * CHECK_MS:
- * same as WAIT_MS, but it also use this time to read back register to
- * verify it.
- * SSD2848_CMD:
- * special command for SSD2848 bridge register, it has fixed 6 bytes format,
- * the fist 2 bytes is the register address, the last is 32 bits register
- * OTM3201_CMD:
- * special command for OTM3201 register, it has flexible register length,
- * the fist byte is the register address
- */
-enum minnow_cmd_type {
- DCS_WRITE_SYNC,
- GENERIC_WRITE_SYNC,
- DCS_WRITE,
- GENERIC_WRITE,
- BTA_SYNC,
- WAIT_MS,
- CHECK_MS,
- SSD2848_CMD,
- OTM3201_CMD,
- CMD_TYPE_MAX
-};
-
-/* Panel initialize command buffer description:
- * it uses compact buffer to store all initialize commands, the first
- * byte of each command is the command length in byte
- *
- */
static u8 panel_init_220x176[] = {
/*n, type, data_0, data_1 ... data_n-1*/
1, DCS_WRITE_SYNC, MIPI_DCS_EXIT_SLEEP_MODE,
@@ -181,86 +142,6 @@ static u8 panel_init_220x220[] = {
0
};
-#define BRIDGE_WIDTH 320
-#define BRIDGE_HEIGHT 320
-#define PANEL_WIDTH BRIDGE_WIDTH
-#define PANEL_HEIGHT 290
-#define UNUSED_LINES (BRIDGE_HEIGHT-PANEL_HEIGHT)
-
-#define SWITCH_TO_PANEL 2, SSD2848_CMD, 0xFF, 0x01
-#define SWITCH_TO_BRIDGE 2, SSD2848_CMD, 0xFF, 0x00
-static u8 panel_init_ssd2848_320x320[] = {
-/*n, type, data_0, data_1 ... data_n-1*/
-SWITCH_TO_BRIDGE,
-6, SSD2848_CMD, 0x00, 0x08, 0x01, 0xF4, 0x04, 0x29,
-6, SSD2848_CMD, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0B,
-6, SSD2848_CMD, 0x00, 0x14, 0x0C, 0x07, 0x80, 0x0F,
-1, DCS_WRITE_SYNC, MIPI_DCS_EXIT_SLEEP_MODE,
-1, WAIT_MS, 1,
-6, SSD2848_CMD, 0x10, 0x08, 0x01, 0x20, 0x01, 0x45,
-6, SSD2848_CMD, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x02,
-6, SSD2848_CMD, 0x20, 0x10, 0x00, 0x1B, 0x00, 0x0C,
-6, SSD2848_CMD, 0x20, 0x14, 0x01, 0x88, 0x00, 0x28,
-6, SSD2848_CMD, 0x20, 0x18, 0x01, 0x4E, 0x00, 0x0A,
-6, SSD2848_CMD, 0x20, 0x20, 0x01, 0x40, 0x01, 0x40,
-6, SSD2848_CMD, 0x20, 0x24, 0x01, 0x40, 0x01, 0x40,
-6, SSD2848_CMD, 0x20, 0x30, 0x00, 0x00, 0x00, 0x15,
-6, SSD2848_CMD, 0x20, 0x34, 0x00, 0x00, 0x00, 0x00,
-6, SSD2848_CMD, 0x20, 0x38, 0x01, 0x3F, 0x01, 0x3F,
-6, SSD2848_CMD, 0x20, 0x3C, 0x01, 0x40, 0x01, 0x40,
-6, SSD2848_CMD, 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, SSD2848_CMD, 0x60, 0x08, 0x00, 0x02, 0x00, 0x0A,
-6, SSD2848_CMD, 0x60, 0x0C, 0x0A, 0x2A, 0x02, 0x0A,
-6, SSD2848_CMD, 0x60, 0x10, 0x01, 0x40, 0x02, 0x14,
-6, SSD2848_CMD, 0x60, 0x14, 0x01, 0x00, 0x01, 0x00,
-6, SSD2848_CMD, 0x60, 0x40, 0x13, 0x01, 0x0A, 0x01,
-6, SSD2848_CMD, 0x60, 0x84, 0x00, 0x00, 0x01, 0x40,
-SWITCH_TO_PANEL,
-2, DCS_WRITE_SYNC, 0x36, 0x10,
-3, OTM3201_CMD, 0xF0, 0x54, 0x47,
-2, OTM3201_CMD, 0xA0, 0x00,
-4, OTM3201_CMD, 0xBD, 0x00, 0x11, 0x31,
-2, OTM3201_CMD, 0xE9, 0x46,
-5, OTM3201_CMD, 0xBA, 0x06, 0x15, 0x2B, 0x01,
-6, OTM3201_CMD, 0xB3, 0x02, 0x0A, 0x14, 0x2A, 0x2A,
-5, OTM3201_CMD, 0xB5, 0x78, 0x78, 0x76, 0xF6,
-18, OTM3201_CMD, 0xC0, 0x00, 0x06, 0x17, 0x11, 0x16, 0x25, 0x0E,
- 0x0C, 0x0C, 0x0E, 0x0C, 0x2F, 0x07, 0x0A, 0x3F, 0x3F, 0x3F,
-18, OTM3201_CMD, 0xC1, 0x00, 0x06, 0x17, 0x11, 0x16, 0x25, 0x0E,
- 0x0C, 0x0C, 0x0E, 0x0C, 0x2F, 0x07, 0x0A, 0x3F, 0x3F, 0x3F,
-18, OTM3201_CMD, 0xC2, 0x00, 0x06, 0x17, 0x11, 0x16, 0x25, 0x0E,
- 0x0C, 0x0C, 0x0E, 0x0C, 0x2F, 0x07, 0x0A, 0x3F, 0x3F, 0x3F,
-18, OTM3201_CMD, 0xC3, 0x00, 0x06, 0x17, 0x11, 0x16, 0x25, 0x0E,
- 0x0C, 0x0C, 0x0E, 0x0C, 0x2F, 0x07, 0x0A, 0x3F, 0x3F, 0x3F,
-18, OTM3201_CMD, 0xC4, 0x00, 0x06, 0x17, 0x11, 0x16, 0x25, 0x0E,
- 0x0C, 0x0C, 0x0E, 0x0C, 0x2F, 0x07, 0x0A, 0x3F, 0x3F, 0x3F,
-18, OTM3201_CMD, 0xC5, 0x00, 0x06, 0x17, 0x11, 0x16, 0x25, 0x0E,
- 0x0C, 0x0C, 0x0E, 0x0C, 0x2F, 0x07, 0x0A, 0x3F, 0x3F, 0x3F,
-1, DCS_WRITE_SYNC, MIPI_DCS_EXIT_SLEEP_MODE,
-1, CHECK_MS, 120,
-/* Needed switch back as it changed by function to clear bottom lines */
-SWITCH_TO_PANEL,
-1, DCS_WRITE_SYNC, MIPI_DCS_SET_DISPLAY_ON,
-SWITCH_TO_BRIDGE,
-0
-};
-
-static u8 panel_off_ssd2848_320x320[] = {
-/*n, type, data_0, data_1 ... data_n-1*/
-SWITCH_TO_PANEL,
-1, DCS_WRITE_SYNC, MIPI_DCS_SET_DISPLAY_OFF,
-1, DCS_WRITE, MIPI_DCS_ENTER_SLEEP_MODE,
-SWITCH_TO_BRIDGE,
-1, DCS_WRITE_SYNC, MIPI_DCS_SET_DISPLAY_OFF,
-1, WAIT_MS, 50,
-1, DCS_WRITE, MIPI_DCS_ENTER_SLEEP_MODE,
-1, WAIT_MS, 20,
-6, GENERIC_WRITE, 0x10, 0x28, 0x00, 0x00, 0x00, 0x01, /*power cut enabled*/
-0
-};
-
static u8 panel_off_common[] = {
/*n, type, data_0, data_1 ... data_n-1*/
1, DCS_WRITE_SYNC, MIPI_DCS_SET_DISPLAY_OFF,
@@ -269,11 +150,11 @@ static u8 panel_off_common[] = {
0
};
-enum minnow_panel_dummy_type {
- DUMMY_NONE = 0,
- DUMMY_ENABLED,
- DUMMY_DISABLED
-};
+#define BRIDGE_WIDTH 320
+#define BRIDGE_HEIGHT 320
+#define PANEL_WIDTH BRIDGE_WIDTH
+#define PANEL_HEIGHT 290
+#define UNUSED_LINES (BRIDGE_HEIGHT-PANEL_HEIGHT)
struct minnow_panel_clk_range {
int min;
@@ -356,13 +237,17 @@ static struct minnow_panel_attr panel_attr_table[MINNOW_PANEL_MAX] = {
.yoffset = 0,
INIT_CMD_BUF(on, panel_init_ssd2848_320x320),
INIT_CMD_BUF(off, panel_off_ssd2848_320x320),
- .hs = { 100000000, 150000000 },
+ .hs = { 104000000, 150000000 },
.lp = { 7000000, 9000000 },
.panel_reset = { ACTIVE_LOW, 5, 10 },
.bridge_reset = { ACTIVE_LOW, 20, 10 }
},
};
+/* panel parameter to indicate if it needs skip first time initialize */
+static enum minnow_panel_type def_panel_type = PANEL_INIT;
+module_param_named(panel_type, def_panel_type, int, 0);
+
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);
@@ -370,6 +255,7 @@ static int _minnow_panel_enable_te(struct omap_dss_device *dssdev, bool enable);
static int minnow_panel_reset(struct omap_dss_device *dssdev);
static int minnow_panel_update(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h);
+static int minnow_panel_wake_up(struct omap_dss_device *dssdev);
struct minnow_panel_data {
@@ -411,7 +297,7 @@ struct minnow_panel_data {
/* runtime variables */
bool enabled;
bool interactive;
- enum minnow_panel_dummy_type dummy_panel;
+ enum minnow_panel_type panel_type;
bool te_enabled;
@@ -423,6 +309,8 @@ struct minnow_panel_data {
unsigned cabc_mode;
bool first_enable;
+ bool skip_first_init;
+ int panel_retry_count;
struct workqueue_struct *workqueue;
@@ -447,18 +335,23 @@ static void minnow_panel_dump_regs(struct seq_file *s)
{"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!");
+ mutex_lock(&mpd->lock);
+ if (!mpd->enabled) {
+ seq_puts(s, "display is disabled!");
goto exit1;
}
+ dsi_bus_lock(dssdev);
+ r = minnow_panel_wake_up(dssdev);
+ if (r) {
+ seq_printf(s, "display wake up failed(%d)!\n", r);
+ goto exit;
+ }
+
if (mpd->dssdev != dssdev) {
seq_puts(s, "dssdev mis-matched!");
goto exit;
@@ -486,22 +379,84 @@ static void minnow_panel_dump_regs(struct seq_file *s)
}
dsi_vc_set_max_rx_packet_size(dssdev, mpd->channel, 1);
-
exit:
- dsi_runtime_put(dsidev);
-exit1:
dsi_bus_unlock(dssdev);
+exit1:
+ mutex_unlock(&mpd->lock);
}
#endif
static void minnow_panel_esd_work(struct work_struct *work);
static void minnow_panel_ulps_work(struct work_struct *work);
-static int set_bridge_retrans(struct minnow_panel_data *mpd, int enable)
+static void minnow_panel_delay(int delay_ms)
+{
+ if (delay_ms > 5)
+ msleep(delay_ms);
+ else
+ usleep_range(1000 * delay_ms, 1000 * delay_ms + 100);
+}
+
+static int panel_ssd2848_set_retransmit(struct minnow_panel_data *mpd,
+ int enable)
{
u8 data[2] = {0xFF, enable ? 0x01 : 0x00};
- return dsi_vc_generic_write(mpd->dssdev,
- mpd->channel, data, sizeof(data));
+ return dsi_vc_generic_write(mpd->dssdev, mpd->channel, data, 2);
+}
+
+static int panel_ssd2848_read_reg(struct minnow_panel_data *mpd,
+ u16 addr, u8 *read)
+{
+ int r;
+ dsi_vc_set_max_rx_packet_size(mpd->dssdev, mpd->channel, 4);
+ r = dsi_vc_generic_read_2(mpd->dssdev, mpd->channel,
+ addr>>8, addr&0xFF, read, 4);
+ dsi_vc_set_max_rx_packet_size(mpd->dssdev, mpd->channel, 1);
+ return r;
+}
+
+static int panel_otm3201_read_reg(struct minnow_panel_data *mpd,
+ u8 addr, u8 *read, u8 len)
+{
+ int r;
+ dsi_vc_set_max_rx_packet_size(mpd->dssdev, mpd->channel, len);
+ r = dsi_vc_dcs_read(mpd->dssdev, mpd->channel, addr, read, len);
+ dsi_vc_set_max_rx_packet_size(mpd->dssdev, mpd->channel, 1);
+ return r;
+}
+
+#define WRITE_OTM3201(mpd, cmd) \
+ dsi_vc_dcs_write(mpd->dssdev, mpd->channel, cmd, sizeof(cmd))
+static int panel_otm3201_rewrite_reg(struct minnow_panel_data *mpd,
+ u8 *data, u8 len, u8 *read)
+{
+ /* retry to write only when it could read back */
+ int r, retry;
+
+ for (retry = 3; retry--; ) {
+ r = WRITE_OTM3201(mpd, otm3201_eng_mode);
+ if (r)
+ break;
+ r = WRITE_OTM3201(mpd, otm3201_write_mode);
+ if (r)
+ break;
+ r = dsi_vc_dcs_write(mpd->dssdev, mpd->channel, data, len);
+ if (r)
+ break;
+ r = WRITE_OTM3201(mpd, otm3201_read_mode);
+ if (r)
+ break;
+ r = panel_otm3201_read_reg(mpd, data[0], read, len-1);
+ if (r)
+ break;
+ /* special register B5h */
+ if (data[0] == 0xB5)
+ read[3] |= data[4]&0x80;
+ if (!memcmp(read, data+1, len-1))
+ break;
+ }
+
+ return r;
}
static int minnow_panel_dcs_read_1(struct minnow_panel_data *mpd, u8 dcs_cmd, u8 *data)
@@ -532,33 +487,21 @@ static int minnow_panel_dcs_write_1(struct minnow_panel_data *mpd, u8 dcs_cmd, u
return dsi_vc_dcs_write(mpd->dssdev, mpd->channel, buf, 2);
}
-static int minnow_panel_get_bridge_rev(struct minnow_panel_data *mpd,
+static int minnow_panel_get_id(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);
+ int r;
- if (!r) {
- u8 reg[4];
- r = dsi_vc_generic_read_2(mpd->dssdev,
- mpd->channel, 0, 0, reg, 4);
+ if (mpd->id_panel == MINNOW_PANEL_CM_BRIDGE_320X320) {
+ u8 data[4];
+ r = panel_ssd2848_read_reg(mpd, 0, data);
if (!r) {
- *id1 = reg[0];
- *id2 = reg[1];
- *id3 = reg[3];
+ *id1 = data[0];
+ *id2 = data[1];
+ *id3 = mpd->panel_type;
}
+ return r;
}
- 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)
@@ -614,17 +557,19 @@ static int minnow_panel_set_update_window(struct minnow_panel_data *mpd,
/* since SSD2848 frame buffer is 320 x 320, but the actual panel is 320 x 290
* it needs clear the unused bottom 30 lines for saving power
*/
-static int minnow_panel_clear_bottom_line(struct minnow_panel_data *mpd)
+static int minnow_panel_clear_bottom_line(struct minnow_panel_data *mpd,
+ unsigned int delay_ms)
{
int r = 0;
#if UNUSED_LINES
+ unsigned int last_ms = jiffies_to_msecs(jiffies);
int plen, total;
u8 buf[124]; /* maximum packet size */
memset(buf, 0, sizeof(buf));
buf[0] = MIPI_DCS_WRITE_MEMORY_START;
- r = set_bridge_retrans(mpd, false);
+ r = panel_ssd2848_set_retransmit(mpd, false);
if (r)
return r;
@@ -649,15 +594,30 @@ static int minnow_panel_clear_bottom_line(struct minnow_panel_data *mpd)
mpd->dssdev->panel.timings.y_res);
omapdss_dsi_vc_enable_hs(mpd->dssdev, mpd->channel, false);
+
+ if (r) {
+ /* waiting for the rest of time */
+ last_ms = jiffies_to_msecs(jiffies) - last_ms;
+ if (last_ms < delay_ms)
+ minnow_panel_delay(delay_ms - last_ms);
+ }
+#else
+ minnow_panel_delay(delay_ms);
#endif
return r;
}
static int minnow_panel_process_cmd(struct minnow_panel_data *mpd,
- u8 cmd, u8 *data, int len)
+ u8 cmd, u8 *data, int len, bool retrans)
{
int r = -EINVAL;
+ if (retrans) {
+ r = panel_ssd2848_set_retransmit(mpd, true);
+ if (r)
+ return r;
+ }
+
switch (cmd) {
case DCS_WRITE_SYNC:
case OTM3201_CMD:
@@ -681,155 +641,178 @@ static int minnow_panel_process_cmd(struct minnow_panel_data *mpd,
r = dsi_vc_send_bta_sync(mpd->dssdev, mpd->channel);
break;
case WAIT_MS:
- case CHECK_MS:
- msleep((len == 1 ? (u32)(*data) : *(u16 *)data));
- r = 0;
+ r = (int)(len == 1 ? (u32)(*data) : *(u16 *)data);
+ /* It needs to clean bottom line for Solomon+Orise,
+ * and to save time it uses the waiting time(120 ms) of
+ * Orise's initialization process
+ */
+ if ((r > 100) &&
+ (mpd->id_panel == MINNOW_PANEL_CM_BRIDGE_320X320))
+ r = minnow_panel_clear_bottom_line(mpd, r);
+ else {
+ minnow_panel_delay(r);
+ r = 0;
+ }
break;
+ default:
+ r = -EINVAL;
}
+ if (retrans)
+ panel_ssd2848_set_retransmit(mpd, false);
+
return r;
}
-static int minnow_panel_verify_ssd2848(struct minnow_panel_data *mpd, u8 *data)
+static int minnow_panel_detect_type(struct minnow_panel_data *mpd)
{
- u8 reg[4];
- int r = -EINVAL;
- if (data[0] != 6)
- return r;
-
- r = dsi_vc_set_max_rx_packet_size(mpd->dssdev, mpd->channel, 4);
- if (r)
- return r;
-
- r = dsi_vc_generic_read_2(mpd->dssdev, mpd->channel,
- data[2], data[3], reg, 4);
- if (!r && (*(u32 *)(data+4) != *(u32 *)reg)) {
- dev_err(&mpd->dssdev->dev, "Failed verify ssd2848 reg"
- "[%02x%02x] %02x %02x %02x %02x\n", data[2], data[3],
- reg[0], reg[1], reg[2], reg[3]);
- r = -EINVAL;
+ u8 rev;
+ int r = panel_otm3201_read_reg(mpd, 0xB0, &rev, sizeof(rev));
+ if (!r) {
+ switch (rev) {
+ case 0x12:
+ mpd->panel_type = OTM3201_1_0;
+ break;
+ case 0x1A:
+ mpd->panel_type = OTM3201_2_0;
+ break;
+ case 0x1C:
+ default:
+ mpd->panel_type = OTM3201_2_1;
+ break;
+ }
}
-
return r;
}
-static int minnow_panel_verify_otm3201(struct minnow_panel_data *mpd, u8 *data)
+static void print_reg_mismatch(struct device *dev, u8 *src, u8 *read, int len)
{
- static u8 reg_wo[] = { 0xA0, 0xF0, 0xB5 }; /* write only registers */
- int i, len, r = 0;
- u8 reg[18];
-
- for (i = r = 0; i < (sizeof(reg_wo)/sizeof(reg_wo[0])); i++) {
- if (data[2] == reg_wo[i]) {
- if (data[2] == 0xA0) {
- /* set OTM3201 read mode */
- reg[0] = 0xA0;
- reg[1] = 0x80;
- r = dsi_vc_dcs_write(mpd->dssdev,
- mpd->channel, reg, 2);
- }
- /* do not read back for write only register */
- return r;
- }
- }
-
- len = data[0] - 1;
- if ((u32)(len) > sizeof(reg))
- return -EINVAL;
-
- r = dsi_vc_set_max_rx_packet_size(mpd->dssdev, mpd->channel, len);
- if (r)
- return r;
-
- r = dsi_vc_dcs_read(mpd->dssdev, mpd->channel, data[2], reg, len);
- if (r)
- return r;
+ char *pstr, str[100];
+ int i;
+ for (i = 0, pstr = str; i < len; i++, pstr += 3)
+ sprintf(pstr, " %02X", src[i]);
+ dev_dbg(dev, " Init:%s\n", str);
+ for (i = 0, pstr = str; i < len; i++, pstr += 3)
+ sprintf(pstr, " %02X", read[i]);
+ dev_dbg(dev, " Read:%s\n", str);
+}
- for (i = 0; i < len; i++) {
- if (reg[i] != data[3+i])
+static int minnow_panel_verify_ssd2848(struct minnow_panel_data *mpd,
+ u8 *cmdbuf)
+{
+ u8 *data, read[4];
+ int r = panel_ssd2848_set_retransmit(mpd, false);
+ for (data = cmdbuf; *data && !r; data += *data+2) {
+ u16 addr;
+ if (data[1] != SSD2848_CMD)
+ continue;
+ if (data[2] == CMD_VERIFY_REG)
break;
- }
- if (i < len) {
- char errstr[88], *pstr;
- sprintf(errstr, "Failed verify otm3201 reg[%02x]", data[2]);
- pstr = errstr + strlen(errstr);
- for (i = 0; i < len; i++, pstr += 3)
- sprintf(pstr, " %02x", reg[i]);
- strcpy(pstr, "\n");
- dev_err(&mpd->dssdev->dev, errstr);
- r = -EINVAL;
+ addr = ((u16)data[2]<<8) | data[3];
+ r = panel_ssd2848_read_reg(mpd, addr, read);
+ if (r)
+ break;
+ if (!memcmp(&read, data+4, 4))
+ continue;
+ dev_err(&mpd->dssdev->dev, "Failed verify ssd2848"
+ " register: %04X\n", addr);
+ print_reg_mismatch(&mpd->dssdev->dev, data+4, read, 4);
+ break;
}
return r;
}
-static int minnow_panel_dummy_check(struct minnow_panel_data *mpd)
+static bool _minnow_panel_replace_cmdbuf(u8 *cmdbuf, u8 *data)
{
- int r = set_bridge_retrans(mpd, true);
- if (!r) {
- u8 id1;
- r = minnow_panel_dcs_read_1(mpd, DCS_GET_ID1, &id1);
- if (r) {
- dev_err(&mpd->dssdev->dev, "Failed get panel id, "
- "enable dummy panel !!!");
- mpd->dummy_panel = DUMMY_ENABLED;
- } else {
- mpd->dummy_panel = DUMMY_DISABLED;
- r = set_bridge_retrans(mpd, false);
+ for (; *cmdbuf; cmdbuf += *cmdbuf+2) {
+ if ((data[0] != cmdbuf[0]) || (data[1] != cmdbuf[1]))
+ continue;
+ if (data[1] == SSD2848_CMD) {
+ if ((data[2] != cmdbuf[2]) || (data[3] != cmdbuf[3]))
+ continue;
+ memcpy(cmdbuf+4, data+4, 4);
+ return true;
+ } else if (data[1] == OTM3201_CMD) {
+ if (data[2] != cmdbuf[2])
+ continue;
+ memcpy(cmdbuf+3, data+3, cmdbuf[0]-1);
+ return true;
}
}
- return r;
+ return false;
}
-static int minnow_panel_verify_cmdbuf(struct minnow_panel_data *mpd,
- struct minnow_panel_cmd_buf *cmd_buf)
+static bool minnow_panel_replace_cmdbuf(u8 *cmdbuf, u8 *data)
{
- u8 *data;
- int i, r = 0;
- unsigned long start_jiffies = jiffies;
- unsigned int delay_ms;
-
- /* it check dummy panel only at first time power on */
- if (mpd->dummy_panel == DUMMY_NONE) {
- r = minnow_panel_dummy_check(mpd);
- if (r)
- return r;
+ bool ret = false;
+ for (; *data; data += *data+2) {
+ if (_minnow_panel_replace_cmdbuf(cmdbuf, data))
+ ret = true;
}
+ return ret;
+}
- data = cmd_buf->cmdbuf;
- for (i = 0; *data && !r; i++, data += *data+2) {
- switch (data[1]) {
- case SSD2848_CMD:
- if (data[0] == 2) {
- /* set bridge retransmission mode */
- r = dsi_vc_generic_write(mpd->dssdev,
- mpd->channel,
- data+2, 2);
- continue;
- }
- r = minnow_panel_verify_ssd2848(mpd, data);
+static int minnow_panel_verify_otm3201(struct minnow_panel_data *mpd,
+ u8 *cmdbuf)
+{
+ u8 *data, addr, read[20];
+ int r = panel_ssd2848_set_retransmit(mpd, true);
+ for (data = cmdbuf; *data && !r; data += *data+2) {
+ if (data[1] != OTM3201_CMD)
+ continue;
+ addr = data[2];
+ if (addr == CMD_VERIFY_REG) {
+ break;
+ } else if (addr == 0xF0) {
+ /* resend command to make sure enable engineer mode */
+ r = dsi_vc_dcs_write(mpd->dssdev, mpd->channel,
+ data+2, data[0]);
continue;
- case OTM3201_CMD:
- if (mpd->dummy_panel == DUMMY_DISABLED)
- r = minnow_panel_verify_otm3201(mpd, data);
+ } else if (addr == 0xA0) {
+ /* for initialization, it needs set write mode,
+ * but for verification, it needs set read mode
+ */
+ r = WRITE_OTM3201(mpd, otm3201_read_mode);
+ if (!r && (mpd->panel_type == PANEL_INIT)) {
+ r = minnow_panel_detect_type(mpd);
+ if (r)
+ break;
+ if (mpd->panel_type != OTM3201_1_0)
+ continue;
+ /* it needs replace some settings for 1.0 */
+ if (minnow_panel_replace_cmdbuf
+ (cmdbuf, panel_init_ssd2848_320x320_1)) {
+ dev_info(&mpd->dssdev->dev,
+ "Force reset for new settings"
+ "of panel 1.0!\n");
+ mpd->panel_retry_count = 0;
+ r = -EIO;
+ break;
+ }
+ }
continue;
}
- if (data[1] == CHECK_MS) {
- delay_ms = (unsigned int)(data[0] == 1
- ? (u16)(data[2]) : *(u16 *)(data+2));
+ r = panel_otm3201_read_reg(mpd, addr, read, data[0]-1);
+ if (r)
+ break;
+ /* special register B5h */
+ if (addr == 0xB5)
+ read[3] |= data[6]&0x80;
+ if (!memcmp(&read, data+3, data[0]-1))
+ continue;
+ /* trying to rewrite register */
+ r = panel_otm3201_rewrite_reg(mpd, data+2, data[0], read);
+ if (r) {
+ print_reg_mismatch(&mpd->dssdev->dev,
+ data+3, read, data[0]-1);
break;
}
}
- dsi_vc_set_max_rx_packet_size(mpd->dssdev, mpd->channel, 1);
-
- if (!r)
- r = minnow_panel_clear_bottom_line(mpd);
- if (!r) {
- unsigned int elapse_ms;
- elapse_ms = jiffies_to_msecs(jiffies - start_jiffies);
- if (elapse_ms < delay_ms)
- msleep(delay_ms - elapse_ms);
- }
+ panel_ssd2848_set_retransmit(mpd, false);
+ if (r)
+ dev_err(&mpd->dssdev->dev, "Failed verify otm3201"
+ " register: %02X\n", addr);
return r;
}
@@ -857,10 +840,12 @@ static int minnow_panel_check_cmdbuf(struct minnow_panel_data *mpd,
}
static int minnow_panel_process_cmdbuf(struct minnow_panel_data *mpd,
- struct minnow_panel_cmd_buf *cmd_buf)
+ struct minnow_panel_cmd_buf *cmd_buf,
+ bool verify)
{
u8 *data;
int i, r;
+ bool retrans = false;
/* be safe to check command data every time before sent to driver */
r = minnow_panel_check_cmdbuf(mpd, cmd_buf->cmdbuf, cmd_buf->count);
@@ -868,11 +853,21 @@ static int minnow_panel_process_cmdbuf(struct minnow_panel_data *mpd,
return r;
for (i = 0, data = cmd_buf->cmdbuf; *data; i++, data += *data+2) {
- if (data[1] == CHECK_MS)
- r = minnow_panel_verify_cmdbuf(mpd, cmd_buf);
- else
- r = minnow_panel_process_cmd(mpd, data[1],
- data+2, data[0]);
+ if ((data[1] == SSD2848_CMD) &&
+ (data[0] == 1) && (data[2] == CMD_VERIFY_REG)) {
+ if (!verify)
+ continue;
+ r = minnow_panel_verify_ssd2848(mpd, cmd_buf->cmdbuf);
+ } else if ((data[1] == OTM3201_CMD) && (data[0] == 1) &&
+ (data[2] == CMD_VERIFY_REG)) {
+ if (!verify)
+ continue;
+ r = minnow_panel_verify_otm3201(mpd, cmd_buf->cmdbuf);
+ } else if (data[1] == SWITCH_TO_PANEL) {
+ retrans = !!data[2];
+ } else
+ r = minnow_panel_process_cmd(mpd, data[1], data+2,
+ data[0], retrans);
if (r) {
dev_err(&mpd->dssdev->dev, "Failed process initialize"
" command[%d] len=%d type=%d ret=%d\n",
@@ -1508,7 +1503,7 @@ static void _minnow_panel_hw_active_reset(struct minnow_panel_data *mpd)
}
/* wait device reset */
- msleep(mpd->reset_ms);
+ minnow_panel_delay(mpd->reset_ms);
}
static void _minnow_panel_hw_reset(struct omap_dss_device *dssdev)
@@ -1528,7 +1523,7 @@ static void _minnow_panel_hw_reset(struct omap_dss_device *dssdev)
/* wait after releasing reset */
if (mpd->release_ms > 0)
- msleep(mpd->release_ms);
+ minnow_panel_delay(mpd->release_ms);
}
static int minnow_panel_set_regulators(struct minnow_panel_data *mpd,
@@ -1778,12 +1773,32 @@ static int minnow_panel_probe(struct omap_dss_device *dssdev)
atomic_set(&mpd->do_update, 0);
+ /* it will reset bridge/panel if boot-loader does not initialize it */
+ mpd->skip_first_init = false;
+ mpd->panel_type = def_panel_type;
+ switch (def_panel_type) {
+ case PANEL_INIT:
+ case PANEL_DUMMY:
+ dev_info(&dssdev->dev,
+ "There is not panel id coming from boot-loader\n");
+ break;
+ case OTM3201_1_0:
+ case OTM3201_2_0:
+ case OTM3201_2_1:
+ mpd->skip_first_init = true;
+ break;
+ default:
+ dev_err(&dssdev->dev,
+ "Wrong panel id(%d) got from boot-loader\n",
+ def_panel_type);
+ break;
+ }
dev_info(&dssdev->dev, "skip first time initialization is %s\n",
- def_skip_first_init ? "enabled" : "disabled");
+ mpd->skip_first_init ? "enabled" : "disabled");
if (gpio_is_valid(mpd->vio_en_gpio)) {
r = devm_gpio_request_one(&dssdev->dev, mpd->vio_en_gpio,
- def_skip_first_init
+ mpd->skip_first_init
? GPIOF_OUT_INIT_LOW
: GPIOF_OUT_INIT_HIGH,
"minnow-panel vio_en");
@@ -1801,16 +1816,19 @@ static int minnow_panel_probe(struct omap_dss_device *dssdev)
"minnow-panel reset",
"minnow-bridge reset"
};
+ bool active_low = (mpd->hw_reset[i].active == ACTIVE_LOW);
if (!gpio_is_valid(mpd->reset_gpio[i]))
continue;
+ /* skip_first_init hw_reset.active gpio_init
+ * Y ACTIVE_LOW INIT_HIGH
+ * Y ACTIVE_HIGH INIT_LOW
+ * N ACTIVE_LOW INIT_LOW
+ * N ACTIVE_HIGH INIT_HIGH
+ */
r = devm_gpio_request_one(&dssdev->dev, mpd->reset_gpio[i],
- def_skip_first_init
- ? (mpd->hw_reset[i].active
- ? GPIOF_OUT_INIT_LOW
- : GPIOF_OUT_INIT_HIGH)
- : (mpd->hw_reset[i].active
- ? GPIOF_OUT_INIT_HIGH
- : GPIOF_OUT_INIT_LOW),
+ (mpd->skip_first_init ^ active_low)
+ ? GPIOF_OUT_INIT_LOW
+ : GPIOF_OUT_INIT_HIGH,
name[i]);
if (r) {
dev_err(&dssdev->dev,
@@ -1862,6 +1880,11 @@ static int minnow_panel_probe(struct omap_dss_device *dssdev)
name[i]);
}
mpd->regulators[i] = rt;
+ if (!mpd->skip_first_init) {
+ /* toggle enable/disable to force disable */
+ r = regulator_enable(rt);
+ r = regulator_disable(rt);
+ }
}
mpd->workqueue = create_singlethread_workqueue("minnow_panel_esd");
@@ -1963,21 +1986,22 @@ static int minnow_panel_check_panel_status(struct minnow_panel_data *mpd)
if (mpd->id_panel != MINNOW_PANEL_CM_BRIDGE_320X320)
return 0;
- r = set_bridge_retrans(mpd, true);
+ r = panel_ssd2848_set_retransmit(mpd, true);
if (!r) {
- r = dsi_vc_dcs_read(mpd->dssdev, mpd->channel,
- MIPI_DCS_GET_POWER_MODE, &mode, 1);
- set_bridge_retrans(mpd, false);
+ r = panel_otm3201_read_reg(mpd, MIPI_DCS_GET_POWER_MODE,
+ &mode, 1);
+ panel_ssd2848_set_retransmit(mpd, false);
}
+
if (r)
- return r;
- if (mode != DCS_POWER_MODE_NORMAL) {
- dev_err(&mpd->dssdev->dev,
+ dev_dbg(&mpd->dssdev->dev, "unable to get panel power mode\n");
+ else if (mode != DCS_POWER_MODE_NORMAL) {
+ dev_dbg(&mpd->dssdev->dev,
"panel is not On, power mode is 0x%02x\n", mode);
- return -ENODEV;
+ r = -EIO;
}
- return 0;
+ return r;
}
#define POWER_ON_RETRY_TIMES 3
@@ -1985,9 +2009,13 @@ static int minnow_panel_power_on(struct omap_dss_device *dssdev)
{
struct minnow_panel_data *mpd = dev_get_drvdata(&dssdev->dev);
u8 id1, id2, id3;
- int r, retry = POWER_ON_RETRY_TIMES;
+ int r;
+ bool need_verify = true;
+
+ mpd->panel_retry_count = 0;
init_start:
+ mpd->panel_retry_count++;
r = omapdss_dsi_configure_pins(dssdev, &mpd->pin_config);
if (r) {
dev_err(&dssdev->dev, "failed to configure DSI pins\n");
@@ -2010,18 +2038,30 @@ init_start:
omapdss_dsi_vc_enable_hs(dssdev, mpd->channel, false);
/* for the first time power on, do not reset h/w to keep logo on */
- if (mpd->first_enable && def_skip_first_init) {
+ if (mpd->first_enable && mpd->skip_first_init) {
dsi_vc_send_bta_sync(dssdev, mpd->channel);
} else {
_minnow_panel_hw_reset(dssdev);
- r = minnow_panel_process_cmdbuf(mpd, &mpd->power_on);
+ r = minnow_panel_process_cmdbuf(mpd, &mpd->power_on,
+ need_verify);
if (!r) {
- if (mpd->dummy_panel == DUMMY_DISABLED)
+ if (mpd->panel_type != PANEL_DUMMY)
r = minnow_panel_check_panel_status(mpd);
}
if (r) {
- if (!retry--)
- goto err;
+ if (mpd->panel_retry_count >= POWER_ON_RETRY_TIMES) {
+ if (mpd->panel_type == PANEL_INIT) {
+ dev_err(&dssdev->dev,
+ "No panel to be detected, "
+ "using dummy panel instead\n");
+ mpd->panel_type = PANEL_DUMMY;
+ } else {
+ if (!need_verify)
+ goto err;
+ }
+ /* try without read back check */
+ need_verify = false;
+ }
dev_err(&dssdev->dev, "Reset hardware to retry ...\n");
omapdss_dsi_display_disable(dssdev, true, false);
goto init_start;
@@ -2075,7 +2115,7 @@ static void minnow_panel_power_off(struct omap_dss_device *dssdev)
dsi_disable_video_output(dssdev, mpd->channel);
- r = minnow_panel_process_cmdbuf(mpd, &mpd->power_off);
+ r = minnow_panel_process_cmdbuf(mpd, &mpd->power_off, false);
if (r)
dev_err(&dssdev->dev,
"error disabling panel, return %d\n", r);
@@ -2134,7 +2174,7 @@ static int minnow_panel_enable(struct omap_dss_device *dssdev)
mutex_unlock(&mpd->lock);
/* do not force update at first time if it needs keep logo on */
- if (!(mpd->first_enable && def_skip_first_init))
+ if (!(mpd->first_enable && mpd->skip_first_init))
r = minnow_panel_update(dssdev, 0, 0,
dssdev->panel.timings.x_res,
dssdev->panel.timings.y_res);