From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9397EC433DF for ; Mon, 22 Jun 2020 08:08:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 64E4620809 for ; Mon, 22 Jun 2020 08:08:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726125AbgFVIIZ (ORCPT ); Mon, 22 Jun 2020 04:08:25 -0400 Received: from asavdk3.altibox.net ([109.247.116.14]:44998 "EHLO asavdk3.altibox.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726000AbgFVIIV (ORCPT ); Mon, 22 Jun 2020 04:08:21 -0400 Received: from ravnborg.org (unknown [188.228.123.71]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by asavdk3.altibox.net (Postfix) with ESMTPS id AAE3720021; Mon, 22 Jun 2020 10:08:03 +0200 (CEST) Date: Mon, 22 Jun 2020 10:08:02 +0200 From: Sam Ravnborg To: =?utf-8?Q?Ond=C5=99ej?= Jirman , linux-sunxi@googlegroups.com, Thierry Reding , David Airlie , Daniel Vetter , Rob Herring , Maxime Ripard , Chen-Yu Tsai , Linus Walleij , Icenowy Zheng , devicetree@vger.kernel.org, Samuel Holland , Bhushan Shah , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Luca Weiss , Martijn Braam , linux-arm-kernel@lists.infradead.org Subject: Re: [PATCH v4 3/5] drm: panel: Add Xingbangda XBD599 panel (ST7703 controller) Message-ID: <20200622080802.GA650963@ravnborg.org> References: <20200617003209.670819-1-megous@megous.com> <20200617003209.670819-4-megous@megous.com> <20200620212529.GB74146@ravnborg.org> <20200620223010.fqjwijiixxkewk3p@core.my.home> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20200620223010.fqjwijiixxkewk3p@core.my.home> X-CMAE-Score: 0 X-CMAE-Analysis: v=2.3 cv=edQTgYMH c=1 sm=1 tr=0 a=S6zTFyMACwkrwXSdXUNehg==:117 a=S6zTFyMACwkrwXSdXUNehg==:17 a=IkcTkHD0fZMA:10 a=J_fg_7IlAAAA:8 a=e5mUnYsNAAAA:8 a=rpfOPJV_7YADzv3fI4AA:9 a=9TJecaD38D1O3S5X:21 a=qYyW2_D2GT2v-q_M:21 a=QEXdDO2ut3YA:10 a=zGOw-GkVl6h1W4ZARoUA:22 a=Vxmtnl_E_bksehYqCbjh:22 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org On Sun, Jun 21, 2020 at 12:30:10AM +0200, Ondřej Jirman wrote: > On Sat, Jun 20, 2020 at 11:25:29PM +0200, Sam Ravnborg wrote: > > Hi Ondrej et al. > > > > On Wed, Jun 17, 2020 at 02:32:07AM +0200, Ondrej Jirman wrote: > > > From: Icenowy Zheng > > > > > > Xingbangda XBD599 is a 5.99" 720x1440 MIPI-DSI IPS LCD panel made by > > > Xingbangda, which is used on PinePhone final assembled phones. > > > > > > It is based on Sitronix ST7703 LCD controller. > > > > I am a little late to the game here - so sorry if this has been > > discussed before. > > We already have panel-rocktech-jh057n00900.c which is a panle driver > > based on st7703. > > Why is it we need a new driver? > > No reason other than the driver not being named after the controller, > so I didn't notice. > > > Would it not be better to have one st7703 driver that suipports both > > panels? > > > > The driver would need dedicated init functions depending on the panel. > > But a lot could also be shared. > > I guess I can move the code there. In the same process the river should then be renamed to follow other sitronix based drivers. So the next developer will recognize this and use the correct driver. Sam > > regards, > o. > > > Sam > > > > > > > > Add support for it. > > > > > > Signed-off-by: Icenowy Zheng > > > Signed-off-by: Ondrej Jirman > > > --- > > > drivers/gpu/drm/panel/Kconfig | 10 + > > > drivers/gpu/drm/panel/Makefile | 1 + > > > drivers/gpu/drm/panel/panel-sitronix-st7703.c | 535 ++++++++++++++++++ > > > 3 files changed, 546 insertions(+) > > > create mode 100644 drivers/gpu/drm/panel/panel-sitronix-st7703.c > > > > > > diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig > > > index 39055c1f0e2f..b7bc157b0612 100644 > > > --- a/drivers/gpu/drm/panel/Kconfig > > > +++ b/drivers/gpu/drm/panel/Kconfig > > > @@ -395,6 +395,16 @@ config DRM_PANEL_SITRONIX_ST7701 > > > ST7701 controller for 480X864 LCD panels with MIPI/RGB/SPI > > > system interfaces. > > > > > > +config DRM_PANEL_SITRONIX_ST7703 > > > + tristate "Sitronix ST7703 panel driver" > > > + depends on OF > > > + depends on DRM_MIPI_DSI > > > + depends on BACKLIGHT_CLASS_DEVICE > > > + help > > > + Say Y here if you want to enable support for the Sitronix > > > + ST7703 controller for 720X1440 LCD panels with MIPI/RGB/SPI > > > + system interfaces. > > > + > > > config DRM_PANEL_SITRONIX_ST7789V > > > tristate "Sitronix ST7789V panel" > > > depends on OF && SPI > > > diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile > > > index de74f282c433..47f4789a8685 100644 > > > --- a/drivers/gpu/drm/panel/Makefile > > > +++ b/drivers/gpu/drm/panel/Makefile > > > @@ -41,6 +41,7 @@ obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o > > > obj-$(CONFIG_DRM_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o > > > obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o > > > obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7701) += panel-sitronix-st7701.o > > > +obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7703) += panel-sitronix-st7703.o > > > obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o > > > obj-$(CONFIG_DRM_PANEL_SONY_ACX424AKP) += panel-sony-acx424akp.o > > > obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o > > > diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c b/drivers/gpu/drm/panel/panel-sitronix-st7703.c > > > new file mode 100644 > > > index 000000000000..dbd46b6c0b46 > > > --- /dev/null > > > +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c > > > @@ -0,0 +1,535 @@ > > > +// SPDX-License-Identifier: GPL-2.0 > > > +/* > > > + * DRM driver for Sitronix ST7703 MIPI DSI panel > > > + * > > > + * Copyright (C) 2020 Ondrej Jirman > > > + * Copyright (C) 2019-2020 Icenowy Zheng > > > + * > > > + * Based on panel-rocktech-jh057n00900.c, which is: > > > + * Copyright (C) Purism SPC 2019 > > > + */ > > > + > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > + > > > +#include > > > +#include > > > +#include > > > +#include > > > + > > > +/* Manufacturer specific DCS commands */ > > > +#define ST7703_CMD_SETDISP 0xB2 > > > +#define ST7703_CMD_SETRGBIF 0xB3 > > > +#define ST7703_CMD_SETCYC 0xB4 > > > +#define ST7703_CMD_SETBGP 0xB5 > > > +#define ST7703_CMD_SETVCOM 0xB6 > > > +#define ST7703_CMD_SETOTP 0xB7 > > > +#define ST7703_CMD_SETPOWER_EXT 0xB8 > > > +#define ST7703_CMD_SETEXTC 0xB9 > > > +#define ST7703_CMD_SETMIPI 0xBA > > > +#define ST7703_CMD_SETVDC 0xBC > > > +#define ST7703_CMD_UNK_BF 0xBF > > > +#define ST7703_CMD_SETSCR 0xC0 > > > +#define ST7703_CMD_SETPOWER 0xC1 > > > +#define ST7703_CMD_UNK_C6 0xC6 > > > +#define ST7703_CMD_SETPANEL 0xCC > > > +#define ST7703_CMD_RDID1 0xDA > > > +#define ST7703_CMD_RDID2 0xDB > > > +#define ST7703_CMD_RDID3 0xDC > > > +#define ST7703_CMD_SETGAMMA 0xE0 > > > +#define ST7703_CMD_SETEQ 0xE3 > > > +#define ST7703_CMD_SETGIP1 0xE9 > > > +#define ST7703_CMD_SETGIP2 0xEA > > > + > > > +struct st7703_panel_desc { > > > + const struct drm_display_mode *mode; > > > + unsigned int lanes; > > > + unsigned long flags; > > > + enum mipi_dsi_pixel_format format; > > > + const char *const *supply_names; > > > + unsigned int num_supplies; > > > +}; > > > + > > > +struct st7703 { > > > + struct device *dev; > > > + struct drm_panel panel; > > > + struct gpio_desc *reset_gpio; > > > + struct regulator_bulk_data *supplies; > > > + const struct st7703_panel_desc *desc; > > > + bool prepared; > > > +}; > > > + > > > +static inline struct st7703 *panel_to_st7703(struct drm_panel *panel) > > > +{ > > > + return container_of(panel, struct st7703, panel); > > > +} > > > + > > > +#define dsi_dcs_write_seq(dsi, cmd, seq...) do { \ > > > + static const u8 d[] = { seq }; \ > > > + int ret; \ > > > + ret = mipi_dsi_dcs_write(dsi, cmd, d, ARRAY_SIZE(d)); \ > > > + if (ret < 0) \ > > > + return ret; \ > > > + } while (0) > > > + > > > + > > > +static int st7703_init_sequence(struct st7703 *ctx) > > > +{ > > > + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); > > > + struct device *dev = ctx->dev; > > > + > > > + /* > > > + * Init sequence was supplied by the panel vendor. > > > + */ > > > + > > > + /* Magic sequence to unlock user commands below. */ > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83); > > > + > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, > > > + 0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */ > > > + 0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */ > > > + 0x05, /* IHSRX = x6 (Low High Speed driving ability) */ > > > + 0xF9, /* TX_CLK_SEL = fDSICLK/16 */ > > > + 0x0E, /* HFP_OSC (min. HFP number in DSI mode) */ > > > + 0x0E, /* HBP_OSC (min. HBP number in DSI mode) */ > > > + /* The rest is undocumented in ST7703 datasheet */ > > > + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > > > + 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02, > > > + 0x4F, 0x11, 0x00, 0x00, 0x37); > > > + > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, > > > + 0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */ > > > + 0x22, /* DT = 15ms XDK_ECP = x2 */ > > > + 0x20, /* PFM_DC_DIV = /1 */ > > > + 0x03 /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */); > > > + > > > + /* RGB I/F porch timing */ > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, > > > + 0x10, /* VBP_RGB_GEN */ > > > + 0x10, /* VFP_RGB_GEN */ > > > + 0x05, /* DE_BP_RGB_GEN */ > > > + 0x05, /* DE_FP_RGB_GEN */ > > > + /* The rest is undocumented in ST7703 datasheet */ > > > + 0x03, 0xFF, > > > + 0x00, 0x00, > > > + 0x00, 0x00); > > > + > > > + /* Source driving settings. */ > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, > > > + 0x73, /* N_POPON */ > > > + 0x73, /* N_NOPON */ > > > + 0x50, /* I_POPON */ > > > + 0x50, /* I_NOPON */ > > > + 0x00, /* SCR[31,24] */ > > > + 0xC0, /* SCR[23,16] */ > > > + 0x08, /* SCR[15,8] */ > > > + 0x70, /* SCR[7,0] */ > > > + 0x00 /* Undocumented */); > > > + > > > + /* NVDDD_SEL = -1.8V, VDDD_SEL = out of range (possibly 1.9V?) */ > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E); > > > + > > > + /* > > > + * SS_PANEL = 1 (reverse scan), GS_PANEL = 0 (normal scan) > > > + * REV_PANEL = 1 (normally black panel), BGR_PANEL = 1 (BGR) > > > + */ > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B); > > > + > > > + /* Zig-Zag Type C column inversion. */ > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80); > > > + > > > + /* Set display resolution. */ > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, > > > + 0xF0, /* NL = 240 */ > > > + 0x12, /* RES_V_LSB = 0, BLK_CON = VSSD, > > > + * RESO_SEL = 720RGB > > > + */ > > > + 0xF0 /* WHITE_GND_EN = 1 (GND), > > > + * WHITE_FRAME_SEL = 7 frames, > > > + * ISC = 0 frames > > > + */); > > > + > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, > > > + 0x00, /* PNOEQ */ > > > + 0x00, /* NNOEQ */ > > > + 0x0B, /* PEQGND */ > > > + 0x0B, /* NEQGND */ > > > + 0x10, /* PEQVCI */ > > > + 0x10, /* NEQVCI */ > > > + 0x00, /* PEQVCI1 */ > > > + 0x00, /* NEQVCI1 */ > > > + 0x00, /* reserved */ > > > + 0x00, /* reserved */ > > > + 0xFF, /* reserved */ > > > + 0x00, /* reserved */ > > > + 0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */ > > > + 0x10 /* SLPIN_OPTION = 1 (no need vsync after sleep-in) > > > + * VEDIO_NO_CHECK_EN = 0 > > > + * ESD_WHITE_GND_EN = 0 > > > + * ESD_DET_TIME_SEL = 0 frames > > > + */); > > > + > > > + /* Undocumented command. */ > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_UNK_C6, 0x01, 0x00, 0xFF, 0xFF, 0x00); > > > + > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, > > > + 0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */ > > > + 0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */ > > > + 0x32, /* VRP */ > > > + 0x32, /* VRN */ > > > + 0x77, /* reserved */ > > > + 0xF1, /* APS = 1 (small), > > > + * VGL_DET_EN = 1, VGH_DET_EN = 1, > > > + * VGL_TURBO = 1, VGH_TURBO = 1 > > > + */ > > > + 0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */ > > > + 0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */ > > > + 0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */ > > > + 0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */ > > > + 0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */ > > > + 0x77 /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */); > > > + > > > + /* Reference voltage. */ > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, > > > + 0x07, /* VREF_SEL = 4.2V */ > > > + 0x07 /* NVREF_SEL = 4.2V */); > > > + > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, > > > + 0x2C, /* VCOMDC_F = -0.67V */ > > > + 0x2C /* VCOMDC_B = -0.67V */); > > > + > > > + /* Undocumented command. */ > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_UNK_BF, 0x02, 0x11, 0x00); > > > + > > > + /* This command is to set forward GIP timing. */ > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, > > > + 0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12, > > > + 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38, > > > + 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, > > > + 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88, > > > + 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64, > > > + 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, > > > + 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > > > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); > > > + > > > + /* This command is to set backward GIP timing. */ > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, > > > + 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > > > + 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88, > > > + 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13, > > > + 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, > > > + 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00, > > > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > > > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A, > > > + 0xA5, 0x00, 0x00, 0x00, 0x00); > > > + > > > + /* Adjust the gamma characteristics of the panel. */ > > > + dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, > > > + 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35, > > > + 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12, > > > + 0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, > > > + 0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, > > > + 0x12, 0x18); > > > + > > > + DRM_DEV_DEBUG_DRIVER(dev, "Panel init sequence done\n"); > > > + return 0; > > > +} > > > + > > > +static int st7703_read_id(struct st7703 *ctx) > > > +{ > > > + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); > > > + u8 id1, id2, id3; > > > + int ret; > > > + > > > + ret = mipi_dsi_dcs_read(dsi, ST7703_CMD_RDID1, &id1, 1); > > > + if (ret < 0) { > > > + DRM_DEV_ERROR(ctx->dev, "could not read ID1\n"); > > > + return ret; > > > + } > > > + > > > + ret = mipi_dsi_dcs_read(dsi, ST7703_CMD_RDID2, &id2, 1); > > > + if (ret < 0) { > > > + DRM_DEV_ERROR(ctx->dev, "could not read ID2\n"); > > > + return ret; > > > + } > > > + > > > + ret = mipi_dsi_dcs_read(dsi, ST7703_CMD_RDID3, &id3, 1); > > > + if (ret < 0) { > > > + DRM_DEV_ERROR(ctx->dev, "could not read ID3\n"); > > > + return ret; > > > + } > > > + > > > + DRM_DEV_INFO(ctx->dev, > > > + "manufacturer: %02x version: %02x driver: %02x\n", > > > + id1, id2, id3); > > > + > > > + return 0; > > > +} > > > + > > > +static int st7703_prepare(struct drm_panel *panel) > > > +{ > > > + struct st7703 *ctx = panel_to_st7703(panel); > > > + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); > > > + int ret; > > > + > > > + if (ctx->prepared) > > > + return 0; > > > + > > > + gpiod_set_value_cansleep(ctx->reset_gpio, 1); > > > + > > > + ret = regulator_bulk_enable(ctx->desc->num_supplies, ctx->supplies); > > > + if (ret) > > > + return ret; > > > + > > > + /* Wait for regulators to stabilize. */ > > > + usleep_range(10000, 20000); > > > + > > > + gpiod_set_value_cansleep(ctx->reset_gpio, 0); > > > + > > > + /* There needs to be at least 15ms post-reset delay. */ > > > + usleep_range(15000, 20000); > > > + > > > + ret = st7703_read_id(ctx); > > > + if (ret < 0) > > > + goto err_poweroff; > > > + > > > + ret = st7703_init_sequence(ctx); > > > + if (ret < 0) { > > > + DRM_DEV_ERROR(ctx->dev, > > > + "Panel init sequence failed (%d)\n", ret); > > > + goto err_poweroff; > > > + } > > > + > > > + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); > > > + if (ret < 0) { > > > + DRM_DEV_ERROR(ctx->dev, > > > + "Failed to exit sleep mode (%d)\n", ret); > > > + goto err_poweroff; > > > + } > > > + > > > + msleep(120); > > > + > > > + ret = mipi_dsi_dcs_set_display_on(dsi); > > > + if (ret) { > > > + DRM_DEV_ERROR(ctx->dev, > > > + "Failed to turn on the display (%d)\n", ret); > > > + goto err_poweroff; > > > + } > > > + > > > + ctx->prepared = true; > > > + > > > + return 0; > > > + > > > +err_poweroff: > > > + gpiod_set_value_cansleep(ctx->reset_gpio, 1); > > > + regulator_bulk_disable(ctx->desc->num_supplies, ctx->supplies); > > > + return ret; > > > +} > > > + > > > +static int st7703_enable(struct drm_panel *panel) > > > +{ > > > + /* > > > + * Avoid flicker by waiting for slightly more than 1 > > > + * frame's interval. > > > + */ > > > + msleep(50); > > > + > > > + return 0; > > > +} > > > + > > > +static int st7703_unprepare(struct drm_panel *panel) > > > +{ > > > + struct st7703 *ctx = panel_to_st7703(panel); > > > + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); > > > + int ret; > > > + > > > + if (!ctx->prepared) > > > + return 0; > > > + > > > + ret = mipi_dsi_dcs_set_display_off(dsi); > > > + if (ret < 0) > > > + DRM_DEV_ERROR(ctx->dev, > > > + "Failed to turn off the display (%d)\n", ret); > > > + > > > + ret = mipi_dsi_dcs_enter_sleep_mode(dsi); > > > + if (ret < 0) > > > + DRM_DEV_ERROR(ctx->dev, > > > + "Failed to enter sleep mode (%d)\n", ret); > > > + > > > + gpiod_set_value_cansleep(ctx->reset_gpio, 1); > > > + regulator_bulk_disable(ctx->desc->num_supplies, ctx->supplies); > > > + ctx->prepared = false; > > > + > > > + return 0; > > > +} > > > + > > > +static int st7703_get_modes(struct drm_panel *panel, > > > + struct drm_connector *connector) > > > +{ > > > + struct st7703 *ctx = panel_to_st7703(panel); > > > + struct drm_display_mode *mode; > > > + > > > + mode = drm_mode_duplicate(connector->dev, ctx->desc->mode); > > > + if (!mode) { > > > + DRM_DEV_ERROR(ctx->dev, "Failed to add mode\n"); > > > + return -ENOMEM; > > > + } > > > + > > > + drm_mode_set_name(mode); > > > + > > > + connector->display_info.width_mm = mode->width_mm; > > > + connector->display_info.height_mm = mode->height_mm; > > > + drm_mode_probed_add(connector, mode); > > > + > > > + return 1; > > > +} > > > + > > > +static const struct drm_panel_funcs st7703_drm_funcs = { > > > + .prepare = st7703_prepare, > > > + .enable = st7703_enable, > > > + .unprepare = st7703_unprepare, > > > + .get_modes = st7703_get_modes, > > > +}; > > > + > > > +static const struct drm_display_mode xbd599_mode = { > > > + .hdisplay = 720, > > > + .hsync_start = 720 + 40, > > > + .hsync_end = 720 + 40 + 40, > > > + .htotal = 720 + 40 + 40 + 40, > > > + .vdisplay = 1440, > > > + .vsync_start = 1440 + 18, > > > + .vsync_end = 1440 + 18 + 10, > > > + .vtotal = 1440 + 18 + 10 + 17, > > > + .vrefresh = 60, > > > + .clock = 69000, > > > + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, > > > + > > > + .width_mm = 68, > > > + .height_mm = 136, > > > + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, > > > +}; > > > + > > > +static const char * const xbd599_supply_names[] = { > > > + "iovcc", > > > + "vcc", > > > +}; > > > + > > > +static const struct st7703_panel_desc xbd599_desc = { > > > + .mode = &xbd599_mode, > > > + .lanes = 4, > > > + .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE, > > > + .format = MIPI_DSI_FMT_RGB888, > > > + .supply_names = xbd599_supply_names, > > > + .num_supplies = ARRAY_SIZE(xbd599_supply_names), > > > +}; > > > + > > > +static int st7703_probe(struct mipi_dsi_device *dsi) > > > +{ > > > + const struct st7703_panel_desc *desc; > > > + struct device *dev = &dsi->dev; > > > + struct st7703 *ctx; > > > + int i, ret; > > > + > > > + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); > > > + if (!ctx) > > > + return -ENOMEM; > > > + > > > + ctx->dev = dev; > > > + ctx->desc = desc = of_device_get_match_data(dev); > > > + > > > + dsi->mode_flags = desc->flags; > > > + dsi->format = desc->format; > > > + dsi->lanes = desc->lanes; > > > + > > > + ctx->supplies = devm_kcalloc(&dsi->dev, desc->num_supplies, > > > + sizeof(*ctx->supplies), > > > + GFP_KERNEL); > > > + if (!ctx->supplies) > > > + return -ENOMEM; > > > + > > > + for (i = 0; i < desc->num_supplies; i++) > > > + ctx->supplies[i].supply = desc->supply_names[i]; > > > + > > > + ret = devm_regulator_bulk_get(&dsi->dev, desc->num_supplies, > > > + ctx->supplies); > > > + if (ret < 0) > > > + return ret; > > > + > > > + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); > > > + if (IS_ERR(ctx->reset_gpio)) { > > > + DRM_DEV_ERROR(dev, "Can't get reset gpio\n"); > > > + return PTR_ERR(ctx->reset_gpio); > > > + } > > > + > > > + mipi_dsi_set_drvdata(dsi, ctx); > > > + > > > + drm_panel_init(&ctx->panel, &dsi->dev, &st7703_drm_funcs, > > > + DRM_MODE_CONNECTOR_DSI); > > > + > > > + ret = drm_panel_of_backlight(&ctx->panel); > > > + if (ret) > > > + return ret; > > > + > > > + drm_panel_add(&ctx->panel); > > > + > > > + ret = mipi_dsi_attach(dsi); > > > + if (ret < 0) { > > > + drm_panel_remove(&ctx->panel); > > > + return ret; > > > + } > > > + > > > + return 0; > > > +} > > > + > > > +static void st7703_shutdown(struct mipi_dsi_device *dsi) > > > +{ > > > + struct st7703 *ctx = mipi_dsi_get_drvdata(dsi); > > > + int ret; > > > + > > > + ret = drm_panel_unprepare(&ctx->panel); > > > + if (ret < 0) > > > + DRM_DEV_ERROR(&dsi->dev, > > > + "Failed to unprepare panel (%d)\n", ret); > > > +} > > > + > > > +static int st7703_remove(struct mipi_dsi_device *dsi) > > > +{ > > > + struct st7703 *ctx = mipi_dsi_get_drvdata(dsi); > > > + int ret; > > > + > > > + st7703_shutdown(dsi); > > > + > > > + ret = mipi_dsi_detach(dsi); > > > + if (ret < 0) > > > + DRM_DEV_ERROR(&dsi->dev, > > > + "Failed to detach from DSI host (%d)\n", ret); > > > + > > > + drm_panel_remove(&ctx->panel); > > > + > > > + return 0; > > > +} > > > + > > > +static const struct of_device_id st7703_of_match[] = { > > > + { .compatible = "xingbangda,xbd599", .data = &xbd599_desc }, > > > + { /* sentinel */ } > > > +}; > > > +MODULE_DEVICE_TABLE(of, st7703_of_match); > > > + > > > +static struct mipi_dsi_driver st7703_driver = { > > > + .probe = st7703_probe, > > > + .remove = st7703_remove, > > > + .shutdown = st7703_shutdown, > > > + .driver = { > > > + .name = "st7703", > > > + .of_match_table = st7703_of_match, > > > + }, > > > +}; > > > +module_mipi_dsi_driver(st7703_driver); > > > + > > > +MODULE_AUTHOR("Icenowy Zheng "); > > > +MODULE_DESCRIPTION("DRM driver for Sitronix ST7703 MIPI DSI panel"); > > > +MODULE_LICENSE("GPL v2"); > > > -- > > > 2.27.0 > > > > > > _______________________________________________ > > > dri-devel mailing list > > > dri-devel@lists.freedesktop.org > > > https://lists.freedesktop.org/mailman/listinfo/dri-devel > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 698A8C433E1 for ; Mon, 22 Jun 2020 08:08:19 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4641E208B8 for ; Mon, 22 Jun 2020 08:08:19 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4641E208B8 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=ravnborg.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B982289DD2; Mon, 22 Jun 2020 08:08:18 +0000 (UTC) Received: from asavdk3.altibox.net (asavdk3.altibox.net [109.247.116.14]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7299989DD2 for ; Mon, 22 Jun 2020 08:08:16 +0000 (UTC) Received: from ravnborg.org (unknown [188.228.123.71]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by asavdk3.altibox.net (Postfix) with ESMTPS id AAE3720021; Mon, 22 Jun 2020 10:08:03 +0200 (CEST) Date: Mon, 22 Jun 2020 10:08:02 +0200 From: Sam Ravnborg To: =?utf-8?Q?Ond=C5=99ej?= Jirman , linux-sunxi@googlegroups.com, Thierry Reding , David Airlie , Daniel Vetter , Rob Herring , Maxime Ripard , Chen-Yu Tsai , Linus Walleij , Icenowy Zheng , devicetree@vger.kernel.org, Samuel Holland , Bhushan Shah , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Luca Weiss , Martijn Braam , linux-arm-kernel@lists.infradead.org Subject: Re: [PATCH v4 3/5] drm: panel: Add Xingbangda XBD599 panel (ST7703 controller) Message-ID: <20200622080802.GA650963@ravnborg.org> References: <20200617003209.670819-1-megous@megous.com> <20200617003209.670819-4-megous@megous.com> <20200620212529.GB74146@ravnborg.org> <20200620223010.fqjwijiixxkewk3p@core.my.home> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20200620223010.fqjwijiixxkewk3p@core.my.home> X-CMAE-Score: 0 X-CMAE-Analysis: v=2.3 cv=edQTgYMH c=1 sm=1 tr=0 a=S6zTFyMACwkrwXSdXUNehg==:117 a=S6zTFyMACwkrwXSdXUNehg==:17 a=IkcTkHD0fZMA:10 a=J_fg_7IlAAAA:8 a=e5mUnYsNAAAA:8 a=rpfOPJV_7YADzv3fI4AA:9 a=9TJecaD38D1O3S5X:21 a=qYyW2_D2GT2v-q_M:21 a=QEXdDO2ut3YA:10 a=zGOw-GkVl6h1W4ZARoUA:22 a=Vxmtnl_E_bksehYqCbjh:22 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" T24gU3VuLCBKdW4gMjEsIDIwMjAgYXQgMTI6MzA6MTBBTSArMDIwMCwgT25kxZllaiBKaXJtYW4g d3JvdGU6Cj4gT24gU2F0LCBKdW4gMjAsIDIwMjAgYXQgMTE6MjU6MjlQTSArMDIwMCwgU2FtIFJh dm5ib3JnIHdyb3RlOgo+ID4gSGkgT25kcmVqIGV0IGFsLgo+ID4gCj4gPiBPbiBXZWQsIEp1biAx NywgMjAyMCBhdCAwMjozMjowN0FNICswMjAwLCBPbmRyZWogSmlybWFuIHdyb3RlOgo+ID4gPiBG cm9tOiBJY2Vub3d5IFpoZW5nIDxpY2Vub3d5QGFvc2MuaW8+Cj4gPiA+IAo+ID4gPiBYaW5nYmFu Z2RhIFhCRDU5OSBpcyBhIDUuOTkiIDcyMHgxNDQwIE1JUEktRFNJIElQUyBMQ0QgcGFuZWwgbWFk ZSBieQo+ID4gPiBYaW5nYmFuZ2RhLCB3aGljaCBpcyB1c2VkIG9uIFBpbmVQaG9uZSBmaW5hbCBh c3NlbWJsZWQgcGhvbmVzLgo+ID4gPiAKPiA+ID4gSXQgaXMgYmFzZWQgb24gU2l0cm9uaXggU1Q3 NzAzIExDRCBjb250cm9sbGVyLgo+ID4gCj4gPiBJIGFtIGEgbGl0dGxlIGxhdGUgdG8gdGhlIGdh bWUgaGVyZSAtIHNvIHNvcnJ5IGlmIHRoaXMgaGFzIGJlZW4KPiA+IGRpc2N1c3NlZCBiZWZvcmUu Cj4gPiBXZSBhbHJlYWR5IGhhdmUgcGFuZWwtcm9ja3RlY2gtamgwNTduMDA5MDAuYyB3aGljaCBp cyBhIHBhbmxlIGRyaXZlcgo+ID4gYmFzZWQgb24gc3Q3NzAzLgo+ID4gV2h5IGlzIGl0IHdlIG5l ZWQgYSBuZXcgZHJpdmVyPwo+IAo+IE5vIHJlYXNvbiBvdGhlciB0aGFuIHRoZSBkcml2ZXIgbm90 IGJlaW5nIG5hbWVkIGFmdGVyIHRoZSBjb250cm9sbGVyLAo+IHNvIEkgZGlkbid0IG5vdGljZS4K PiAKPiA+IFdvdWxkIGl0IG5vdCBiZSBiZXR0ZXIgdG8gaGF2ZSBvbmUgc3Q3NzAzIGRyaXZlciB0 aGF0IHN1aXBwb3J0cyBib3RoCj4gPiBwYW5lbHM/Cj4gPgo+ID4gVGhlIGRyaXZlciB3b3VsZCBu ZWVkIGRlZGljYXRlZCBpbml0IGZ1bmN0aW9ucyBkZXBlbmRpbmcgb24gdGhlIHBhbmVsLgo+ID4g QnV0IGEgbG90IGNvdWxkIGFsc28gYmUgc2hhcmVkLgo+IAo+IEkgZ3Vlc3MgSSBjYW4gbW92ZSB0 aGUgY29kZSB0aGVyZS4gCkluIHRoZSBzYW1lIHByb2Nlc3MgdGhlIHJpdmVyIHNob3VsZCB0aGVu IGJlIHJlbmFtZWQgdG8gZm9sbG93IG90aGVyCnNpdHJvbml4IGJhc2VkIGRyaXZlcnMuClNvIHRo ZSBuZXh0IGRldmVsb3BlciB3aWxsIHJlY29nbml6ZSB0aGlzIGFuZCB1c2UgdGhlIGNvcnJlY3Qg ZHJpdmVyLgoKCVNhbQoKPiAKPiByZWdhcmRzLAo+IAlvLgo+IAo+ID4gCVNhbQo+ID4gCj4gPiA+ IAo+ID4gPiBBZGQgc3VwcG9ydCBmb3IgaXQuCj4gPiA+IAo+ID4gPiBTaWduZWQtb2ZmLWJ5OiBJ Y2Vub3d5IFpoZW5nIDxpY2Vub3d5QGFvc2MuaW8+Cj4gPiA+IFNpZ25lZC1vZmYtYnk6IE9uZHJl aiBKaXJtYW4gPG1lZ291c0BtZWdvdXMuY29tPgo+ID4gPiAtLS0KPiA+ID4gIGRyaXZlcnMvZ3B1 L2RybS9wYW5lbC9LY29uZmlnICAgICAgICAgICAgICAgICB8ICAxMCArCj4gPiA+ICBkcml2ZXJz L2dwdS9kcm0vcGFuZWwvTWFrZWZpbGUgICAgICAgICAgICAgICAgfCAgIDEgKwo+ID4gPiAgZHJp dmVycy9ncHUvZHJtL3BhbmVsL3BhbmVsLXNpdHJvbml4LXN0NzcwMy5jIHwgNTM1ICsrKysrKysr KysrKysrKysrKwo+ID4gPiAgMyBmaWxlcyBjaGFuZ2VkLCA1NDYgaW5zZXJ0aW9ucygrKQo+ID4g PiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvZ3B1L2RybS9wYW5lbC9wYW5lbC1zaXRyb25p eC1zdDc3MDMuYwo+ID4gPiAKPiA+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9wYW5l bC9LY29uZmlnIGIvZHJpdmVycy9ncHUvZHJtL3BhbmVsL0tjb25maWcKPiA+ID4gaW5kZXggMzkw NTVjMWYwZTJmLi5iN2JjMTU3YjA2MTIgMTAwNjQ0Cj4gPiA+IC0tLSBhL2RyaXZlcnMvZ3B1L2Ry bS9wYW5lbC9LY29uZmlnCj4gPiA+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9wYW5lbC9LY29uZmln Cj4gPiA+IEBAIC0zOTUsNiArMzk1LDE2IEBAIGNvbmZpZyBEUk1fUEFORUxfU0lUUk9OSVhfU1Q3 NzAxCj4gPiA+ICAJICBTVDc3MDEgY29udHJvbGxlciBmb3IgNDgwWDg2NCBMQ0QgcGFuZWxzIHdp dGggTUlQSS9SR0IvU1BJCj4gPiA+ICAJICBzeXN0ZW0gaW50ZXJmYWNlcy4KPiA+ID4gIAo+ID4g PiArY29uZmlnIERSTV9QQU5FTF9TSVRST05JWF9TVDc3MDMKPiA+ID4gKwl0cmlzdGF0ZSAiU2l0 cm9uaXggU1Q3NzAzIHBhbmVsIGRyaXZlciIKPiA+ID4gKwlkZXBlbmRzIG9uIE9GCj4gPiA+ICsJ ZGVwZW5kcyBvbiBEUk1fTUlQSV9EU0kKPiA+ID4gKwlkZXBlbmRzIG9uIEJBQ0tMSUdIVF9DTEFT U19ERVZJQ0UKPiA+ID4gKwloZWxwCj4gPiA+ICsJICBTYXkgWSBoZXJlIGlmIHlvdSB3YW50IHRv IGVuYWJsZSBzdXBwb3J0IGZvciB0aGUgU2l0cm9uaXgKPiA+ID4gKwkgIFNUNzcwMyBjb250cm9s bGVyIGZvciA3MjBYMTQ0MCBMQ0QgcGFuZWxzIHdpdGggTUlQSS9SR0IvU1BJCj4gPiA+ICsJICBz eXN0ZW0gaW50ZXJmYWNlcy4KPiA+ID4gKwo+ID4gPiAgY29uZmlnIERSTV9QQU5FTF9TSVRST05J WF9TVDc3ODlWCj4gPiA+ICAJdHJpc3RhdGUgIlNpdHJvbml4IFNUNzc4OVYgcGFuZWwiCj4gPiA+ ICAJZGVwZW5kcyBvbiBPRiAmJiBTUEkKPiA+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2Ry bS9wYW5lbC9NYWtlZmlsZSBiL2RyaXZlcnMvZ3B1L2RybS9wYW5lbC9NYWtlZmlsZQo+ID4gPiBp bmRleCBkZTc0ZjI4MmM0MzMuLjQ3ZjQ3ODlhODY4NSAxMDA2NDQKPiA+ID4gLS0tIGEvZHJpdmVy cy9ncHUvZHJtL3BhbmVsL01ha2VmaWxlCj4gPiA+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9wYW5l bC9NYWtlZmlsZQo+ID4gPiBAQCAtNDEsNiArNDEsNyBAQCBvYmotJChDT05GSUdfRFJNX1BBTkVM X1NIQVJQX0xRMTAxUjFTWDAxKSArPSBwYW5lbC1zaGFycC1scTEwMXIxc3gwMS5vCj4gPiA+ICBv YmotJChDT05GSUdfRFJNX1BBTkVMX1NIQVJQX0xTMDM3VjdEVzAxKSArPSBwYW5lbC1zaGFycC1s czAzN3Y3ZHcwMS5vCj4gPiA+ICBvYmotJChDT05GSUdfRFJNX1BBTkVMX1NIQVJQX0xTMDQzVDFM RTAxKSArPSBwYW5lbC1zaGFycC1sczA0M3QxbGUwMS5vCj4gPiA+ICBvYmotJChDT05GSUdfRFJN X1BBTkVMX1NJVFJPTklYX1NUNzcwMSkgKz0gcGFuZWwtc2l0cm9uaXgtc3Q3NzAxLm8KPiA+ID4g K29iai0kKENPTkZJR19EUk1fUEFORUxfU0lUUk9OSVhfU1Q3NzAzKSArPSBwYW5lbC1zaXRyb25p eC1zdDc3MDMubwo+ID4gPiAgb2JqLSQoQ09ORklHX0RSTV9QQU5FTF9TSVRST05JWF9TVDc3ODlW KSArPSBwYW5lbC1zaXRyb25peC1zdDc3ODl2Lm8KPiA+ID4gIG9iai0kKENPTkZJR19EUk1fUEFO RUxfU09OWV9BQ1g0MjRBS1ApICs9IHBhbmVsLXNvbnktYWN4NDI0YWtwLm8KPiA+ID4gIG9iai0k KENPTkZJR19EUk1fUEFORUxfU09OWV9BQ1g1NjVBS00pICs9IHBhbmVsLXNvbnktYWN4NTY1YWtt Lm8KPiA+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9wYW5lbC9wYW5lbC1zaXRyb25p eC1zdDc3MDMuYyBiL2RyaXZlcnMvZ3B1L2RybS9wYW5lbC9wYW5lbC1zaXRyb25peC1zdDc3MDMu Ywo+ID4gPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+ID4gPiBpbmRleCAwMDAwMDAwMDAwMDAuLmRi ZDQ2YjZjMGI0Ngo+ID4gPiAtLS0gL2Rldi9udWxsCj4gPiA+ICsrKyBiL2RyaXZlcnMvZ3B1L2Ry bS9wYW5lbC9wYW5lbC1zaXRyb25peC1zdDc3MDMuYwo+ID4gPiBAQCAtMCwwICsxLDUzNSBAQAo+ ID4gPiArLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAKPiA+ID4gKy8qCj4gPiA+ ICsgKiBEUk0gZHJpdmVyIGZvciBTaXRyb25peCBTVDc3MDMgTUlQSSBEU0kgcGFuZWwKPiA+ID4g KyAqCj4gPiA+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMjAgT25kcmVqIEppcm1hbiA8bWVnb3VzQG1l Z291cy5jb20+Cj4gPiA+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMTktMjAyMCBJY2Vub3d5IFpoZW5n IDxpY2Vub3d5QGFvc2MuaW8+Cj4gPiA+ICsgKgo+ID4gPiArICogQmFzZWQgb24gcGFuZWwtcm9j a3RlY2gtamgwNTduMDA5MDAuYywgd2hpY2ggaXM6Cj4gPiA+ICsgKiAgIENvcHlyaWdodCAoQykg UHVyaXNtIFNQQyAyMDE5Cj4gPiA+ICsgKi8KPiA+ID4gKwo+ID4gPiArI2luY2x1ZGUgPGxpbnV4 L2RlbGF5Lmg+Cj4gPiA+ICsjaW5jbHVkZSA8bGludXgvZ3Bpby9jb25zdW1lci5oPgo+ID4gPiAr I2luY2x1ZGUgPGxpbnV4L21vZF9kZXZpY2V0YWJsZS5oPgo+ID4gPiArI2luY2x1ZGUgPGxpbnV4 L21vZHVsZS5oPgo+ID4gPiArI2luY2x1ZGUgPGxpbnV4L29mX2RldmljZS5oPgo+ID4gPiArI2lu Y2x1ZGUgPGxpbnV4L3JlZ3VsYXRvci9jb25zdW1lci5oPgo+ID4gPiArCj4gPiA+ICsjaW5jbHVk ZSA8ZHJtL2RybV9taXBpX2RzaS5oPgo+ID4gPiArI2luY2x1ZGUgPGRybS9kcm1fbW9kZXMuaD4K PiA+ID4gKyNpbmNsdWRlIDxkcm0vZHJtX3BhbmVsLmg+Cj4gPiA+ICsjaW5jbHVkZSA8ZHJtL2Ry bV9wcmludC5oPgo+ID4gPiArCj4gPiA+ICsvKiBNYW51ZmFjdHVyZXIgc3BlY2lmaWMgRENTIGNv bW1hbmRzICovCj4gPiA+ICsjZGVmaW5lIFNUNzcwM19DTURfU0VURElTUAkweEIyCj4gPiA+ICsj ZGVmaW5lIFNUNzcwM19DTURfU0VUUkdCSUYJMHhCMwo+ID4gPiArI2RlZmluZSBTVDc3MDNfQ01E X1NFVENZQwkweEI0Cj4gPiA+ICsjZGVmaW5lIFNUNzcwM19DTURfU0VUQkdQCTB4QjUKPiA+ID4g KyNkZWZpbmUgU1Q3NzAzX0NNRF9TRVRWQ09NCTB4QjYKPiA+ID4gKyNkZWZpbmUgU1Q3NzAzX0NN RF9TRVRPVFAJMHhCNwo+ID4gPiArI2RlZmluZSBTVDc3MDNfQ01EX1NFVFBPV0VSX0VYVAkweEI4 Cj4gPiA+ICsjZGVmaW5lIFNUNzcwM19DTURfU0VURVhUQwkweEI5Cj4gPiA+ICsjZGVmaW5lIFNU NzcwM19DTURfU0VUTUlQSQkweEJBCj4gPiA+ICsjZGVmaW5lIFNUNzcwM19DTURfU0VUVkRDCTB4 QkMKPiA+ID4gKyNkZWZpbmUgU1Q3NzAzX0NNRF9VTktfQkYJMHhCRgo+ID4gPiArI2RlZmluZSBT VDc3MDNfQ01EX1NFVFNDUgkweEMwCj4gPiA+ICsjZGVmaW5lIFNUNzcwM19DTURfU0VUUE9XRVIJ MHhDMQo+ID4gPiArI2RlZmluZSBTVDc3MDNfQ01EX1VOS19DNgkweEM2Cj4gPiA+ICsjZGVmaW5l IFNUNzcwM19DTURfU0VUUEFORUwJMHhDQwo+ID4gPiArI2RlZmluZSBTVDc3MDNfQ01EX1JESUQx CTB4REEKPiA+ID4gKyNkZWZpbmUgU1Q3NzAzX0NNRF9SRElEMgkweERCCj4gPiA+ICsjZGVmaW5l IFNUNzcwM19DTURfUkRJRDMJMHhEQwo+ID4gPiArI2RlZmluZSBTVDc3MDNfQ01EX1NFVEdBTU1B CTB4RTAKPiA+ID4gKyNkZWZpbmUgU1Q3NzAzX0NNRF9TRVRFUQkweEUzCj4gPiA+ICsjZGVmaW5l IFNUNzcwM19DTURfU0VUR0lQMQkweEU5Cj4gPiA+ICsjZGVmaW5lIFNUNzcwM19DTURfU0VUR0lQ MgkweEVBCj4gPiA+ICsKPiA+ID4gK3N0cnVjdCBzdDc3MDNfcGFuZWxfZGVzYyB7Cj4gPiA+ICsJ Y29uc3Qgc3RydWN0IGRybV9kaXNwbGF5X21vZGUgKm1vZGU7Cj4gPiA+ICsJdW5zaWduZWQgaW50 IGxhbmVzOwo+ID4gPiArCXVuc2lnbmVkIGxvbmcgZmxhZ3M7Cj4gPiA+ICsJZW51bSBtaXBpX2Rz aV9waXhlbF9mb3JtYXQgZm9ybWF0Owo+ID4gPiArCWNvbnN0IGNoYXIgKmNvbnN0ICpzdXBwbHlf bmFtZXM7Cj4gPiA+ICsJdW5zaWduZWQgaW50IG51bV9zdXBwbGllczsKPiA+ID4gK307Cj4gPiA+ ICsKPiA+ID4gK3N0cnVjdCBzdDc3MDMgewo+ID4gPiArCXN0cnVjdCBkZXZpY2UgKmRldjsKPiA+ ID4gKwlzdHJ1Y3QgZHJtX3BhbmVsIHBhbmVsOwo+ID4gPiArCXN0cnVjdCBncGlvX2Rlc2MgKnJl c2V0X2dwaW87Cj4gPiA+ICsJc3RydWN0IHJlZ3VsYXRvcl9idWxrX2RhdGEgKnN1cHBsaWVzOwo+ ID4gPiArCWNvbnN0IHN0cnVjdCBzdDc3MDNfcGFuZWxfZGVzYyAqZGVzYzsKPiA+ID4gKwlib29s IHByZXBhcmVkOwo+ID4gPiArfTsKPiA+ID4gKwo+ID4gPiArc3RhdGljIGlubGluZSBzdHJ1Y3Qg c3Q3NzAzICpwYW5lbF90b19zdDc3MDMoc3RydWN0IGRybV9wYW5lbCAqcGFuZWwpCj4gPiA+ICt7 Cj4gPiA+ICsJcmV0dXJuIGNvbnRhaW5lcl9vZihwYW5lbCwgc3RydWN0IHN0NzcwMywgcGFuZWwp Owo+ID4gPiArfQo+ID4gPiArCj4gPiA+ICsjZGVmaW5lIGRzaV9kY3Nfd3JpdGVfc2VxKGRzaSwg Y21kLCBzZXEuLi4pIGRvIHsJCQlcCj4gPiA+ICsJCXN0YXRpYyBjb25zdCB1OCBkW10gPSB7IHNl cSB9OwkJCQlcCj4gPiA+ICsJCWludCByZXQ7CQkJCQkJXAo+ID4gPiArCQlyZXQgPSBtaXBpX2Rz aV9kY3Nfd3JpdGUoZHNpLCBjbWQsIGQsIEFSUkFZX1NJWkUoZCkpOwlcCj4gPiA+ICsJCWlmIChy ZXQgPCAwKQkJCQkJCVwKPiA+ID4gKwkJCXJldHVybiByZXQ7CQkJCQlcCj4gPiA+ICsJfSB3aGls ZSAoMCkKPiA+ID4gKwo+ID4gPiArCj4gPiA+ICtzdGF0aWMgaW50IHN0NzcwM19pbml0X3NlcXVl bmNlKHN0cnVjdCBzdDc3MDMgKmN0eCkKPiA+ID4gK3sKPiA+ID4gKwlzdHJ1Y3QgbWlwaV9kc2lf ZGV2aWNlICpkc2kgPSB0b19taXBpX2RzaV9kZXZpY2UoY3R4LT5kZXYpOwo+ID4gPiArCXN0cnVj dCBkZXZpY2UgKmRldiA9IGN0eC0+ZGV2Owo+ID4gPiArCj4gPiA+ICsJLyoKPiA+ID4gKwkgKiBJ bml0IHNlcXVlbmNlIHdhcyBzdXBwbGllZCBieSB0aGUgcGFuZWwgdmVuZG9yLgo+ID4gPiArCSAq Lwo+ID4gPiArCj4gPiA+ICsJLyogTWFnaWMgc2VxdWVuY2UgdG8gdW5sb2NrIHVzZXIgY29tbWFu ZHMgYmVsb3cuICovCj4gPiA+ICsJZHNpX2Rjc193cml0ZV9zZXEoZHNpLCBTVDc3MDNfQ01EX1NF VEVYVEMsIDB4RjEsIDB4MTIsIDB4ODMpOwo+ID4gPiArCj4gPiA+ICsJZHNpX2Rjc193cml0ZV9z ZXEoZHNpLCBTVDc3MDNfQ01EX1NFVE1JUEksCj4gPiA+ICsJCQkgIDB4MzMsIC8qIFZDX21haW4g PSAwLCBMYW5lX051bWJlciA9IDMgKDQgbGFuZXMpICovCj4gPiA+ICsJCQkgIDB4ODEsIC8qIERT SV9MRE9fU0VMID0gMS43ViwgUlRFUk0gPSA5MCBPaG0gKi8KPiA+ID4gKwkJCSAgMHgwNSwgLyog SUhTUlggPSB4NiAoTG93IEhpZ2ggU3BlZWQgZHJpdmluZyBhYmlsaXR5KSAqLwo+ID4gPiArCQkJ ICAweEY5LCAvKiBUWF9DTEtfU0VMID0gZkRTSUNMSy8xNiAqLwo+ID4gPiArCQkJICAweDBFLCAv KiBIRlBfT1NDIChtaW4uIEhGUCBudW1iZXIgaW4gRFNJIG1vZGUpICovCj4gPiA+ICsJCQkgIDB4 MEUsIC8qIEhCUF9PU0MgKG1pbi4gSEJQIG51bWJlciBpbiBEU0kgbW9kZSkgKi8KPiA+ID4gKwkJ CSAgLyogVGhlIHJlc3QgaXMgdW5kb2N1bWVudGVkIGluIFNUNzcwMyBkYXRhc2hlZXQgKi8KPiA+ ID4gKwkJCSAgMHgyMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwK PiA+ID4gKwkJCSAgMHg0NCwgMHgyNSwgMHgwMCwgMHg5MSwgMHgwYSwgMHgwMCwgMHgwMCwgMHgw MiwKPiA+ID4gKwkJCSAgMHg0RiwgMHgxMSwgMHgwMCwgMHgwMCwgMHgzNyk7Cj4gPiA+ICsKPiA+ ID4gKwlkc2lfZGNzX3dyaXRlX3NlcShkc2ksIFNUNzcwM19DTURfU0VUUE9XRVJfRVhULAo+ID4g PiArCQkJICAweDI1LCAvKiBQQ0NTID0gMiwgRUNQX0RDX0RJViA9IDEvNCBIU1lOQyAqLwo+ID4g PiArCQkJICAweDIyLCAvKiBEVCA9IDE1bXMgWERLX0VDUCA9IHgyICovCj4gPiA+ICsJCQkgIDB4 MjAsIC8qIFBGTV9EQ19ESVYgPSAvMSAqLwo+ID4gPiArCQkJICAweDAzICAvKiBFQ1BfU1lOQ19F TiA9IDEsIFZHWF9TWU5DX0VOID0gMSAqLyk7Cj4gPiA+ICsKPiA+ID4gKwkvKiBSR0IgSS9GIHBv cmNoIHRpbWluZyAqLwo+ID4gPiArCWRzaV9kY3Nfd3JpdGVfc2VxKGRzaSwgU1Q3NzAzX0NNRF9T RVRSR0JJRiwKPiA+ID4gKwkJCSAgMHgxMCwgLyogVkJQX1JHQl9HRU4gKi8KPiA+ID4gKwkJCSAg MHgxMCwgLyogVkZQX1JHQl9HRU4gKi8KPiA+ID4gKwkJCSAgMHgwNSwgLyogREVfQlBfUkdCX0dF TiAqLwo+ID4gPiArCQkJICAweDA1LCAvKiBERV9GUF9SR0JfR0VOICovCj4gPiA+ICsJCQkgIC8q IFRoZSByZXN0IGlzIHVuZG9jdW1lbnRlZCBpbiBTVDc3MDMgZGF0YXNoZWV0ICovCj4gPiA+ICsJ CQkgIDB4MDMsIDB4RkYsCj4gPiA+ICsJCQkgIDB4MDAsIDB4MDAsCj4gPiA+ICsJCQkgIDB4MDAs IDB4MDApOwo+ID4gPiArCj4gPiA+ICsJLyogU291cmNlIGRyaXZpbmcgc2V0dGluZ3MuICovCj4g PiA+ICsJZHNpX2Rjc193cml0ZV9zZXEoZHNpLCBTVDc3MDNfQ01EX1NFVFNDUiwKPiA+ID4gKwkJ CSAgMHg3MywgLyogTl9QT1BPTiAqLwo+ID4gPiArCQkJICAweDczLCAvKiBOX05PUE9OICovCj4g PiA+ICsJCQkgIDB4NTAsIC8qIElfUE9QT04gKi8KPiA+ID4gKwkJCSAgMHg1MCwgLyogSV9OT1BP TiAqLwo+ID4gPiArCQkJICAweDAwLCAvKiBTQ1JbMzEsMjRdICovCj4gPiA+ICsJCQkgIDB4QzAs IC8qIFNDUlsyMywxNl0gKi8KPiA+ID4gKwkJCSAgMHgwOCwgLyogU0NSWzE1LDhdICovCj4gPiA+ ICsJCQkgIDB4NzAsIC8qIFNDUls3LDBdICovCj4gPiA+ICsJCQkgIDB4MDAgIC8qIFVuZG9jdW1l bnRlZCAqLyk7Cj4gPiA+ICsKPiA+ID4gKwkvKiBOVkRERF9TRUwgPSAtMS44ViwgVkRERF9TRUwg PSBvdXQgb2YgcmFuZ2UgKHBvc3NpYmx5IDEuOVY/KSAqLwo+ID4gPiArCWRzaV9kY3Nfd3JpdGVf c2VxKGRzaSwgU1Q3NzAzX0NNRF9TRVRWREMsIDB4NEUpOwo+ID4gPiArCj4gPiA+ICsJLyoKPiA+ ID4gKwkgKiBTU19QQU5FTCA9IDEgKHJldmVyc2Ugc2NhbiksIEdTX1BBTkVMID0gMCAobm9ybWFs IHNjYW4pCj4gPiA+ICsJICogUkVWX1BBTkVMID0gMSAobm9ybWFsbHkgYmxhY2sgcGFuZWwpLCBC R1JfUEFORUwgPSAxIChCR1IpCj4gPiA+ICsJICovCj4gPiA+ICsJZHNpX2Rjc193cml0ZV9zZXEo ZHNpLCBTVDc3MDNfQ01EX1NFVFBBTkVMLCAweDBCKTsKPiA+ID4gKwo+ID4gPiArCS8qIFppZy1a YWcgVHlwZSBDIGNvbHVtbiBpbnZlcnNpb24uICovCj4gPiA+ICsJZHNpX2Rjc193cml0ZV9zZXEo ZHNpLCBTVDc3MDNfQ01EX1NFVENZQywgMHg4MCk7Cj4gPiA+ICsKPiA+ID4gKwkvKiBTZXQgZGlz cGxheSByZXNvbHV0aW9uLiAqLwo+ID4gPiArCWRzaV9kY3Nfd3JpdGVfc2VxKGRzaSwgU1Q3NzAz X0NNRF9TRVRESVNQLAo+ID4gPiArCQkJICAweEYwLCAvKiBOTCA9IDI0MCAqLwo+ID4gPiArCQkJ ICAweDEyLCAvKiBSRVNfVl9MU0IgPSAwLCBCTEtfQ09OID0gVlNTRCwKPiA+ID4gKwkJCQkgKiBS RVNPX1NFTCA9IDcyMFJHQgo+ID4gPiArCQkJCSAqLwo+ID4gPiArCQkJICAweEYwICAvKiBXSElU RV9HTkRfRU4gPSAxIChHTkQpLAo+ID4gPiArCQkJCSAqIFdISVRFX0ZSQU1FX1NFTCA9IDcgZnJh bWVzLAo+ID4gPiArCQkJCSAqIElTQyA9IDAgZnJhbWVzCj4gPiA+ICsJCQkJICovKTsKPiA+ID4g Kwo+ID4gPiArCWRzaV9kY3Nfd3JpdGVfc2VxKGRzaSwgU1Q3NzAzX0NNRF9TRVRFUSwKPiA+ID4g KwkJCSAgMHgwMCwgLyogUE5PRVEgKi8KPiA+ID4gKwkJCSAgMHgwMCwgLyogTk5PRVEgKi8KPiA+ ID4gKwkJCSAgMHgwQiwgLyogUEVRR05EICovCj4gPiA+ICsJCQkgIDB4MEIsIC8qIE5FUUdORCAq Lwo+ID4gPiArCQkJICAweDEwLCAvKiBQRVFWQ0kgKi8KPiA+ID4gKwkJCSAgMHgxMCwgLyogTkVR VkNJICovCj4gPiA+ICsJCQkgIDB4MDAsIC8qIFBFUVZDSTEgKi8KPiA+ID4gKwkJCSAgMHgwMCwg LyogTkVRVkNJMSAqLwo+ID4gPiArCQkJICAweDAwLCAvKiByZXNlcnZlZCAqLwo+ID4gPiArCQkJ ICAweDAwLCAvKiByZXNlcnZlZCAqLwo+ID4gPiArCQkJICAweEZGLCAvKiByZXNlcnZlZCAqLwo+ ID4gPiArCQkJICAweDAwLCAvKiByZXNlcnZlZCAqLwo+ID4gPiArCQkJICAweEMwLCAvKiBFU0Rf REVUX0RBVEFfV0hJVEUgPSAxLCBFU0RfV0hJVEVfRU4gPSAxICovCj4gPiA+ICsJCQkgIDB4MTAg IC8qIFNMUElOX09QVElPTiA9IDEgKG5vIG5lZWQgdnN5bmMgYWZ0ZXIgc2xlZXAtaW4pCj4gPiA+ ICsJCQkJICogVkVESU9fTk9fQ0hFQ0tfRU4gPSAwCj4gPiA+ICsJCQkJICogRVNEX1dISVRFX0dO RF9FTiA9IDAKPiA+ID4gKwkJCQkgKiBFU0RfREVUX1RJTUVfU0VMID0gMCBmcmFtZXMKPiA+ID4g KwkJCQkgKi8pOwo+ID4gPiArCj4gPiA+ICsJLyogVW5kb2N1bWVudGVkIGNvbW1hbmQuICovCj4g PiA+ICsJZHNpX2Rjc193cml0ZV9zZXEoZHNpLCBTVDc3MDNfQ01EX1VOS19DNiwgMHgwMSwgMHgw MCwgMHhGRiwgMHhGRiwgMHgwMCk7Cj4gPiA+ICsKPiA+ID4gKwlkc2lfZGNzX3dyaXRlX3NlcShk c2ksIFNUNzcwM19DTURfU0VUUE9XRVIsCj4gPiA+ICsJCQkgIDB4NzQsIC8qIFZCVEhTLCBWQlRM UzogVkdIID0gMTdWLCBWQkwgPSAtMTFWICovCj4gPiA+ICsJCQkgIDB4MDAsIC8qIEZCT0ZGX1ZH SCA9IDAsIEZCT0ZGX1ZHTCA9IDAgKi8KPiA+ID4gKwkJCSAgMHgzMiwgLyogVlJQICAqLwo+ID4g PiArCQkJICAweDMyLCAvKiBWUk4gKi8KPiA+ID4gKwkJCSAgMHg3NywgLyogcmVzZXJ2ZWQgKi8K PiA+ID4gKwkJCSAgMHhGMSwgLyogQVBTID0gMSAoc21hbGwpLAo+ID4gPiArCQkJCSAqIFZHTF9E RVRfRU4gPSAxLCBWR0hfREVUX0VOID0gMSwKPiA+ID4gKwkJCQkgKiBWR0xfVFVSQk8gPSAxLCBW R0hfVFVSQk8gPSAxCj4gPiA+ICsJCQkJICovCj4gPiA+ICsJCQkgIDB4RkYsIC8qIFZHSDFfTF9E SVYsIFZHTDFfTF9ESVYgKDEuNU1IeikgKi8KPiA+ID4gKwkJCSAgMHhGRiwgLyogVkdIMV9SX0RJ ViwgVkdMMV9SX0RJViAoMS41TUh6KSAqLwo+ID4gPiArCQkJICAweENDLCAvKiBWR0gyX0xfRElW LCBWR0wyX0xfRElWICgyLjZNSHopICovCj4gPiA+ICsJCQkgIDB4Q0MsIC8qIFZHSDJfUl9ESVYs IFZHTDJfUl9ESVYgKDIuNk1IeikgKi8KPiA+ID4gKwkJCSAgMHg3NywgLyogVkdIM19MX0RJViwg VkdMM19MX0RJViAoNC41TUh6KSAqLwo+ID4gPiArCQkJICAweDc3ICAvKiBWR0gzX1JfRElWLCBW R0wzX1JfRElWICg0LjVNSHopICovKTsKPiA+ID4gKwo+ID4gPiArCS8qIFJlZmVyZW5jZSB2b2x0 YWdlLiAqLwo+ID4gPiArCWRzaV9kY3Nfd3JpdGVfc2VxKGRzaSwgU1Q3NzAzX0NNRF9TRVRCR1As Cj4gPiA+ICsJCQkgIDB4MDcsIC8qIFZSRUZfU0VMID0gNC4yViAqLwo+ID4gPiArCQkJICAweDA3 ICAvKiBOVlJFRl9TRUwgPSA0LjJWICovKTsKPiA+ID4gKwo+ID4gPiArCWRzaV9kY3Nfd3JpdGVf c2VxKGRzaSwgU1Q3NzAzX0NNRF9TRVRWQ09NLAo+ID4gPiArCQkJICAweDJDLCAvKiBWQ09NRENf RiA9IC0wLjY3ViAqLwo+ID4gPiArCQkJICAweDJDICAvKiBWQ09NRENfQiA9IC0wLjY3ViAqLyk7 Cj4gPiA+ICsKPiA+ID4gKwkvKiBVbmRvY3VtZW50ZWQgY29tbWFuZC4gKi8KPiA+ID4gKwlkc2lf ZGNzX3dyaXRlX3NlcShkc2ksIFNUNzcwM19DTURfVU5LX0JGLCAweDAyLCAweDExLCAweDAwKTsK PiA+ID4gKwo+ID4gPiArCS8qIFRoaXMgY29tbWFuZCBpcyB0byBzZXQgZm9yd2FyZCBHSVAgdGlt aW5nLiAqLwo+ID4gPiArCWRzaV9kY3Nfd3JpdGVfc2VxKGRzaSwgU1Q3NzAzX0NNRF9TRVRHSVAx LAo+ID4gPiArCQkJICAweDgyLCAweDEwLCAweDA2LCAweDA1LCAweEEyLCAweDBBLCAweEE1LCAw eDEyLAo+ID4gPiArCQkJICAweDMxLCAweDIzLCAweDM3LCAweDgzLCAweDA0LCAweEJDLCAweDI3 LCAweDM4LAo+ID4gPiArCQkJICAweDBDLCAweDAwLCAweDAzLCAweDAwLCAweDAwLCAweDAwLCAw eDBDLCAweDAwLAo+ID4gPiArCQkJICAweDAzLCAweDAwLCAweDAwLCAweDAwLCAweDc1LCAweDc1 LCAweDMxLCAweDg4LAo+ID4gPiArCQkJICAweDg4LCAweDg4LCAweDg4LCAweDg4LCAweDg4LCAw eDEzLCAweDg4LCAweDY0LAo+ID4gPiArCQkJICAweDY0LCAweDIwLCAweDg4LCAweDg4LCAweDg4 LCAweDg4LCAweDg4LCAweDg4LAo+ID4gPiArCQkJICAweDAyLCAweDg4LCAweDAwLCAweDAwLCAw eDAwLCAweDAwLCAweDAwLCAweDAwLAo+ID4gPiArCQkJICAweDAwLCAweDAwLCAweDAwLCAweDAw LCAweDAwLCAweDAwLCAweDAwKTsKPiA+ID4gKwo+ID4gPiArCS8qIFRoaXMgY29tbWFuZCBpcyB0 byBzZXQgYmFja3dhcmQgR0lQIHRpbWluZy4gKi8KPiA+ID4gKwlkc2lfZGNzX3dyaXRlX3NlcShk c2ksIFNUNzcwM19DTURfU0VUR0lQMiwKPiA+ID4gKwkJCSAgMHgwMiwgMHgyMSwgMHgwMCwgMHgw MCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwKPiA+ID4gKwkJCSAgMHgwMCwgMHgwMCwgMHgwMCwg MHgwMCwgMHgwMiwgMHg0NiwgMHgwMiwgMHg4OCwKPiA+ID4gKwkJCSAgMHg4OCwgMHg4OCwgMHg4 OCwgMHg4OCwgMHg4OCwgMHg2NCwgMHg4OCwgMHgxMywKPiA+ID4gKwkJCSAgMHg1NywgMHgxMywg MHg4OCwgMHg4OCwgMHg4OCwgMHg4OCwgMHg4OCwgMHg4OCwKPiA+ID4gKwkJCSAgMHg3NSwgMHg4 OCwgMHgyMywgMHgxNCwgMHgwMCwgMHgwMCwgMHgwMiwgMHgwMCwKPiA+ID4gKwkJCSAgMHgwMCwg MHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwKPiA+ID4gKwkJCSAgMHgw MCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMywgMHgwQSwKPiA+ID4gKwkJCSAg MHhBNSwgMHgwMCwgMHgwMCwgMHgwMCwgMHgwMCk7Cj4gPiA+ICsKPiA+ID4gKwkvKiBBZGp1c3Qg dGhlIGdhbW1hIGNoYXJhY3RlcmlzdGljcyBvZiB0aGUgcGFuZWwuICovCj4gPiA+ICsJZHNpX2Rj c193cml0ZV9zZXEoZHNpLCBTVDc3MDNfQ01EX1NFVEdBTU1BLAo+ID4gPiArCQkJICAweDAwLCAw eDA5LCAweDBELCAweDIzLCAweDI3LCAweDNDLCAweDQxLCAweDM1LAo+ID4gPiArCQkJICAweDA3 LCAweDBELCAweDBFLCAweDEyLCAweDEzLCAweDEwLCAweDEyLCAweDEyLAo+ID4gPiArCQkJICAw eDE4LCAweDAwLCAweDA5LCAweDBELCAweDIzLCAweDI3LCAweDNDLCAweDQxLAo+ID4gPiArCQkJ ICAweDM1LCAweDA3LCAweDBELCAweDBFLCAweDEyLCAweDEzLCAweDEwLCAweDEyLAo+ID4gPiAr CQkJICAweDEyLCAweDE4KTsKPiA+ID4gKwo+ID4gPiArCURSTV9ERVZfREVCVUdfRFJJVkVSKGRl diwgIlBhbmVsIGluaXQgc2VxdWVuY2UgZG9uZVxuIik7Cj4gPiA+ICsJcmV0dXJuIDA7Cj4gPiA+ ICt9Cj4gPiA+ICsKPiA+ID4gK3N0YXRpYyBpbnQgc3Q3NzAzX3JlYWRfaWQoc3RydWN0IHN0Nzcw MyAqY3R4KQo+ID4gPiArewo+ID4gPiArCXN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRzaSA9IHRv X21pcGlfZHNpX2RldmljZShjdHgtPmRldik7Cj4gPiA+ICsJdTggaWQxLCBpZDIsIGlkMzsKPiA+ ID4gKwlpbnQgcmV0Owo+ID4gPiArCj4gPiA+ICsJcmV0ID0gbWlwaV9kc2lfZGNzX3JlYWQoZHNp LCBTVDc3MDNfQ01EX1JESUQxLCAmaWQxLCAxKTsKPiA+ID4gKwlpZiAocmV0IDwgMCkgewo+ID4g PiArCQlEUk1fREVWX0VSUk9SKGN0eC0+ZGV2LCAiY291bGQgbm90IHJlYWQgSUQxXG4iKTsKPiA+ ID4gKwkJcmV0dXJuIHJldDsKPiA+ID4gKwl9Cj4gPiA+ICsKPiA+ID4gKwlyZXQgPSBtaXBpX2Rz aV9kY3NfcmVhZChkc2ksIFNUNzcwM19DTURfUkRJRDIsICZpZDIsIDEpOwo+ID4gPiArCWlmIChy ZXQgPCAwKSB7Cj4gPiA+ICsJCURSTV9ERVZfRVJST1IoY3R4LT5kZXYsICJjb3VsZCBub3QgcmVh ZCBJRDJcbiIpOwo+ID4gPiArCQlyZXR1cm4gcmV0Owo+ID4gPiArCX0KPiA+ID4gKwo+ID4gPiAr CXJldCA9IG1pcGlfZHNpX2Rjc19yZWFkKGRzaSwgU1Q3NzAzX0NNRF9SRElEMywgJmlkMywgMSk7 Cj4gPiA+ICsJaWYgKHJldCA8IDApIHsKPiA+ID4gKwkJRFJNX0RFVl9FUlJPUihjdHgtPmRldiwg ImNvdWxkIG5vdCByZWFkIElEM1xuIik7Cj4gPiA+ICsJCXJldHVybiByZXQ7Cj4gPiA+ICsJfQo+ ID4gPiArCj4gPiA+ICsJRFJNX0RFVl9JTkZPKGN0eC0+ZGV2LAo+ID4gPiArCQkgICAgICJtYW51 ZmFjdHVyZXI6ICUwMnggdmVyc2lvbjogJTAyeCBkcml2ZXI6ICUwMnhcbiIsCj4gPiA+ICsJCSAg ICAgaWQxLCBpZDIsIGlkMyk7Cj4gPiA+ICsKPiA+ID4gKwlyZXR1cm4gMDsKPiA+ID4gK30KPiA+ ID4gKwo+ID4gPiArc3RhdGljIGludCBzdDc3MDNfcHJlcGFyZShzdHJ1Y3QgZHJtX3BhbmVsICpw YW5lbCkKPiA+ID4gK3sKPiA+ID4gKwlzdHJ1Y3Qgc3Q3NzAzICpjdHggPSBwYW5lbF90b19zdDc3 MDMocGFuZWwpOwo+ID4gPiArCXN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRzaSA9IHRvX21pcGlf ZHNpX2RldmljZShjdHgtPmRldik7Cj4gPiA+ICsJaW50IHJldDsKPiA+ID4gKwo+ID4gPiArCWlm IChjdHgtPnByZXBhcmVkKQo+ID4gPiArCQlyZXR1cm4gMDsKPiA+ID4gKwo+ID4gPiArCWdwaW9k X3NldF92YWx1ZV9jYW5zbGVlcChjdHgtPnJlc2V0X2dwaW8sIDEpOwo+ID4gPiArCj4gPiA+ICsJ cmV0ID0gcmVndWxhdG9yX2J1bGtfZW5hYmxlKGN0eC0+ZGVzYy0+bnVtX3N1cHBsaWVzLCBjdHgt PnN1cHBsaWVzKTsKPiA+ID4gKwlpZiAocmV0KQo+ID4gPiArCQlyZXR1cm4gcmV0Owo+ID4gPiAr Cj4gPiA+ICsJLyogV2FpdCBmb3IgcmVndWxhdG9ycyB0byBzdGFiaWxpemUuICovCj4gPiA+ICsJ dXNsZWVwX3JhbmdlKDEwMDAwLCAyMDAwMCk7Cj4gPiA+ICsKPiA+ID4gKwlncGlvZF9zZXRfdmFs dWVfY2Fuc2xlZXAoY3R4LT5yZXNldF9ncGlvLCAwKTsKPiA+ID4gKwo+ID4gPiArCS8qIFRoZXJl IG5lZWRzIHRvIGJlIGF0IGxlYXN0IDE1bXMgcG9zdC1yZXNldCBkZWxheS4gKi8KPiA+ID4gKwl1 c2xlZXBfcmFuZ2UoMTUwMDAsIDIwMDAwKTsKPiA+ID4gKwo+ID4gPiArCXJldCA9IHN0NzcwM19y ZWFkX2lkKGN0eCk7Cj4gPiA+ICsJaWYgKHJldCA8IDApCj4gPiA+ICsJCWdvdG8gZXJyX3Bvd2Vy b2ZmOwo+ID4gPiArCj4gPiA+ICsJcmV0ID0gc3Q3NzAzX2luaXRfc2VxdWVuY2UoY3R4KTsKPiA+ ID4gKwlpZiAocmV0IDwgMCkgewo+ID4gPiArCQlEUk1fREVWX0VSUk9SKGN0eC0+ZGV2LAo+ID4g PiArCQkJICAgICAgIlBhbmVsIGluaXQgc2VxdWVuY2UgZmFpbGVkICglZClcbiIsIHJldCk7Cj4g PiA+ICsJCWdvdG8gZXJyX3Bvd2Vyb2ZmOwo+ID4gPiArCX0KPiA+ID4gKwo+ID4gPiArCXJldCA9 IG1pcGlfZHNpX2Rjc19leGl0X3NsZWVwX21vZGUoZHNpKTsKPiA+ID4gKwlpZiAocmV0IDwgMCkg ewo+ID4gPiArCQlEUk1fREVWX0VSUk9SKGN0eC0+ZGV2LAo+ID4gPiArCQkJICAgICAgIkZhaWxl ZCB0byBleGl0IHNsZWVwIG1vZGUgKCVkKVxuIiwgcmV0KTsKPiA+ID4gKwkJZ290byBlcnJfcG93 ZXJvZmY7Cj4gPiA+ICsJfQo+ID4gPiArCj4gPiA+ICsJbXNsZWVwKDEyMCk7Cj4gPiA+ICsKPiA+ ID4gKwlyZXQgPSBtaXBpX2RzaV9kY3Nfc2V0X2Rpc3BsYXlfb24oZHNpKTsKPiA+ID4gKwlpZiAo cmV0KSB7Cj4gPiA+ICsJCURSTV9ERVZfRVJST1IoY3R4LT5kZXYsCj4gPiA+ICsJCQkgICAgICAi RmFpbGVkIHRvIHR1cm4gb24gdGhlIGRpc3BsYXkgKCVkKVxuIiwgcmV0KTsKPiA+ID4gKwkJZ290 byBlcnJfcG93ZXJvZmY7Cj4gPiA+ICsJfQo+ID4gPiArCj4gPiA+ICsJY3R4LT5wcmVwYXJlZCA9 IHRydWU7Cj4gPiA+ICsKPiA+ID4gKwlyZXR1cm4gMDsKPiA+ID4gKwo+ID4gPiArZXJyX3Bvd2Vy b2ZmOgo+ID4gPiArCWdwaW9kX3NldF92YWx1ZV9jYW5zbGVlcChjdHgtPnJlc2V0X2dwaW8sIDEp Owo+ID4gPiArCXJlZ3VsYXRvcl9idWxrX2Rpc2FibGUoY3R4LT5kZXNjLT5udW1fc3VwcGxpZXMs IGN0eC0+c3VwcGxpZXMpOwo+ID4gPiArCXJldHVybiByZXQ7Cj4gPiA+ICt9Cj4gPiA+ICsKPiA+ ID4gK3N0YXRpYyBpbnQgc3Q3NzAzX2VuYWJsZShzdHJ1Y3QgZHJtX3BhbmVsICpwYW5lbCkKPiA+ ID4gK3sKPiA+ID4gKwkvKgo+ID4gPiArCSAqIEF2b2lkIGZsaWNrZXIgYnkgd2FpdGluZyBmb3Ig c2xpZ2h0bHkgbW9yZSB0aGFuIDEKPiA+ID4gKwkgKiBmcmFtZSdzIGludGVydmFsLgo+ID4gPiAr CSAqLwo+ID4gPiArCW1zbGVlcCg1MCk7Cj4gPiA+ICsKPiA+ID4gKwlyZXR1cm4gMDsKPiA+ID4g K30KPiA+ID4gKwo+ID4gPiArc3RhdGljIGludCBzdDc3MDNfdW5wcmVwYXJlKHN0cnVjdCBkcm1f cGFuZWwgKnBhbmVsKQo+ID4gPiArewo+ID4gPiArCXN0cnVjdCBzdDc3MDMgKmN0eCA9IHBhbmVs X3RvX3N0NzcwMyhwYW5lbCk7Cj4gPiA+ICsJc3RydWN0IG1pcGlfZHNpX2RldmljZSAqZHNpID0g dG9fbWlwaV9kc2lfZGV2aWNlKGN0eC0+ZGV2KTsKPiA+ID4gKwlpbnQgcmV0Owo+ID4gPiArCj4g PiA+ICsJaWYgKCFjdHgtPnByZXBhcmVkKQo+ID4gPiArCQlyZXR1cm4gMDsKPiA+ID4gKwo+ID4g PiArCXJldCA9IG1pcGlfZHNpX2Rjc19zZXRfZGlzcGxheV9vZmYoZHNpKTsKPiA+ID4gKwlpZiAo cmV0IDwgMCkKPiA+ID4gKwkJRFJNX0RFVl9FUlJPUihjdHgtPmRldiwKPiA+ID4gKwkJCSAgICAg ICJGYWlsZWQgdG8gdHVybiBvZmYgdGhlIGRpc3BsYXkgKCVkKVxuIiwgcmV0KTsKPiA+ID4gKwo+ ID4gPiArCXJldCA9IG1pcGlfZHNpX2Rjc19lbnRlcl9zbGVlcF9tb2RlKGRzaSk7Cj4gPiA+ICsJ aWYgKHJldCA8IDApCj4gPiA+ICsJCURSTV9ERVZfRVJST1IoY3R4LT5kZXYsCj4gPiA+ICsJCQkg ICAgICAiRmFpbGVkIHRvIGVudGVyIHNsZWVwIG1vZGUgKCVkKVxuIiwgcmV0KTsKPiA+ID4gKwo+ ID4gPiArCWdwaW9kX3NldF92YWx1ZV9jYW5zbGVlcChjdHgtPnJlc2V0X2dwaW8sIDEpOwo+ID4g PiArCXJlZ3VsYXRvcl9idWxrX2Rpc2FibGUoY3R4LT5kZXNjLT5udW1fc3VwcGxpZXMsIGN0eC0+ c3VwcGxpZXMpOwo+ID4gPiArCWN0eC0+cHJlcGFyZWQgPSBmYWxzZTsKPiA+ID4gKwo+ID4gPiAr CXJldHVybiAwOwo+ID4gPiArfQo+ID4gPiArCj4gPiA+ICtzdGF0aWMgaW50IHN0NzcwM19nZXRf bW9kZXMoc3RydWN0IGRybV9wYW5lbCAqcGFuZWwsCj4gPiA+ICsJCQkgICAgc3RydWN0IGRybV9j b25uZWN0b3IgKmNvbm5lY3RvcikKPiA+ID4gK3sKPiA+ID4gKwlzdHJ1Y3Qgc3Q3NzAzICpjdHgg PSBwYW5lbF90b19zdDc3MDMocGFuZWwpOwo+ID4gPiArCXN0cnVjdCBkcm1fZGlzcGxheV9tb2Rl ICptb2RlOwo+ID4gPiArCj4gPiA+ICsJbW9kZSA9IGRybV9tb2RlX2R1cGxpY2F0ZShjb25uZWN0 b3ItPmRldiwgY3R4LT5kZXNjLT5tb2RlKTsKPiA+ID4gKwlpZiAoIW1vZGUpIHsKPiA+ID4gKwkJ RFJNX0RFVl9FUlJPUihjdHgtPmRldiwgIkZhaWxlZCB0byBhZGQgbW9kZVxuIik7Cj4gPiA+ICsJ CXJldHVybiAtRU5PTUVNOwo+ID4gPiArCX0KPiA+ID4gKwo+ID4gPiArCWRybV9tb2RlX3NldF9u YW1lKG1vZGUpOwo+ID4gPiArCj4gPiA+ICsJY29ubmVjdG9yLT5kaXNwbGF5X2luZm8ud2lkdGhf bW0gPSBtb2RlLT53aWR0aF9tbTsKPiA+ID4gKwljb25uZWN0b3ItPmRpc3BsYXlfaW5mby5oZWln aHRfbW0gPSBtb2RlLT5oZWlnaHRfbW07Cj4gPiA+ICsJZHJtX21vZGVfcHJvYmVkX2FkZChjb25u ZWN0b3IsIG1vZGUpOwo+ID4gPiArCj4gPiA+ICsJcmV0dXJuIDE7Cj4gPiA+ICt9Cj4gPiA+ICsK PiA+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgZHJtX3BhbmVsX2Z1bmNzIHN0NzcwM19kcm1fZnVu Y3MgPSB7Cj4gPiA+ICsJLnByZXBhcmUgICA9IHN0NzcwM19wcmVwYXJlLAo+ID4gPiArCS5lbmFi bGUgICAgPSBzdDc3MDNfZW5hYmxlLAo+ID4gPiArCS51bnByZXBhcmUgPSBzdDc3MDNfdW5wcmVw YXJlLAo+ID4gPiArCS5nZXRfbW9kZXMgPSBzdDc3MDNfZ2V0X21vZGVzLAo+ID4gPiArfTsKPiA+ ID4gKwo+ID4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBkcm1fZGlzcGxheV9tb2RlIHhiZDU5OV9t b2RlID0gewo+ID4gPiArCS5oZGlzcGxheSAgICA9IDcyMCwKPiA+ID4gKwkuaHN5bmNfc3RhcnQg PSA3MjAgKyA0MCwKPiA+ID4gKwkuaHN5bmNfZW5kICAgPSA3MjAgKyA0MCArIDQwLAo+ID4gPiAr CS5odG90YWwJICAgICA9IDcyMCArIDQwICsgNDAgKyA0MCwKPiA+ID4gKwkudmRpc3BsYXkgICAg PSAxNDQwLAo+ID4gPiArCS52c3luY19zdGFydCA9IDE0NDAgKyAxOCwKPiA+ID4gKwkudnN5bmNf ZW5kICAgPSAxNDQwICsgMTggKyAxMCwKPiA+ID4gKwkudnRvdGFsCSAgICAgPSAxNDQwICsgMTgg KyAxMCArIDE3LAo+ID4gPiArCS52cmVmcmVzaCAgICA9IDYwLAo+ID4gPiArCS5jbG9jawkgICAg ID0gNjkwMDAsCj4gPiA+ICsJLmZsYWdzCSAgICAgPSBEUk1fTU9ERV9GTEFHX05IU1lOQyB8IERS TV9NT0RFX0ZMQUdfTlZTWU5DLAo+ID4gPiArCj4gPiA+ICsJLndpZHRoX21tICAgID0gNjgsCj4g PiA+ICsJLmhlaWdodF9tbSAgID0gMTM2LAo+ID4gPiArCS50eXBlICAgICAgICA9IERSTV9NT0RF X1RZUEVfRFJJVkVSIHwgRFJNX01PREVfVFlQRV9QUkVGRVJSRUQsCj4gPiA+ICt9Owo+ID4gPiAr Cj4gPiA+ICtzdGF0aWMgY29uc3QgY2hhciAqIGNvbnN0IHhiZDU5OV9zdXBwbHlfbmFtZXNbXSA9 IHsKPiA+ID4gKwkiaW92Y2MiLAo+ID4gPiArCSJ2Y2MiLAo+ID4gPiArfTsKPiA+ID4gKwo+ID4g PiArc3RhdGljIGNvbnN0IHN0cnVjdCBzdDc3MDNfcGFuZWxfZGVzYyB4YmQ1OTlfZGVzYyA9IHsK PiA+ID4gKwkubW9kZSA9ICZ4YmQ1OTlfbW9kZSwKPiA+ID4gKwkubGFuZXMgPSA0LAo+ID4gPiAr CS5mbGFncyA9IE1JUElfRFNJX01PREVfVklERU8gfCBNSVBJX0RTSV9NT0RFX1ZJREVPX1NZTkNf UFVMU0UsCj4gPiA+ICsJLmZvcm1hdCA9IE1JUElfRFNJX0ZNVF9SR0I4ODgsCj4gPiA+ICsJLnN1 cHBseV9uYW1lcyA9IHhiZDU5OV9zdXBwbHlfbmFtZXMsCj4gPiA+ICsJLm51bV9zdXBwbGllcyA9 IEFSUkFZX1NJWkUoeGJkNTk5X3N1cHBseV9uYW1lcyksCj4gPiA+ICt9Owo+ID4gPiArCj4gPiA+ ICtzdGF0aWMgaW50IHN0NzcwM19wcm9iZShzdHJ1Y3QgbWlwaV9kc2lfZGV2aWNlICpkc2kpCj4g PiA+ICt7Cj4gPiA+ICsJY29uc3Qgc3RydWN0IHN0NzcwM19wYW5lbF9kZXNjICpkZXNjOwo+ID4g PiArCXN0cnVjdCBkZXZpY2UgKmRldiA9ICZkc2ktPmRldjsKPiA+ID4gKwlzdHJ1Y3Qgc3Q3NzAz ICpjdHg7Cj4gPiA+ICsJaW50IGksIHJldDsKPiA+ID4gKwo+ID4gPiArCWN0eCA9IGRldm1fa3ph bGxvYyhkZXYsIHNpemVvZigqY3R4KSwgR0ZQX0tFUk5FTCk7Cj4gPiA+ICsJaWYgKCFjdHgpCj4g PiA+ICsJCXJldHVybiAtRU5PTUVNOwo+ID4gPiArCj4gPiA+ICsJY3R4LT5kZXYgPSBkZXY7Cj4g PiA+ICsJY3R4LT5kZXNjID0gZGVzYyA9IG9mX2RldmljZV9nZXRfbWF0Y2hfZGF0YShkZXYpOwo+ ID4gPiArCj4gPiA+ICsJZHNpLT5tb2RlX2ZsYWdzID0gZGVzYy0+ZmxhZ3M7Cj4gPiA+ICsJZHNp LT5mb3JtYXQgPSBkZXNjLT5mb3JtYXQ7Cj4gPiA+ICsJZHNpLT5sYW5lcyA9IGRlc2MtPmxhbmVz Owo+ID4gPiArCj4gPiA+ICsJY3R4LT5zdXBwbGllcyA9IGRldm1fa2NhbGxvYygmZHNpLT5kZXYs IGRlc2MtPm51bV9zdXBwbGllcywKPiA+ID4gKwkJCQkJc2l6ZW9mKCpjdHgtPnN1cHBsaWVzKSwK PiA+ID4gKwkJCQkJR0ZQX0tFUk5FTCk7Cj4gPiA+ICsJaWYgKCFjdHgtPnN1cHBsaWVzKQo+ID4g PiArCQlyZXR1cm4gLUVOT01FTTsKPiA+ID4gKwo+ID4gPiArCWZvciAoaSA9IDA7IGkgPCBkZXNj LT5udW1fc3VwcGxpZXM7IGkrKykKPiA+ID4gKwkJY3R4LT5zdXBwbGllc1tpXS5zdXBwbHkgPSBk ZXNjLT5zdXBwbHlfbmFtZXNbaV07Cj4gPiA+ICsKPiA+ID4gKwlyZXQgPSBkZXZtX3JlZ3VsYXRv cl9idWxrX2dldCgmZHNpLT5kZXYsIGRlc2MtPm51bV9zdXBwbGllcywKPiA+ID4gKwkJCQkgICAg ICBjdHgtPnN1cHBsaWVzKTsKPiA+ID4gKwlpZiAocmV0IDwgMCkKPiA+ID4gKwkJcmV0dXJuIHJl dDsKPiA+ID4gKwo+ID4gPiArCWN0eC0+cmVzZXRfZ3BpbyA9IGRldm1fZ3Bpb2RfZ2V0KGRldiwg InJlc2V0IiwgR1BJT0RfT1VUX0xPVyk7Cj4gPiA+ICsJaWYgKElTX0VSUihjdHgtPnJlc2V0X2dw aW8pKSB7Cj4gPiA+ICsJCURSTV9ERVZfRVJST1IoZGV2LCAiQ2FuJ3QgZ2V0IHJlc2V0IGdwaW9c biIpOwo+ID4gPiArCQlyZXR1cm4gUFRSX0VSUihjdHgtPnJlc2V0X2dwaW8pOwo+ID4gPiArCX0K PiA+ID4gKwo+ID4gPiArCW1pcGlfZHNpX3NldF9kcnZkYXRhKGRzaSwgY3R4KTsKPiA+ID4gKwo+ ID4gPiArCWRybV9wYW5lbF9pbml0KCZjdHgtPnBhbmVsLCAmZHNpLT5kZXYsICZzdDc3MDNfZHJt X2Z1bmNzLAo+ID4gPiArCQkgICAgICAgRFJNX01PREVfQ09OTkVDVE9SX0RTSSk7Cj4gPiA+ICsK PiA+ID4gKwlyZXQgPSBkcm1fcGFuZWxfb2ZfYmFja2xpZ2h0KCZjdHgtPnBhbmVsKTsKPiA+ID4g KwlpZiAocmV0KQo+ID4gPiArCQlyZXR1cm4gcmV0Owo+ID4gPiArCj4gPiA+ICsJZHJtX3BhbmVs X2FkZCgmY3R4LT5wYW5lbCk7Cj4gPiA+ICsKPiA+ID4gKwlyZXQgPSBtaXBpX2RzaV9hdHRhY2go ZHNpKTsKPiA+ID4gKwlpZiAocmV0IDwgMCkgewo+ID4gPiArCQlkcm1fcGFuZWxfcmVtb3ZlKCZj dHgtPnBhbmVsKTsKPiA+ID4gKwkJcmV0dXJuIHJldDsKPiA+ID4gKwl9Cj4gPiA+ICsKPiA+ID4g KwlyZXR1cm4gMDsKPiA+ID4gK30KPiA+ID4gKwo+ID4gPiArc3RhdGljIHZvaWQgc3Q3NzAzX3No dXRkb3duKHN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRzaSkKPiA+ID4gK3sKPiA+ID4gKwlzdHJ1 Y3Qgc3Q3NzAzICpjdHggPSBtaXBpX2RzaV9nZXRfZHJ2ZGF0YShkc2kpOwo+ID4gPiArCWludCBy ZXQ7Cj4gPiA+ICsKPiA+ID4gKwlyZXQgPSBkcm1fcGFuZWxfdW5wcmVwYXJlKCZjdHgtPnBhbmVs KTsKPiA+ID4gKwlpZiAocmV0IDwgMCkKPiA+ID4gKwkJRFJNX0RFVl9FUlJPUigmZHNpLT5kZXYs Cj4gPiA+ICsJCQkgICAgICAiRmFpbGVkIHRvIHVucHJlcGFyZSBwYW5lbCAoJWQpXG4iLCByZXQp Owo+ID4gPiArfQo+ID4gPiArCj4gPiA+ICtzdGF0aWMgaW50IHN0NzcwM19yZW1vdmUoc3RydWN0 IG1pcGlfZHNpX2RldmljZSAqZHNpKQo+ID4gPiArewo+ID4gPiArCXN0cnVjdCBzdDc3MDMgKmN0 eCA9IG1pcGlfZHNpX2dldF9kcnZkYXRhKGRzaSk7Cj4gPiA+ICsJaW50IHJldDsKPiA+ID4gKwo+ ID4gPiArCXN0NzcwM19zaHV0ZG93bihkc2kpOwo+ID4gPiArCj4gPiA+ICsJcmV0ID0gbWlwaV9k c2lfZGV0YWNoKGRzaSk7Cj4gPiA+ICsJaWYgKHJldCA8IDApCj4gPiA+ICsJCURSTV9ERVZfRVJS T1IoJmRzaS0+ZGV2LAo+ID4gPiArCQkJICAgICAgIkZhaWxlZCB0byBkZXRhY2ggZnJvbSBEU0kg aG9zdCAoJWQpXG4iLCByZXQpOwo+ID4gPiArCj4gPiA+ICsJZHJtX3BhbmVsX3JlbW92ZSgmY3R4 LT5wYW5lbCk7Cj4gPiA+ICsKPiA+ID4gKwlyZXR1cm4gMDsKPiA+ID4gK30KPiA+ID4gKwo+ID4g PiArc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQgc3Q3NzAzX29mX21hdGNoW10gPSB7 Cj4gPiA+ICsJeyAuY29tcGF0aWJsZSA9ICJ4aW5nYmFuZ2RhLHhiZDU5OSIsIC5kYXRhID0gJnhi ZDU5OV9kZXNjIH0sCj4gPiA+ICsJeyAvKiBzZW50aW5lbCAqLyB9Cj4gPiA+ICt9Owo+ID4gPiAr TU9EVUxFX0RFVklDRV9UQUJMRShvZiwgc3Q3NzAzX29mX21hdGNoKTsKPiA+ID4gKwo+ID4gPiAr c3RhdGljIHN0cnVjdCBtaXBpX2RzaV9kcml2ZXIgc3Q3NzAzX2RyaXZlciA9IHsKPiA+ID4gKwku cHJvYmUJPSBzdDc3MDNfcHJvYmUsCj4gPiA+ICsJLnJlbW92ZSA9IHN0NzcwM19yZW1vdmUsCj4g PiA+ICsJLnNodXRkb3duID0gc3Q3NzAzX3NodXRkb3duLAo+ID4gPiArCS5kcml2ZXIgPSB7Cj4g PiA+ICsJCS5uYW1lID0gInN0NzcwMyIsCj4gPiA+ICsJCS5vZl9tYXRjaF90YWJsZSA9IHN0Nzcw M19vZl9tYXRjaCwKPiA+ID4gKwl9LAo+ID4gPiArfTsKPiA+ID4gK21vZHVsZV9taXBpX2RzaV9k cml2ZXIoc3Q3NzAzX2RyaXZlcik7Cj4gPiA+ICsKPiA+ID4gK01PRFVMRV9BVVRIT1IoIkljZW5v d3kgWmhlbmcgPGljZW5vd3lAYW9zYy5pbz4iKTsKPiA+ID4gK01PRFVMRV9ERVNDUklQVElPTigi RFJNIGRyaXZlciBmb3IgU2l0cm9uaXggU1Q3NzAzIE1JUEkgRFNJIHBhbmVsIik7Cj4gPiA+ICtN T0RVTEVfTElDRU5TRSgiR1BMIHYyIik7Cj4gPiA+IC0tIAo+ID4gPiAyLjI3LjAKPiA+ID4gCj4g PiA+IF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCj4gPiA+ IGRyaS1kZXZlbCBtYWlsaW5nIGxpc3QKPiA+ID4gZHJpLWRldmVsQGxpc3RzLmZyZWVkZXNrdG9w Lm9yZwo+ID4gPiBodHRwczovL2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9tYWlsbWFuL2xpc3RpbmZv L2RyaS1kZXZlbAo+IF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fCj4gZHJpLWRldmVsIG1haWxpbmcgbGlzdAo+IGRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3Rv cC5vcmcKPiBodHRwczovL2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2Ry aS1kZXZlbApfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpk cmktZGV2ZWwgbWFpbGluZyBsaXN0CmRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3RvcC5vcmcKaHR0 cHM6Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcvbWFpbG1hbi9saXN0aW5mby9kcmktZGV2ZWwK