From mboxrd@z Thu Jan 1 00:00:00 1970 From: noralf@tronnes.org (=?UTF-8?Q?Noralf_Tr=c3=b8nnes?=) Date: Tue, 15 Aug 2017 23:49:56 +0200 Subject: [PATCH 2/4] drm/tve200: Add new driver for TVE200 In-Reply-To: <20170813151132.24736-3-linus.walleij@linaro.org> References: <20170813151132.24736-1-linus.walleij@linaro.org> <20170813151132.24736-3-linus.walleij@linaro.org> Message-ID: To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Den 13.08.2017 17.11, skrev Linus Walleij: > This adds a new DRM driver for the Faraday Technology TVE200 > block. This "TV Encoder" encodes a ITU-T BT.656 stream and can > be found in the StorLink SL3516 (later Cortina Systems CS3516) > as well as the Grain Media GM8180. > > I do not have definitive word from anyone at Faraday that this > IP block is theirs, but it bears the hallmark of their 3-digit > version code (200) and is used in two SoCs from completely > different companies. (Grain Media was fully owned by Faraday > until it was transferred to NovoTek this january, and > Faraday did lots of work on the StorLink SoCs.) > > The D-Link DIR-685 uses this in connection with the Ilitek > ILI9322 panel driver that supports BT.656 input, while the > GM8180 apparently has been used with the Cirrus Logic CS4954 > digital video encoder. The oldest user seems to be > something called Techwall 2835. > > This driver is heavily inspired by Eric Anholt's PL111 > driver and therefore I have mentioned all the ancestor authors > in the header file. > > Signed-off-by: Linus Walleij > --- [...] > diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c [...] > +static struct drm_driver tve200_drm_driver = { > + .driver_features = > + DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, > + .lastclose = tve200_lastclose, > + .ioctls = NULL, > + .fops = &drm_fops, > + .name = "tve200", > + .desc = DRIVER_DESC, > + .date = "20170703", > + .major = 1, > + .minor = 0, > + .patchlevel = 0, > + .dumb_create = drm_gem_cma_dumb_create, > + .dumb_destroy = drm_gem_dumb_destroy, > + .dumb_map_offset = drm_gem_cma_dumb_map_offset, The dumb_destroy and dumb_map_offset callbacks have defaults now that fits the cma helper drivers so you don't need to set them. And drm_gem_cma_dumb_map_offset() is gone as soon as I get and ack on the remaining cleanup patches. Noralf. > + .gem_free_object = drm_gem_cma_free_object, > + .gem_vm_ops = &drm_gem_cma_vm_ops, > + > + .enable_vblank = tve200_enable_vblank, > + .disable_vblank = tve200_disable_vblank, > + > + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, > + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, > + .gem_prime_import = drm_gem_prime_import, > + .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, > + .gem_prime_export = drm_gem_prime_export, > + .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, > +}; > + > +static int tve200_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct tve200_drm_dev_private *priv; > + struct drm_device *drm; > + struct resource *res; > + int irq; > + int ret; > + > + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + drm = drm_dev_alloc(&tve200_drm_driver, dev); > + if (IS_ERR(drm)) > + return PTR_ERR(drm); > + platform_set_drvdata(pdev, drm); > + priv->drm = drm; > + drm->dev_private = priv; > + > + /* Clock the silicon so we can access the registers */ > + priv->pclk = devm_clk_get(dev, "PCLK"); > + if (IS_ERR(priv->pclk)) { > + dev_err(dev, "unable to get PCLK\n"); > + ret = PTR_ERR(priv->pclk); > + goto dev_unref; > + } > + ret = clk_prepare_enable(priv->pclk); > + if (ret) { > + dev_err(dev, "failed to enable PCLK\n"); > + goto dev_unref; > + } > + > + /* This clock is for the pixels (27MHz) */ > + priv->clk = devm_clk_get(dev, "TVE"); > + if (IS_ERR(priv->clk)) { > + dev_err(dev, "unable to get TVE clock\n"); > + ret = PTR_ERR(priv->clk); > + goto clk_disable; > + } > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + priv->regs = devm_ioremap_resource(dev, res); > + if (!priv->regs) { > + dev_err(dev, "%s failed mmio\n", __func__); > + ret = -EINVAL; > + goto dev_unref; > + } > + > + irq = platform_get_irq(pdev, 0); > + if (!irq) { > + ret = -EINVAL; > + goto dev_unref; > + } > + > + /* turn off interrupts before requesting the irq */ > + writel(0, priv->regs + TVE200_INT_EN); > + > + ret = devm_request_irq(dev, irq, tve200_irq, 0, "tve200", priv); > + if (ret) { > + dev_err(dev, "failed to request irq %d\n", ret); > + return ret; > + } > + > + ret = tve200_modeset_init(drm); > + if (ret) > + goto dev_unref; > + > + ret = drm_dev_register(drm, 0); > + if (ret < 0) > + goto dev_unref; > + > + return 0; > + > +clk_disable: > + clk_disable_unprepare(priv->pclk); > +dev_unref: > + drm_dev_unref(drm); > + return ret; > +} > + > +static int tve200_remove(struct platform_device *pdev) > +{ > + struct drm_device *drm = platform_get_drvdata(pdev); > + struct tve200_drm_dev_private *priv = drm->dev_private; > + > + drm_dev_unregister(drm); > + if (priv->fbdev) > + drm_fbdev_cma_fini(priv->fbdev); > + drm_mode_config_cleanup(drm); > + clk_disable_unprepare(priv->pclk); > + drm_dev_unref(drm); > + > + return 0; > +} > + > +static const struct of_device_id tve200_of_match[] = { > + { > + .compatible = "faraday,tve200", > + }, > + {}, > +}; > + > +static struct platform_driver tve200_driver = { > + .driver = { > + .name = "tve200", > + .of_match_table = of_match_ptr(tve200_of_match), > + }, > + .probe = tve200_probe, > + .remove = tve200_remove, > +}; > +module_platform_driver(tve200_driver); > + > +MODULE_DESCRIPTION(DRIVER_DESC); > +MODULE_AUTHOR("Linus Walleij "); > +MODULE_LICENSE("GPL"); From mboxrd@z Thu Jan 1 00:00:00 1970 From: =?UTF-8?Q?Noralf_Tr=c3=b8nnes?= Subject: Re: [PATCH 2/4] drm/tve200: Add new driver for TVE200 Date: Tue, 15 Aug 2017 23:49:56 +0200 Message-ID: References: <20170813151132.24736-1-linus.walleij@linaro.org> <20170813151132.24736-3-linus.walleij@linaro.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8"; Format="flowed" Content-Transfer-Encoding: base64 Return-path: Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id BDA796E04F for ; Tue, 15 Aug 2017 21:50:13 +0000 (UTC) In-Reply-To: <20170813151132.24736-3-linus.walleij@linaro.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Linus Walleij , dri-devel@lists.freedesktop.org, Eric Anholt , Daniel Vetter , Jani Nikula , Sean Paul Cc: linux-arm-kernel@lists.infradead.org List-Id: dri-devel@lists.freedesktop.org CkRlbiAxMy4wOC4yMDE3IDE3LjExLCBza3JldiBMaW51cyBXYWxsZWlqOgo+IFRoaXMgYWRkcyBh IG5ldyBEUk0gZHJpdmVyIGZvciB0aGUgRmFyYWRheSBUZWNobm9sb2d5IFRWRTIwMAo+IGJsb2Nr LiBUaGlzICJUViBFbmNvZGVyIiBlbmNvZGVzIGEgSVRVLVQgQlQuNjU2IHN0cmVhbSBhbmQgY2Fu Cj4gYmUgZm91bmQgaW4gdGhlIFN0b3JMaW5rIFNMMzUxNiAobGF0ZXIgQ29ydGluYSBTeXN0ZW1z IENTMzUxNikKPiBhcyB3ZWxsIGFzIHRoZSBHcmFpbiBNZWRpYSBHTTgxODAuCj4KPiBJIGRvIG5v dCBoYXZlIGRlZmluaXRpdmUgd29yZCBmcm9tIGFueW9uZSBhdCBGYXJhZGF5IHRoYXQgdGhpcwo+ IElQIGJsb2NrIGlzIHRoZWlycywgYnV0IGl0IGJlYXJzIHRoZSBoYWxsbWFyayBvZiB0aGVpciAz LWRpZ2l0Cj4gdmVyc2lvbiBjb2RlICgyMDApIGFuZCBpcyB1c2VkIGluIHR3byBTb0NzIGZyb20g Y29tcGxldGVseQo+IGRpZmZlcmVudCBjb21wYW5pZXMuIChHcmFpbiBNZWRpYSB3YXMgZnVsbHkg b3duZWQgYnkgRmFyYWRheQo+IHVudGlsIGl0IHdhcyB0cmFuc2ZlcnJlZCB0byBOb3ZvVGVrIHRo aXMgamFudWFyeSwgYW5kCj4gRmFyYWRheSBkaWQgbG90cyBvZiB3b3JrIG9uIHRoZSBTdG9yTGlu ayBTb0NzLikKPgo+IFRoZSBELUxpbmsgRElSLTY4NSB1c2VzIHRoaXMgaW4gY29ubmVjdGlvbiB3 aXRoIHRoZSBJbGl0ZWsKPiBJTEk5MzIyIHBhbmVsIGRyaXZlciB0aGF0IHN1cHBvcnRzIEJULjY1 NiBpbnB1dCwgd2hpbGUgdGhlCj4gR004MTgwIGFwcGFyZW50bHkgaGFzIGJlZW4gdXNlZCB3aXRo IHRoZSBDaXJydXMgTG9naWMgQ1M0OTU0Cj4gZGlnaXRhbCB2aWRlbyBlbmNvZGVyLiBUaGUgb2xk ZXN0IHVzZXIgc2VlbXMgdG8gYmUKPiBzb21ldGhpbmcgY2FsbGVkIFRlY2h3YWxsIDI4MzUuCj4K PiBUaGlzIGRyaXZlciBpcyBoZWF2aWx5IGluc3BpcmVkIGJ5IEVyaWMgQW5ob2x0J3MgUEwxMTEK PiBkcml2ZXIgYW5kIHRoZXJlZm9yZSBJIGhhdmUgbWVudGlvbmVkIGFsbCB0aGUgYW5jZXN0b3Ig YXV0aG9ycwo+IGluIHRoZSBoZWFkZXIgZmlsZS4KPgo+IFNpZ25lZC1vZmYtYnk6IExpbnVzIFdh bGxlaWogPGxpbnVzLndhbGxlaWpAbGluYXJvLm9yZz4KPiAtLS0KClsuLi5dCgo+IGRpZmYgLS1n aXQgYS9kcml2ZXJzL2dwdS9kcm0vdHZlMjAwL3R2ZTIwMF9kcnYuYyBiL2RyaXZlcnMvZ3B1L2Ry bS90dmUyMDAvdHZlMjAwX2Rydi5jCgpbLi4uXQoKPiArc3RhdGljIHN0cnVjdCBkcm1fZHJpdmVy IHR2ZTIwMF9kcm1fZHJpdmVyID0gewo+ICsJLmRyaXZlcl9mZWF0dXJlcyA9Cj4gKwkJRFJJVkVS X01PREVTRVQgfCBEUklWRVJfR0VNIHwgRFJJVkVSX1BSSU1FIHwgRFJJVkVSX0FUT01JQywKPiAr CS5sYXN0Y2xvc2UgPSB0dmUyMDBfbGFzdGNsb3NlLAo+ICsJLmlvY3RscyA9IE5VTEwsCj4gKwku Zm9wcyA9ICZkcm1fZm9wcywKPiArCS5uYW1lID0gInR2ZTIwMCIsCj4gKwkuZGVzYyA9IERSSVZF Ul9ERVNDLAo+ICsJLmRhdGUgPSAiMjAxNzA3MDMiLAo+ICsJLm1ham9yID0gMSwKPiArCS5taW5v ciA9IDAsCj4gKwkucGF0Y2hsZXZlbCA9IDAsCj4gKwkuZHVtYl9jcmVhdGUgPSBkcm1fZ2VtX2Nt YV9kdW1iX2NyZWF0ZSwKPiArCS5kdW1iX2Rlc3Ryb3kgPSBkcm1fZ2VtX2R1bWJfZGVzdHJveSwK PiArCS5kdW1iX21hcF9vZmZzZXQgPSBkcm1fZ2VtX2NtYV9kdW1iX21hcF9vZmZzZXQsCgpUaGUg ZHVtYl9kZXN0cm95IGFuZCBkdW1iX21hcF9vZmZzZXQgY2FsbGJhY2tzIGhhdmUgZGVmYXVsdHMg bm93IHRoYXQKZml0cyB0aGUgY21hIGhlbHBlciBkcml2ZXJzIHNvIHlvdSBkb24ndCBuZWVkIHRv IHNldCB0aGVtLiBBbmQKZHJtX2dlbV9jbWFfZHVtYl9tYXBfb2Zmc2V0KCkgaXMgZ29uZSBhcyBz b29uIGFzIEkgZ2V0IGFuZCBhY2sgb24gdGhlCnJlbWFpbmluZyBjbGVhbnVwIHBhdGNoZXMuCgpO b3JhbGYuCgo+ICsJLmdlbV9mcmVlX29iamVjdCA9IGRybV9nZW1fY21hX2ZyZWVfb2JqZWN0LAo+ ICsJLmdlbV92bV9vcHMgPSAmZHJtX2dlbV9jbWFfdm1fb3BzLAo+ICsKPiArCS5lbmFibGVfdmJs YW5rID0gdHZlMjAwX2VuYWJsZV92YmxhbmssCj4gKwkuZGlzYWJsZV92YmxhbmsgPSB0dmUyMDBf ZGlzYWJsZV92YmxhbmssCj4gKwo+ICsJLnByaW1lX2hhbmRsZV90b19mZCA9IGRybV9nZW1fcHJp bWVfaGFuZGxlX3RvX2ZkLAo+ICsJLnByaW1lX2ZkX3RvX2hhbmRsZSA9IGRybV9nZW1fcHJpbWVf ZmRfdG9faGFuZGxlLAo+ICsJLmdlbV9wcmltZV9pbXBvcnQgPSBkcm1fZ2VtX3ByaW1lX2ltcG9y dCwKPiArCS5nZW1fcHJpbWVfaW1wb3J0X3NnX3RhYmxlID0gZHJtX2dlbV9jbWFfcHJpbWVfaW1w b3J0X3NnX3RhYmxlLAo+ICsJLmdlbV9wcmltZV9leHBvcnQgPSBkcm1fZ2VtX3ByaW1lX2V4cG9y dCwKPiArCS5nZW1fcHJpbWVfZ2V0X3NnX3RhYmxlCT0gZHJtX2dlbV9jbWFfcHJpbWVfZ2V0X3Nn X3RhYmxlLAo+ICt9Owo+ICsKPiArc3RhdGljIGludCB0dmUyMDBfcHJvYmUoc3RydWN0IHBsYXRm b3JtX2RldmljZSAqcGRldikKPiArewo+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRl djsKPiArCXN0cnVjdCB0dmUyMDBfZHJtX2Rldl9wcml2YXRlICpwcml2Owo+ICsJc3RydWN0IGRy bV9kZXZpY2UgKmRybTsKPiArCXN0cnVjdCByZXNvdXJjZSAqcmVzOwo+ICsJaW50IGlycTsKPiAr CWludCByZXQ7Cj4gKwo+ICsJcHJpdiA9IGRldm1fa3phbGxvYyhkZXYsIHNpemVvZigqcHJpdiks IEdGUF9LRVJORUwpOwo+ICsJaWYgKCFwcml2KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiAr CWRybSA9IGRybV9kZXZfYWxsb2MoJnR2ZTIwMF9kcm1fZHJpdmVyLCBkZXYpOwo+ICsJaWYgKElT X0VSUihkcm0pKQo+ICsJCXJldHVybiBQVFJfRVJSKGRybSk7Cj4gKwlwbGF0Zm9ybV9zZXRfZHJ2 ZGF0YShwZGV2LCBkcm0pOwo+ICsJcHJpdi0+ZHJtID0gZHJtOwo+ICsJZHJtLT5kZXZfcHJpdmF0 ZSA9IHByaXY7Cj4gKwo+ICsJLyogQ2xvY2sgdGhlIHNpbGljb24gc28gd2UgY2FuIGFjY2VzcyB0 aGUgcmVnaXN0ZXJzICovCj4gKwlwcml2LT5wY2xrID0gZGV2bV9jbGtfZ2V0KGRldiwgIlBDTEsi KTsKPiArCWlmIChJU19FUlIocHJpdi0+cGNsaykpIHsKPiArCQlkZXZfZXJyKGRldiwgInVuYWJs ZSB0byBnZXQgUENMS1xuIik7Cj4gKwkJcmV0ID0gUFRSX0VSUihwcml2LT5wY2xrKTsKPiArCQln b3RvIGRldl91bnJlZjsKPiArCX0KPiArCXJldCA9IGNsa19wcmVwYXJlX2VuYWJsZShwcml2LT5w Y2xrKTsKPiArCWlmIChyZXQpIHsKPiArCQlkZXZfZXJyKGRldiwgImZhaWxlZCB0byBlbmFibGUg UENMS1xuIik7Cj4gKwkJZ290byBkZXZfdW5yZWY7Cj4gKwl9Cj4gKwo+ICsJLyogVGhpcyBjbG9j ayBpcyBmb3IgdGhlIHBpeGVscyAoMjdNSHopICovCj4gKwlwcml2LT5jbGsgPSBkZXZtX2Nsa19n ZXQoZGV2LCAiVFZFIik7Cj4gKwlpZiAoSVNfRVJSKHByaXYtPmNsaykpIHsKPiArCQlkZXZfZXJy KGRldiwgInVuYWJsZSB0byBnZXQgVFZFIGNsb2NrXG4iKTsKPiArCQlyZXQgPSBQVFJfRVJSKHBy aXYtPmNsayk7Cj4gKwkJZ290byBjbGtfZGlzYWJsZTsKPiArCX0KPiArCj4gKwlyZXMgPSBwbGF0 Zm9ybV9nZXRfcmVzb3VyY2UocGRldiwgSU9SRVNPVVJDRV9NRU0sIDApOwo+ICsJcHJpdi0+cmVn cyA9IGRldm1faW9yZW1hcF9yZXNvdXJjZShkZXYsIHJlcyk7Cj4gKwlpZiAoIXByaXYtPnJlZ3Mp IHsKPiArCQlkZXZfZXJyKGRldiwgIiVzIGZhaWxlZCBtbWlvXG4iLCBfX2Z1bmNfXyk7Cj4gKwkJ cmV0ID0gLUVJTlZBTDsKPiArCQlnb3RvIGRldl91bnJlZjsKPiArCX0KPiArCj4gKwlpcnEgPSBw bGF0Zm9ybV9nZXRfaXJxKHBkZXYsIDApOwo+ICsJaWYgKCFpcnEpIHsKPiArCQlyZXQgPSAtRUlO VkFMOwo+ICsJCWdvdG8gZGV2X3VucmVmOwo+ICsJfQo+ICsKPiArCS8qIHR1cm4gb2ZmIGludGVy cnVwdHMgYmVmb3JlIHJlcXVlc3RpbmcgdGhlIGlycSAqLwo+ICsJd3JpdGVsKDAsIHByaXYtPnJl Z3MgKyBUVkUyMDBfSU5UX0VOKTsKPiArCj4gKwlyZXQgPSBkZXZtX3JlcXVlc3RfaXJxKGRldiwg aXJxLCB0dmUyMDBfaXJxLCAwLCAidHZlMjAwIiwgcHJpdik7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJ ZGV2X2VycihkZXYsICJmYWlsZWQgdG8gcmVxdWVzdCBpcnEgJWRcbiIsIHJldCk7Cj4gKwkJcmV0 dXJuIHJldDsKPiArCX0KPiArCj4gKwlyZXQgPSB0dmUyMDBfbW9kZXNldF9pbml0KGRybSk7Cj4g KwlpZiAocmV0KQo+ICsJCWdvdG8gZGV2X3VucmVmOwo+ICsKPiArCXJldCA9IGRybV9kZXZfcmVn aXN0ZXIoZHJtLCAwKTsKPiArCWlmIChyZXQgPCAwKQo+ICsJCWdvdG8gZGV2X3VucmVmOwo+ICsK PiArCXJldHVybiAwOwo+ICsKPiArY2xrX2Rpc2FibGU6Cj4gKwljbGtfZGlzYWJsZV91bnByZXBh cmUocHJpdi0+cGNsayk7Cj4gK2Rldl91bnJlZjoKPiArCWRybV9kZXZfdW5yZWYoZHJtKTsKPiAr CXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdHZlMjAwX3JlbW92ZShzdHJ1Y3Qg cGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+ICt7Cj4gKwlzdHJ1Y3QgZHJtX2RldmljZSAqZHJtID0g cGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7Cj4gKwlzdHJ1Y3QgdHZlMjAwX2RybV9kZXZfcHJp dmF0ZSAqcHJpdiA9IGRybS0+ZGV2X3ByaXZhdGU7Cj4gKwo+ICsJZHJtX2Rldl91bnJlZ2lzdGVy KGRybSk7Cj4gKwlpZiAocHJpdi0+ZmJkZXYpCj4gKwkJZHJtX2ZiZGV2X2NtYV9maW5pKHByaXYt PmZiZGV2KTsKPiArCWRybV9tb2RlX2NvbmZpZ19jbGVhbnVwKGRybSk7Cj4gKwljbGtfZGlzYWJs ZV91bnByZXBhcmUocHJpdi0+cGNsayk7Cj4gKwlkcm1fZGV2X3VucmVmKGRybSk7Cj4gKwo+ICsJ cmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNlX2lkIHR2 ZTIwMF9vZl9tYXRjaFtdID0gewo+ICsJewo+ICsJCS5jb21wYXRpYmxlID0gImZhcmFkYXksdHZl MjAwIiwKPiArCX0sCj4gKwl7fSwKPiArfTsKPiArCj4gK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1f ZHJpdmVyIHR2ZTIwMF9kcml2ZXIgPSB7Cj4gKwkuZHJpdmVyID0gewo+ICsJCS5uYW1lICAgICAg ICAgICA9ICJ0dmUyMDAiLAo+ICsJCS5vZl9tYXRjaF90YWJsZSA9IG9mX21hdGNoX3B0cih0dmUy MDBfb2ZfbWF0Y2gpLAo+ICsJfSwKPiArCS5wcm9iZSA9IHR2ZTIwMF9wcm9iZSwKPiArCS5yZW1v dmUgPSB0dmUyMDBfcmVtb3ZlLAo+ICt9Owo+ICttb2R1bGVfcGxhdGZvcm1fZHJpdmVyKHR2ZTIw MF9kcml2ZXIpOwo+ICsKPiArTU9EVUxFX0RFU0NSSVBUSU9OKERSSVZFUl9ERVNDKTsKPiArTU9E VUxFX0FVVEhPUigiTGludXMgV2FsbGVpaiA8bGludXMud2FsbGVpakBsaW5hcm8ub3JnPiIpOwo+ ICtNT0RVTEVfTElDRU5TRSgiR1BMIik7CgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fXwpkcmktZGV2ZWwgbWFpbGluZyBsaXN0CmRyaS1kZXZlbEBsaXN0cy5m cmVlZGVza3RvcC5vcmcKaHR0cHM6Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcvbWFpbG1hbi9saXN0 aW5mby9kcmktZGV2ZWwK