From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753106AbeDFNYu (ORCPT ); Fri, 6 Apr 2018 09:24:50 -0400 Received: from galahad.ideasonboard.com ([185.26.127.97]:34925 "EHLO galahad.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752517AbeDFNYr (ORCPT ); Fri, 6 Apr 2018 09:24:47 -0400 From: Laurent Pinchart To: Jacopo Mondi Cc: architt@codeaurora.org, a.hajda@samsung.com, airlied@linux.ie, vladimir_zapolskiy@mentor.com, horms@verge.net.au, magnus.damm@gmail.com, geert@linux-m68k.org, niklas.soderlund@ragnatech.se, sergei.shtylyov@cogentembedded.com, robh+dt@kernel.org, mark.rutland@arm.com, dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v7 2/2] drm: bridge: Add thc63lvd1024 LVDS decoder driver Date: Fri, 06 Apr 2018 16:24:44 +0300 Message-ID: <3367141.XOMI5ldQnc@avalon> Organization: Ideas on Board Oy In-Reply-To: <1523018517-24121-3-git-send-email-jacopo+renesas@jmondi.org> References: <1523018517-24121-1-git-send-email-jacopo+renesas@jmondi.org> <1523018517-24121-3-git-send-email-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by mail.home.local id w36DOsYQ012105 Hi Jacopo, Thank you for the patch. On Friday, 6 April 2018 15:41:57 EEST Jacopo Mondi wrote: > Add DRM bridge driver for Thine THC63LVD1024 LVDS to digital parallel > output converter. > > Signed-off-by: Jacopo Mondi > Reviewed-by: Andrzej Hajda > Reviewed-by: Niklas Söderlund > --- > drivers/gpu/drm/bridge/Kconfig | 6 + > drivers/gpu/drm/bridge/Makefile | 1 + > drivers/gpu/drm/bridge/thc63lvd1024.c | 212 +++++++++++++++++++++++++++++++ > 3 files changed, 219 insertions(+) > create mode 100644 drivers/gpu/drm/bridge/thc63lvd1024.c > > diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig > index 3aa65bd..42c9c2d 100644 > --- a/drivers/gpu/drm/bridge/Kconfig > +++ b/drivers/gpu/drm/bridge/Kconfig > @@ -93,6 +93,12 @@ config DRM_SII9234 > It is an I2C driver, that detects connection of MHL bridge > and starts encapsulation of HDMI signal. > > +config DRM_THINE_THC63LVD1024 > + tristate "Thine THC63LVD1024 LVDS decoder bridge" > + depends on OF > + ---help--- > + Thine THC63LVD1024 LVDS/parallel converter driver. > + > config DRM_TOSHIBA_TC358767 > tristate "Toshiba TC358767 eDP bridge" > depends on OF > diff --git a/drivers/gpu/drm/bridge/Makefile > b/drivers/gpu/drm/bridge/Makefile index 373eb28..fd90b16 100644 > --- a/drivers/gpu/drm/bridge/Makefile > +++ b/drivers/gpu/drm/bridge/Makefile > @@ -8,6 +8,7 @@ obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o > obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o > obj-$(CONFIG_DRM_SII902X) += sii902x.o > obj-$(CONFIG_DRM_SII9234) += sii9234.o > +obj-$(CONFIG_DRM_THINE_THC63LVD1024) += thc63lvd1024.o > obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o > obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/ > obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/ > diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c > b/drivers/gpu/drm/bridge/thc63lvd1024.c new file mode 100644 > index 0000000..c8fad9c > --- /dev/null > +++ b/drivers/gpu/drm/bridge/thc63lvd1024.c > @@ -0,0 +1,212 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * THC63LVD1024 LVDS to parallel data DRM bridge driver. > + * > + * Copyright (C) 2018 Jacopo Mondi > + */ > + > +#include > +#include > +#include > + > +#include > +#include > +#include You should include slab.h as you're using devm_kzalloc(). > + > +enum thc63_ports { > + THC63_LVDS_IN0, > + THC63_LVDS_IN1, > + THC63_RGB_OUT0, > + THC63_RGB_OUT1, > +}; > + > +struct thc63_dev { > + struct device *dev; > + > + struct regulator *vcc; > + > + struct gpio_desc *pdwn; pwdn ? > + struct gpio_desc *oe; > + > + struct drm_bridge bridge; > + struct drm_bridge *next; > +}; > + > +static inline struct thc63_dev *to_thc63(struct drm_bridge *bridge) > +{ > + return container_of(bridge, struct thc63_dev, bridge); > +} > + > +static int thc63_attach(struct drm_bridge *bridge) > +{ > + struct thc63_dev *thc63 = to_thc63(bridge); > + > + return drm_bridge_attach(bridge->encoder, thc63->next, bridge); > +} > + > +static void thc63_enable(struct drm_bridge *bridge) > +{ > + struct thc63_dev *thc63 = to_thc63(bridge); > + int ret; > + > + ret = regulator_enable(thc63->vcc); > + if (ret) { > + dev_err(thc63->dev, > + "Failed to enable regulator \"vcc\": %d\n", ret); > + return; > + } > + > + if (thc63->pdwn) > + gpiod_set_value(thc63->pdwn, 0); > + > + if (thc63->oe) > + gpiod_set_value(thc63->oe, 1); You don't need to check the gpio_desc pointers first, gpiod_set_value() is a no-op if the pointer is NULL. > +} > + > +static void thc63_disable(struct drm_bridge *bridge) > +{ > + struct thc63_dev *thc63 = to_thc63(bridge); > + int ret; > + > + if (thc63->oe) > + gpiod_set_value(thc63->oe, 0); > + > + if (thc63->pdwn) > + gpiod_set_value(thc63->pdwn, 1); Same here. > + ret = regulator_disable(thc63->vcc); > + if (ret) > + dev_err(thc63->dev, > + "Failed to disable regulator \"vcc\": %d\n", ret); > +} > + > +static const struct drm_bridge_funcs thc63_bridge_func = { > + .attach = thc63_attach, > + .enable = thc63_enable, > + .disable = thc63_disable, > +}; > + > +static int thc63_parse_dt(struct thc63_dev *thc63) > +{ > + struct device_node *thc63_out; > + struct device_node *remote; > + > + thc63_out = of_graph_get_endpoint_by_regs(thc63->dev->of_node, > + THC63_RGB_OUT0, -1); > + if (!thc63_out) { > + dev_err(thc63->dev, "Missing endpoint in port@%u\n", > + THC63_RGB_OUT0); > + return -ENODEV; > + } > + > + remote = of_graph_get_remote_port_parent(thc63_out); > + of_node_put(thc63_out); > + if (!remote) { > + dev_err(thc63->dev, "Endpoint in port@%u unconnected\n", > + THC63_RGB_OUT0); > + return -ENODEV; > + } > + > + if (!of_device_is_available(remote)) { > + dev_err(thc63->dev, "port@%u remote endpoint is disabled\n", > + THC63_RGB_OUT0); > + of_node_put(remote); > + return -ENODEV; > + } > + > + thc63->next = of_drm_find_bridge(remote); > + if (!thc63->next) { > + of_node_put(remote); > + return -EPROBE_DEFER; > + } > + > + return 0; > +} > + > +static int thc63_gpio_init(struct thc63_dev *thc63) > +{ > + thc63->oe = devm_gpiod_get_optional(thc63->dev, "enable", GPIOD_OUT_LOW); If you agree with my comment regarding the DT bindings, this should be "oe". > + if (IS_ERR(thc63->oe)) { > + dev_err(thc63->dev, "Unable to get \"enable-gpios\": %ld\n", > + PTR_ERR(thc63->oe)); And the message should be update here too. With those small issues fixed, Reviewed-by: Laurent Pinchart > + return PTR_ERR(thc63->oe); > + } > + > + thc63->pdwn = devm_gpiod_get_optional(thc63->dev, "powerdown", > + GPIOD_OUT_HIGH); > + if (IS_ERR(thc63->pdwn)) { > + dev_err(thc63->dev, "Unable to get \"powerdown-gpios\": %ld\n", > + PTR_ERR(thc63->pdwn)); > + return PTR_ERR(thc63->pdwn); > + } > + > + return 0; > +} > + > +static int thc63_probe(struct platform_device *pdev) > +{ > + struct thc63_dev *thc63; > + int ret; > + > + thc63 = devm_kzalloc(&pdev->dev, sizeof(*thc63), GFP_KERNEL); > + if (!thc63) > + return -ENOMEM; > + > + thc63->dev = &pdev->dev; > + platform_set_drvdata(pdev, thc63); > + > + thc63->vcc = devm_regulator_get(thc63->dev, "vcc"); > + if (IS_ERR(thc63->vcc)) { > + if (PTR_ERR(thc63->vcc) == -EPROBE_DEFER) > + return -EPROBE_DEFER; > + > + dev_err(thc63->dev, "Unable to get \"vcc\" supply: %ld\n", > + PTR_ERR(thc63->vcc)); > + return PTR_ERR(thc63->vcc); > + } > + > + ret = thc63_gpio_init(thc63); > + if (ret) > + return ret; > + > + ret = thc63_parse_dt(thc63); > + if (ret) > + return ret; > + > + thc63->bridge.driver_private = thc63; > + thc63->bridge.of_node = pdev->dev.of_node; > + thc63->bridge.funcs = &thc63_bridge_func; > + > + drm_bridge_add(&thc63->bridge); > + > + return 0; > +} > + > +static int thc63_remove(struct platform_device *pdev) > +{ > + struct thc63_dev *thc63 = platform_get_drvdata(pdev); > + > + drm_bridge_remove(&thc63->bridge); > + > + return 0; > +} > + > +static const struct of_device_id thc63_match[] = { > + { .compatible = "thine,thc63lvd1024", }, > + { }, > +}; > +MODULE_DEVICE_TABLE(of, thc63_match); > + > +static struct platform_driver thc63_driver = { > + .probe = thc63_probe, > + .remove = thc63_remove, > + .driver = { > + .name = "thc63lvd1024", > + .of_match_table = thc63_match, > + }, > +}; > +module_platform_driver(thc63_driver); > + > +MODULE_AUTHOR("Jacopo Mondi "); > +MODULE_DESCRIPTION("Thine THC63LVD1024 LVDS decoder DRM bridge driver"); > +MODULE_LICENSE("GPL v2"); -- Regards, Laurent Pinchart From mboxrd@z Thu Jan 1 00:00:00 1970 From: Laurent Pinchart Subject: Re: [PATCH v7 2/2] drm: bridge: Add thc63lvd1024 LVDS decoder driver Date: Fri, 06 Apr 2018 16:24:44 +0300 Message-ID: <3367141.XOMI5ldQnc@avalon> References: <1523018517-24121-1-git-send-email-jacopo+renesas@jmondi.org> <1523018517-24121-3-git-send-email-jacopo+renesas@jmondi.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <1523018517-24121-3-git-send-email-jacopo+renesas@jmondi.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Jacopo Mondi Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, sergei.shtylyov@cogentembedded.com, airlied@linux.ie, magnus.damm@gmail.com, linux-kernel@vger.kernel.org, robh+dt@kernel.org, linux-renesas-soc@vger.kernel.org, horms@verge.net.au, geert@linux-m68k.org, dri-devel@lists.freedesktop.org, niklas.soderlund@ragnatech.se, vladimir_zapolskiy@mentor.com List-Id: devicetree@vger.kernel.org SGkgSmFjb3BvLAoKVGhhbmsgeW91IGZvciB0aGUgcGF0Y2guCgpPbiBGcmlkYXksIDYgQXByaWwg MjAxOCAxNTo0MTo1NyBFRVNUIEphY29wbyBNb25kaSB3cm90ZToKPiBBZGQgRFJNIGJyaWRnZSBk cml2ZXIgZm9yIFRoaW5lIFRIQzYzTFZEMTAyNCBMVkRTIHRvIGRpZ2l0YWwgcGFyYWxsZWwKPiBv dXRwdXQgY29udmVydGVyLgo+IAo+IFNpZ25lZC1vZmYtYnk6IEphY29wbyBNb25kaSA8amFjb3Bv K3JlbmVzYXNAam1vbmRpLm9yZz4KPiBSZXZpZXdlZC1ieTogQW5kcnplaiBIYWpkYSA8YS5oYWpk YUBzYW1zdW5nLmNvbT4KPiBSZXZpZXdlZC1ieTogTmlrbGFzIFPDtmRlcmx1bmQgPG5pa2xhcy5z b2Rlcmx1bmQrcmVuZXNhc0ByYWduYXRlY2guc2U+Cj4gLS0tCj4gIGRyaXZlcnMvZ3B1L2RybS9i cmlkZ2UvS2NvbmZpZyAgICAgICAgfCAgIDYgKwo+ICBkcml2ZXJzL2dwdS9kcm0vYnJpZGdlL01h a2VmaWxlICAgICAgIHwgICAxICsKPiAgZHJpdmVycy9ncHUvZHJtL2JyaWRnZS90aGM2M2x2ZDEw MjQuYyB8IDIxMiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCj4gIDMgZmlsZXMgY2hh bmdlZCwgMjE5IGluc2VydGlvbnMoKykKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvZ3B1 L2RybS9icmlkZ2UvdGhjNjNsdmQxMDI0LmMKPiAKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUv ZHJtL2JyaWRnZS9LY29uZmlnIGIvZHJpdmVycy9ncHUvZHJtL2JyaWRnZS9LY29uZmlnCj4gaW5k ZXggM2FhNjViZC4uNDJjOWMyZCAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL2dwdS9kcm0vYnJpZGdl L0tjb25maWcKPiArKysgYi9kcml2ZXJzL2dwdS9kcm0vYnJpZGdlL0tjb25maWcKPiBAQCAtOTMs NiArOTMsMTIgQEAgY29uZmlnIERSTV9TSUk5MjM0Cj4gIAkgIEl0IGlzIGFuIEkyQyBkcml2ZXIs IHRoYXQgZGV0ZWN0cyBjb25uZWN0aW9uIG9mIE1ITCBicmlkZ2UKPiAgCSAgYW5kIHN0YXJ0cyBl bmNhcHN1bGF0aW9uIG9mIEhETUkgc2lnbmFsLgo+IAo+ICtjb25maWcgRFJNX1RISU5FX1RIQzYz TFZEMTAyNAo+ICsJdHJpc3RhdGUgIlRoaW5lIFRIQzYzTFZEMTAyNCBMVkRTIGRlY29kZXIgYnJp ZGdlIgo+ICsJZGVwZW5kcyBvbiBPRgo+ICsJLS0taGVscC0tLQo+ICsJICBUaGluZSBUSEM2M0xW RDEwMjQgTFZEUy9wYXJhbGxlbCBjb252ZXJ0ZXIgZHJpdmVyLgo+ICsKPiAgY29uZmlnIERSTV9U T1NISUJBX1RDMzU4NzY3Cj4gIAl0cmlzdGF0ZSAiVG9zaGliYSBUQzM1ODc2NyBlRFAgYnJpZGdl Igo+ICAJZGVwZW5kcyBvbiBPRgo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vYnJpZGdl L01ha2VmaWxlCj4gYi9kcml2ZXJzL2dwdS9kcm0vYnJpZGdlL01ha2VmaWxlIGluZGV4IDM3M2Vi MjguLmZkOTBiMTYgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy9ncHUvZHJtL2JyaWRnZS9NYWtlZmls ZQo+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9icmlkZ2UvTWFrZWZpbGUKPiBAQCAtOCw2ICs4LDcg QEAgb2JqLSQoQ09ORklHX0RSTV9QQVJBREVfUFM4NjIyKSArPSBwYXJhZGUtcHM4NjIyLm8KPiAg b2JqLSQoQ09ORklHX0RSTV9TSUxfU0lJODYyMCkgKz0gc2lsLXNpaTg2MjAubwo+ICBvYmotJChD T05GSUdfRFJNX1NJSTkwMlgpICs9IHNpaTkwMngubwo+ICBvYmotJChDT05GSUdfRFJNX1NJSTky MzQpICs9IHNpaTkyMzQubwo+ICtvYmotJChDT05GSUdfRFJNX1RISU5FX1RIQzYzTFZEMTAyNCkg Kz0gdGhjNjNsdmQxMDI0Lm8KPiAgb2JqLSQoQ09ORklHX0RSTV9UT1NISUJBX1RDMzU4NzY3KSAr PSB0YzM1ODc2Ny5vCj4gIG9iai0kKENPTkZJR19EUk1fQU5BTE9HSVhfRFApICs9IGFuYWxvZ2l4 Lwo+ICBvYmotJChDT05GSUdfRFJNX0kyQ19BRFY3NTExKSArPSBhZHY3NTExLwo+IGRpZmYgLS1n aXQgYS9kcml2ZXJzL2dwdS9kcm0vYnJpZGdlL3RoYzYzbHZkMTAyNC5jCj4gYi9kcml2ZXJzL2dw dS9kcm0vYnJpZGdlL3RoYzYzbHZkMTAyNC5jIG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXgg MDAwMDAwMC4uYzhmYWQ5Ywo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL2dwdS9kcm0v YnJpZGdlL3RoYzYzbHZkMTAyNC5jCj4gQEAgLTAsMCArMSwyMTIgQEAKPiArLy8gU1BEWC1MaWNl bnNlLUlkZW50aWZpZXI6IEdQTC0yLjAKPiArLyoKPiArICogVEhDNjNMVkQxMDI0IExWRFMgdG8g cGFyYWxsZWwgZGF0YSBEUk0gYnJpZGdlIGRyaXZlci4KPiArICoKPiArICogQ29weXJpZ2h0IChD KSAyMDE4IEphY29wbyBNb25kaSA8amFjb3BvK3JlbmVzYXNAam1vbmRpLm9yZz4KPiArICovCj4g Kwo+ICsjaW5jbHVkZSA8ZHJtL2RybVAuaD4KPiArI2luY2x1ZGUgPGRybS9kcm1fYnJpZGdlLmg+ Cj4gKyNpbmNsdWRlIDxkcm0vZHJtX3BhbmVsLmg+Cj4gKwo+ICsjaW5jbHVkZSA8bGludXgvZ3Bp by9jb25zdW1lci5oPgo+ICsjaW5jbHVkZSA8bGludXgvb2ZfZ3JhcGguaD4KPiArI2luY2x1ZGUg PGxpbnV4L3JlZ3VsYXRvci9jb25zdW1lci5oPgoKWW91IHNob3VsZCBpbmNsdWRlIHNsYWIuaCBh cyB5b3UncmUgdXNpbmcgZGV2bV9remFsbG9jKCkuCgo+ICsKPiArZW51bSB0aGM2M19wb3J0cyB7 Cj4gKwlUSEM2M19MVkRTX0lOMCwKPiArCVRIQzYzX0xWRFNfSU4xLAo+ICsJVEhDNjNfUkdCX09V VDAsCj4gKwlUSEM2M19SR0JfT1VUMSwKPiArfTsKPiArCj4gK3N0cnVjdCB0aGM2M19kZXYgewo+ ICsJc3RydWN0IGRldmljZSAqZGV2Owo+ICsKPiArCXN0cnVjdCByZWd1bGF0b3IgKnZjYzsKPiAr Cj4gKwlzdHJ1Y3QgZ3Bpb19kZXNjICpwZHduOwoKcHdkbiA/Cgo+ICsJc3RydWN0IGdwaW9fZGVz YyAqb2U7Cj4gKwo+ICsJc3RydWN0IGRybV9icmlkZ2UgYnJpZGdlOwo+ICsJc3RydWN0IGRybV9i cmlkZ2UgKm5leHQ7Cj4gK307Cj4gKwo+ICtzdGF0aWMgaW5saW5lIHN0cnVjdCB0aGM2M19kZXYg KnRvX3RoYzYzKHN0cnVjdCBkcm1fYnJpZGdlICpicmlkZ2UpCj4gK3sKPiArCXJldHVybiBjb250 YWluZXJfb2YoYnJpZGdlLCBzdHJ1Y3QgdGhjNjNfZGV2LCBicmlkZ2UpOwo+ICt9Cj4gKwo+ICtz dGF0aWMgaW50IHRoYzYzX2F0dGFjaChzdHJ1Y3QgZHJtX2JyaWRnZSAqYnJpZGdlKQo+ICt7Cj4g KwlzdHJ1Y3QgdGhjNjNfZGV2ICp0aGM2MyA9IHRvX3RoYzYzKGJyaWRnZSk7Cj4gKwo+ICsJcmV0 dXJuIGRybV9icmlkZ2VfYXR0YWNoKGJyaWRnZS0+ZW5jb2RlciwgdGhjNjMtPm5leHQsIGJyaWRn ZSk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHRoYzYzX2VuYWJsZShzdHJ1Y3QgZHJtX2JyaWRn ZSAqYnJpZGdlKQo+ICt7Cj4gKwlzdHJ1Y3QgdGhjNjNfZGV2ICp0aGM2MyA9IHRvX3RoYzYzKGJy aWRnZSk7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCXJldCA9IHJlZ3VsYXRvcl9lbmFibGUodGhjNjMt PnZjYyk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZGV2X2Vycih0aGM2My0+ZGV2LAo+ICsJCQkiRmFp bGVkIHRvIGVuYWJsZSByZWd1bGF0b3IgXCJ2Y2NcIjogJWRcbiIsIHJldCk7Cj4gKwkJcmV0dXJu Owo+ICsJfQo+ICsKPiArCWlmICh0aGM2My0+cGR3bikKPiArCQlncGlvZF9zZXRfdmFsdWUodGhj NjMtPnBkd24sIDApOwo+ICsKPiArCWlmICh0aGM2My0+b2UpCj4gKwkJZ3Bpb2Rfc2V0X3ZhbHVl KHRoYzYzLT5vZSwgMSk7CgpZb3UgZG9uJ3QgbmVlZCB0byBjaGVjayB0aGUgZ3Bpb19kZXNjIHBv aW50ZXJzIGZpcnN0LCBncGlvZF9zZXRfdmFsdWUoKSBpcyBhIApuby1vcCBpZiB0aGUgcG9pbnRl ciBpcyBOVUxMLgoKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgdGhjNjNfZGlzYWJsZShzdHJ1Y3Qg ZHJtX2JyaWRnZSAqYnJpZGdlKQo+ICt7Cj4gKwlzdHJ1Y3QgdGhjNjNfZGV2ICp0aGM2MyA9IHRv X3RoYzYzKGJyaWRnZSk7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWlmICh0aGM2My0+b2UpCj4gKwkJ Z3Bpb2Rfc2V0X3ZhbHVlKHRoYzYzLT5vZSwgMCk7Cj4gKwo+ICsJaWYgKHRoYzYzLT5wZHduKQo+ ICsJCWdwaW9kX3NldF92YWx1ZSh0aGM2My0+cGR3biwgMSk7CgpTYW1lIGhlcmUuCgo+ICsJcmV0 ID0gcmVndWxhdG9yX2Rpc2FibGUodGhjNjMtPnZjYyk7Cj4gKwlpZiAocmV0KQo+ICsJCWRldl9l cnIodGhjNjMtPmRldiwKPiArCQkJIkZhaWxlZCB0byBkaXNhYmxlIHJlZ3VsYXRvciBcInZjY1wi OiAlZFxuIiwgcmV0KTsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBkcm1fYnJpZGdl X2Z1bmNzIHRoYzYzX2JyaWRnZV9mdW5jID0gewo+ICsJLmF0dGFjaAk9IHRoYzYzX2F0dGFjaCwK PiArCS5lbmFibGUgPSB0aGM2M19lbmFibGUsCj4gKwkuZGlzYWJsZSA9IHRoYzYzX2Rpc2FibGUs Cj4gK307Cj4gKwo+ICtzdGF0aWMgaW50IHRoYzYzX3BhcnNlX2R0KHN0cnVjdCB0aGM2M19kZXYg KnRoYzYzKQo+ICt7Cj4gKwlzdHJ1Y3QgZGV2aWNlX25vZGUgKnRoYzYzX291dDsKPiArCXN0cnVj dCBkZXZpY2Vfbm9kZSAqcmVtb3RlOwo+ICsKPiArCXRoYzYzX291dCA9IG9mX2dyYXBoX2dldF9l bmRwb2ludF9ieV9yZWdzKHRoYzYzLT5kZXYtPm9mX25vZGUsCj4gKwkJCQkJCSAgVEhDNjNfUkdC X09VVDAsIC0xKTsKPiArCWlmICghdGhjNjNfb3V0KSB7Cj4gKwkJZGV2X2Vycih0aGM2My0+ZGV2 LCAiTWlzc2luZyBlbmRwb2ludCBpbiBwb3J0QCV1XG4iLAo+ICsJCQlUSEM2M19SR0JfT1VUMCk7 Cj4gKwkJcmV0dXJuIC1FTk9ERVY7Cj4gKwl9Cj4gKwo+ICsJcmVtb3RlID0gb2ZfZ3JhcGhfZ2V0 X3JlbW90ZV9wb3J0X3BhcmVudCh0aGM2M19vdXQpOwo+ICsJb2Zfbm9kZV9wdXQodGhjNjNfb3V0 KTsKPiArCWlmICghcmVtb3RlKSB7Cj4gKwkJZGV2X2Vycih0aGM2My0+ZGV2LCAiRW5kcG9pbnQg aW4gcG9ydEAldSB1bmNvbm5lY3RlZFxuIiwKPiArCQkJVEhDNjNfUkdCX09VVDApOwo+ICsJCXJl dHVybiAtRU5PREVWOwo+ICsJfQo+ICsKPiArCWlmICghb2ZfZGV2aWNlX2lzX2F2YWlsYWJsZShy ZW1vdGUpKSB7Cj4gKwkJZGV2X2Vycih0aGM2My0+ZGV2LCAicG9ydEAldSByZW1vdGUgZW5kcG9p bnQgaXMgZGlzYWJsZWRcbiIsCj4gKwkJCVRIQzYzX1JHQl9PVVQwKTsKPiArCQlvZl9ub2RlX3B1 dChyZW1vdGUpOwo+ICsJCXJldHVybiAtRU5PREVWOwo+ICsJfQo+ICsKPiArCXRoYzYzLT5uZXh0 ID0gb2ZfZHJtX2ZpbmRfYnJpZGdlKHJlbW90ZSk7Cj4gKwlpZiAoIXRoYzYzLT5uZXh0KSB7Cj4g KwkJb2Zfbm9kZV9wdXQocmVtb3RlKTsKPiArCQlyZXR1cm4gLUVQUk9CRV9ERUZFUjsKPiArCX0K PiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCB0aGM2M19ncGlvX2luaXQo c3RydWN0IHRoYzYzX2RldiAqdGhjNjMpCj4gK3sKPiArCXRoYzYzLT5vZSA9IGRldm1fZ3Bpb2Rf Z2V0X29wdGlvbmFsKHRoYzYzLT5kZXYsICJlbmFibGUiLCBHUElPRF9PVVRfTE9XKTsKCklmIHlv dSBhZ3JlZSB3aXRoIG15IGNvbW1lbnQgcmVnYXJkaW5nIHRoZSBEVCBiaW5kaW5ncywgdGhpcyBz aG91bGQgYmUgIm9lIi4KCj4gKwlpZiAoSVNfRVJSKHRoYzYzLT5vZSkpIHsKPiArCQlkZXZfZXJy KHRoYzYzLT5kZXYsICJVbmFibGUgdG8gZ2V0IFwiZW5hYmxlLWdwaW9zXCI6ICVsZFxuIiwKPiAr CQkJUFRSX0VSUih0aGM2My0+b2UpKTsKCkFuZCB0aGUgbWVzc2FnZSBzaG91bGQgYmUgdXBkYXRl IGhlcmUgdG9vLgoKV2l0aCB0aG9zZSBzbWFsbCBpc3N1ZXMgZml4ZWQsCgpSZXZpZXdlZC1ieTog TGF1cmVudCBQaW5jaGFydCA8bGF1cmVudC5waW5jaGFydEBpZGVhc29uYm9hcmQuY29tPgoKPiAr CQlyZXR1cm4gUFRSX0VSUih0aGM2My0+b2UpOwo+ICsJfQo+ICsKPiArCXRoYzYzLT5wZHduID0g ZGV2bV9ncGlvZF9nZXRfb3B0aW9uYWwodGhjNjMtPmRldiwgInBvd2VyZG93biIsCj4gKwkJCQkJ ICAgICAgR1BJT0RfT1VUX0hJR0gpOwo+ICsJaWYgKElTX0VSUih0aGM2My0+cGR3bikpIHsKPiAr CQlkZXZfZXJyKHRoYzYzLT5kZXYsICJVbmFibGUgdG8gZ2V0IFwicG93ZXJkb3duLWdwaW9zXCI6 ICVsZFxuIiwKPiArCQkJUFRSX0VSUih0aGM2My0+cGR3bikpOwo+ICsJCXJldHVybiBQVFJfRVJS KHRoYzYzLT5wZHduKTsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGlj IGludCB0aGM2M19wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+ICt7Cj4gKwlz dHJ1Y3QgdGhjNjNfZGV2ICp0aGM2MzsKPiArCWludCByZXQ7Cj4gKwo+ICsJdGhjNjMgPSBkZXZt X2t6YWxsb2MoJnBkZXYtPmRldiwgc2l6ZW9mKCp0aGM2MyksIEdGUF9LRVJORUwpOwo+ICsJaWYg KCF0aGM2MykKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwl0aGM2My0+ZGV2ID0gJnBkZXYt PmRldjsKPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIHRoYzYzKTsKPiArCj4gKwl0aGM2 My0+dmNjID0gZGV2bV9yZWd1bGF0b3JfZ2V0KHRoYzYzLT5kZXYsICJ2Y2MiKTsKPiArCWlmIChJ U19FUlIodGhjNjMtPnZjYykpIHsKPiArCQlpZiAoUFRSX0VSUih0aGM2My0+dmNjKSA9PSAtRVBS T0JFX0RFRkVSKQo+ICsJCQlyZXR1cm4gLUVQUk9CRV9ERUZFUjsKPiArCj4gKwkJZGV2X2Vycih0 aGM2My0+ZGV2LCAiVW5hYmxlIHRvIGdldCBcInZjY1wiIHN1cHBseTogJWxkXG4iLAo+ICsJCQlQ VFJfRVJSKHRoYzYzLT52Y2MpKTsKPiArCQlyZXR1cm4gUFRSX0VSUih0aGM2My0+dmNjKTsKPiAr CX0KPiArCj4gKwlyZXQgPSB0aGM2M19ncGlvX2luaXQodGhjNjMpOwo+ICsJaWYgKHJldCkKPiAr CQlyZXR1cm4gcmV0Owo+ICsKPiArCXJldCA9IHRoYzYzX3BhcnNlX2R0KHRoYzYzKTsKPiArCWlm IChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwl0aGM2My0+YnJpZGdlLmRyaXZlcl9wcml2 YXRlID0gdGhjNjM7Cj4gKwl0aGM2My0+YnJpZGdlLm9mX25vZGUgPSBwZGV2LT5kZXYub2Zfbm9k ZTsKPiArCXRoYzYzLT5icmlkZ2UuZnVuY3MgPSAmdGhjNjNfYnJpZGdlX2Z1bmM7Cj4gKwo+ICsJ ZHJtX2JyaWRnZV9hZGQoJnRoYzYzLT5icmlkZ2UpOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4g Kwo+ICtzdGF0aWMgaW50IHRoYzYzX3JlbW92ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2 KQo+ICt7Cj4gKwlzdHJ1Y3QgdGhjNjNfZGV2ICp0aGM2MyA9IHBsYXRmb3JtX2dldF9kcnZkYXRh KHBkZXYpOwo+ICsKPiArCWRybV9icmlkZ2VfcmVtb3ZlKCZ0aGM2My0+YnJpZGdlKTsKPiArCj4g KwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQg dGhjNjNfbWF0Y2hbXSA9IHsKPiArCXsgLmNvbXBhdGlibGUgPSAidGhpbmUsdGhjNjNsdmQxMDI0 IiwgfSwKPiArCXsgfSwKPiArfTsKPiArTU9EVUxFX0RFVklDRV9UQUJMRShvZiwgdGhjNjNfbWF0 Y2gpOwo+ICsKPiArc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgdGhjNjNfZHJpdmVyID0g ewo+ICsJLnByb2JlCT0gdGhjNjNfcHJvYmUsCj4gKwkucmVtb3ZlCT0gdGhjNjNfcmVtb3ZlLAo+ ICsJLmRyaXZlcgk9IHsKPiArCQkubmFtZQkJPSAidGhjNjNsdmQxMDI0IiwKPiArCQkub2ZfbWF0 Y2hfdGFibGUJPSB0aGM2M19tYXRjaCwKPiArCX0sCj4gK307Cj4gK21vZHVsZV9wbGF0Zm9ybV9k cml2ZXIodGhjNjNfZHJpdmVyKTsKPiArCj4gK01PRFVMRV9BVVRIT1IoIkphY29wbyBNb25kaSA8 amFjb3BvQGptb25kaS5vcmc+Iik7Cj4gK01PRFVMRV9ERVNDUklQVElPTigiVGhpbmUgVEhDNjNM VkQxMDI0IExWRFMgZGVjb2RlciBEUk0gYnJpZGdlIGRyaXZlciIpOwo+ICtNT0RVTEVfTElDRU5T RSgiR1BMIHYyIik7CgotLSAKUmVnYXJkcywKCkxhdXJlbnQgUGluY2hhcnQKCgoKX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KZHJpLWRldmVsIG1haWxpbmcg bGlzdApkcmktZGV2ZWxAbGlzdHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlzdHMuZnJlZWRl c2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vZHJpLWRldmVsCg==