From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751614AbdAXCAw (ORCPT ); Mon, 23 Jan 2017 21:00:52 -0500 Received: from mailout1.samsung.com ([203.254.224.24]:49405 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750710AbdAXCAt (ORCPT ); Mon, 23 Jan 2017 21:00:49 -0500 X-AuditID: b6c32a39-f79c86d000001a4c-69-5886b2f784fa Subject: Re: [PATCH v8 2/3] drm/panel: Add support for S6E3HA2 panel driver on TM2 board To: thierry.reding@gmail.com Cc: robh@kernel.org, Krzysztof Kozlowski , airlied@linux.ie, kgene@kernel.org, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-samsung-soc@vger.kernel.org, inki.dae@samsung.com, a.hajda@samsung.com, cw00.choi@samsung.com, jh80.chung@samsung.com, andi.shyti@samsung.com, Donghwa Lee , Hyungwon Hwang From: Hoegeun Kwon Message-id: <08c5d94b-c76f-af14-c08f-478e26a34a7c@samsung.com> Date: Tue, 24 Jan 2017 10:50:46 +0900 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-version: 1.0 In-reply-to: <1484116439-7275-3-git-send-email-hoegeun.kwon@samsung.com> Content-type: text/plain; charset=windows-1252; format=flowed Content-transfer-encoding: 7bit X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrDJsWRmVeSWpSXmKPExsWy7bCmru73TW0RBt0dAha31p1jteg9d5LJ YvuRZ6wW1788Z7WYfwQodv28ncWVr+/ZLJbO6GO1mHR/AovFjV9trBb9j18zW5w/v4Hd4vKu OWwWM87vY7L4v2cHu8XPXfNYHAQ8ds66y+6xaVUnm8f2bw9YPe53H2fy6NuyitHj8ya5ALao VJuM1MSU1CKF1Lzk/JTMvHRbJe/geOd4UzMDQ11DSwtzJYW8xNxUWyUXnwBdt8wcoLuVFMoS c0qBQgGJxcVK+nY2RfmlJakKGfnFJbZK0YaGRnqGBuZ6RkZGeibGsVZGpkAlCakZH889YSuY 8pyx4sfW20wNjNd2MHYxcnJICJhIPL07iw3CFpO4cG89mC0ksINR4v0Duy5GLiC7nUnix8fL cA03O3cxQySWM0rc753BBuHcZZS4+6aBBaRKWCBKYvLCb6wgtoiAjMSlU//YQYqYBVYwSxzY vRSsiE1AV+Jrz3WmLkYODl4BO4mtL7JBwiwCqhLzr54HKxEViJA4dOw2M4jNKyAo8WPyPbA4 p4CHxJf+LWCnMgs4SjxYtJMVwpaX2LzmLdh1EgJf2SU27F/MCjJfQkBWYtMBZogPXCTub5rF CmELS7w6voUdwpaWWPXvFhNEbzejxPemFVCDJjBK/GzYANVtLHH/wT1miG18Eu++9kAt4JXo aBOCKPGQ+DXjBjS4HCW+7G1hh4TQTUaJe59XsU9glJ+F5KFZSJ6YheSJBYzMqxjFUguKc9NT iw0LTPWKE3OLS/PS9ZLzczcxglOuluUOxmPnfA4xCnAwKvHwFki1RQixJpYVV+YeYpTgYFYS 4eVeCBTiTUmsrEotyo8vKs1JLT7EaAoM5InMUqLJ+cB8kFcSb2hiZmhiZGJoaG5kYKQkzru4 0TpCSCA9sSQ1OzW1ILUIpo+Jg1OqgXHKS6++ltiImpQv77r2mt7Zbmfi3XBx85138xYb6v3i U/n++G/U2hldAcdfHbBaoaSaf7tsVuz9s1usTA41LZ/asbmkW3qvYsRigamrPnOlHEzVkRCt 0HcvbG1fdL3617KVm3adOL7wlCJH88dspvXt0sIvH18NXn9oEXe6/oqVLVnl239fyQ5VYinO SDTUYi4qTgQA7aKERc8DAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrGIsWRmVeSWpSXmKPExsVy+t9jAd1vm9oiDJ5ts7K4te4cq0XvuZNM FtuPPGO1uP7lOavF/CNAsevn7SyufH3PZrF0Rh+rxaT7E1gsbvxqY7Xof/ya2eL8+Q3sFpd3 zWGzmHF+H5PF/z072C1+7prH4iDgsXPWXXaPTas62Ty2f3vA6nG/+ziTR9+WVYwenzfJBbBF udlkpCampBYppOYl56dk5qXbKoWGuOlaKCnkJeam2ipF6PqGBCkplCXmlAJ5RgZowME5wD1Y Sd8uwS3j47knbAVTnjNW/Nh6m6mB8doOxi5GTg4JAROJm527mCFsMYkL99azgdhCAksZJe51 8XUxcgHZ9xklvu7/DlYkLBAlcW76W1YQW0RARuLSqX/sEA03GSVmnvQGaWAWWMYs0bngKVgD m4CuxNee60xdjBwcvAJ2EltfZIOEWQRUJeZfPc8CEhYViJBoOJwOEuYVEJT4MfkeC4jNKeAh 8aV/C9g9zAK2Egver2OBsOUlNq95yzyBUWAWkpZZSMpmISlbwMi8ilEitSC5oDgpPdcwL7Vc rzgxt7g0L10vOT93EyM4jp9J7WA8uMv9EKMAB6MSD++L5rYIIdbEsuLK3EOMEhzMSiK83AuB QrwpiZVVqUX58UWlOanFhxhNgf6YyCwlmpwPTDF5JfGGJuYm5sYGFuaWliZGSuK8jbOfhQsJ pCeWpGanphakFsH0MXFwSjUwrhM8WhDSoF7p9WqeieVXAXtf1saypvO3PTZuuCdzotGXiUtt gcKUl5vOGLzXcTmhJm91yF377Ym2P+p/Fp+O/7DMJdNp2ixfBZ9El8vRdrKnFLg5Aqz5tWdu Wa7YxL55/9XVWltSMr8mru7t/7py/tr6qAntK5jevyuc+y1oC0/F+Y1yc2qZlFiKMxINtZiL ihMBYzHFFPkCAAA= X-MTR: 20000000000000000@CPGS X-CMS-MailID: 20170124015047epcas1p13bbbb9ff5e636330bad476c79fb07626 X-Msg-Generator: CA X-Sender-IP: 203.254.230.26 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: 101P DLP-Filter: Pass X-CFilter-Loop: Reflected X-HopCount: 7 X-CMS-RootMailID: 20170111063408epcas5p2e6ec091549c3ffed8462fd95d11d3c82 X-RootMTR: 20170111063408epcas5p2e6ec091549c3ffed8462fd95d11d3c82 References: <1484116439-7275-1-git-send-email-hoegeun.kwon@samsung.com> <1484116439-7275-3-git-send-email-hoegeun.kwon@samsung.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Dear Thierry, Could you please review this patch? Best Regards, Hoegeun Kwon On 01/11/2017 03:33 PM, Hoegeun Kwon wrote: > 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 | 754 ++++++++++++++++++++++++++ > 3 files changed, 761 insertions(+) > create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c > > 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..0b9c6f4 > --- /dev/null > +++ b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c > @@ -0,0 +1,754 @@ > +/* > + * 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; > + > + /* This field is tested by functions directly accessing DSI bus before > + * transfer, transfer is skipped if it is set. In case of transfer > + * failure or unexpected response the field is set to error value. > + * Such construct allows to eliminate many checks in higher level > + * functions. > + */ > + int error; > +}; > + > +static int s6e3ha2_clear_error(struct s6e3ha2 *ctx) > +{ > + int ret = ctx->error; > + > + ctx->error = 0; > + return ret; > +} > + > +static void s6e3ha2_dcs_write(struct s6e3ha2 *ctx, const void *data, size_t len) > +{ > + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); > + ssize_t ret; > + > + if (ctx->error < 0) > + return; > + > + ret = mipi_dsi_dcs_write_buffer(dsi, data, len); > + if (ret < 0) { > + dev_err(ctx->dev, "error %zd writing dcs seq: %*ph\n", > + ret, (int)len, data); > + ctx->error = ret; > + } > +} > + > +#define s6e3ha2_dcs_write_seq_static(ctx, seq...) do { \ > + static const u8 d[] = { seq }; \ > + s6e3ha2_dcs_write(ctx, d, ARRAY_SIZE(d)); \ > +} while (0) > + > +static void s6e3ha2_test_key_on_f0(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a); > +} > + > +static void s6e3ha2_test_key_off_f0(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0xa5, 0xa5); > +} > + > +static void s6e3ha2_test_key_on_fc(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a); > +} > + > +static void s6e3ha2_test_key_off_fc(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0xa5, 0xa5); > +} > + > +static void s6e3ha2_single_dsi_set(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xf2, 0x67); > + s6e3ha2_dcs_write_seq_static(ctx, 0xf9, 0x09); > +} > + > +static void 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); > +} > + > +static void s6e3ha2_aor_control(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xb2, 0x03, 0x10); > +} > + > +static void s6e3ha2_caps_elvss_set(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xb6, 0x9c, 0x0a); > +} > + > +static void s6e3ha2_acl_off(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0x55, 0x00); > +} > + > +static void s6e3ha2_acl_off_opr(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xb5, 0x40); > +} > + > +static void s6e3ha2_test_global(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x07); > +} > + > +static void s6e3ha2_test(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xb8, 0x19); > +} > + > +static void s6e3ha2_touch_hsync_on1(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, > + 0xbd, 0x33, 0x11, 0x02, 0x16, 0x02, 0x16); > +} > + > +static void s6e3ha2_pentile_control(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xc0, 0x00, 0x00, 0xd8, 0xd8); > +} > + > +static void s6e3ha2_poc_global(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x20); > +} > + > +static void s6e3ha2_poc_setting(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x08); > +} > + > +static void s6e3ha2_pcd_set_off(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xcc, 0x40, 0x51); > +} > + > +static void s6e3ha2_err_fg_set(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xed, 0x44); > +} > + > +static void s6e3ha2_hbm_off(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0x53, 0x00); > +} > + > +static void s6e3ha2_te_start_setting(struct s6e3ha2 *ctx) > +{ > + s6e3ha2_dcs_write_seq_static(ctx, 0xb9, 0x10, 0x09, 0xff, 0x00, 0x09); > +} > + > +static void 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); > +} > + > +static int s6e3ha2_get_brightness(struct backlight_device *bl_dev) > +{ > + return bl_dev->props.brightness; > +} > + > +static void 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] }; > + > + 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, }; > + > + memcpy(data + 1, gamma_tbl + index, S6E3HA2_GAMMA_CMD_CNT); > + s6e3ha2_dcs_write(ctx, data, ARRAY_SIZE(data)); > + > + 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; > + > + 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_test_key_on_f0(ctx); > + s6e3ha2_update_gamma(ctx, brightness); > + s6e3ha2_aor_control(ctx); > + s6e3ha2_set_vint(ctx); > + s6e3ha2_test_key_off_f0(ctx); > + > + return ctx->error; > +} > + > +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; > + > + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); > + if (ret < 0) > + return ret; > + usleep_range(5000, 6000); > + > + s6e3ha2_test_key_on_f0(ctx); > + s6e3ha2_single_dsi_set(ctx); > + s6e3ha2_test_key_on_fc(ctx); > + s6e3ha2_freq_calibration(ctx); > + s6e3ha2_test_key_off_fc(ctx); > + 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; > + > + ret = mipi_dsi_dcs_enter_sleep_mode(dsi); > + if (ret < 0) > + return ret; > + > + ret = mipi_dsi_dcs_set_display_off(dsi); > + if (ret < 0) > + return ret; > + > + 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); > + int ret; > + > + ret = s6e3ha2_clear_error(ctx); > + if (!ret) > + ctx->bl_dev->props.power = FB_BLANK_POWERDOWN; > + > + 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; > + > + ret = s6e3ha2_clear_error(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 */ > + ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); > + if (ret < 0) > + return ret; > + > + s6e3ha2_test_key_on_f0(ctx); > + s6e3ha2_test_key_on_fc(ctx); > + s6e3ha2_touch_hsync_on1(ctx); > + s6e3ha2_pentile_control(ctx); > + s6e3ha2_poc_global(ctx); > + s6e3ha2_poc_setting(ctx); > + s6e3ha2_test_key_off_fc(ctx); > + > + /* pcd setting off for TB */ > + s6e3ha2_pcd_set_off(ctx); > + s6e3ha2_err_fg_set(ctx); > + s6e3ha2_te_start_setting(ctx); > + > + /* brightness setting */ > + s6e3ha2_set_brightness(ctx->bl_dev); > + s6e3ha2_aor_control(ctx); > + s6e3ha2_caps_elvss_set(ctx); > + s6e3ha2_gamma_update(ctx); > + s6e3ha2_acl_off(ctx); > + s6e3ha2_acl_off_opr(ctx); > + s6e3ha2_hbm_off(ctx); > + > + /* elvss temp compensation */ > + s6e3ha2_test_global(ctx); > + s6e3ha2_test(ctx); > + s6e3ha2_test_key_off_f0(ctx); > + > + if (ctx->error != 0) > + return ctx->error; > + > + ret = mipi_dsi_dcs_set_display_on(dsi); > + if (ret < 0) > + return ret; > + > + 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 "); > +MODULE_AUTHOR("Hoegeun Kwon "); > +MODULE_DESCRIPTION("MIPI-DSI based s6e3ha2 AMOLED Panel Driver"); > +MODULE_LICENSE("GPL v2");