diff options
| -rw-r--r-- | drivers/gpu/pvr/Makefile | 3 | ||||
| -rw-r--r-- | drivers/gpu/pvr/services4/3rdparty/dc_omapfb3_linux/omaplfb_linux.c | 10 | ||||
| -rw-r--r-- | drivers/video/omap2/displays/panel-minnow-common.h | 175 | ||||
| -rw-r--r-- | drivers/video/omap2/displays/panel-minnow.c | 664 |
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); |