From patchwork Wed Feb 22 01:09:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hoegeun Kwon X-Patchwork-Id: 9585951 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 63D63600CA for ; Wed, 22 Feb 2017 01:10:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4934E2853C for ; Wed, 22 Feb 2017 01:10:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3D9FA28649; Wed, 22 Feb 2017 01:10:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id C3D752853C for ; Wed, 22 Feb 2017 01:10:01 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id CE7EE6E2FF; Wed, 22 Feb 2017 01:10:00 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mailout4.samsung.com (mailout4.samsung.com [203.254.224.34]) by gabe.freedesktop.org (Postfix) with ESMTPS id ECF556E73B for ; Wed, 22 Feb 2017 01:09:57 +0000 (UTC) Received: from epcas1p2.samsung.com (unknown [182.195.41.46]) by mailout4.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0OLR02QCS4KI7Z40@mailout4.samsung.com> for dri-devel@lists.freedesktop.org; Wed, 22 Feb 2017 10:09:54 +0900 (KST) Received: from epsmges5p1.samsung.com (unknown [182.195.40.66]) by epcas1p4.samsung.com (KnoxPortal) with ESMTP id 20170222010954epcas1p4e9de63efda7c63da3f7839e5b39a4ee9~ldrpVBVpF0397703977epcas1p4o; Wed, 22 Feb 2017 01:09:54 +0000 (GMT) Received: from epcas5p2.samsung.com ( [182.195.41.40]) by epsmges5p1.samsung.com (EPCPMTA) with SMTP id F6.81.04848.2E4ECA85; Wed, 22 Feb 2017 10:09:54 +0900 (KST) Received: from epcpsbgm2new.samsung.com (u27.gpu120.samsung.co.kr [203.254.230.27]) by epcas5p1.samsung.com (KnoxPortal) with ESMTP id 20170222010953epcas5p1c8fd194058f1000290937b1c2baf13ab~ldroJssn11954319543epcas5p1g; Wed, 22 Feb 2017 01:09:53 +0000 (GMT) X-AuditID: b6c32a2c-f79b56d0000012f0-e8-58ace4e2f99a Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2new.samsung.com (EPCPMTA) with SMTP id 4C.D8.06422.1E4ECA85; Wed, 22 Feb 2017 10:09:53 +0900 (KST) Received: from [10.113.63.38] by mmp1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0OLR00EQ04KGTVA0@mmp1.samsung.com>; Wed, 22 Feb 2017 10:09:52 +0900 (KST) From: Hoegeun Kwon Subject: [PATCH v10 2/3] drm/panel: Add support for S6E3HA2 panel driver on TM2 board To: thierry.reding@gmail.com, airlied@linux.ie, robh+dt@kernel.org, mark.rutland@arm.com, catalin.marinas@arm.com, will.deacon@arm.com, kgene@kernel.org, krzk@kernel.org Message-id: Date: Wed, 22 Feb 2017 10:09:52 +0900 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.7.0 MIME-version: 1.0 In-reply-to: X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrHJsWRmVeSWpSXmKPExsWy7bCmhu6jJ2siDO72yVvcWneO1aL33Ekm i+1HnrFavF/Ww2hx/ctzVov5R4ASV76+Z7N4v7yLzWLS/QksFm/ermGyuPGrjdWi//FrZovz 5zewW2x6fI3V4vKuOWwWM87vY7JYev0ik0Xr3iPsFj93zWOxePnxBIuDiMeaeWsYPXbOusvu sWlVJ5vH9m8PWD3udx9n8ti8pN5jSz9QvG/LKkaPz5vkAjijUm0yUhNTUosUUvOS81My89Jt lbyD453jTc0MDHUNLS3MlRTyEnNTbZVcfAJ03TJzgF5TUihLzCkFCgUkFhcr6dvZFOWXlqQq ZOQXl9gqRRsaGukZGpjrGRkZ6ZkYx1oZmQKVJKRmvHuwjqVg0j3GiuXL57A0MB7YxtjFyMkh IWAiMe/PUTYIW0ziwr31QDYXh5DAUkaJ27s6mCCcdiaJf729zDAdv2/eBusWEljOKNE/0wCi 6C6jxJ4jP8BGsQnoSnztuc4EYgsLhEts7D3BDFIkIrCWUaLh8ENGEIdZ4CGTxOTfv1hAqngF 7CQWPNwKZrMIqEosmH0PzBYViJDYcaOHDaJGUOLHZJA4BwenQILE47dgFzELOEo8WLSTFcKW l9i85i3YMgmBhRwSy77dZAeplxCQldh0gBnCdJH4Ol0K4hlhiVfHt7BD2NISf5feYoRo7WaU +N60AmrOBEaJnw0boN43lrj/4B7UYj6J3t9PmCCG8kp0tAlBmB4SD07LQ1Q7Sjy+084OCaA5 jBKP5j5mn8AoPwvJN7OQvDALyQsLGJlXMYqlFhTnpqcWmxYY6hUn5haX5qXrJefnbmIEp20t nR2M9xZ4H2IU4GBU4uGtOLsmQog1say4MvcQowQHs5II76SdQCHelMTKqtSi/Pii0pzU4kOM psAQnsgsJZqcD8wpeSXxhiZmhiZGlkBobmiuJM4bZTAxQkggPbEkNTs1tSC1CKaPiYNTqoFx 4fzOFaUuUp1WM185aCfdUzTSWypRd/dt02LTuKn/89Jevnp7eOJuqcAOxW93N80/v12+pzSi h3XZ0qX/15dckst/xZhwM/LYxntfzL9eiHu/+Dl/fkjuhpMtN8vtvwZ1zl6/1WvGrVR512tn JASW+myX2zHzIG/zzvYsn0eLylXX8Ojy1btMVWIpzkg01GIuKk4EAAejrBnxAwAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupjleLIzCtJLcpLzFFi42I5/e+xgO7DJ2siDO4t4Le4te4cq0XvuZNM FtuPPGO1eL+sh9Hi+pfnrBbzjwAlrnx9z2bxfnkXm8Wk+xNYLN68XcNkceNXG6tF/+PXzBbn z29gt9j0+BqrxeVdc9gsZpzfx2Sx9PpFJovWvUfYLX7umsdi8fLjCRYHEY8189YweuycdZfd Y9OqTjaP7d8esHrc7z7O5LF5Sb3Hln6geN+WVYwenzfJBXBGudlkpCampBYppOYl56dk5qXb KoWGuOlaKCnkJeam2ipF6PqGBCkplCXmlAJ5RgZowME5wD1YSd8uwS3j3YN1LAWT7jFWLF8+ h6WB8cA2xi5GTg4JAROJ3zdvQ9liEhfurWfrYuTiEBJYyiix4lYjO4Rzn1HiwrUdYFVsAroS X3uuM4HYwgLhEp37/jGCFIkIrGWU2LjkMlT7HEaJk5t2sYA4zAIPmSRe/LjMDNLCK2AnseDh VhYQm0VAVWLB7HtgtqhAhMT8p6uYIGoEJX5MhohzCiRILH82GSzOLGArseD9OhYIW15i85q3 zBMYBWYhaZmFpGwWkrIFjMyrGCVSC5ILipPSc43yUsv1ihNzi0vz0vWS83M3MYLTwjPpHYyH d7kfYhTgYFTi4X3gviZCiDWxrLgy9xCjBAezkgjvpJ1AId6UxMqq1KL8+KLSnNTiQ4ymQI9M ZJYSTc4Hpqy8knhDE3MTc2MDC3NLSxMjJXHextnPwoUE0hNLUrNTUwtSi2D6mDg4pRoYNVhs p36ZmX/KJt/paFzwHc0c//sCIZ5B5iybTLlKV1sqrnmpe65LYt2GaffXH5m4oZjvN9OWVvaQ DT+3GpwW6TR8dF6e4eNUmZymdz1XncQzD82S4kyck2LsJbYgPil1mxOjooCIp0Wf/jwJ2WsH nqz8VOb23EL1unj63j1s1bn7Wr+GbspWYinOSDTUYi4qTgQA9e/QciEDAAA= X-MTR: 20000000000000000@CPGS X-CMS-MailID: 20170222010953epcas5p1c8fd194058f1000290937b1c2baf13ab X-Msg-Generator: CA X-Sender-IP: 203.254.230.27 X-Local-Sender: =?UTF-8?B?6raM7ZqM6re8G1RpemVuIFBsYXRmb3JtIExhYihTL1fshLw=?= =?UTF-8?B?7YSwKRvsgrzshLHsoITsnpAbUzMo7IKs7JuQKS/sgqzsm5A=?= X-Global-Sender: =?UTF-8?B?SG9lZ2V1biBLd29uG1RpemVuIFBsYXRmb3JtIExhYi4bU2Ft?= =?UTF-8?B?c3VuZyBFbGVjdHJvbmljcxtTMy9Bc3Npc3RhbnQgRW5naW5lZXI=?= X-Sender-Code: =?UTF-8?B?QzEwG1NUQUYbQzEwVjgxMTE=?= CMS-TYPE: 105P DLP-Filter: Pass X-CFilter-Loop: Reflected X-HopCount: 7 X-CMS-RootMailID: 20170220071001epcas1p39f8f4b9dcd96c7fb2e808ed3b943dfd3 X-RootMTR: 20170220071001epcas1p39f8f4b9dcd96c7fb2e808ed3b943dfd3 References: <1487574582-15746-1-git-send-email-hoegeun.kwon@samsung.com> Cc: devicetree@vger.kernel.org, linux-samsung-soc@vger.kernel.org, cw00.choi@samsung.com, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, javier@osg.samsung.com, jh80.chung@samsung.com, andi.shyti@samsung.com, Hoegeun Kwon , linux-arm-kernel@lists.infradead.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP This patch add support for MIPI-DSI based S6E3HA2 AMOLED panel driver. This panel has 1440x2560 resolution in 5.7-inch physical panel in the TM2 device. Signed-off-by: Donghwa Lee Signed-off-by: Hyungwon Hwang Signed-off-by: Hoegeun Kwon Tested-by: Chanwoo Choi Reviewed-by: Andrzej Hajda --- drivers/gpu/drm/panel/Kconfig | 6 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c | 739 ++++++++++++++++++++++++++ 3 files changed, 746 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c +MODULE_AUTHOR("Hoegeun Kwon "); +MODULE_DESCRIPTION("MIPI-DSI based s6e3ha2 AMOLED Panel Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 62aba97..d913c83 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -52,6 +52,12 @@ config DRM_PANEL_PANASONIC_VVX10F034N00 WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some Xperia Z2 tablets +config DRM_PANEL_SAMSUNG_S6E3HA2 + tristate "Samsung S6E3HA2 DSI video mode panel" + depends on OF + depends on DRM_MIPI_DSI + select VIDEOMODE_HELPERS + config DRM_PANEL_SAMSUNG_S6E8AA0 tristate "Samsung S6E8AA0 DSI video mode panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index a5c7ec0..1d483b0 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o +obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c new file mode 100644 index 0000000..4cc08d7 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c @@ -0,0 +1,739 @@ +/* + * MIPI-DSI based s6e3ha2 AMOLED 5.7 inch panel driver. + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Donghwa Lee + * Hyungwon Hwang + * Hoegeun Kwon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#define S6E3HA2_MIN_BRIGHTNESS 0 +#define S6E3HA2_MAX_BRIGHTNESS 100 +#define S6E3HA2_DEFAULT_BRIGHTNESS 80 + +#define S6E3HA2_NUM_GAMMA_STEPS 46 +#define S6E3HA2_GAMMA_CMD_CNT 35 +#define S6E3HA2_VINT_STATUS_MAX 10 + +static const u8 gamma_tbl[S6E3HA2_NUM_GAMMA_STEPS][S6E3HA2_GAMMA_CMD_CNT] = { + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x82, 0x83, + 0x85, 0x88, 0x8b, 0x8b, 0x84, 0x88, 0x82, 0x82, 0x89, 0x86, 0x8c, + 0x94, 0x84, 0xb1, 0xaf, 0x8e, 0xcf, 0xad, 0xc9, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x84, 0x84, + 0x85, 0x87, 0x8b, 0x8a, 0x84, 0x88, 0x82, 0x82, 0x89, 0x86, 0x8a, + 0x93, 0x84, 0xb0, 0xae, 0x8e, 0xc9, 0xa8, 0xc5, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83, + 0x85, 0x86, 0x8a, 0x8a, 0x84, 0x88, 0x81, 0x84, 0x8a, 0x88, 0x8a, + 0x91, 0x84, 0xb1, 0xae, 0x8b, 0xd5, 0xb2, 0xcc, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83, + 0x85, 0x86, 0x8a, 0x8a, 0x84, 0x87, 0x81, 0x84, 0x8a, 0x87, 0x8a, + 0x91, 0x85, 0xae, 0xac, 0x8a, 0xc3, 0xa3, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x85, 0x85, + 0x86, 0x85, 0x88, 0x89, 0x84, 0x89, 0x82, 0x84, 0x87, 0x85, 0x8b, + 0x91, 0x88, 0xad, 0xab, 0x8a, 0xb7, 0x9b, 0xb6, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83, + 0x85, 0x86, 0x89, 0x8a, 0x84, 0x89, 0x83, 0x83, 0x86, 0x84, 0x8b, + 0x90, 0x84, 0xb0, 0xae, 0x8b, 0xce, 0xad, 0xc8, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83, + 0x85, 0x87, 0x89, 0x8a, 0x83, 0x87, 0x82, 0x85, 0x88, 0x87, 0x89, + 0x8f, 0x84, 0xac, 0xaa, 0x89, 0xb1, 0x98, 0xaf, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83, + 0x85, 0x86, 0x88, 0x89, 0x84, 0x88, 0x83, 0x82, 0x85, 0x84, 0x8c, + 0x91, 0x86, 0xac, 0xaa, 0x89, 0xc2, 0xa5, 0xbd, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, + 0x85, 0x87, 0x89, 0x8a, 0x83, 0x87, 0x82, 0x85, 0x88, 0x87, 0x88, + 0x8b, 0x82, 0xad, 0xaa, 0x8a, 0xc2, 0xa5, 0xbd, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83, + 0x85, 0x86, 0x87, 0x89, 0x84, 0x88, 0x83, 0x82, 0x85, 0x84, 0x8a, + 0x8e, 0x84, 0xae, 0xac, 0x89, 0xda, 0xb7, 0xd0, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, + 0x85, 0x86, 0x87, 0x89, 0x84, 0x88, 0x83, 0x80, 0x83, 0x82, 0x8b, + 0x8e, 0x85, 0xac, 0xaa, 0x89, 0xc8, 0xaa, 0xc1, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, + 0x85, 0x86, 0x87, 0x89, 0x81, 0x85, 0x81, 0x84, 0x86, 0x84, 0x8c, + 0x8c, 0x84, 0xa9, 0xa8, 0x87, 0xa3, 0x92, 0xa1, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, + 0x85, 0x86, 0x87, 0x89, 0x84, 0x86, 0x83, 0x80, 0x83, 0x81, 0x8c, + 0x8d, 0x84, 0xaa, 0xaa, 0x89, 0xce, 0xaf, 0xc5, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, + 0x85, 0x86, 0x87, 0x89, 0x81, 0x83, 0x80, 0x83, 0x85, 0x85, 0x8c, + 0x8c, 0x84, 0xa8, 0xa8, 0x88, 0xb5, 0x9f, 0xb0, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, + 0x86, 0x86, 0x87, 0x88, 0x81, 0x83, 0x80, 0x83, 0x85, 0x85, 0x8c, + 0x8b, 0x84, 0xab, 0xa8, 0x86, 0xd4, 0xb4, 0xc9, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, + 0x86, 0x86, 0x87, 0x88, 0x81, 0x83, 0x80, 0x84, 0x84, 0x85, 0x8b, + 0x8a, 0x83, 0xa6, 0xa5, 0x84, 0xbb, 0xa4, 0xb3, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, + 0x86, 0x85, 0x86, 0x86, 0x82, 0x85, 0x81, 0x82, 0x83, 0x84, 0x8e, + 0x8b, 0x83, 0xa4, 0xa3, 0x8a, 0xa1, 0x93, 0x9d, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83, + 0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x82, 0x82, 0x84, 0x8e, + 0x8b, 0x83, 0xa4, 0xa2, 0x86, 0xc1, 0xa9, 0xb7, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83, + 0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x82, 0x82, 0x84, 0x8d, + 0x89, 0x82, 0xa2, 0xa1, 0x84, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83, + 0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x83, 0x83, 0x85, 0x8c, + 0x87, 0x7f, 0xa2, 0x9d, 0x88, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xbb, 0x00, 0xc5, 0x00, 0xb4, 0x87, 0x86, 0x86, 0x84, 0x83, + 0x86, 0x87, 0x87, 0x87, 0x80, 0x82, 0x7f, 0x86, 0x86, 0x88, 0x8a, + 0x84, 0x7e, 0x9d, 0x9c, 0x82, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xbd, 0x00, 0xc7, 0x00, 0xb7, 0x87, 0x85, 0x85, 0x84, 0x83, + 0x86, 0x86, 0x86, 0x88, 0x81, 0x83, 0x80, 0x83, 0x84, 0x85, 0x8a, + 0x85, 0x7e, 0x9c, 0x9b, 0x85, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xc0, 0x00, 0xca, 0x00, 0xbb, 0x87, 0x86, 0x85, 0x83, 0x83, + 0x85, 0x86, 0x86, 0x88, 0x81, 0x83, 0x80, 0x84, 0x85, 0x86, 0x89, + 0x83, 0x7d, 0x9c, 0x99, 0x87, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xc4, 0x00, 0xcd, 0x00, 0xbe, 0x87, 0x86, 0x85, 0x83, 0x83, + 0x86, 0x85, 0x85, 0x87, 0x81, 0x82, 0x80, 0x82, 0x82, 0x83, 0x8a, + 0x85, 0x7f, 0x9f, 0x9b, 0x86, 0xb4, 0xa1, 0xac, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xc7, 0x00, 0xd0, 0x00, 0xc2, 0x87, 0x85, 0x85, 0x83, 0x82, + 0x85, 0x85, 0x85, 0x86, 0x82, 0x83, 0x80, 0x82, 0x82, 0x84, 0x87, + 0x86, 0x80, 0x9e, 0x9a, 0x87, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xca, 0x00, 0xd2, 0x00, 0xc5, 0x87, 0x85, 0x84, 0x82, 0x82, + 0x84, 0x85, 0x85, 0x86, 0x81, 0x82, 0x7f, 0x82, 0x82, 0x84, 0x88, + 0x86, 0x81, 0x9d, 0x98, 0x86, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xce, 0x00, 0xd6, 0x00, 0xca, 0x86, 0x85, 0x84, 0x83, 0x83, + 0x85, 0x84, 0x84, 0x85, 0x81, 0x82, 0x80, 0x81, 0x81, 0x82, 0x89, + 0x86, 0x81, 0x9c, 0x97, 0x86, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xd1, 0x00, 0xd9, 0x00, 0xce, 0x86, 0x84, 0x83, 0x83, 0x82, + 0x85, 0x85, 0x85, 0x86, 0x81, 0x83, 0x81, 0x82, 0x82, 0x83, 0x86, + 0x83, 0x7f, 0x99, 0x95, 0x86, 0xbb, 0xa4, 0xb3, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xd4, 0x00, 0xdb, 0x00, 0xd1, 0x86, 0x85, 0x83, 0x83, 0x82, + 0x85, 0x84, 0x84, 0x85, 0x80, 0x83, 0x82, 0x80, 0x80, 0x81, 0x87, + 0x84, 0x81, 0x98, 0x93, 0x85, 0xae, 0x9c, 0xa8, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xd8, 0x00, 0xde, 0x00, 0xd6, 0x86, 0x84, 0x83, 0x81, 0x81, + 0x83, 0x85, 0x85, 0x85, 0x82, 0x83, 0x81, 0x81, 0x81, 0x83, 0x86, + 0x84, 0x80, 0x98, 0x91, 0x85, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xdc, 0x00, 0xe2, 0x00, 0xda, 0x85, 0x84, 0x83, 0x82, 0x82, + 0x84, 0x84, 0x84, 0x85, 0x81, 0x82, 0x82, 0x80, 0x80, 0x81, 0x83, + 0x82, 0x7f, 0x99, 0x93, 0x86, 0x94, 0x8b, 0x92, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xdf, 0x00, 0xe5, 0x00, 0xde, 0x85, 0x84, 0x82, 0x82, 0x82, + 0x84, 0x83, 0x83, 0x84, 0x81, 0x81, 0x80, 0x83, 0x82, 0x84, 0x82, + 0x81, 0x7f, 0x99, 0x92, 0x86, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81, + 0x82, 0x83, 0x83, 0x84, 0x80, 0x81, 0x80, 0x83, 0x83, 0x84, 0x80, + 0x81, 0x7c, 0x99, 0x92, 0x87, 0xa1, 0x93, 0x9d, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x85, 0x84, 0x83, 0x81, 0x81, + 0x82, 0x82, 0x82, 0x83, 0x80, 0x81, 0x80, 0x81, 0x80, 0x82, 0x83, + 0x82, 0x80, 0x91, 0x8d, 0x83, 0x9a, 0x90, 0x96, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81, + 0x82, 0x83, 0x83, 0x84, 0x80, 0x81, 0x80, 0x81, 0x80, 0x82, 0x83, + 0x81, 0x7f, 0x91, 0x8c, 0x82, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81, + 0x82, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x82, 0x82, + 0x82, 0x7f, 0x94, 0x89, 0x84, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81, + 0x82, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x82, 0x83, + 0x82, 0x7f, 0x91, 0x85, 0x81, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81, + 0x82, 0x83, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x83, 0x82, 0x84, 0x83, + 0x82, 0x7f, 0x90, 0x84, 0x81, 0x9a, 0x90, 0x96, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x80, 0x80, + 0x82, 0x83, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x81, 0x81, + 0x82, 0x83, 0x7e, 0x80, 0x7c, 0xa4, 0x97, 0x9f, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xe9, 0x00, 0xec, 0x00, 0xe8, 0x84, 0x83, 0x82, 0x81, 0x81, + 0x82, 0x82, 0x82, 0x83, 0x7f, 0x7f, 0x7f, 0x81, 0x80, 0x82, 0x83, + 0x83, 0x84, 0x79, 0x7c, 0x79, 0xb1, 0xa0, 0xaa, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xed, 0x00, 0xf0, 0x00, 0xec, 0x83, 0x83, 0x82, 0x80, 0x80, + 0x81, 0x82, 0x82, 0x82, 0x7f, 0x7f, 0x7e, 0x81, 0x81, 0x82, 0x80, + 0x81, 0x81, 0x84, 0x84, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xf1, 0x00, 0xf4, 0x00, 0xf1, 0x83, 0x82, 0x82, 0x80, 0x80, + 0x81, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x7d, + 0x7e, 0x7f, 0x84, 0x84, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xf6, 0x00, 0xf7, 0x00, 0xf5, 0x82, 0x82, 0x81, 0x80, 0x80, + 0x80, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x82, + 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x00, 0xfa, 0x00, 0xfb, 0x00, 0xfa, 0x81, 0x81, 0x81, 0x80, 0x80, + 0x80, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + { 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00 } +}; + +unsigned char vint_table[S6E3HA2_VINT_STATUS_MAX] = { + 0x18, 0x19, 0x1a, 0x1b, 0x1c, + 0x1d, 0x1e, 0x1f, 0x20, 0x21 +}; + +struct s6e3ha2 { + struct device *dev; + struct drm_panel panel; + struct backlight_device *bl_dev; + + struct regulator_bulk_data supplies[2]; + struct gpio_desc *reset_gpio; + struct gpio_desc *enable_gpio; +}; + +static int s6e3ha2_dcs_write(struct s6e3ha2 *ctx, const void *data, size_t len) +{ + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + + return mipi_dsi_dcs_write_buffer(dsi, data, len); +} + +#define s6e3ha2_dcs_write_seq_static(ctx, seq...) do { \ + static const u8 d[] = { seq }; \ + int ret; \ + ret = s6e3ha2_dcs_write(ctx, d, ARRAY_SIZE(d)); \ + if (ret < 0) \ + return ret; \ +} while (0) + +#define s6e3ha2_call_write_func(ret, func) do { \ + ret = (func); \ + if (ret < 0) \ + return ret; \ +} while (0) + +static int s6e3ha2_test_key_on_f0(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a); + return 0; +} + +static int s6e3ha2_test_key_off_f0(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0xa5, 0xa5); + return 0; +} + +static int s6e3ha2_test_key_on_fc(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a); + return 0; +} + +static int s6e3ha2_test_key_off_fc(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0xa5, 0xa5); + return 0; +} + +static int s6e3ha2_single_dsi_set(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xf2, 0x67); + s6e3ha2_dcs_write_seq_static(ctx, 0xf9, 0x09); + return 0; +} + +static int s6e3ha2_freq_calibration(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xfd, 0x1c); + s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20, 0x39); + s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0xa0); + s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20); + s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x12, 0x62, 0x40, + 0x80, 0xc0, 0x28, 0x28, 0x28, 0x28, 0x39, 0xc5); + return 0; +} + +static int s6e3ha2_aor_control(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xb2, 0x03, 0x10); + return 0; +} + +static int s6e3ha2_caps_elvss_set(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xb6, 0x9c, 0x0a); + return 0; +} + +static int s6e3ha2_acl_off(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0x55, 0x00); + return 0; +} + +static int s6e3ha2_acl_off_opr(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xb5, 0x40); + return 0; +} + +static int s6e3ha2_test_global(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x07); + return 0; +} + +static int s6e3ha2_test(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xb8, 0x19); + return 0; +} + +static int s6e3ha2_touch_hsync_on1(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xbd, 0x33, 0x11, 0x02, + 0x16, 0x02, 0x16); + return 0; +} + +static int s6e3ha2_pentile_control(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xc0, 0x00, 0x00, 0xd8, 0xd8); + return 0; +} + +static int s6e3ha2_poc_global(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x20); + return 0; +} + +static int s6e3ha2_poc_setting(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x08); + return 0; +} + +static int s6e3ha2_pcd_set_off(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xcc, 0x40, 0x51); + return 0; +} + +static int s6e3ha2_err_fg_set(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xed, 0x44); + return 0; +} + +static int s6e3ha2_hbm_off(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0x53, 0x00); + return 0; +} + +static int s6e3ha2_te_start_setting(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xb9, 0x10, 0x09, 0xff, 0x00, 0x09); + return 0; +} + +static int s6e3ha2_gamma_update(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xf7, 0x03); + ndelay(100); /* need for 100ns delay */ + s6e3ha2_dcs_write_seq_static(ctx, 0xf7, 0x00); + return 0; +} + +static int s6e3ha2_get_brightness(struct backlight_device *bl_dev) +{ + return bl_dev->props.brightness; +} + +static int s6e3ha2_set_vint(struct s6e3ha2 *ctx) +{ + struct backlight_device *bl_dev = ctx->bl_dev; + unsigned int brightness = bl_dev->props.brightness; + unsigned char data[] = { 0xf4, 0x8b, + vint_table[brightness * (S6E3HA2_VINT_STATUS_MAX - 1) / + S6E3HA2_MAX_BRIGHTNESS] }; + + return s6e3ha2_dcs_write(ctx, data, ARRAY_SIZE(data)); +} + +static unsigned int s6e3ha2_get_brightness_index(unsigned int brightness) +{ + return (brightness * (S6E3HA2_NUM_GAMMA_STEPS - 1)) / + S6E3HA2_MAX_BRIGHTNESS; +} + +static int s6e3ha2_update_gamma(struct s6e3ha2 *ctx, unsigned int brightness) +{ + struct backlight_device *bl_dev = ctx->bl_dev; + unsigned int index = s6e3ha2_get_brightness_index(brightness); + u8 data[S6E3HA2_GAMMA_CMD_CNT + 1] = { 0xca, }; + int ret; + + memcpy(data + 1, gamma_tbl + index, S6E3HA2_GAMMA_CMD_CNT); + s6e3ha2_call_write_func(ret, + s6e3ha2_dcs_write(ctx, data, ARRAY_SIZE(data))); + + s6e3ha2_call_write_func(ret, s6e3ha2_gamma_update(ctx)); + bl_dev->props.brightness = brightness; + + return 0; +} + +static int s6e3ha2_set_brightness(struct backlight_device *bl_dev) +{ + struct s6e3ha2 *ctx = bl_get_data(bl_dev); + unsigned int brightness = bl_dev->props.brightness; + int ret; + + if (brightness < S6E3HA2_MIN_BRIGHTNESS || + brightness > bl_dev->props.max_brightness) { + dev_err(ctx->dev, "Invalid brightness: %u\n", brightness); + return -EINVAL; + } + + if (bl_dev->props.power > FB_BLANK_NORMAL) + return -EPERM; + + s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_update_gamma(ctx, brightness)); + s6e3ha2_call_write_func(ret, s6e3ha2_aor_control(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_set_vint(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx)); + + return 0; +} + +static const struct backlight_ops s6e3ha2_bl_ops = { + .get_brightness = s6e3ha2_get_brightness, + .update_status = s6e3ha2_set_brightness, +}; + +static int s6e3ha2_panel_init(struct s6e3ha2 *ctx) +{ + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + int ret; + + s6e3ha2_call_write_func(ret, mipi_dsi_dcs_exit_sleep_mode(dsi)); + usleep_range(5000, 6000); + + s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_single_dsi_set(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_fc(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_freq_calibration(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_fc(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx)); + + return 0; +} + +static int s6e3ha2_power_off(struct s6e3ha2 *ctx) +{ + return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); +} + +static int s6e3ha2_disable(struct drm_panel *panel) +{ + struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel); + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + int ret; + + s6e3ha2_call_write_func(ret, mipi_dsi_dcs_enter_sleep_mode(dsi)); + s6e3ha2_call_write_func(ret, mipi_dsi_dcs_set_display_off(dsi)); + + msleep(40); + ctx->bl_dev->props.power = FB_BLANK_NORMAL; + + return 0; +} + +static int s6e3ha2_unprepare(struct drm_panel *panel) +{ + struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel); + + return s6e3ha2_power_off(ctx); +} + +static int s6e3ha2_power_on(struct s6e3ha2 *ctx) +{ + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); + if (ret < 0) + return ret; + + msleep(120); + + gpiod_set_value(ctx->enable_gpio, 0); + usleep_range(5000, 6000); + gpiod_set_value(ctx->enable_gpio, 1); + + gpiod_set_value(ctx->reset_gpio, 1); + usleep_range(5000, 6000); + gpiod_set_value(ctx->reset_gpio, 0); + usleep_range(5000, 6000); + + return 0; +} +static int s6e3ha2_prepare(struct drm_panel *panel) +{ + struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel); + int ret; + + ret = s6e3ha2_power_on(ctx); + if (ret < 0) + return ret; + + ret = s6e3ha2_panel_init(ctx); + if (ret < 0) + goto err; + + ctx->bl_dev->props.power = FB_BLANK_NORMAL; + + return 0; + +err: + s6e3ha2_power_off(ctx); + return ret; +} + +static int s6e3ha2_enable(struct drm_panel *panel) +{ + struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel); + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + int ret; + + /* common setting */ + s6e3ha2_call_write_func(ret, + mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK)); + + s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_fc(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_touch_hsync_on1(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_pentile_control(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_poc_global(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_poc_setting(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_fc(ctx)); + + /* pcd setting off for TB */ + s6e3ha2_call_write_func(ret, s6e3ha2_pcd_set_off(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_err_fg_set(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_te_start_setting(ctx)); + + /* brightness setting */ + s6e3ha2_call_write_func(ret, s6e3ha2_set_brightness(ctx->bl_dev)); + s6e3ha2_call_write_func(ret, s6e3ha2_aor_control(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_caps_elvss_set(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_gamma_update(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_acl_off(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_acl_off_opr(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_hbm_off(ctx)); + + /* elvss temp compensation */ + s6e3ha2_call_write_func(ret, s6e3ha2_test_global(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_test(ctx)); + s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx)); + + s6e3ha2_call_write_func(ret, mipi_dsi_dcs_set_display_on(dsi)); + ctx->bl_dev->props.power = FB_BLANK_UNBLANK; + + return 0; +} + +static const struct drm_display_mode default_mode = { + .clock = 222372, + .hdisplay = 1440, + .hsync_start = 1440 + 1, + .hsync_end = 1440 + 1 + 1, + .htotal = 1440 + 1 + 1 + 1, + .vdisplay = 2560, + .vsync_start = 2560 + 1, + .vsync_end = 2560 + 1 + 1, + .vtotal = 2560 + 1 + 1 + 15, + .vrefresh = 60, + .flags = 0, +}; + +static int s6e3ha2_get_modes(struct drm_panel *panel) +{ + struct drm_connector *connector = panel->connector; + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(panel->drm, &default_mode); + if (!mode) { + DRM_ERROR("failed to add mode %ux%ux@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + default_mode.vrefresh); + return -ENOMEM; + } + + drm_mode_set_name(mode); + + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, mode); + + connector->display_info.width_mm = 71; + connector->display_info.height_mm = 125; + + return 1; +} + +static const struct drm_panel_funcs s6e3ha2_drm_funcs = { + .disable = s6e3ha2_disable, + .unprepare = s6e3ha2_unprepare, + .prepare = s6e3ha2_prepare, + .enable = s6e3ha2_enable, + .get_modes = s6e3ha2_get_modes, +}; + +static int s6e3ha2_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct s6e3ha2 *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + mipi_dsi_set_drvdata(dsi, ctx); + + ctx->dev = dev; + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS; + + ctx->supplies[0].supply = "vdd3"; + ctx->supplies[1].supply = "vci"; + + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), + ctx->supplies); + if (ret < 0) { + dev_err(dev, "failed to get regulators: %d\n", ret); + return ret; + } + + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(ctx->reset_gpio)) { + dev_err(dev, "cannot get reset-gpios %ld\n", + PTR_ERR(ctx->reset_gpio)); + return PTR_ERR(ctx->reset_gpio); + } + + ctx->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); + if (IS_ERR(ctx->enable_gpio)) { + dev_err(dev, "cannot get enable-gpios %ld\n", + PTR_ERR(ctx->enable_gpio)); + return PTR_ERR(ctx->enable_gpio); + } + + ctx->bl_dev = backlight_device_register("s6e3ha2", dev, ctx, + &s6e3ha2_bl_ops, NULL); + if (IS_ERR(ctx->bl_dev)) { + dev_err(dev, "failed to register backlight device\n"); + return PTR_ERR(ctx->bl_dev); + } + + ctx->bl_dev->props.max_brightness = S6E3HA2_MAX_BRIGHTNESS; + ctx->bl_dev->props.brightness = S6E3HA2_DEFAULT_BRIGHTNESS; + ctx->bl_dev->props.power = FB_BLANK_POWERDOWN; + + drm_panel_init(&ctx->panel); + ctx->panel.dev = dev; + ctx->panel.funcs = &s6e3ha2_drm_funcs; + + ret = drm_panel_add(&ctx->panel); + if (ret < 0) + goto unregister_backlight; + + ret = mipi_dsi_attach(dsi); + if (ret < 0) + goto remove_panel; + + return ret; + +remove_panel: + drm_panel_remove(&ctx->panel); + +unregister_backlight: + backlight_device_unregister(ctx->bl_dev); + + return ret; +} + +static int s6e3ha2_remove(struct mipi_dsi_device *dsi) +{ + struct s6e3ha2 *ctx = mipi_dsi_get_drvdata(dsi); + + mipi_dsi_detach(dsi); + drm_panel_remove(&ctx->panel); + backlight_device_unregister(ctx->bl_dev); + + return 0; +} + +static const struct of_device_id s6e3ha2_of_match[] = { + { .compatible = "samsung,s6e3ha2" }, + { } +}; +MODULE_DEVICE_TABLE(of, s6e3ha2_of_match); + +static struct mipi_dsi_driver s6e3ha2_driver = { + .probe = s6e3ha2_probe, + .remove = s6e3ha2_remove, + .driver = { + .name = "panel-samsung-s6e3ha2", + .of_match_table = s6e3ha2_of_match, + }, +}; +module_mipi_dsi_driver(s6e3ha2_driver); + +MODULE_AUTHOR("Donghwa Lee "); +MODULE_AUTHOR("Hyungwon Hwang ");