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 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1BB2CC433EF for ; Tue, 4 Jan 2022 11:07:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:Content-Type: Content-Transfer-Encoding:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:Date:Message-ID:From: References:Cc:To:Subject:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=c3QhZIR5QwRCGyQVeisdPMBA/O2XZt8x1ZYPcZqLlUc=; b=xGAI/G0AHdOC34mUAn+/JFVYNW ShhGHLmOzdzEbDekBLyEhrSa+BKbxWDPeJ8EN664HeVYBv65XP0FgwBVW4wT9mmmZhh6okvO6xb30 qYCOadAkX3LeUbAHveMoL3QWNAtGnww282JjmMS9xVOasHczSBW21LRiw3WnZ61T7IhmTJXSjo1fR behBQtRLUgPe2HH0j+ivCC6KiVIbAwFBv5frQ7KapHYGwbStc3AzBcVcrWJ9tMAL3MjFEpyYqzkv9 EqngafBViQ28ci/079VOPAA2fQvVWR7L9zQ4XVD0Fy8I9FNAWUQgbz7unt5zloGrq4CvNZ4OXgn7Y FLhwr7OQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1n4hfK-00BFmP-AR; Tue, 04 Jan 2022 11:07:42 +0000 Received: from regular1.263xmail.com ([211.150.70.204]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1n4hfC-00BFl6-8h; Tue, 04 Jan 2022 11:07:40 +0000 Received: from localhost (unknown [192.168.167.16]) by regular1.263xmail.com (Postfix) with ESMTP id 58C5A503; Tue, 4 Jan 2022 19:07:25 +0800 (CST) X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-ADDR-CHECKED4: 1 X-SKE-CHECKED: 1 X-ABS-CHECKED: 1 X-ANTISPAM-LEVEL: 2 Received: from [172.16.12.89] (unknown [58.22.7.114]) by smtp.263.net (postfix) whith ESMTP id P12624T140276825810688S1641294444616683_; Tue, 04 Jan 2022 19:07:25 +0800 (CST) X-IP-DOMAINF: 1 X-RL-SENDER: andy.yan@rock-chips.com X-SENDER: yxj@rock-chips.com X-LOGIN-NAME: andy.yan@rock-chips.com X-FST-TO: kever.yang@rock-chips.com X-RCPT-COUNT: 12 X-LOCAL-RCPT-COUNT: 2 X-MUTI-DOMAIN-COUNT: 0 X-SENDER-IP: 58.22.7.114 X-ATTACHMENT-NUM: 0 X-UNIQUE-TAG: X-System-Flag: 0 Subject: Re: [PATCH 22/22] drm: rockchip: Add VOP2 driver To: Sascha Hauer , dri-devel@lists.freedesktop.org Cc: linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org, kernel@pengutronix.de, Benjamin Gaignard , Michael Riesch , Sandy Huang , =?UTF-8?Q?Heiko_St=c3=bcbner?= , Peter Geis , Kever Yang References: <20211220110630.3521121-1-s.hauer@pengutronix.de> <20211220110630.3521121-23-s.hauer@pengutronix.de> From: Andy Yan Message-ID: Date: Tue, 4 Jan 2022 19:07:23 +0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.14.0 MIME-Version: 1.0 In-Reply-To: <20211220110630.3521121-23-s.hauer@pengutronix.de> Content-Language: en-US X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org SGkgU2FzY2hhOgoKClBsZWFzZSBhZGQgU2VyaWVzLXZlcnNpb24gZm9yIGFsbCB0aGUgcGF0Y2gg c2VyaWVzLiBhZGQgYWxzbyBTZXJpZXMtY2hhbmdlcy4KCkkgc2F3IHlvdSBoYXZlIFNlcmllcy1j aGFuZ2VzIGluIGNvdmVyLWxldHRlciwgYnV0IHdlIHVzdWFsbHkgaW5jbHVkZSAKdGhlbSBpbiBw YXRjaC4KCkhlcmUgaXMgYSBsaW5rIHlvdSBjYW4gdGFrZSBmb3IgcmVmZXJlbmNlWzBdCgpbMF1o dHRwczovL3NvdXJjZS5kZW54LmRlL3UtYm9vdC91LWJvb3QvLS90cmVlL21hc3Rlci90b29scy9w YXRtYW4KCk9uIDEyLzIwLzIxIDc6MDYgUE0sIFNhc2NoYSBIYXVlciB3cm90ZToKPiBGcm9tOiBB bmR5IFlhbiA8YW5keS55YW5Acm9jay1jaGlwcy5jb20+Cj4KPiBUaGUgVk9QMiB1bml0IGlzIGZv dW5kIG9uIFJvY2tjaGlwIFNvQ3MgYmVnaW5uaW5nIHdpdGggcmszNTY2L3JrMzU2OC4KPiBJdCBy ZXBsYWNlcyB0aGUgVk9QIHVuaXQgZm91bmQgaW4gdGhlIG9sZGVyIFJvY2tjaGlwIFNvQ3MuCj4K PiBUaGlzIGRyaXZlciBoYXMgYmVlbiBkZXJpdmVkIGZyb20gdGhlIGRvd25zdHJlYW0gUm9ja2No aXAgS2VybmVsIGFuZAo+IGhlYXZpbHkgbW9kaWZpZWQ6Cj4KPiAtIEFsbCBub25zdGFuZGFyZCBE Uk0gcHJvcGVydGllcyBoYXZlIGJlZW4gcmVtb3ZlZAo+IC0gZHJvcHBlZCBzdHJ1Y3Qgdm9wMl9w bGFuZV9zdGF0ZSBhbmQgcGFzcyBhcm91bmQgbGVzcyBkYXRhIGJldHdlZW4KPiAgICBmdW5jdGlv bnMKPiAtIERyb3BwZWQgYWxsIERSTV9GT1JNQVRfKiBub3Qga25vd24gb24gdXBzdHJlYW0KPiAt IHJld29yayByZWdpc3RlciBhY2Nlc3MgdG8gZ2V0IHJpZCBvZiBleGNlc3NpdmVseSB1c2VkIG1h Y3Jvcwo+IC0gRHJvcCBhbGwgd2FpdGluZyBmb3IgZnJhbWVzeW5jcwo+Cj4gVGhlIGRyaXZlciBp cyB0ZXN0ZWQgd2l0aCBIRE1JIGFuZCBNSVBJLURTSSBkaXNwbGF5IG9uIGEgUkszNTY4LUVWQgo+ IGJvYXJkLiBPdmVybGF5IHN1cHBvcnQgaXMgdGVzdGVkIHdpdGggdGhlIG1vZGV0ZXN0IHV0aWxp dHkuIEFGQkMgc3VwcG9ydAo+IG9uIHRoZSBjbHVzdGVyIHdpbmRvd3MgaXMgdGVzdGVkIHdpdGgg d2VzdG9uLXNpbXBsZS1kbWFidWYtZWdsIG9uCj4gd2VzdG9uIHVzaW5nIHRoZSAoeWV0IHRvIGJl IHVwc3RyZWFtZWQpIHBhbmZyb3N0IGRyaXZlciBzdXBwb3J0Lgo+Cj4gU2lnbmVkLW9mZi1ieTog U2FzY2hhIEhhdWVyIDxzLmhhdWVyQHBlbmd1dHJvbml4LmRlPgo+IC0tLQo+ICAgZHJpdmVycy9n cHUvZHJtL3JvY2tjaGlwL0tjb25maWcgICAgICAgICAgICAgfCAgICA2ICsKPiAgIGRyaXZlcnMv Z3B1L2RybS9yb2NrY2hpcC9NYWtlZmlsZSAgICAgICAgICAgIHwgICAgMSArCj4gICBkcml2ZXJz L2dwdS9kcm0vcm9ja2NoaXAvcm9ja2NoaXBfZHJtX2Rydi5jICB8ICAgIDEgKwo+ICAgZHJpdmVy cy9ncHUvZHJtL3JvY2tjaGlwL3JvY2tjaGlwX2RybV9kcnYuaCAgfCAgICA3ICstCj4gICBkcml2 ZXJzL2dwdS9kcm0vcm9ja2NoaXAvcm9ja2NoaXBfZHJtX2ZiLmMgICB8ICAgIDIgKwo+ICAgZHJp dmVycy9ncHUvZHJtL3JvY2tjaGlwL3JvY2tjaGlwX2RybV92b3AuaCAgfCAgIDE1ICsKPiAgIGRy aXZlcnMvZ3B1L2RybS9yb2NrY2hpcC9yb2NrY2hpcF9kcm1fdm9wMi5jIHwgMjc2OCArKysrKysr KysrKysrKysrKysKPiAgIGRyaXZlcnMvZ3B1L2RybS9yb2NrY2hpcC9yb2NrY2hpcF9kcm1fdm9w Mi5oIHwgIDQ4MCArKysKPiAgIGRyaXZlcnMvZ3B1L2RybS9yb2NrY2hpcC9yb2NrY2hpcF92b3Ay X3JlZy5jIHwgIDI4NSArKwo+ICAgOSBmaWxlcyBjaGFuZ2VkLCAzNTY0IGluc2VydGlvbnMoKyks IDEgZGVsZXRpb24oLSkKPiAgIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2dwdS9kcm0vcm9j a2NoaXAvcm9ja2NoaXBfZHJtX3ZvcDIuYwo+ICAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMv Z3B1L2RybS9yb2NrY2hpcC9yb2NrY2hpcF9kcm1fdm9wMi5oCj4gICBjcmVhdGUgbW9kZSAxMDA2 NDQgZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlwL3JvY2tjaGlwX3ZvcDJfcmVnLmMKPgo+IGRpZmYg LS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvS2NvbmZpZyBiL2RyaXZlcnMvZ3B1L2Ry bS9yb2NrY2hpcC9LY29uZmlnCj4gaW5kZXggYjliMTU2MzA4NDYwYS4uNGZmMDA0M2YwZWU3MCAx MDA2NDQKPiAtLS0gYS9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvS2NvbmZpZwo+ICsrKyBiL2Ry aXZlcnMvZ3B1L2RybS9yb2NrY2hpcC9LY29uZmlnCj4gQEAgLTI4LDYgKzI4LDEyIEBAIGNvbmZp ZyBST0NLQ0hJUF9WT1AKPiAgIAkgIFRoaXMgc2VsZWN0cyBzdXBwb3J0IGZvciB0aGUgVk9QIGRy aXZlci4gWW91IHNob3VsZCBlbmFibGUgaXQKPiAgIAkgIG9uIGFsbCBvbGRlciBTb0NzIHVwIHRv IFJLMzM5OS4KPiAgIAo+ICtjb25maWcgUk9DS0NISVBfVk9QMgo+ICsJYm9vbCAiUm9ja2NoaXAg Vk9QMiBkcml2ZXIiCj4gKwloZWxwCj4gKwkgIFRoaXMgc2VsZWN0cyBzdXBwb3J0IGZvciB0aGUg Vk9QMiBkcml2ZXIuIFlvdSBzaG91bGQgZW5hYmxlIGl0Cj4gKwkgIG9uIGFsbCBuZXdlciBTb0Nz IGJlZ2lubmluZyBmb3JtIFJLMzU2OC4KPiArCj4gICBjb25maWcgUk9DS0NISVBfQU5BTE9HSVhf RFAKPiAgIAlib29sICJSb2NrY2hpcCBzcGVjaWZpYyBleHRlbnNpb25zIGZvciBBbmFsb2dpeCBE UCBkcml2ZXIiCj4gICAJZGVwZW5kcyBvbiBST0NLQ0hJUF9WT1AKPiBkaWZmIC0tZ2l0IGEvZHJp dmVycy9ncHUvZHJtL3JvY2tjaGlwL01ha2VmaWxlIGIvZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlw L01ha2VmaWxlCj4gaW5kZXggY2Q2ZTdiYjVjZTljNS4uMjk4NDhjYWVmNWMyMSAxMDA2NDQKPiAt LS0gYS9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvTWFrZWZpbGUKPiArKysgYi9kcml2ZXJzL2dw dS9kcm0vcm9ja2NoaXAvTWFrZWZpbGUKPiBAQCAtNyw2ICs3LDcgQEAgcm9ja2NoaXBkcm0teSA6 PSByb2NrY2hpcF9kcm1fZHJ2Lm8gcm9ja2NoaXBfZHJtX2ZiLm8gXAo+ICAgCQlyb2NrY2hpcF9k cm1fZ2VtLm8KPiAgIHJvY2tjaGlwZHJtLSQoQ09ORklHX0RSTV9GQkRFVl9FTVVMQVRJT04pICs9 IHJvY2tjaGlwX2RybV9mYmRldi5vCj4gICAKPiArcm9ja2NoaXBkcm0tJChDT05GSUdfUk9DS0NI SVBfVk9QMikgKz0gcm9ja2NoaXBfZHJtX3ZvcDIubyByb2NrY2hpcF92b3AyX3JlZy5vCj4gICBy b2NrY2hpcGRybS0kKENPTkZJR19ST0NLQ0hJUF9WT1ApICs9IHJvY2tjaGlwX2RybV92b3AubyBy b2NrY2hpcF92b3BfcmVnLm8KPiAgIHJvY2tjaGlwZHJtLSQoQ09ORklHX1JPQ0tDSElQX0FOQUxP R0lYX0RQKSArPSBhbmFsb2dpeF9kcC1yb2NrY2hpcC5vCj4gICByb2NrY2hpcGRybS0kKENPTkZJ R19ST0NLQ0hJUF9DRE5fRFApICs9IGNkbi1kcC1jb3JlLm8gY2RuLWRwLXJlZy5vCj4gZGlmZiAt LWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9yb2NrY2hpcC9yb2NrY2hpcF9kcm1fZHJ2LmMgYi9kcml2 ZXJzL2dwdS9kcm0vcm9ja2NoaXAvcm9ja2NoaXBfZHJtX2Rydi5jCj4gaW5kZXggNjRmYTVmZDYy YzAxYS4uMmJkOWFjYjI2NWU1YSAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL2dwdS9kcm0vcm9ja2No aXAvcm9ja2NoaXBfZHJtX2Rydi5jCj4gKysrIGIvZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlwL3Jv Y2tjaGlwX2RybV9kcnYuYwo+IEBAIC00NzQsNiArNDc0LDcgQEAgc3RhdGljIGludCBfX2luaXQg cm9ja2NoaXBfZHJtX2luaXQodm9pZCkKPiAgIAo+ICAgCW51bV9yb2NrY2hpcF9zdWJfZHJpdmVy cyA9IDA7Cj4gICAJQUREX1JPQ0tDSElQX1NVQl9EUklWRVIodm9wX3BsYXRmb3JtX2RyaXZlciwg Q09ORklHX1JPQ0tDSElQX1ZPUCk7Cj4gKwlBRERfUk9DS0NISVBfU1VCX0RSSVZFUih2b3AyX3Bs YXRmb3JtX2RyaXZlciwgQ09ORklHX1JPQ0tDSElQX1ZPUDIpOwo+ICAgCUFERF9ST0NLQ0hJUF9T VUJfRFJJVkVSKHJvY2tjaGlwX2x2ZHNfZHJpdmVyLAo+ICAgCQkJCUNPTkZJR19ST0NLQ0hJUF9M VkRTKTsKPiAgIAlBRERfUk9DS0NISVBfU1VCX0RSSVZFUihyb2NrY2hpcF9kcF9kcml2ZXIsCj4g ZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9yb2NrY2hpcC9yb2NrY2hpcF9kcm1fZHJ2Lmgg Yi9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvcm9ja2NoaXBfZHJtX2Rydi5oCj4gaW5kZXggYWEw OTA5ZThlZGY5My4uZmQ2OTk0ZjIxODE3ZSAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL2dwdS9kcm0v cm9ja2NoaXAvcm9ja2NoaXBfZHJtX2Rydi5oCj4gKysrIGIvZHJpdmVycy9ncHUvZHJtL3JvY2tj aGlwL3JvY2tjaGlwX2RybV9kcnYuaAo+IEBAIC0xOCw3ICsxOCw3IEBACj4gICAKPiAgICNkZWZp bmUgUk9DS0NISVBfTUFYX0ZCX0JVRkZFUgkzCj4gICAjZGVmaW5lIFJPQ0tDSElQX01BWF9DT05O RUNUT1IJMgo+IC0jZGVmaW5lIFJPQ0tDSElQX01BWF9DUlRDCTIKPiArI2RlZmluZSBST0NLQ0hJ UF9NQVhfQ1JUQwk0Cj4gICAKPiAgIHN0cnVjdCBkcm1fZGV2aWNlOwo+ICAgc3RydWN0IGRybV9j b25uZWN0b3I7Cj4gQEAgLTMxLDYgKzMxLDkgQEAgc3RydWN0IHJvY2tjaGlwX2NydGNfc3RhdGUg ewo+ICAgCWludCBvdXRwdXRfYnBjOwo+ICAgCWludCBvdXRwdXRfZmxhZ3M7Cj4gICAJYm9vbCBl bmFibGVfYWZiYzsKPiArCXVpbnQzMl90IGJ1c19mb3JtYXQ7Cj4gKwl1MzIgYnVzX2ZsYWdzOwo+ ICsJaW50IGNvbG9yX3NwYWNlOwo+ICAgfTsKPiAgICNkZWZpbmUgdG9fcm9ja2NoaXBfY3J0Y19z dGF0ZShzKSBcCj4gICAJCWNvbnRhaW5lcl9vZihzLCBzdHJ1Y3Qgcm9ja2NoaXBfY3J0Y19zdGF0 ZSwgYmFzZSkKPiBAQCAtNjUsNCArNjgsNiBAQCBleHRlcm4gc3RydWN0IHBsYXRmb3JtX2RyaXZl ciByb2NrY2hpcF9kcF9kcml2ZXI7Cj4gICBleHRlcm4gc3RydWN0IHBsYXRmb3JtX2RyaXZlciBy b2NrY2hpcF9sdmRzX2RyaXZlcjsKPiAgIGV4dGVybiBzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIHZv cF9wbGF0Zm9ybV9kcml2ZXI7Cj4gICBleHRlcm4gc3RydWN0IHBsYXRmb3JtX2RyaXZlciByazMw NjZfaGRtaV9kcml2ZXI7Cj4gK2V4dGVybiBzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIHZvcDJfcGxh dGZvcm1fZHJpdmVyOwo+ICsKPiAgICNlbmRpZiAvKiBfUk9DS0NISVBfRFJNX0RSVl9IXyAqLwo+ IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvcm9ja2NoaXBfZHJtX2ZiLmMg Yi9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvcm9ja2NoaXBfZHJtX2ZiLmMKPiBpbmRleCAzYWEz N2UxNzc2NjdlLi4wZDJjYjRmMzkyMmI4IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvZ3B1L2RybS9y b2NrY2hpcC9yb2NrY2hpcF9kcm1fZmIuYwo+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9yb2NrY2hp cC9yb2NrY2hpcF9kcm1fZmIuYwo+IEBAIC0xMzQsNCArMTM0LDYgQEAgdm9pZCByb2NrY2hpcF9k cm1fbW9kZV9jb25maWdfaW5pdChzdHJ1Y3QgZHJtX2RldmljZSAqZGV2KQo+ICAgCj4gICAJZGV2 LT5tb2RlX2NvbmZpZy5mdW5jcyA9ICZyb2NrY2hpcF9kcm1fbW9kZV9jb25maWdfZnVuY3M7Cj4g ICAJZGV2LT5tb2RlX2NvbmZpZy5oZWxwZXJfcHJpdmF0ZSA9ICZyb2NrY2hpcF9tb2RlX2NvbmZp Z19oZWxwZXJzOwo+ICsKPiArCWRldi0+bW9kZV9jb25maWcubm9ybWFsaXplX3pwb3MgPSB0cnVl Owo+ICAgfQo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvcm9ja2NoaXBf ZHJtX3ZvcC5oIGIvZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlwL3JvY2tjaGlwX2RybV92b3AuaAo+ IGluZGV4IDg1N2Q5N2NkYzY3YzYuLjFlMzY0ZDdiNTBlNjkgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVy cy9ncHUvZHJtL3JvY2tjaGlwL3JvY2tjaGlwX2RybV92b3AuaAo+ICsrKyBiL2RyaXZlcnMvZ3B1 L2RybS9yb2NrY2hpcC9yb2NrY2hpcF9kcm1fdm9wLmgKPiBAQCAtNTQsOSArNTQsMjMgQEAgc3Ry dWN0IHZvcF9hZmJjIHsKPiAgIAlzdHJ1Y3Qgdm9wX3JlZyBlbmFibGU7Cj4gICAJc3RydWN0IHZv cF9yZWcgd2luX3NlbDsKPiAgIAlzdHJ1Y3Qgdm9wX3JlZyBmb3JtYXQ7Cj4gKwlzdHJ1Y3Qgdm9w X3JlZyByYl9zd2FwOwo+ICsJc3RydWN0IHZvcF9yZWcgdXZfc3dhcDsKPiArCXN0cnVjdCB2b3Bf cmVnIGF1dG9fZ2F0aW5nX2VuOwo+ICsJc3RydWN0IHZvcF9yZWcgYmxvY2tfc3BsaXRfZW47Cj4g KwlzdHJ1Y3Qgdm9wX3JlZyBwaWNfdmlyX3dpZHRoOwo+ICsJc3RydWN0IHZvcF9yZWcgdGlsZV9u dW07Cj4gICAJc3RydWN0IHZvcF9yZWcgaHJlZ19ibG9ja19zcGxpdDsKPiArCXN0cnVjdCB2b3Bf cmVnIHBpY19vZmZzZXQ7Cj4gICAJc3RydWN0IHZvcF9yZWcgcGljX3NpemU7Cj4gKwlzdHJ1Y3Qg dm9wX3JlZyBkc3Bfb2Zmc2V0Owo+ICsJc3RydWN0IHZvcF9yZWcgdHJhbnNmb3JtX29mZnNldDsK PiAgIAlzdHJ1Y3Qgdm9wX3JlZyBoZHJfcHRyOwo+ICsJc3RydWN0IHZvcF9yZWcgaGFsZl9ibG9j a19lbjsKPiArCXN0cnVjdCB2b3BfcmVnIHhtaXJyb3I7Cj4gKwlzdHJ1Y3Qgdm9wX3JlZyB5bWly cm9yOwo+ICsJc3RydWN0IHZvcF9yZWcgcm90YXRlXzI3MDsKPiArCXN0cnVjdCB2b3BfcmVnIHJv dGF0ZV85MDsKPiAgIAlzdHJ1Y3Qgdm9wX3JlZyByc3RuOwo+ICAgfTsKPiAgIAo+IEBAIC00MTAs NCArNDI0LDUgQEAgc3RhdGljIGlubGluZSBpbnQgc2NsX3ZvcF9jYWxfbGJfbW9kZShpbnQgd2lk dGgsIGJvb2wgaXNfeXV2KQo+ICAgfQo+ICAgCj4gICBleHRlcm4gY29uc3Qgc3RydWN0IGNvbXBv bmVudF9vcHMgdm9wX2NvbXBvbmVudF9vcHM7Cj4gKwo+ICAgI2VuZGlmIC8qIF9ST0NLQ0hJUF9E Uk1fVk9QX0ggKi8KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlwL3JvY2tj aGlwX2RybV92b3AyLmMgYi9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvcm9ja2NoaXBfZHJtX3Zv cDIuYwo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMDAwMDAwMC4uN2QzOWJh OTAwNjFkMQo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAv cm9ja2NoaXBfZHJtX3ZvcDIuYwo+IEBAIC0wLDAgKzEsMjc2OCBAQAo+ICsvLyBTUERYLUxpY2Vu c2UtSWRlbnRpZmllcjogKEdQTC0yLjArIE9SIE1JVCkKPiArLyoKPiArICogQ29weXJpZ2h0IChj KSAyMDIwIFJvY2tjaGlwIEVsZWN0cm9uaWNzIENvLiwgTHRkLgo+ICsgKiBBdXRob3I6IEFuZHkg WWFuIDxhbmR5LnlhbkByb2NrLWNoaXBzLmNvbT4KPiArICovCj4gKyNpbmNsdWRlIDxkcm0vZHJt Lmg+Cj4gKyNpbmNsdWRlIDxkcm0vZHJtX2F0b21pYy5oPgo+ICsjaW5jbHVkZSA8ZHJtL2RybV9j cnRjLmg+Cj4gKyNpbmNsdWRlIDxkcm0vZHJtX2NydGNfaGVscGVyLmg+Cj4gKyNpbmNsdWRlIDxk cm0vZHJtX2ZsaXBfd29yay5oPgo+ICsjaW5jbHVkZSA8ZHJtL2RybV9wbGFuZV9oZWxwZXIuaD4K PiArI2luY2x1ZGUgPGRybS9kcm1fd3JpdGViYWNrLmg+Ckl0IHNlZW1zIHRoYXQgeW91IHJlbW92 ZWQgdGhlIHdyaXRlYmFjayBjb2RlIGluIHRoZSBkcml2ZXIgPwo+ICsjaW5jbHVkZSA8ZHJtL2Ry bV9wcm9iZV9oZWxwZXIuaD4KPiArI2luY2x1ZGUgPGRybS9kcm1fYXRvbWljX3VhcGkuaD4KPiAr Cj4gKyNpbmNsdWRlIDxsaW51eC9pb3BvbGwuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5o Pgo+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9wbGF0Zm9y bV9kZXZpY2UuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2Nsay5oPgo+ICsjaW5jbHVkZSA8bGludXgv aW9wb2xsLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9vZi5oPgo+ICsjaW5jbHVkZSA8bGludXgvb2Zf ZGV2aWNlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9vZl9ncmFwaC5oPgo+ICsjaW5jbHVkZSA8bGlu dXgvcG1fcnVudGltZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvY29tcG9uZW50Lmg+Cj4gKyNpbmNs dWRlIDxsaW51eC9yZWdtYXAuaD4KPiArI2luY2x1ZGUgPGxpbnV4L21mZC9zeXNjb24uaD4KPiAr I2luY2x1ZGUgPGxpbnV4L2RlbGF5Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zd2FiLmg+Cj4gKyNp bmNsdWRlIDxsaW51eC9iaXRmaWVsZC5oPgo+ICsjaW5jbHVkZSA8ZHJtL2RybV9kZWJ1Z2ZzLmg+ Cj4gKyNpbmNsdWRlIDx1YXBpL2xpbnV4L3ZpZGVvZGV2Mi5oPgo+ICsjaW5jbHVkZSA8ZHJtL2Ry bV92YmxhbmsuaD4KPiArI2luY2x1ZGUgPGR0LWJpbmRpbmdzL3NvYy9yb2NrY2hpcCx2b3AyLmg+ Cj4gKwo+ICsjaW5jbHVkZSAicm9ja2NoaXBfZHJtX2Rydi5oIgo+ICsjaW5jbHVkZSAicm9ja2No aXBfZHJtX2dlbS5oIgo+ICsjaW5jbHVkZSAicm9ja2NoaXBfZHJtX2ZiLmgiCj4gKyNpbmNsdWRl ICJyb2NrY2hpcF9kcm1fdm9wMi5oIgo+ICsKPiArLyoKPiArICogVk9QMiBhcmNoaXRlY3R1cmUK PiArICoKPiArICstLS0tLS0tLS0tKyAgICstLS0tLS0tLS0tLS0tKyAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKy0tLS0tLS0tLS0tKwo+ICsg fCAgQ2x1c3RlciB8ICAgfCBTZWwgMSBmcm9tIDZ8ICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgZnJvbSAzICB8Cj4gKyB8ICB3aW5kb3cw IHwgICB8ICAgIExheWVyMCAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIHwgICAgUkdCICAgIHwKPiArICstLS0tLS0tLS0tKyAgICstLS0t LS0tLS0tLS0tKyAgICAgICAgICAgICAgKy0tLS0tLS0tLS0tLS0tLSsgICAgKy0tLS0tLS0tLS0t LS0rICAgICAgKy0tLS0tLS0tLS0tKwo+ICsgKy0tLS0tLS0tLS0rICAgKy0tLS0tLS0tLS0tLS0r ICAgICAgICAgICAgICB8TiBmcm9tIDYgbGF5ZXJzfCAgICB8ICAgICAgICAgICAgIHwKPiArIHwg IENsdXN0ZXIgfCAgIHwgU2VsIDEgZnJvbSA2fCAgICAgICAgICAgICAgfCAgIE92ZXJsYXkwICAg ICstLS0+fCBWaWRlbyBQb3J0MCB8ICAgICAgKy0tLS0tLS0tLS0tKwo+ICsgfCAgd2luZG93MSB8 ICAgfCAgICBMYXllcjEgICB8ICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgfCAgICB8ICAg ICAgICAgICAgIHwgICAgICB8IDEgZnJvbSAzICB8Cj4gKyArLS0tLS0tLS0tLSsgICArLS0tLS0t LS0tLS0tLSsgICAgICAgICAgICAgICstLS0tLS0tLS0tLS0tLS0rICAgICstLS0tLS0tLS0tLS0t KyAgICAgIHwgICBMVkRTICAgIHwKPiArICstLS0tLS0tLS0tKyAgICstLS0tLS0tLS0tLS0tKyAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKy0t LS0tLS0tLS0tKwo+ICsgfCAgRXNtYXJ0ICB8ICAgfCBTZWwgMSBmcm9tIDZ8Cj4gKyB8ICB3aW5k b3cwIHwgICB8ICAgTGF5ZXIyICAgIHwgICAgICAgICAgICAgICstLS0tLS0tLS0tLS0tLS0rICAg ICstLS0tLS0tLS0tLS0tKyAgICAgICstLS0tLS0tLS0tLSsKPiArICstLS0tLS0tLS0tKyAgICst LS0tLS0tLS0tLS0tKyAgICAgICAgICAgICAgfE4gZnJvbSA2IExheWVyc3wgICAgfCAgICAgICAg ICAgICB8ICstLT4gfCAxIGZyb20gMyAgfAo+ICsgKy0tLS0tLS0tLS0rICAgKy0tLS0tLS0tLS0t LS0rICAgLS0tLS0tLS0+ICB8ICAgT3ZlcmxheTEgICAgKy0tLT58IFZpZGVvIFBvcnQxIHwgICAg ICB8ICAgTUlQSSAgICB8Cj4gKyB8ICBFc21hcnQgIHwgICB8IFNlbCAxIGZyb20gNnwgICAtLS0t LS0tLT4gIHwgICAgICAgICAgICAgICB8ICAgIHwgICAgICAgICAgICAgfCAgICAgICstLS0tLS0t LS0tLSsKPiArIHwgIFdpbmRvdzEgfCAgIHwgICBMYXllcjMgICAgfCAgICAgICAgICAgICAgKy0t LS0tLS0tLS0tLS0tLSsgICAgKy0tLS0tLS0tLS0tLS0rCj4gKyArLS0tLS0tLS0tLSsgICArLS0t LS0tLS0tLS0tLSsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICstLS0tLS0tLS0tLSsKPiArICstLS0tLS0tLS0tKyAgICstLS0tLS0tLS0tLS0t KyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg fCAxIGZyb20gMyAgfAo+ICsgfCAgU21hcnQgICB8ICAgfCBTZWwgMSBmcm9tIDZ8ICAgICAgICAg ICAgICArLS0tLS0tLS0tLS0tLS0tKyAgICArLS0tLS0tLS0tLS0tLSsgICAgICB8ICAgSERNSSAg ICB8Cj4gKyB8ICBXaW5kb3cwIHwgICB8ICAgIExheWVyNCAgIHwgICAgICAgICAgICAgIHxOIGZy b20gNiBMYXllcnN8ICAgIHwgICAgICAgICAgICAgfCAgICAgICstLS0tLS0tLS0tLSsKPiArICst LS0tLS0tLS0tKyAgICstLS0tLS0tLS0tLS0tKyAgICAgICAgICAgICAgfCAgIE92ZXJsYXkyICAg ICstLS0+fCBWaWRlbyBQb3J0MiB8Cj4gKyArLS0tLS0tLS0tLSsgICArLS0tLS0tLS0tLS0tLSsg ICAgICAgICAgICAgIHwgICAgICAgICAgICAgICB8ICAgIHwgICAgICAgICAgICAgfCAgICAgICst LS0tLS0tLS0tLSsKPiArIHwgIFNtYXJ0ICAgfCAgIHwgU2VsIDEgZnJvbSA2fCAgICAgICAgICAg ICAgKy0tLS0tLS0tLS0tLS0tLSsgICAgKy0tLS0tLS0tLS0tLS0rICAgICAgfCAgMSBmcm9tIDMg fAo+ICsgfCAgV2luZG93MSB8ICAgfCAgICBMYXllcjUgICB8ICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgIGVEUCAgICB8Cj4gKyArLS0t LS0tLS0tLSsgICArLS0tLS0tLS0tLS0tLSsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICstLS0tLS0tLS0tLSsKPiArICoKPiArICovCj4gKwo+ ICtlbnVtIHZvcDJfZGF0YV9mb3JtYXQgewo+ICsJVk9QMl9GTVRfQVJHQjg4ODggPSAwLAo+ICsJ Vk9QMl9GTVRfUkdCODg4LAo+ICsJVk9QMl9GTVRfUkdCNTY1LAo+ICsJVk9QMl9GTVRfWFJHQjEw MTAxMCwKPiArCVZPUDJfRk1UX1lVVjQyMFNQLAo+ICsJVk9QMl9GTVRfWVVWNDIyU1AsCj4gKwlW T1AyX0ZNVF9ZVVY0NDRTUCwKPiArCVZPUDJfRk1UX1lVWVY0MjIgPSA4LAo+ICsJVk9QMl9GTVRf WVVZVjQyMCwKPiArCVZPUDJfRk1UX1ZZVVk0MjIsCj4gKwlWT1AyX0ZNVF9WWVVZNDIwLAo+ICsJ Vk9QMl9GTVRfWVVWNDIwU1BfVElMRV84eDQgPSAweDEwLAo+ICsJVk9QMl9GTVRfWVVWNDIwU1Bf VElMRV8xNngyLAo+ICsJVk9QMl9GTVRfWVVWNDIyU1BfVElMRV84eDQsCj4gKwlWT1AyX0ZNVF9Z VVY0MjJTUF9USUxFXzE2eDIsCj4gKwlWT1AyX0ZNVF9ZVVY0MjBTUF8xMCwKPiArCVZPUDJfRk1U X1lVVjQyMlNQXzEwLAo+ICsJVk9QMl9GTVRfWVVWNDQ0U1BfMTAsCj4gK307Cj4gKwo+ICtlbnVt IHZvcDJfYWZiY19mb3JtYXQgewo+ICsJVk9QMl9BRkJDX0ZNVF9SR0I1NjUsCj4gKwlWT1AyX0FG QkNfRk1UX0FSR0IyMTAxMDEwID0gMiwKPiArCVZPUDJfQUZCQ19GTVRfWVVWNDIwXzEwQklULAo+ ICsJVk9QMl9BRkJDX0ZNVF9SR0I4ODgsCj4gKwlWT1AyX0FGQkNfRk1UX0FSR0I4ODg4LAo+ICsJ Vk9QMl9BRkJDX0ZNVF9ZVVY0MjAgPSA5LAo+ICsJVk9QMl9BRkJDX0ZNVF9ZVVY0MjIgPSAweGIs Cj4gKwlWT1AyX0FGQkNfRk1UX1lVVjQyMl8xMEJJVCA9IDB4ZSwKPiArCVZPUDJfQUZCQ19GTVRf SU5WQUxJRCA9IC0xLAo+ICt9Owo+ICsKPiArdW5pb24gdm9wMl9hbHBoYV9jdHJsIHsKPiArCXVp bnQzMl90IHZhbDsKPiArCXN0cnVjdCB7Cj4gKwkJLyogWzA6MV0gKi8KPiArCQl1aW50MzJfdCBj b2xvcl9tb2RlOjE7Cj4gKwkJdWludDMyX3QgYWxwaGFfbW9kZToxOwo+ICsJCS8qIFsyOjNdICov Cj4gKwkJdWludDMyX3QgYmxlbmRfbW9kZToyOwo+ICsJCXVpbnQzMl90IGFscGhhX2NhbF9tb2Rl OjE7Cj4gKwkJLyogWzU6N10gKi8KPiArCQl1aW50MzJfdCBmYWN0b3JfbW9kZTozOwo+ICsJCS8q IFs4OjldICovCj4gKwkJdWludDMyX3QgYWxwaGFfZW46MTsKPiArCQl1aW50MzJfdCBzcmNfZHN0 X3N3YXA6MTsKPiArCQl1aW50MzJfdCByZXNlcnZlZDo2Owo+ICsJCS8qIFsxNjoyM10gKi8KPiAr CQl1aW50MzJfdCBnbGJfYWxwaGE6ODsKPiArCX0gYml0czsKPiArfTsKPiArCj4gK3N0cnVjdCB2 b3AyX2FscGhhIHsKPiArCXVuaW9uIHZvcDJfYWxwaGFfY3RybCBzcmNfY29sb3JfY3RybDsKPiAr CXVuaW9uIHZvcDJfYWxwaGFfY3RybCBkc3RfY29sb3JfY3RybDsKPiArCXVuaW9uIHZvcDJfYWxw aGFfY3RybCBzcmNfYWxwaGFfY3RybDsKPiArCXVuaW9uIHZvcDJfYWxwaGFfY3RybCBkc3RfYWxw aGFfY3RybDsKPiArfTsKPiArCj4gK3N0cnVjdCB2b3AyX2FscGhhX2NvbmZpZyB7Cj4gKwlib29s IHNyY19wcmVtdWx0aV9lbjsKPiArCWJvb2wgZHN0X3ByZW11bHRpX2VuOwo+ICsJYm9vbCBzcmNf cGl4ZWxfYWxwaGFfZW47Cj4gKwlib29sIGRzdF9waXhlbF9hbHBoYV9lbjsKPiArCXVpbnQxNl90 IHNyY19nbGJfYWxwaGFfdmFsdWU7Cj4gKwl1aW50MTZfdCBkc3RfZ2xiX2FscGhhX3ZhbHVlOwo+ ICt9Owo+ICsKPiArc3RydWN0IHZvcDJfd2luIHsKPiArCXN0cnVjdCB2b3AyICp2b3AyOwo+ICsJ c3RydWN0IGRybV9wbGFuZSBiYXNlOwo+ICsJY29uc3Qgc3RydWN0IHZvcDJfd2luX2RhdGEgKmRh dGE7Cj4gKwlzdHJ1Y3QgcmVnbWFwX2ZpZWxkICpyZWdbVk9QMl9XSU5fTUFYX1JFR107Cj4gKwo+ ICsJLyoqCj4gKwkgKiBAd2luX2lkOiBncmFwaGljIHdpbmRvdyBpZCwgYSBjbHVzdGVyIG1heWJl IHNwbGl0IGludG8gdHdvCj4gKwkgKiBncmFwaGljcyB3aW5kb3dzLgo+ICsJICovCj4gKwl1aW50 OF90IHdpbl9pZDsKPiArCj4gKwl1aW50MzJfdCBvZmZzZXQ7Cj4gKwo+ICsJdWludDhfdCBkZWxh eTsKPiArCWVudW0gZHJtX3BsYW5lX3R5cGUgdHlwZTsKPiArfTsKPiArCj4gK3N0cnVjdCB2b3Ay X3ZpZGVvX3BvcnQgewo+ICsJc3RydWN0IGRybV9jcnRjIGNydGM7Cj4gKwlzdHJ1Y3Qgdm9wMiAq dm9wMjsKPiArCXN0cnVjdCBjbGsgKmRjbGs7Cj4gKwl1aW50OF90IGlkOwo+ICsJY29uc3Qgc3Ry dWN0IHZvcDJfdmlkZW9fcG9ydF9yZWdzICpyZWdzOwo+ICsJY29uc3Qgc3RydWN0IHZvcDJfdmlk ZW9fcG9ydF9kYXRhICpkYXRhOwo+ICsKPiArCXN0cnVjdCBjb21wbGV0aW9uIGRzcF9ob2xkX2Nv bXBsZXRpb247Cj4gKwo+ICsJLyoqCj4gKwkgKiBAd2luX21hc2s6IEJpdG1hc2sgb2Ygd2lucyBh dHRhY2hlZCB0byB0aGUgdmlkZW8gcG9ydDsKPiArCSAqLwo+ICsJdWludDMyX3Qgd2luX21hc2s7 Cj4gKwo+ICsJc3RydWN0IHZvcDJfd2luICpwcmltYXJ5X3BsYW5lOwo+ICsJc3RydWN0IGRybV9w ZW5kaW5nX3ZibGFua19ldmVudCAqZXZlbnQ7Cj4gKwo+ICsJaW50IG5sYXllcnM7Cj4gK307Cj4g Kwo+ICtzdHJ1Y3Qgdm9wMiB7Cj4gKwlzdHJ1Y3QgZGV2aWNlICpkZXY7Cj4gKwlzdHJ1Y3QgZHJt X2RldmljZSAqZHJtOwo+ICsJc3RydWN0IHZvcDJfdmlkZW9fcG9ydCB2cHNbUk9DS0NISVBfTUFY X0NSVENdOwo+ICsKPiArCWNvbnN0IHN0cnVjdCB2b3AyX2RhdGEgKmRhdGE7Cj4gKwkvKiBOdW1i ZXIgb2Ygd2luIHRoYXQgcmVnaXN0ZXJlZCBhcyBwbGFuZSwKPiArCSAqIG1heWJlIGxlc3MgdGhh biB0aGUgdG90YWwgbnVtYmVyIG9mIGhhcmR3YXJlCj4gKwkgKiB3aW4uCj4gKwkgKi8KPiArCXVp bnQzMl90IHJlZ2lzdGVyZWRfbnVtX3dpbnM7Cj4gKwo+ICsJdm9pZCBfX2lvbWVtICpyZWdzOwo+ ICsJc3RydWN0IHJlZ21hcCAqbWFwOwo+ICsKPiArCXN0cnVjdCByZWdtYXAgKmdyZjsKPiArCj4g KwkvKiBwaHlzaWNhbCBtYXAgbGVuZ3RoIG9mIHZvcDIgcmVnaXN0ZXIgKi8KPiArCXVpbnQzMl90 IGxlbjsKPiArCj4gKwl2b2lkIF9faW9tZW0gKmx1dF9yZWdzOwo+ICsJLyogb25lIHRpbWUgb25s eSBvbmUgcHJvY2VzcyBhbGxvd2VkIHRvIGNvbmZpZyB0aGUgcmVnaXN0ZXIgKi8KPiArCXNwaW5s b2NrX3QgcmVnX2xvY2s7Cj4gKwo+ICsJLyogcHJvdGVjdHMgY3J0YyBlbmFibGUvZGlzYWJsZSAq Lwo+ICsJc3RydWN0IG11dGV4IHZvcDJfbG9jazsKPiArCj4gKwlpbnQgaXJxOwo+ICsKPiArCS8q Cj4gKwkgKiBTb21lIGdsb2JsZSByZXNvdXJjZSBhcmUgc2hhcmVkIGJldHdlZW4gYWxsCj4gKwkg KiB0aGUgdmlkb2UgcG9ydHMoY3J0Y3MpLCBzbyB3ZSBuZWVkIGEgcmVmIGNvdW50ZXIgaGVyZS4K PiArCSAqLwo+ICsJdW5zaWduZWQgaW50IGVuYWJsZV9jb3VudDsKPiArCXN0cnVjdCBjbGsgKmhj bGs7Cj4gKwlzdHJ1Y3QgY2xrICphY2xrOwo+ICsKPiArCS8qIG11c3QgcHV0IGF0IHRoZSBlbmQg b2YgdGhlIHN0cnVjdCAqLwo+ICsJc3RydWN0IHZvcDJfd2luIHdpbltdOwo+ICt9Owo+ICsKPiAr c3RhdGljIHN0cnVjdCB2b3AyX3ZpZGVvX3BvcnQgKnRvX3ZvcDJfdmlkZW9fcG9ydChzdHJ1Y3Qg ZHJtX2NydGMgKmNydGMpCj4gK3sKPiArCXJldHVybiBjb250YWluZXJfb2YoY3J0Yywgc3RydWN0 IHZvcDJfdmlkZW9fcG9ydCwgY3J0Yyk7Cj4gK30KPiArCj4gK3N0YXRpYyBzdHJ1Y3Qgdm9wMl93 aW4gKnRvX3ZvcDJfd2luKHN0cnVjdCBkcm1fcGxhbmUgKnApCj4gK3sKPiArCXJldHVybiBjb250 YWluZXJfb2YocCwgc3RydWN0IHZvcDJfd2luLCBiYXNlKTsKPiArfQo+ICsKPiArc3RhdGljIHZv aWQgdm9wMl9sb2NrKHN0cnVjdCB2b3AyICp2b3AyKQo+ICt7Cj4gKwltdXRleF9sb2NrKCZ2b3Ay LT52b3AyX2xvY2spOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2b3AyX3VubG9jayhzdHJ1Y3Qg dm9wMiAqdm9wMikKPiArewo+ICsJbXV0ZXhfdW5sb2NrKCZ2b3AyLT52b3AyX2xvY2spOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgdm9pZCB2b3AyX3dyaXRlbChzdHJ1Y3Qgdm9wMiAqdm9wMiwgdWludDMy X3Qgb2Zmc2V0LCB1aW50MzJfdCB2KQo+ICt7Cj4gKwlyZWdtYXBfd3JpdGUodm9wMi0+bWFwLCBv ZmZzZXQsIHYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2b3AyX3ZwX3dyaXRlKHN0cnVjdCB2 b3AyX3ZpZGVvX3BvcnQgKnZwLCB1aW50MzJfdCBvZmZzZXQsCj4gKwkJCSAgdWludDMyX3QgdikK PiArewo+ICsJcmVnbWFwX3dyaXRlKHZwLT52b3AyLT5tYXAsIHZwLT5kYXRhLT5vZmZzZXQgKyBv ZmZzZXQsIHYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdWludDMyX3Qgdm9wMl9yZWFkbChzdHJ1Y3Qg dm9wMiAqdm9wMiwgdWludDMyX3Qgb2Zmc2V0KQo+ICt7Cj4gKwl1aW50MzJfdCB2YWw7Cj4gKwo+ ICsJcmVnbWFwX3JlYWQodm9wMi0+bWFwLCBvZmZzZXQsICZ2YWwpOwo+ICsKPiArCXJldHVybiB2 YWw7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHZvcDJfd2luX3dyaXRlKGNvbnN0IHN0cnVjdCB2 b3AyX3dpbiAqd2luLCB1bnNpZ25lZCBpbnQgcmVnLAo+ICsJCQkgICB1aW50MzJfdCB2KQo+ICt7 Cj4gKwlyZWdtYXBfZmllbGRfd3JpdGUod2luLT5yZWdbcmVnXSwgdik7Cj4gK30KPiArCj4gK3N0 YXRpYyBib29sIHZvcDJfY2x1c3Rlcl93aW5kb3coY29uc3Qgc3RydWN0IHZvcDJfd2luICp3aW4p Cj4gK3sKPiArCXJldHVybiB3aW4tPmRhdGEtPmZlYXR1cmUgJiBXSU5fRkVBVFVSRV9DTFVTVEVS Owo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2b3AyX2NmZ19kb25lKHN0cnVjdCB2b3AyX3ZpZGVv X3BvcnQgKnZwKQo+ICt7Cj4gKwlzdHJ1Y3Qgdm9wMiAqdm9wMiA9IHZwLT52b3AyOwo+ICsJdWlu dDMyX3QgdmFsOwo+ICsKPiArCXZhbCA9IHZvcDJfcmVhZGwodm9wMiwgUkszNTY4X1JFR19DRkdf RE9ORSk7Cj4gKwo+ICsJdmFsICY9IDB4NzsKPiArCj4gKwl2b3AyX3dyaXRlbCh2b3AyLCBSSzM1 NjhfUkVHX0NGR19ET05FLAo+ICsJCSAgICB2YWwgfCBCSVQodnAtPmlkKSB8IFJLMzU2OF9SRUdf Q0ZHX0RPTkVfX0dMQl9DRkdfRE9ORV9FTik7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHZvcDJf d2luX2Rpc2FibGUoc3RydWN0IHZvcDJfd2luICp3aW4pCj4gK3sKPiArCXZvcDJfd2luX3dyaXRl KHdpbiwgVk9QMl9XSU5fRU5BQkxFLCAwKTsKPiArCj4gKwlpZiAodm9wMl9jbHVzdGVyX3dpbmRv dyh3aW4pKQo+ICsJCXZvcDJfd2luX3dyaXRlKHdpbiwgVk9QMl9XSU5fQ0xVU1RFUl9FTkFCTEUs IDApOwo+ICt9Cj4gKwo+ICtzdGF0aWMgZW51bSB2b3AyX2RhdGFfZm9ybWF0IHZvcDJfY29udmVy dF9mb3JtYXQodWludDMyX3QgZm9ybWF0KQo+ICt7Cj4gKwlzd2l0Y2ggKGZvcm1hdCkgewo+ICsJ Y2FzZSBEUk1fRk9STUFUX1hSR0I4ODg4Ogo+ICsJY2FzZSBEUk1fRk9STUFUX0FSR0I4ODg4Ogo+ ICsJY2FzZSBEUk1fRk9STUFUX1hCR1I4ODg4Ogo+ICsJY2FzZSBEUk1fRk9STUFUX0FCR1I4ODg4 Ogo+ICsJCXJldHVybiBWT1AyX0ZNVF9BUkdCODg4ODsKPiArCWNhc2UgRFJNX0ZPUk1BVF9SR0I4 ODg6Cj4gKwljYXNlIERSTV9GT1JNQVRfQkdSODg4Ogo+ICsJCXJldHVybiBWT1AyX0ZNVF9SR0I4 ODg7Cj4gKwljYXNlIERSTV9GT1JNQVRfUkdCNTY1Ogo+ICsJY2FzZSBEUk1fRk9STUFUX0JHUjU2 NToKPiArCQlyZXR1cm4gVk9QMl9GTVRfUkdCNTY1Owo+ICsJY2FzZSBEUk1fRk9STUFUX05WMTI6 Cj4gKwkJcmV0dXJuIFZPUDJfRk1UX1lVVjQyMFNQOwo+ICsJY2FzZSBEUk1fRk9STUFUX05WMTY6 Cj4gKwkJcmV0dXJuIFZPUDJfRk1UX1lVVjQyMlNQOwo+ICsJY2FzZSBEUk1fRk9STUFUX05WMjQ6 Cj4gKwkJcmV0dXJuIFZPUDJfRk1UX1lVVjQ0NFNQOwo+ICsJY2FzZSBEUk1fRk9STUFUX1lVWVY6 Cj4gKwljYXNlIERSTV9GT1JNQVRfWVZZVToKPiArCQlyZXR1cm4gVk9QMl9GTVRfVllVWTQyMjsK PiArCWNhc2UgRFJNX0ZPUk1BVF9WWVVZOgo+ICsJY2FzZSBEUk1fRk9STUFUX1VZVlk6Cj4gKwkJ cmV0dXJuIFZPUDJfRk1UX1lVWVY0MjI7Cj4gKwlkZWZhdWx0Ogo+ICsJCURSTV9FUlJPUigidW5z dXBwb3J0ZWQgZm9ybWF0WyUwOHhdXG4iLCBmb3JtYXQpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ ICsJfQo+ICt9Cj4gKwo+ICtzdGF0aWMgZW51bSB2b3AyX2FmYmNfZm9ybWF0IHZvcDJfY29udmVy dF9hZmJjX2Zvcm1hdCh1aW50MzJfdCBmb3JtYXQpCj4gK3sKPiArCXN3aXRjaCAoZm9ybWF0KSB7 Cj4gKwljYXNlIERSTV9GT1JNQVRfWFJHQjg4ODg6Cj4gKwljYXNlIERSTV9GT1JNQVRfQVJHQjg4 ODg6Cj4gKwljYXNlIERSTV9GT1JNQVRfWEJHUjg4ODg6Cj4gKwljYXNlIERSTV9GT1JNQVRfQUJH Ujg4ODg6Cj4gKwkJcmV0dXJuIFZPUDJfQUZCQ19GTVRfQVJHQjg4ODg7Cj4gKwljYXNlIERSTV9G T1JNQVRfUkdCODg4Ogo+ICsJY2FzZSBEUk1fRk9STUFUX0JHUjg4ODoKPiArCQlyZXR1cm4gVk9Q Ml9BRkJDX0ZNVF9SR0I4ODg7Cj4gKwljYXNlIERSTV9GT1JNQVRfUkdCNTY1Ogo+ICsJY2FzZSBE Uk1fRk9STUFUX0JHUjU2NToKPiArCQlyZXR1cm4gVk9QMl9BRkJDX0ZNVF9SR0I1NjU7Cj4gKwlj YXNlIERSTV9GT1JNQVRfTlYxMjoKPiArCQlyZXR1cm4gVk9QMl9BRkJDX0ZNVF9ZVVY0MjA7Cj4g KwljYXNlIERSTV9GT1JNQVRfTlYxNjoKPiArCQlyZXR1cm4gVk9QMl9BRkJDX0ZNVF9ZVVY0MjI7 Cj4gKwlkZWZhdWx0Ogo+ICsJCXJldHVybiBWT1AyX0FGQkNfRk1UX0lOVkFMSUQ7Cj4gKwl9Cj4g Kwo+ICsJcmV0dXJuIFZPUDJfQUZCQ19GTVRfSU5WQUxJRDsKPiArfQo+ICsKPiArc3RhdGljIGJv b2wgdm9wMl93aW5fcmJfc3dhcCh1aW50MzJfdCBmb3JtYXQpCj4gK3sKPiArCXN3aXRjaCAoZm9y bWF0KSB7Cj4gKwljYXNlIERSTV9GT1JNQVRfWEJHUjg4ODg6Cj4gKwljYXNlIERSTV9GT1JNQVRf QUJHUjg4ODg6Cj4gKwljYXNlIERSTV9GT1JNQVRfQkdSODg4Ogo+ICsJY2FzZSBEUk1fRk9STUFU X0JHUjU2NToKPiArCQlyZXR1cm4gdHJ1ZTsKPiArCWRlZmF1bHQ6Cj4gKwkJcmV0dXJuIGZhbHNl Owo+ICsJfQo+ICt9Cj4gKwo+ICtzdGF0aWMgYm9vbCB2b3AyX2FmYmNfcmJfc3dhcCh1aW50MzJf dCBmb3JtYXQpCj4gK3sKPiArCXN3aXRjaCAoZm9ybWF0KSB7Cj4gKwljYXNlIERSTV9GT1JNQVRf TlYyNDoKPiArCQlyZXR1cm4gdHJ1ZTsKPiArCWRlZmF1bHQ6Cj4gKwkJcmV0dXJuIGZhbHNlOwo+ ICsJfQo+ICt9Cj4gKwo+ICtzdGF0aWMgYm9vbCB2b3AyX2FmYmNfdXZfc3dhcCh1aW50MzJfdCBm b3JtYXQpCj4gK3sKPiArCXN3aXRjaCAoZm9ybWF0KSB7Cj4gKwljYXNlIERSTV9GT1JNQVRfTlYx MjoKPiArCWNhc2UgRFJNX0ZPUk1BVF9OVjE2Ogo+ICsJCXJldHVybiB0cnVlOwo+ICsJZGVmYXVs dDoKPiArCQlyZXR1cm4gZmFsc2U7Cj4gKwl9Cj4gK30KPiArCj4gK3N0YXRpYyBib29sIHZvcDJf d2luX3V2X3N3YXAodWludDMyX3QgZm9ybWF0KQo+ICt7Cj4gKwlzd2l0Y2ggKGZvcm1hdCkgewo+ ICsJY2FzZSBEUk1fRk9STUFUX05WMTI6Cj4gKwljYXNlIERSTV9GT1JNQVRfTlYxNjoKPiArCWNh c2UgRFJNX0ZPUk1BVF9OVjI0Ogo+ICsJCXJldHVybiB0cnVlOwo+ICsJZGVmYXVsdDoKPiArCQly ZXR1cm4gZmFsc2U7Cj4gKwl9Cj4gK30KPiArCj4gK3N0YXRpYyBib29sIHZvcDJfd2luX2RpdGhl cl91cCh1aW50MzJfdCBmb3JtYXQpCj4gK3sKPiArCXN3aXRjaCAoZm9ybWF0KSB7Cj4gKwljYXNl IERSTV9GT1JNQVRfQkdSNTY1Ogo+ICsJY2FzZSBEUk1fRk9STUFUX1JHQjU2NToKPiArCQlyZXR1 cm4gdHJ1ZTsKPiArCWRlZmF1bHQ6Cj4gKwkJcmV0dXJuIGZhbHNlOwo+ICsJfQo+ICt9Cj4gKwo+ ICtzdGF0aWMgYm9vbCB2b3AyX291dHB1dF91dl9zd2FwKHVpbnQzMl90IGJ1c19mb3JtYXQsIHVp bnQzMl90IG91dHB1dF9tb2RlKQo+ICt7Cj4gKwkvKgo+ICsJICogRklYTUU6Cj4gKwkgKgo+ICsJ ICogVGhlcmUgaXMgbm8gbWVkaWEgdHlwZSBmb3IgWVVWNDQ0IG91dHB1dCwKPiArCSAqIHNvIHdo ZW4gb3V0X21vZGUgaXMgQUFBQSBvciBQODg4LCBhc3N1bWUgb3V0cHV0IGlzIFlVVjQ0NCBvbgo+ ICsJICogeXV2IGZvcm1hdC4KPiArCSAqCj4gKwkgKiBGcm9tIEgvVyB0ZXN0aW5nLCBZVVY0NDQg bW9kZSBuZWVkIGEgcmIgc3dhcC4KPiArCSAqLwo+ICsJaWYgKGJ1c19mb3JtYXQgPT0gTUVESUFf QlVTX0ZNVF9ZVllVOF8xWDE2IHx8Cj4gKwkgICAgYnVzX2Zvcm1hdCA9PSBNRURJQV9CVVNfRk1U X1ZZVVk4XzFYMTYgfHwKPiArCSAgICBidXNfZm9ybWF0ID09IE1FRElBX0JVU19GTVRfWVZZVThf Mlg4IHx8Cj4gKwkgICAgYnVzX2Zvcm1hdCA9PSBNRURJQV9CVVNfRk1UX1ZZVVk4XzJYOCB8fAo+ ICsJICAgICgoYnVzX2Zvcm1hdCA9PSBNRURJQV9CVVNfRk1UX1lVVjhfMVgyNCB8fAo+ICsJICAg ICAgYnVzX2Zvcm1hdCA9PSBNRURJQV9CVVNfRk1UX1lVVjEwXzFYMzApICYmCj4gKwkgICAgIChv dXRwdXRfbW9kZSA9PSBST0NLQ0hJUF9PVVRfTU9ERV9BQUFBIHx8Cj4gKwkgICAgICBvdXRwdXRf bW9kZSA9PSBST0NLQ0hJUF9PVVRfTU9ERV9QODg4KSkpCj4gKwkJcmV0dXJuIHRydWU7Cj4gKwll bHNlCj4gKwkJcmV0dXJuIGZhbHNlOwo+ICt9Cj4gKwo+ICtzdGF0aWMgYm9vbCBpc195dXZfb3V0 cHV0KHVpbnQzMl90IGJ1c19mb3JtYXQpCj4gK3sKPiArCXN3aXRjaCAoYnVzX2Zvcm1hdCkgewo+ ICsJY2FzZSBNRURJQV9CVVNfRk1UX1lVVjhfMVgyNDoKPiArCWNhc2UgTUVESUFfQlVTX0ZNVF9Z VVYxMF8xWDMwOgo+ICsJY2FzZSBNRURJQV9CVVNfRk1UX1VZWVZZWThfMF81WDI0Ogo+ICsJY2Fz ZSBNRURJQV9CVVNfRk1UX1VZWVZZWTEwXzBfNVgzMDoKPiArCWNhc2UgTUVESUFfQlVTX0ZNVF9Z VVlWOF8yWDg6Cj4gKwljYXNlIE1FRElBX0JVU19GTVRfWVZZVThfMlg4Ogo+ICsJY2FzZSBNRURJ QV9CVVNfRk1UX1VZVlk4XzJYODoKPiArCWNhc2UgTUVESUFfQlVTX0ZNVF9WWVVZOF8yWDg6Cj4g KwljYXNlIE1FRElBX0JVU19GTVRfWVVZVjhfMVgxNjoKPiArCWNhc2UgTUVESUFfQlVTX0ZNVF9Z VllVOF8xWDE2Ogo+ICsJY2FzZSBNRURJQV9CVVNfRk1UX1VZVlk4XzFYMTY6Cj4gKwljYXNlIE1F RElBX0JVU19GTVRfVllVWThfMVgxNjoKPiArCQlyZXR1cm4gdHJ1ZTsKPiArCWRlZmF1bHQ6Cj4g KwkJcmV0dXJuIGZhbHNlOwo+ICsJfQo+ICt9Cj4gKwo+ICtzdGF0aWMgYm9vbCByb2NrY2hpcF9h ZmJjKHN0cnVjdCBkcm1fcGxhbmUgKnBsYW5lLCB1NjQgbW9kaWZpZXIpCj4gK3sKPiArCWludCBp Owo+ICsKPiArCWlmIChtb2RpZmllciA9PSBEUk1fRk9STUFUX01PRF9MSU5FQVIpCj4gKwkJcmV0 dXJuIGZhbHNlOwo+ICsKPiArCWZvciAoaSA9IDAgOyBpIDwgcGxhbmUtPm1vZGlmaWVyX2NvdW50 OyBpKyspCj4gKwkJaWYgKHBsYW5lLT5tb2RpZmllcnNbaV0gPT0gbW9kaWZpZXIpCj4gKwkJCWJy ZWFrOwo+ICsKPiArCXJldHVybiAoaSA8IHBsYW5lLT5tb2RpZmllcl9jb3VudCkgPyB0cnVlIDog ZmFsc2U7Cj4gKwo+ICt9Cj4gKwo+ICtzdGF0aWMgYm9vbCByb2NrY2hpcF92b3AyX21vZF9zdXBw b3J0ZWQoc3RydWN0IGRybV9wbGFuZSAqcGxhbmUsIHVpbnQzMl90IGZvcm1hdCwgdTY0IG1vZGlm aWVyKQo+ICt7Cj4gKwlzdHJ1Y3Qgdm9wMl93aW4gKndpbiA9IHRvX3ZvcDJfd2luKHBsYW5lKTsK PiArCXN0cnVjdCB2b3AyICp2b3AyID0gd2luLT52b3AyOwo+ICsKPiArCWlmIChtb2RpZmllciA9 PSBEUk1fRk9STUFUX01PRF9JTlZBTElEKQo+ICsJCXJldHVybiBmYWxzZTsKPiArCj4gKwlpZiAo bW9kaWZpZXIgPT0gRFJNX0ZPUk1BVF9NT0RfTElORUFSKQo+ICsJCXJldHVybiB0cnVlOwo+ICsK PiArCWlmICghcm9ja2NoaXBfYWZiYyhwbGFuZSwgbW9kaWZpZXIpKSB7Cj4gKwkJZHJtX2Vycih2 b3AyLT5kcm0sICJVbnN1cHBvcnRlZCBmb3JtYXQgbW9kaWZpZXIgMHglbGx4XG4iLCBtb2RpZmll cik7Cj4gKwo+ICsJCXJldHVybiBmYWxzZTsKPiArCX0KPiArCj4gKwlyZXR1cm4gdm9wMl9jb252 ZXJ0X2FmYmNfZm9ybWF0KGZvcm1hdCkgPj0gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCB2b3Ay X2FmYmNfaGFsZl9ibG9ja19lbmFibGUoc3RydWN0IGRybV9wbGFuZV9zdGF0ZSAqcHN0YXRlKQo+ ICt7Cj4gKwlpZiAoKHBzdGF0ZS0+cm90YXRpb24gJiBEUk1fTU9ERV9ST1RBVEVfMjcwKSB8fCAo cHN0YXRlLT5yb3RhdGlvbiAmIERSTV9NT0RFX1JPVEFURV85MCkpCj4gKwkJcmV0dXJuIDA7Cj4g KwllbHNlCj4gKwkJcmV0dXJuIDE7Cj4gK30KPiArCj4gK3N0YXRpYyB1aW50MzJfdCB2b3AyX2Fm YmNfdHJhbnNmb3JtX29mZnNldChzdHJ1Y3QgZHJtX3BsYW5lX3N0YXRlICpwc3RhdGUsCj4gKwkJ CQkJICAgYm9vbCBhZmJjX2hhbGZfYmxvY2tfZW4pCj4gK3sKPiArCXN0cnVjdCBkcm1fcmVjdCAq c3JjID0gJnBzdGF0ZS0+c3JjOwo+ICsJc3RydWN0IGRybV9mcmFtZWJ1ZmZlciAqZmIgPSBwc3Rh dGUtPmZiOwo+ICsJdWludDMyX3QgYnBwID0gZmItPmZvcm1hdC0+Y3BwWzBdICogODsKPiArCXVp bnQzMl90IHZpcl93aWR0aCA9IChmYi0+cGl0Y2hlc1swXSA8PCAzKSAvIGJwcDsKPiArCXVpbnQz Ml90IHdpZHRoID0gZHJtX3JlY3Rfd2lkdGgoc3JjKSA+PiAxNjsKPiArCXVpbnQzMl90IGhlaWdo dCA9IGRybV9yZWN0X2hlaWdodChzcmMpID4+IDE2Owo+ICsJdWludDMyX3QgYWN0X3hvZmZzZXQg PSBzcmMtPngxID4+IDE2Owo+ICsJdWludDMyX3QgYWN0X3lvZmZzZXQgPSBzcmMtPnkxID4+IDE2 Owo+ICsJdWludDMyX3QgYWxpZ24xNl9jcm9wID0gMDsKPiArCXVpbnQzMl90IGFsaWduNjRfY3Jv cCA9IDA7Cj4gKwl1aW50MzJfdCBoZWlnaHRfdG1wID0gMDsKPiArCXVpbnQzMl90IHRyYW5zZm9y bV90bXAgPSAwOwo+ICsJdWludDhfdCB0cmFuc2Zvcm1feG9mZnNldCA9IDA7Cj4gKwl1aW50OF90 IHRyYW5zZm9ybV95b2Zmc2V0ID0gMDsKPiArCXVpbnQ4X3QgdG9wX2Nyb3AgPSAwOwo+ICsJdWlu dDhfdCB0b3BfY3JvcF9saW5lX251bSA9IDA7Cj4gKwl1aW50OF90IGJvdHRvbV9jcm9wX2xpbmVf bnVtID0gMDsKPiArCj4gKwkvKiAxNiBwaXhlbCBhbGlnbiAqLwo+ICsJaWYgKGhlaWdodCAmIDB4 ZikKPiArCQlhbGlnbjE2X2Nyb3AgPSAxNiAtIChoZWlnaHQgJiAweGYpOwo+ICsKPiArCWhlaWdo dF90bXAgPSBoZWlnaHQgKyBhbGlnbjE2X2Nyb3A7Cj4gKwo+ICsJLyogNjQgcGl4ZWwgYWxpZ24g Ki8KPiArCWlmIChoZWlnaHRfdG1wICYgMHgzZikKPiArCQlhbGlnbjY0X2Nyb3AgPSA2NCAtICho ZWlnaHRfdG1wICYgMHgzZik7Cj4gKwo+ICsJdG9wX2Nyb3BfbGluZV9udW0gPSB0b3BfY3JvcCA8 PCAyOwo+ICsJaWYgKHRvcF9jcm9wID09IDApCj4gKwkJYm90dG9tX2Nyb3BfbGluZV9udW0gPSBh bGlnbjE2X2Nyb3AgKyBhbGlnbjY0X2Nyb3A7Cj4gKwllbHNlIGlmICh0b3BfY3JvcCA9PSAxKQo+ ICsJCWJvdHRvbV9jcm9wX2xpbmVfbnVtID0gYWxpZ24xNl9jcm9wICsgYWxpZ242NF9jcm9wICsg MTI7Cj4gKwllbHNlIGlmICh0b3BfY3JvcCA9PSAyKQo+ICsJCWJvdHRvbV9jcm9wX2xpbmVfbnVt ID0gYWxpZ24xNl9jcm9wICsgYWxpZ242NF9jcm9wICsgODsKPiArCj4gKwlzd2l0Y2ggKHBzdGF0 ZS0+cm90YXRpb24gJgo+ICsJCShEUk1fTU9ERV9SRUZMRUNUX1ggfAo+ICsJCSBEUk1fTU9ERV9S RUZMRUNUX1kgfAo+ICsJCSBEUk1fTU9ERV9ST1RBVEVfOTAgfAo+ICsJCSBEUk1fTU9ERV9ST1RB VEVfMjcwKSkgewo+ICsJY2FzZSBEUk1fTU9ERV9SRUZMRUNUX1ggfCBEUk1fTU9ERV9SRUZMRUNU X1k6Cj4gKwkJdHJhbnNmb3JtX3RtcCA9IGFjdF94b2Zmc2V0ICsgd2lkdGg7Cj4gKwkJdHJhbnNm b3JtX3hvZmZzZXQgPSAxNiAtICh0cmFuc2Zvcm1fdG1wICYgMHhmKTsKPiArCQl0cmFuc2Zvcm1f dG1wID0gYm90dG9tX2Nyb3BfbGluZV9udW0gLSBhY3RfeW9mZnNldDsKPiArCj4gKwkJaWYgKGFm YmNfaGFsZl9ibG9ja19lbikKPiArCQkJdHJhbnNmb3JtX3lvZmZzZXQgPSB0cmFuc2Zvcm1fdG1w ICYgMHg3Owo+ICsJCWVsc2UKPiArCQkJdHJhbnNmb3JtX3lvZmZzZXQgPSAodHJhbnNmb3JtX3Rt cCAmIDB4Zik7Cj4gKwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBEUk1fTU9ERV9SRUZMRUNUX1ggfCBE Uk1fTU9ERV9ST1RBVEVfOTA6Cj4gKwkJdHJhbnNmb3JtX3RtcCA9IGJvdHRvbV9jcm9wX2xpbmVf bnVtIC0gYWN0X3lvZmZzZXQ7Cj4gKwkJdHJhbnNmb3JtX3hvZmZzZXQgPSB0cmFuc2Zvcm1fdG1w ICYgMHhmOwo+ICsJCXRyYW5zZm9ybV90bXAgPSB2aXJfd2lkdGggLSB3aWR0aCAtIGFjdF94b2Zm c2V0Owo+ICsJCXRyYW5zZm9ybV95b2Zmc2V0ID0gdHJhbnNmb3JtX3RtcCAmIDB4ZjsKPiArCQli cmVhazsKPiArCWNhc2UgRFJNX01PREVfUkVGTEVDVF9YIHwgRFJNX01PREVfUk9UQVRFXzI3MDoK PiArCQl0cmFuc2Zvcm1fdG1wID0gdG9wX2Nyb3BfbGluZV9udW0gKyBhY3RfeW9mZnNldDsKPiAr CQl0cmFuc2Zvcm1feG9mZnNldCA9IHRyYW5zZm9ybV90bXAgJiAweGY7Cj4gKwkJdHJhbnNmb3Jt X3RtcCA9IGFjdF94b2Zmc2V0Owo+ICsJCXRyYW5zZm9ybV95b2Zmc2V0ID0gdHJhbnNmb3JtX3Rt cCAmIDB4ZjsKPiArCQlicmVhazsKPiArCWNhc2UgRFJNX01PREVfUkVGTEVDVF9YOgo+ICsJCXRy YW5zZm9ybV90bXAgPSBhY3RfeG9mZnNldCArIHdpZHRoOwo+ICsJCXRyYW5zZm9ybV94b2Zmc2V0 ID0gMTYgLSAodHJhbnNmb3JtX3RtcCAmIDB4Zik7Cj4gKwkJdHJhbnNmb3JtX3RtcCA9IHRvcF9j cm9wX2xpbmVfbnVtICsgYWN0X3lvZmZzZXQ7Cj4gKwo+ICsJCWlmIChhZmJjX2hhbGZfYmxvY2tf ZW4pCj4gKwkJCXRyYW5zZm9ybV95b2Zmc2V0ID0gdHJhbnNmb3JtX3RtcCAmIDB4NzsKPiArCQll bHNlCj4gKwkJCXRyYW5zZm9ybV95b2Zmc2V0ID0gdHJhbnNmb3JtX3RtcCAmIDB4ZjsKPiArCj4g KwkJYnJlYWs7Cj4gKwljYXNlIERSTV9NT0RFX1JFRkxFQ1RfWToKPiArCQl0cmFuc2Zvcm1fdG1w ID0gYWN0X3hvZmZzZXQ7Cj4gKwkJdHJhbnNmb3JtX3hvZmZzZXQgPSB0cmFuc2Zvcm1fdG1wICYg MHhmOwo+ICsJCXRyYW5zZm9ybV90bXAgPSBib3R0b21fY3JvcF9saW5lX251bSAtIGFjdF95b2Zm c2V0Owo+ICsKPiArCQlpZiAoYWZiY19oYWxmX2Jsb2NrX2VuKQo+ICsJCQl0cmFuc2Zvcm1feW9m ZnNldCA9IHRyYW5zZm9ybV90bXAgJiAweDc7Cj4gKwkJZWxzZQo+ICsJCQl0cmFuc2Zvcm1feW9m ZnNldCA9IHRyYW5zZm9ybV90bXAgJiAweGY7Cj4gKwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBEUk1f TU9ERV9ST1RBVEVfOTA6Cj4gKwkJdHJhbnNmb3JtX3RtcCA9IGJvdHRvbV9jcm9wX2xpbmVfbnVt IC0gYWN0X3lvZmZzZXQ7Cj4gKwkJdHJhbnNmb3JtX3hvZmZzZXQgPSB0cmFuc2Zvcm1fdG1wICYg MHhmOwo+ICsJCXRyYW5zZm9ybV90bXAgPSBhY3RfeG9mZnNldDsKPiArCQl0cmFuc2Zvcm1feW9m ZnNldCA9IHRyYW5zZm9ybV90bXAgJiAweGY7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIERSTV9NT0RF X1JPVEFURV8yNzA6Cj4gKwkJdHJhbnNmb3JtX3RtcCA9IHRvcF9jcm9wX2xpbmVfbnVtICsgYWN0 X3lvZmZzZXQ7Cj4gKwkJdHJhbnNmb3JtX3hvZmZzZXQgPSB0cmFuc2Zvcm1fdG1wICYgMHhmOwo+ ICsJCXRyYW5zZm9ybV90bXAgPSB2aXJfd2lkdGggLSB3aWR0aCAtIGFjdF94b2Zmc2V0Owo+ICsJ CXRyYW5zZm9ybV95b2Zmc2V0ID0gdHJhbnNmb3JtX3RtcCAmIDB4ZjsKPiArCQlicmVhazsKPiAr CWNhc2UgMDoKPiArCQl0cmFuc2Zvcm1fdG1wID0gYWN0X3hvZmZzZXQ7Cj4gKwkJdHJhbnNmb3Jt X3hvZmZzZXQgPSB0cmFuc2Zvcm1fdG1wICYgMHhmOwo+ICsJCXRyYW5zZm9ybV90bXAgPSB0b3Bf Y3JvcF9saW5lX251bSArIGFjdF95b2Zmc2V0Owo+ICsKPiArCQlpZiAoYWZiY19oYWxmX2Jsb2Nr X2VuKQo+ICsJCQl0cmFuc2Zvcm1feW9mZnNldCA9IHRyYW5zZm9ybV90bXAgJiAweDc7Cj4gKwkJ ZWxzZQo+ICsJCQl0cmFuc2Zvcm1feW9mZnNldCA9IHRyYW5zZm9ybV90bXAgJiAweGY7Cj4gKwo+ ICsJCWJyZWFrOwo+ICsJfQo+ICsKPiArCXJldHVybiAodHJhbnNmb3JtX3hvZmZzZXQgJiAweGYp IHwgKCh0cmFuc2Zvcm1feW9mZnNldCAmIDB4ZikgPDwgMTYpOwo+ICt9Cj4gKwo+ICsvKgo+ICsg KiBBIENsdXN0ZXIgd2luZG93IGhhcyAyMDQ4IHggMTYgbGluZSBidWZmZXIsIHdoaWNoIGNhbgo+ ICsgKiB3b3JrcyBhdCAyMDQ4IHggMTYoRnVsbCkgb3IgNDA5NiB4IDggKEhhbGYpIG1vZGUuCj4g KyAqIGZvciBDbHVzdGVyX2xiX21vZGUgcmVnaXN0ZXI6Cj4gKyAqIDA6IGhhbGYgbW9kZSwgZm9y IHBsYW5lIGlucHV0IHdpZHRoIHJhbmdlIDIwNDggfiA0MDk2Cj4gKyAqIDE6IGhhbGYgbW9kZSwg Zm9yIGNsdXN0ZXIgd29yayBhdCAyICogMjA0OCBwbGFuZSBtb2RlCj4gKyAqIDI6IGhhbGYgbW9k ZSwgZm9yIHJvdGF0ZV85MC8yNzAgbW9kZQo+ICsgKgo+ICsgKi8KPiArc3RhdGljIGludCB2b3Ay X2dldF9jbHVzdGVyX2xiX21vZGUoc3RydWN0IHZvcDJfd2luICp3aW4sIHN0cnVjdCBkcm1fcGxh bmVfc3RhdGUgKnBzdGF0ZSkKPiArewo+ICsJaWYgKChwc3RhdGUtPnJvdGF0aW9uICYgRFJNX01P REVfUk9UQVRFXzI3MCkgfHwgKHBzdGF0ZS0+cm90YXRpb24gJiBEUk1fTU9ERV9ST1RBVEVfOTAp KQo+ICsJCXJldHVybiAyOwo+ICsJZWxzZQo+ICsJCXJldHVybiAwOwo+ICt9Cj4gKwo+ICsvKgo+ ICsgKiBibGlfc2RfZmFjdG9yID0gKHNyYyAtIDEpIC8gKGRzdCAtIDEpIDw8IDEyOwo+ICsgKiBh dmdfc2RfZmFjdG9yOgo+ICsgKiBibGlfc3VfZmFjdG9yOgo+ICsgKiBiaWNfc3VfZmFjdG9yOgo+ ICsgKiA9IChzcmMgLSAxKSAvIChkc3QgLSAxKSA8PCAxNjsKPiArICoKPiArICogZ3QyIGVuYWJs ZTogZHN0IGdldCBvbmUgbGluZSBmcm9tIHR3byBsaW5lIG9mIHRoZSBzcmMKPiArICogZ3Q0IGVu YWJsZTogZHN0IGdldCBvbmUgbGluZSBmcm9tIGZvdXIgbGluZSBvZiB0aGUgc3JjLgo+ICsgKgo+ ICsgKi8KPiArc3RhdGljIHVpbnQxNl90IHZvcDJfc2NhbGVfZmFjdG9yKGVudW0gc2NhbGVfbW9k ZSBtb2RlLAo+ICsJCQkJICBpbnQzMl90IGZpbHRlcl9tb2RlLAo+ICsJCQkJICB1aW50MzJfdCBz cmMsIHVpbnQzMl90IGRzdCkKPiArewo+ICsJdWludDMyX3QgZmFjOwo+ICsJaW50IGk7Cj4gKwo+ ICsJaWYgKG1vZGUgPT0gU0NBTEVfTk9ORSkKPiArCQlyZXR1cm4gMDsKPiArCj4gKwkvKgo+ICsJ ICogQSB3b3JrYXJvdW5kIHRvIGF2b2lkIHplcm8gZGl2Lgo+ICsJICovCj4gKwlpZiAoZHN0ID09 IDEgfHwgc3JjID09IDEpIHsKPiArCQlkc3QrKzsKPiArCQlzcmMrKzsKPiArCX0KPiArCj4gKwlp ZiAoKG1vZGUgPT0gU0NBTEVfRE9XTikgJiYgKGZpbHRlcl9tb2RlID09IFZPUDJfU0NBTEVfRE9X Tl9CSUwpKSB7Cj4gKwkJZmFjID0gKChzcmMgLSAxKSA8PCAxMikgLyAoZHN0IC0gMSk7Cj4gKwkJ Zm9yIChpID0gMDsgaSA8IDEwMDsgaSsrKSB7Cj4gKwkJCWlmIChmYWMgKiAoZHN0IC0gMSkgPj4g MTIgPCAoc3JjIC0gMSkpCj4gKwkJCQlicmVhazsKPiArCQkJZmFjIC09IDE7Cj4gKwkJCURSTV9E RUJVRygiZG93biBmYWMgY2FsaTogc3JjOiVkLCBkc3Q6JWQsIGZhYzoweCV4XG4iLCBzcmMsIGRz dCwgZmFjKTsKPiArCQl9Cj4gKwl9IGVsc2Ugewo+ICsJCWZhYyA9ICgoc3JjIC0gMSkgPDwgMTYp IC8gKGRzdCAtIDEpOwo+ICsJCWZvciAoaSA9IDA7IGkgPCAxMDA7IGkrKykgewo+ICsJCQlpZiAo ZmFjICogKGRzdCAtIDEpID4+IDE2IDwgKHNyYyAtIDEpKQo+ICsJCQkJYnJlYWs7Cj4gKwkJCWZh YyAtPSAxOwo+ICsJCQlEUk1fREVCVUcoInVwIGZhYyBjYWxpOiAgc3JjOiVkLCBkc3Q6JWQsIGZh YzoweCV4XG4iLCBzcmMsIGRzdCwgZmFjKTsKPiArCQl9Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIGZh YzsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgdm9wMl9zZXR1cF9zY2FsZShzdHJ1Y3Qgdm9wMiAq dm9wMiwgY29uc3Qgc3RydWN0IHZvcDJfd2luICp3aW4sCj4gKwkJCSAgICAgdWludDMyX3Qgc3Jj X3csIHVpbnQzMl90IHNyY19oLCB1aW50MzJfdCBkc3RfdywKPiArCQkJICAgICB1aW50MzJfdCBk c3RfaCwgdWludDMyX3QgcGl4ZWxfZm9ybWF0KQo+ICt7Cj4gKwljb25zdCBzdHJ1Y3QgZHJtX2Zv cm1hdF9pbmZvICppbmZvOwo+ICsJdWludDE2X3QgY2Jjcl9zcmNfdzsKPiArCXVpbnQxNl90IGNi Y3Jfc3JjX2g7Cj4gKwl1aW50MTZfdCB5cmdiX2hvcl9zY2xfbW9kZSwgeXJnYl92ZXJfc2NsX21v ZGU7Cj4gKwl1aW50MTZfdCBjYmNyX2hvcl9zY2xfbW9kZSwgY2Jjcl92ZXJfc2NsX21vZGU7Cj4g Kwl1aW50MTZfdCBoc2NsX2ZpbHRlcl9tb2RlLCB2c2NsX2ZpbHRlcl9tb2RlOwo+ICsJdWludDhf dCBndDIgPSAwOwo+ICsJdWludDhfdCBndDQgPSAwOwo+ICsJdWludDMyX3QgdmFsOwo+ICsKPiAr CWluZm8gPSBkcm1fZm9ybWF0X2luZm8ocGl4ZWxfZm9ybWF0KTsKPiArCj4gKwljYmNyX3NyY193 ID0gc3JjX3cgLyBpbmZvLT5oc3ViOwo+ICsJY2Jjcl9zcmNfaCA9IHNyY19oIC8gaW5mby0+dnN1 YjsKPiArCj4gKwlpZiAoc3JjX2ggPj0gKDQgKiBkc3RfaCkpIHsKPiArCQlndDQgPSAxOwo+ICsJ CXNyY19oID4+PSAyOwo+ICsJfSBlbHNlIGlmIChzcmNfaCA+PSAoMiAqIGRzdF9oKSkgewo+ICsJ CWd0MiA9IDE7Cj4gKwkJc3JjX2ggPj49IDE7Cj4gKwl9Cj4gKwo+ICsJeXJnYl9ob3Jfc2NsX21v ZGUgPSBzY2xfZ2V0X3NjbF9tb2RlKHNyY193LCBkc3Rfdyk7Cj4gKwl5cmdiX3Zlcl9zY2xfbW9k ZSA9IHNjbF9nZXRfc2NsX21vZGUoc3JjX2gsIGRzdF9oKTsKPiArCj4gKwlpZiAoeXJnYl9ob3Jf c2NsX21vZGUgPT0gU0NBTEVfVVApCj4gKwkJaHNjbF9maWx0ZXJfbW9kZSA9IFZPUDJfU0NBTEVf VVBfQklDOwo+ICsJZWxzZQo+ICsJCWhzY2xfZmlsdGVyX21vZGUgPSBWT1AyX1NDQUxFX0RPV05f QklMOwo+ICsKPiArCWlmICh5cmdiX3Zlcl9zY2xfbW9kZSA9PSBTQ0FMRV9VUCkKPiArCQl2c2Ns X2ZpbHRlcl9tb2RlID0gVk9QMl9TQ0FMRV9VUF9CSUw7Cj4gKwllbHNlCj4gKwkJdnNjbF9maWx0 ZXJfbW9kZSA9IFZPUDJfU0NBTEVfRE9XTl9CSUw7Cj4gKwo+ICsJLyoKPiArCSAqIFJLMzU2OCBW T1AgRXNtYXJ0L1NtYXJ0IGRzcF93IHNob3VsZCBiZSBldmVuIHBpeGVsCj4gKwkgKiBhdCBzY2Fs ZSBkb3duIG1vZGUKPiArCSAqLwo+ICsJaWYgKCEod2luLT5kYXRhLT5mZWF0dXJlICYgV0lOX0ZF QVRVUkVfQUZCREMpKSB7Cj4gKwkJaWYgKCh5cmdiX2hvcl9zY2xfbW9kZSA9PSBTQ0FMRV9ET1dO KSAmJiAoZHN0X3cgJiAweDEpKSB7Cj4gKwkJCWRybV9kYmcodm9wMi0+ZHJtLCAiJXMgZHN0X3db JWRdIHNob3VsZCBhbGlnbiBhcyAyIHBpeGVsXG4iLAo+ICsJCQkJd2luLT5kYXRhLT5uYW1lLCBk c3Rfdyk7Cj4gKwkJCWRzdF93ICs9IDE7Cj4gKwkJfQo+ICsJfQo+ICsKPiArCXZhbCA9IHZvcDJf c2NhbGVfZmFjdG9yKHlyZ2JfaG9yX3NjbF9tb2RlLCBoc2NsX2ZpbHRlcl9tb2RlLAo+ICsJCQkJ c3JjX3csIGRzdF93KTsKPiArCXZvcDJfd2luX3dyaXRlKHdpbiwgVk9QMl9XSU5fU0NBTEVfWVJH Ql9YLCB2YWwpOwo+ICsJdmFsID0gdm9wMl9zY2FsZV9mYWN0b3IoeXJnYl92ZXJfc2NsX21vZGUs IHZzY2xfZmlsdGVyX21vZGUsCj4gKwkJCQlzcmNfaCwgZHN0X2gpOwo+ICsJdm9wMl93aW5fd3Jp dGUod2luLCBWT1AyX1dJTl9TQ0FMRV9ZUkdCX1ksIHZhbCk7Cj4gKwo+ICsJdm9wMl93aW5fd3Jp dGUod2luLCBWT1AyX1dJTl9WU0RfWVJHQl9HVDQsIGd0NCk7Cj4gKwl2b3AyX3dpbl93cml0ZSh3 aW4sIFZPUDJfV0lOX1ZTRF9ZUkdCX0dUMiwgZ3QyKTsKPiArCj4gKwl2b3AyX3dpbl93cml0ZSh3 aW4sIFZPUDJfV0lOX1lSR0JfSE9SX1NDTF9NT0RFLCB5cmdiX2hvcl9zY2xfbW9kZSk7Cj4gKwl2 b3AyX3dpbl93cml0ZSh3aW4sIFZPUDJfV0lOX1lSR0JfVkVSX1NDTF9NT0RFLCB5cmdiX3Zlcl9z Y2xfbW9kZSk7Cj4gKwo+ICsJaWYgKHZvcDJfY2x1c3Rlcl93aW5kb3cod2luKSkKPiArCQlyZXR1 cm47Cj4gKwo+ICsJdm9wMl93aW5fd3JpdGUod2luLCBWT1AyX1dJTl9ZUkdCX0hTQ0xfRklMVEVS X01PREUsIGhzY2xfZmlsdGVyX21vZGUpOwo+ICsJdm9wMl93aW5fd3JpdGUod2luLCBWT1AyX1dJ Tl9ZUkdCX1ZTQ0xfRklMVEVSX01PREUsIHZzY2xfZmlsdGVyX21vZGUpOwo+ICsKPiArCWlmIChp bmZvLT5pc195dXYpIHsKPiArCQlndDQgPSBndDIgPSAwOwo+ICsKPiArCQlpZiAoY2Jjcl9zcmNf aCA+PSAoNCAqIGRzdF9oKSkKPiArCQkJZ3Q0ID0gMTsKPiArCQllbHNlIGlmIChjYmNyX3NyY19o ID49ICgyICogZHN0X2gpKQo+ICsJCQlndDIgPSAxOwo+ICsKPiArCQlpZiAoZ3Q0KQo+ICsJCQlj YmNyX3NyY19oID4+PSAyOwo+ICsJCWVsc2UgaWYgKGd0MikKPiArCQkJY2Jjcl9zcmNfaCA+Pj0g MTsKPiArCj4gKwkJY2Jjcl9ob3Jfc2NsX21vZGUgPSBzY2xfZ2V0X3NjbF9tb2RlKGNiY3Jfc3Jj X3csIGRzdF93KTsKPiArCQljYmNyX3Zlcl9zY2xfbW9kZSA9IHNjbF9nZXRfc2NsX21vZGUoY2Jj cl9zcmNfaCwgZHN0X2gpOwo+ICsKPiArCQl2YWwgPSB2b3AyX3NjYWxlX2ZhY3RvcihjYmNyX2hv cl9zY2xfbW9kZSwgaHNjbF9maWx0ZXJfbW9kZSwKPiArCQkJCQljYmNyX3NyY193LCBkc3Rfdyk7 Cj4gKwkJdm9wMl93aW5fd3JpdGUod2luLCBWT1AyX1dJTl9TQ0FMRV9DQkNSX1gsIHZhbCk7Cj4g Kwo+ICsJCXZhbCA9IHZvcDJfc2NhbGVfZmFjdG9yKGNiY3JfdmVyX3NjbF9tb2RlLCB2c2NsX2Zp bHRlcl9tb2RlLAo+ICsJCQkJCWNiY3Jfc3JjX2gsIGRzdF9oKTsKPiArCQl2b3AyX3dpbl93cml0 ZSh3aW4sIFZPUDJfV0lOX1NDQUxFX0NCQ1JfWSwgdmFsKTsKPiArCj4gKwkJdm9wMl93aW5fd3Jp dGUod2luLCBWT1AyX1dJTl9WU0RfQ0JDUl9HVDQsIGd0NCk7Cj4gKwkJdm9wMl93aW5fd3JpdGUo d2luLCBWT1AyX1dJTl9WU0RfQ0JDUl9HVDIsIGd0Mik7Cj4gKwkJdm9wMl93aW5fd3JpdGUod2lu LCBWT1AyX1dJTl9DQkNSX0hPUl9TQ0xfTU9ERSwgY2Jjcl9ob3Jfc2NsX21vZGUpOwo+ICsJCXZv cDJfd2luX3dyaXRlKHdpbiwgVk9QMl9XSU5fQ0JDUl9WRVJfU0NMX01PREUsIGNiY3JfdmVyX3Nj bF9tb2RlKTsKPiArCQl2b3AyX3dpbl93cml0ZSh3aW4sIFZPUDJfV0lOX0NCQ1JfSFNDTF9GSUxU RVJfTU9ERSwgaHNjbF9maWx0ZXJfbW9kZSk7Cj4gKwkJdm9wMl93aW5fd3JpdGUod2luLCBWT1Ay X1dJTl9DQkNSX1ZTQ0xfRklMVEVSX01PREUsIHZzY2xfZmlsdGVyX21vZGUpOwo+ICsJfQo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW50IHZvcDJfY29udmVydF9jc2NfbW9kZShpbnQgY3NjX21vZGUpCj4g K3sKPiArCXN3aXRjaCAoY3NjX21vZGUpIHsKPiArCWNhc2UgVjRMMl9DT0xPUlNQQUNFX1NNUFRF MTcwTToKPiArCWNhc2UgVjRMMl9DT0xPUlNQQUNFXzQ3MF9TWVNURU1fTToKPiArCWNhc2UgVjRM Ml9DT0xPUlNQQUNFXzQ3MF9TWVNURU1fQkc6Cj4gKwkJcmV0dXJuIENTQ19CVDYwMUw7Cj4gKwlj YXNlIFY0TDJfQ09MT1JTUEFDRV9SRUM3MDk6Cj4gKwljYXNlIFY0TDJfQ09MT1JTUEFDRV9TTVBU RTI0ME06Cj4gKwljYXNlIFY0TDJfQ09MT1JTUEFDRV9ERUZBVUxUOgo+ICsJCXJldHVybiBDU0Nf QlQ3MDlMOwo+ICsJY2FzZSBWNEwyX0NPTE9SU1BBQ0VfSlBFRzoKPiArCQlyZXR1cm4gQ1NDX0JU NjAxRjsKPiArCWNhc2UgVjRMMl9DT0xPUlNQQUNFX0JUMjAyMDoKPiArCQlyZXR1cm4gQ1NDX0JU MjAyMDsKPiArCWRlZmF1bHQ6Cj4gKwkJcmV0dXJuIENTQ19CVDcwOUw7Cj4gKwl9Cj4gK30KPiAr Cj4gKy8qCj4gKyAqIGNvbG9yc3BhY2UgcGF0aDoKPiArICogICAgICBJbnB1dCAgICAgICAgV2lu IGNzYyAgICAgICAgICAgICAgICAgICAgIE91dHB1dAo+ICsgKiAxLiBZVVYoMjAyMCkgIC0tPiBZ MlItPjIwMjBUbzcwOS0+UjJZICAgLS0+IFlVVl9PVVRQVVQoNjAxLzcwOSkKPiArICogICAgUkdC ICAgICAgICAtLT4gUjJZICAgICAgICAgICAgICAgICAgX18vCj4gKyAqCj4gKyAqIDIuIFlVVigy MDIwKSAgLS0+IGJ5cGFzc3MgICAgICAgICAgICAgICAtLT4gWVVWX09VVFBVVCgyMDIwKQo+ICsg KiAgICBSR0IgICAgICAgIC0tPiA3MDlUbzIwMjAtPlIyWSAgICAgICBfXy8KPiArICoKPiArICog My4gWVVWKDIwMjApICAtLT4gWTJSLT4yMDIwVG83MDkgICAgICAgIC0tPiBSR0JfT1VUUFVUKDcw OSkKPiArICogICAgUkdCICAgICAgICAtLT4gUjJZICAgICAgICAgICAgICAgICAgX18vCj4gKyAq Cj4gKyAqIDQuIFlVVig2MDEvNzA5KS0+IFkyUi0+NzA5VG8yMDIwLT5SMlkgICAtLT4gWVVWX09V VFBVVCgyMDIwKQo+ICsgKiAgICBSR0IgICAgICAgIC0tPiA3MDlUbzIwMjAtPlIyWSAgICAgICBf Xy8KPiArICoKPiArICogNS4gWVVWKDYwMS83MDkpLT4gYnlwYXNzICAgICAgICAgICAgICAgIC0t PiBZVVZfT1VUUFVUKDcwOSkKPiArICogICAgUkdCICAgICAgICAtLT4gUjJZICAgICAgICAgICAg ICAgICAgX18vCj4gKyAqCj4gKyAqIDYuIFlVVig2MDEvNzA5KS0+IGJ5cGFzcyAgICAgICAgICAg ICAgICAtLT4gWVVWX09VVFBVVCg2MDEpCj4gKyAqICAgIFJHQiAgICAgICAgLS0+IFIyWSg2MDEp ICAgICAgICAgICAgIF9fLwo+ICsgKgo+ICsgKiA3LiBZVVYgICAgICAgIC0tPiBZMlIoNzA5KSAg ICAgICAgICAgICAgLS0+IFJHQl9PVVRQVVQoNzA5KQo+ICsgKiAgICBSR0IgICAgICAgIC0tPiBi eXBhc3MgICAgICAgICAgICAgICBfXy8KPiArICoKPiArICogOC4gUkdCICAgICAgICAtLT4gNzA5 VG8yMDIwLT5SMlkgICAgICAgIC0tPiBZVVZfT1VUUFVUKDIwMjApCj4gKyAqCj4gKyAqIDkuIFJH QiAgICAgICAgLS0+IFIyWSg3MDkpICAgICAgICAgICAgICAtLT4gWVVWX09VVFBVVCg3MDkpCj4g KyAqCj4gKyAqIDEwLiBSR0IgICAgICAgLS0+IFIyWSg2MDEpICAgICAgICAgICAgICAtLT4gWVVW X09VVFBVVCg2MDEpCj4gKyAqCj4gKyAqIDExLiBSR0IgICAgICAgLS0+IGJ5cGFzcyAgICAgICAg ICAgICAgICAtLT4gUkdCX09VVFBVVCg3MDkpCj4gKyAqLwo+ICsKPiArc3RhdGljIHZvaWQgdm9w Ml9zZXR1cF9jc2NfbW9kZShzdHJ1Y3Qgdm9wMl92aWRlb19wb3J0ICp2cCwKPiArCQkJCXN0cnVj dCB2b3AyX3dpbiAqd2luLAo+ICsJCQkJc3RydWN0IGRybV9wbGFuZV9zdGF0ZSAqcHN0YXRlKQo+ ICt7Cj4gKwlzdHJ1Y3Qgcm9ja2NoaXBfY3J0Y19zdGF0ZSAqdmNzdGF0ZSA9IHRvX3JvY2tjaGlw X2NydGNfc3RhdGUodnAtPmNydGMuc3RhdGUpOwo+ICsJaW50IGlzX2lucHV0X3l1diA9IHBzdGF0 ZS0+ZmItPmZvcm1hdC0+aXNfeXV2Owo+ICsJaW50IGlzX291dHB1dF95dXYgPSBpc195dXZfb3V0 cHV0KHZjc3RhdGUtPmJ1c19mb3JtYXQpOwo+ICsJaW50IGlucHV0X2NzYyA9IFY0TDJfQ09MT1JT UEFDRV9ERUZBVUxUOwo+ICsJaW50IG91dHB1dF9jc2MgPSB2Y3N0YXRlLT5jb2xvcl9zcGFjZTsK PiArCWJvb2wgcjJ5X2VuLCB5MnJfZW47Cj4gKwlpbnQgY3NjX21vZGU7Cj4gKwo+ICsJaWYgKGlz X2lucHV0X3l1diAmJiAhaXNfb3V0cHV0X3l1dikgewo+ICsJCXkycl9lbiA9IDE7Cj4gKwkJcjJ5 X2VuID0gMDsKPiArCQljc2NfbW9kZSA9IHZvcDJfY29udmVydF9jc2NfbW9kZShpbnB1dF9jc2Mp Owo+ICsJfSBlbHNlIGlmICghaXNfaW5wdXRfeXV2ICYmIGlzX291dHB1dF95dXYpIHsKPiArCQl5 MnJfZW4gPSAwOwo+ICsJCXIyeV9lbiA9IDE7Cj4gKwkJY3NjX21vZGUgPSB2b3AyX2NvbnZlcnRf Y3NjX21vZGUob3V0cHV0X2NzYyk7Cj4gKwl9IGVsc2Ugewo+ICsJCXkycl9lbiA9IDA7Cj4gKwkJ cjJ5X2VuID0gMDsKPiArCQljc2NfbW9kZSA9IDA7Cj4gKwl9Cj4gKwo+ICsJdm9wMl93aW5fd3Jp dGUod2luLCBWT1AyX1dJTl9ZMlJfRU4sIHkycl9lbik7Cj4gKwl2b3AyX3dpbl93cml0ZSh3aW4s IFZPUDJfV0lOX1IyWV9FTiwgcjJ5X2VuKTsKPiArCXZvcDJfd2luX3dyaXRlKHdpbiwgVk9QMl9X SU5fQ1NDX01PREUsIGNzY19tb2RlKTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgdm9wMl9jcnRj X2VuYWJsZV9pcnEoc3RydWN0IHZvcDJfdmlkZW9fcG9ydCAqdnAsIHVpbnQzMl90IGlycSkKPiAr ewo+ICsJc3RydWN0IHZvcDIgKnZvcDIgPSB2cC0+dm9wMjsKPiArCj4gKwl2b3AyX3dyaXRlbCh2 b3AyLCBSSzM1NjhfVlBfSU5UX0NMUih2cC0+aWQpLCBpcnEgPDwgMTYgfCBpcnEpOwo+ICsJdm9w Ml93cml0ZWwodm9wMiwgUkszNTY4X1ZQX0lOVF9FTih2cC0+aWQpLCBpcnEgPDwgMTYgfCBpcnEp Owo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2b3AyX2NydGNfZGlzYWJsZV9pcnEoc3RydWN0IHZv cDJfdmlkZW9fcG9ydCAqdnAsIHVpbnQzMl90IGlycSkKPiArewo+ICsJc3RydWN0IHZvcDIgKnZv cDIgPSB2cC0+dm9wMjsKPiArCj4gKwl2b3AyX3dyaXRlbCh2b3AyLCBSSzM1NjhfVlBfSU5UX0VO KHZwLT5pZCksIGlycSA8PCAxNik7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdm9wMl9jb3JlX2Ns a3NfcHJlcGFyZV9lbmFibGUoc3RydWN0IHZvcDIgKnZvcDIpCj4gK3sKPiArCWludCByZXQ7Cj4g Kwo+ICsJcmV0ID0gY2xrX3ByZXBhcmVfZW5hYmxlKHZvcDItPmhjbGspOwo+ICsJaWYgKHJldCA8 IDApIHsKPiArCQlkcm1fZXJyKHZvcDItPmRybSwgImZhaWxlZCB0byBlbmFibGUgaGNsayAtICVk XG4iLCByZXQpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0ID0gY2xrX3ByZXBh cmVfZW5hYmxlKHZvcDItPmFjbGspOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlkcm1fZXJyKHZv cDItPmRybSwgImZhaWxlZCB0byBlbmFibGUgYWNsayAtICVkXG4iLCByZXQpOwo+ICsJCWdvdG8g ZXJyOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICtlcnI6Cj4gKwljbGtfZGlzYWJsZV91bnBy ZXBhcmUodm9wMi0+aGNsayk7Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGlj IHZvaWQgdm9wMl9lbmFibGUoc3RydWN0IHZvcDIgKnZvcDIpCj4gK3sKPiArCWludCByZXQ7Cj4g Kwl1aW50MzJfdCB2Owo+ICsKPiArCXJldCA9IHBtX3J1bnRpbWVfZ2V0X3N5bmModm9wMi0+ZGV2 KTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJZHJtX2Vycih2b3AyLT5kcm0sICJmYWlsZWQgdG8g Z2V0IHBtIHJ1bnRpbWU6ICVkXG4iLCByZXQpOwo+ICsJCXJldHVybjsKPiArCX0KPiArCj4gKwly ZXQgPSB2b3AyX2NvcmVfY2xrc19wcmVwYXJlX2VuYWJsZSh2b3AyKTsKPiArCWlmIChyZXQpIHsK PiArCQlwbV9ydW50aW1lX3B1dF9zeW5jKHZvcDItPmRldik7Cj4gKwkJcmV0dXJuOwo+ICsJfQo+ ICsKPiArCWlmICh2b3AyLT5kYXRhLT5zb2NfaWQgPT0gMzU2NikKPiArCQl2b3AyX3dyaXRlbCh2 b3AyLCBSSzM1NjhfT1RQX1dJTl9FTiwgMSk7Cj4gKwo+ICsJdm9wMl93cml0ZWwodm9wMiwgUksz NTY4X1JFR19DRkdfRE9ORSwgUkszNTY4X1JFR19DRkdfRE9ORV9fR0xCX0NGR19ET05FX0VOKTsK PiArCj4gKwkvKgo+ICsJICogRGlzYWJsZSBhdXRvIGdhdGluZywgdGhpcyBpcyBhIHdvcmthcm91 bmQgdG8KPiArCSAqIGF2b2lkIGRpc3BsYXkgaW1hZ2Ugc2hpZnQgd2hlbiBhIHdpbmRvdyBlbmFi bGVkLgo+ICsJICovCj4gKwl2ID0gdm9wMl9yZWFkbCh2b3AyLCBSSzM1NjhfU1lTX0FVVE9fR0FU SU5HX0NUUkwpOwo+ICsJdiAmPSB+UkszNTY4X1NZU19BVVRPX0dBVElOR19DVFJMX19BVVRPX0dB VElOR19FTjsKPiArCXZvcDJfd3JpdGVsKHZvcDIsIFJLMzU2OF9TWVNfQVVUT19HQVRJTkdfQ1RS TCwgdik7Cj4gKwo+ICsJdm9wMl93cml0ZWwodm9wMiwgUkszNTY4X1NZUzBfSU5UX0NMUiwKPiAr CQkgICAgVk9QMl9JTlRfQlVTX0VSUlBSIDw8IDE2IHwgVk9QMl9JTlRfQlVTX0VSUlBSKTsKPiAr CXZvcDJfd3JpdGVsKHZvcDIsIFJLMzU2OF9TWVMwX0lOVF9FTiwKPiArCQkgICAgVk9QMl9JTlRf QlVTX0VSUlBSIDw8IDE2IHwgVk9QMl9JTlRfQlVTX0VSUlBSKTsKPiArCXZvcDJfd3JpdGVsKHZv cDIsIFJLMzU2OF9TWVMxX0lOVF9DTFIsCj4gKwkJICAgIFZPUDJfSU5UX0JVU19FUlJQUiA8PCAx NiB8IFZPUDJfSU5UX0JVU19FUlJQUik7Cj4gKwl2b3AyX3dyaXRlbCh2b3AyLCBSSzM1NjhfU1lT MV9JTlRfRU4sCj4gKwkJICAgIFZPUDJfSU5UX0JVU19FUlJQUiA8PCAxNiB8IFZPUDJfSU5UX0JV U19FUlJQUik7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHZvcDJfZGlzYWJsZShzdHJ1Y3Qgdm9w MiAqdm9wMikKPiArewo+ICsJcG1fcnVudGltZV9wdXRfc3luYyh2b3AyLT5kZXYpOwo+ICsKPiAr CWNsa19kaXNhYmxlX3VucHJlcGFyZSh2b3AyLT5hY2xrKTsKPiArCWNsa19kaXNhYmxlX3VucHJl cGFyZSh2b3AyLT5oY2xrKTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgdm9wMl9jcnRjX2F0b21p Y19kaXNhYmxlKHN0cnVjdCBkcm1fY3J0YyAqY3J0YywKPiArCQkJCSAgICAgc3RydWN0IGRybV9h dG9taWNfc3RhdGUgKnN0YXRlKQo+ICt7Cj4gKwlzdHJ1Y3Qgdm9wMl92aWRlb19wb3J0ICp2cCA9 IHRvX3ZvcDJfdmlkZW9fcG9ydChjcnRjKTsKPiArCXN0cnVjdCB2b3AyICp2b3AyID0gdnAtPnZv cDI7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCXZvcDJfbG9jayh2b3AyKTsKPiArCj4gKwlkcm1fY3J0 Y192Ymxhbmtfb2ZmKGNydGMpOwo+ICsKPiArCS8qCj4gKwkgKiBWb3Agc3RhbmRieSB3aWxsIHRh a2UgZWZmZWN0IGF0IGVuZCBvZiBjdXJyZW50IGZyYW1lLAo+ICsJICogaWYgZHNwIGhvbGQgdmFs aWQgaXJxIGhhcHBlbiwgaXQgbWVhbnMgc3RhbmRieSBjb21wbGV0ZS4KPiArCSAqCj4gKwkgKiB3 ZSBtdXN0IHdhaXQgc3RhbmRieSBjb21wbGV0ZSB3aGVuIHdlIHdhbnQgdG8gZGlzYWJsZSBhY2xr LAo+ICsJICogaWYgbm90LCBtZW1vcnkgYnVzIG1heWJlIGRlYWQuCj4gKwkgKi8KPiArCXJlaW5p dF9jb21wbGV0aW9uKCZ2cC0+ZHNwX2hvbGRfY29tcGxldGlvbik7Cj4gKwo+ICsJdm9wMl9jcnRj X2VuYWJsZV9pcnEodnAsIFZQX0lOVF9EU1BfSE9MRF9WQUxJRCk7Cj4gKwlzcGluX2xvY2soJnZv cDItPnJlZ19sb2NrKTsKPiArCj4gKwl2b3AyX3dyaXRlbCh2b3AyLCBSSzM1NjhfVlBfRFNQX0NU UkwsIDEpOwo+ICsKPiArCXNwaW5fdW5sb2NrKCZ2b3AyLT5yZWdfbG9jayk7Cj4gKwo+ICsJcmV0 ID0gd2FpdF9mb3JfY29tcGxldGlvbl90aW1lb3V0KCZ2cC0+ZHNwX2hvbGRfY29tcGxldGlvbiwg bXNlY3NfdG9famlmZmllcyg1MCkpOwo+ICsJaWYgKCFyZXQpCj4gKwkJZHJtX2luZm8odm9wMi0+ ZHJtLCAid2FpdCBmb3IgdnAlZCBkc3BfaG9sZCB0aW1lb3V0XG4iLCB2cC0+aWQpOwo+ICsKPiAr CXZvcDJfY3J0Y19kaXNhYmxlX2lycSh2cCwgVlBfSU5UX0RTUF9IT0xEX1ZBTElEKTsKPiArCj4g KwljbGtfZGlzYWJsZV91bnByZXBhcmUodnAtPmRjbGspOwo+ICsKPiArCXZvcDItPmVuYWJsZV9j b3VudC0tOwo+ICsKPiArCWlmICghdm9wMi0+ZW5hYmxlX2NvdW50KQo+ICsJCXZvcDJfZGlzYWJs ZSh2b3AyKTsKPiArCj4gKwl2b3AyX3VubG9jayh2b3AyKTsKPiArCj4gKwlpZiAoY3J0Yy0+c3Rh dGUtPmV2ZW50ICYmICFjcnRjLT5zdGF0ZS0+YWN0aXZlKSB7Cj4gKwkJc3Bpbl9sb2NrX2lycSgm Y3J0Yy0+ZGV2LT5ldmVudF9sb2NrKTsKPiArCQlkcm1fY3J0Y19zZW5kX3ZibGFua19ldmVudChj cnRjLCBjcnRjLT5zdGF0ZS0+ZXZlbnQpOwo+ICsJCXNwaW5fdW5sb2NrX2lycSgmY3J0Yy0+ZGV2 LT5ldmVudF9sb2NrKTsKPiArCj4gKwkJY3J0Yy0+c3RhdGUtPmV2ZW50ID0gTlVMTDsKPiArCX0K PiArfQo+ICsKPiArc3RhdGljIGludCB2b3AyX3BsYW5lX2F0b21pY19jaGVjayhzdHJ1Y3QgZHJt X3BsYW5lICpwbGFuZSwgc3RydWN0IGRybV9hdG9taWNfc3RhdGUgKmFzdGF0ZSkKPiArewo+ICsJ c3RydWN0IGRybV9wbGFuZV9zdGF0ZSAqcHN0YXRlID0gZHJtX2F0b21pY19nZXRfbmV3X3BsYW5l X3N0YXRlKGFzdGF0ZSwgcGxhbmUpOwo+ICsJc3RydWN0IGRybV9mcmFtZWJ1ZmZlciAqZmIgPSBw c3RhdGUtPmZiOwo+ICsJc3RydWN0IGRybV9jcnRjICpjcnRjID0gcHN0YXRlLT5jcnRjOwo+ICsJ c3RydWN0IGRybV9jcnRjX3N0YXRlICpjc3RhdGU7Cj4gKwlzdHJ1Y3Qgdm9wMl92aWRlb19wb3J0 ICp2cDsKPiArCXN0cnVjdCB2b3AyICp2b3AyOwo+ICsJY29uc3Qgc3RydWN0IHZvcDJfZGF0YSAq dm9wMl9kYXRhOwo+ICsJc3RydWN0IGRybV9yZWN0ICpkZXN0ID0gJnBzdGF0ZS0+ZHN0Owo+ICsJ c3RydWN0IGRybV9yZWN0ICpzcmMgPSAmcHN0YXRlLT5zcmM7Cj4gKwlpbnQgbWluX3NjYWxlID0g RlJBQ18xNl8xNigxLCA4KTsKPiArCWludCBtYXhfc2NhbGUgPSBGUkFDXzE2XzE2KDgsIDEpOwo+ ICsJaW50IGZvcm1hdDsKPiArCWludCByZXQ7Cj4gKwo+ICsJaWYgKCFjcnRjKQo+ICsJCXJldHVy biAwOwo+ICsKPiArCXZwID0gdG9fdm9wMl92aWRlb19wb3J0KGNydGMpOwo+ICsJdm9wMiA9IHZw LT52b3AyOwo+ICsJdm9wMl9kYXRhID0gdm9wMi0+ZGF0YTsKPiArCj4gKwljc3RhdGUgPSBkcm1f YXRvbWljX2dldF9leGlzdGluZ19jcnRjX3N0YXRlKHBzdGF0ZS0+c3RhdGUsIGNydGMpOwo+ICsJ aWYgKFdBUk5fT04oIWNzdGF0ZSkpCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJcmV0ID0g ZHJtX2F0b21pY19oZWxwZXJfY2hlY2tfcGxhbmVfc3RhdGUocHN0YXRlLCBjc3RhdGUsCj4gKwkJ CQkJCSAgbWluX3NjYWxlLCBtYXhfc2NhbGUsCj4gKwkJCQkJCSAgdHJ1ZSwgdHJ1ZSk7Cj4gKwlp ZiAocmV0KQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJaWYgKCFwc3RhdGUtPnZpc2libGUpCj4g KwkJcmV0dXJuIDA7Cj4gKwo+ICsJZm9ybWF0ID0gdm9wMl9jb252ZXJ0X2Zvcm1hdChmYi0+Zm9y bWF0LT5mb3JtYXQpOwo+ICsJaWYgKGZvcm1hdCA8IDApCj4gKwkJcmV0dXJuIGZvcm1hdDsKPiAr Cj4gKwlpZiAoZHJtX3JlY3Rfd2lkdGgoc3JjKSA+PiAxNiA8IDQgfHwgZHJtX3JlY3RfaGVpZ2h0 KHNyYykgPj4gMTYgPCA0IHx8Cj4gKwkgICAgZHJtX3JlY3Rfd2lkdGgoZGVzdCkgPCA0IHx8IGRy bV9yZWN0X3dpZHRoKGRlc3QpIDwgNCkgewo+ICsJCWRybV9lcnIodm9wMi0+ZHJtLCAiSW52YWxp ZCBzaXplOiAlZHglZC0+JWR4JWQsIG1pbiBzaXplIGlzIDR4NFxuIiwKPiArCQkJICBkcm1fcmVj dF93aWR0aChzcmMpID4+IDE2LCBkcm1fcmVjdF9oZWlnaHQoc3JjKSA+PiAxNiwKPiArCQkJICBk cm1fcmVjdF93aWR0aChkZXN0KSwgZHJtX3JlY3RfaGVpZ2h0KGRlc3QpKTsKPiArCQlwc3RhdGUt PnZpc2libGUgPSBmYWxzZTsKPiArCQlyZXR1cm4gMDsKPiArCX0KPiArCj4gKwlpZiAoZHJtX3Jl Y3Rfd2lkdGgoc3JjKSA+PiAxNiA+IHZvcDJfZGF0YS0+bWF4X2lucHV0LndpZHRoIHx8Cj4gKwkg ICAgZHJtX3JlY3RfaGVpZ2h0KHNyYykgPj4gMTYgPiB2b3AyX2RhdGEtPm1heF9pbnB1dC5oZWln aHQpIHsKPiArCQlkcm1fZXJyKHZvcDItPmRybSwgIkludmFsaWQgc291cmNlOiAlZHglZC4gbWF4 IGlucHV0OiAlZHglZFxuIiwKPiArCQkJICBkcm1fcmVjdF93aWR0aChzcmMpID4+IDE2LAo+ICsJ CQkgIGRybV9yZWN0X2hlaWdodChzcmMpID4+IDE2LAo+ICsJCQkgIHZvcDJfZGF0YS0+bWF4X2lu cHV0LndpZHRoLAo+ICsJCQkgIHZvcDJfZGF0YS0+bWF4X2lucHV0LmhlaWdodCk7Cj4gKwkJcmV0 dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJLyoKPiArCSAqIFNyYy54MSBjYW4gYmUgb2RkIHdo ZW4gZG8gY2xpcCwgYnV0IHl1diBwbGFuZSBzdGFydCBwb2ludAo+ICsJICogbmVlZCBhbGlnbiB3 aXRoIDIgcGl4ZWwuCj4gKwkgKi8KPiArCWlmIChmYi0+Zm9ybWF0LT5pc195dXYgJiYgKChwc3Rh dGUtPnNyYy54MSA+PiAxNikgJSAyKSkgewo+ICsJCWRybV9lcnIodm9wMi0+ZHJtLCAiSW52YWxp ZCBTb3VyY2U6IFl1diBmb3JtYXQgbm90IHN1cHBvcnQgb2RkIHhwb3NcbiIpOwo+ICsJCXJldHVy biAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9p ZCB2b3AyX3BsYW5lX2F0b21pY19kaXNhYmxlKHN0cnVjdCBkcm1fcGxhbmUgKnBsYW5lLCBzdHJ1 Y3QgZHJtX2F0b21pY19zdGF0ZSAqc3RhdGUpCj4gK3sKPiArCXN0cnVjdCBkcm1fcGxhbmVfc3Rh dGUgKm9sZF9wc3RhdGUgPSBkcm1fYXRvbWljX2dldF9vbGRfcGxhbmVfc3RhdGUoc3RhdGUsIHBs YW5lKTsKPiArCXN0cnVjdCB2b3AyX3dpbiAqd2luID0gdG9fdm9wMl93aW4ocGxhbmUpOwo+ICsJ c3RydWN0IHZvcDIgKnZvcDIgPSB3aW4tPnZvcDI7Cj4gKwo+ICsJZHJtX2RiZyh2b3AyLT5kcm0s ICIlcyBkaXNhYmxlXG4iLCB3aW4tPmRhdGEtPm5hbWUpOwo+ICsKPiArCWlmICghb2xkX3BzdGF0 ZS0+Y3J0YykKPiArCQlyZXR1cm47Cj4gKwo+ICsJc3Bpbl9sb2NrKCZ2b3AyLT5yZWdfbG9jayk7 Cj4gKwo+ICsJdm9wMl93aW5fZGlzYWJsZSh3aW4pOwo+ICsJdm9wMl93aW5fd3JpdGUod2luLCBW T1AyX1dJTl9ZVVZfQ0xJUCwgMCk7Cj4gKwo+ICsJc3Bpbl91bmxvY2soJnZvcDItPnJlZ19sb2Nr KTsKPiArfQo+ICsKPiArLyoKPiArICogVGhlIGNvbG9yIGtleSBpcyAxMCBiaXQsIHNvIGFsbCBm b3JtYXQgc2hvdWxkCj4gKyAqIGNvbnZlcnQgdG8gMTAgYml0IGhlcmUuCj4gKyAqLwo+ICtzdGF0 aWMgdm9pZCB2b3AyX3BsYW5lX3NldHVwX2NvbG9yX2tleShzdHJ1Y3QgZHJtX3BsYW5lICpwbGFu ZSwgdWludDMyX3QgY29sb3Jfa2V5KQo+ICt7Cj4gKwlzdHJ1Y3QgZHJtX3BsYW5lX3N0YXRlICpw c3RhdGUgPSBwbGFuZS0+c3RhdGU7Cj4gKwlzdHJ1Y3QgZHJtX2ZyYW1lYnVmZmVyICpmYiA9IHBz dGF0ZS0+ZmI7Cj4gKwlzdHJ1Y3Qgdm9wMl93aW4gKndpbiA9IHRvX3ZvcDJfd2luKHBsYW5lKTsK PiArCXVpbnQzMl90IGNvbG9yX2tleV9lbiA9IDA7Cj4gKwl1aW50MzJfdCByID0gMDsKPiArCXVp bnQzMl90IGcgPSAwOwo+ICsJdWludDMyX3QgYiA9IDA7Cj4gKwo+ICsJaWYgKCEoY29sb3Jfa2V5 ICYgVk9QMl9DT0xPUl9LRVlfTUFTSykgfHwgZmItPmZvcm1hdC0+aXNfeXV2KSB7Cj4gKwkJdm9w Ml93aW5fd3JpdGUod2luLCBWT1AyX1dJTl9DT0xPUl9LRVlfRU4sIDApOwo+ICsJCXJldHVybjsK PiArCX0KPiArCj4gKwlzd2l0Y2ggKGZiLT5mb3JtYXQtPmZvcm1hdCkgewo+ICsJY2FzZSBEUk1f Rk9STUFUX1JHQjU2NToKPiArCWNhc2UgRFJNX0ZPUk1BVF9CR1I1NjU6Cj4gKwkJciA9IChjb2xv cl9rZXkgJiAweGY4MDApID4+IDExOwo+ICsJCWcgPSAoY29sb3Jfa2V5ICYgMHg3ZTApID4+IDU7 Cj4gKwkJYiA9IChjb2xvcl9rZXkgJiAweDFmKTsKPiArCQlyIDw8PSA1Owo+ICsJCWcgPDw9IDQ7 Cj4gKwkJYiA8PD0gNTsKPiArCQljb2xvcl9rZXlfZW4gPSAxOwo+ICsJCWJyZWFrOwo+ICsJY2Fz ZSBEUk1fRk9STUFUX1hSR0I4ODg4Ogo+ICsJY2FzZSBEUk1fRk9STUFUX0FSR0I4ODg4Ogo+ICsJ Y2FzZSBEUk1fRk9STUFUX1hCR1I4ODg4Ogo+ICsJY2FzZSBEUk1fRk9STUFUX0FCR1I4ODg4Ogo+ ICsJY2FzZSBEUk1fRk9STUFUX1JHQjg4ODoKPiArCWNhc2UgRFJNX0ZPUk1BVF9CR1I4ODg6Cj4g KwkJciA9IChjb2xvcl9rZXkgJiAweGZmMDAwMCkgPj4gMTY7Cj4gKwkJZyA9IChjb2xvcl9rZXkg JiAweGZmMDApID4+IDg7Cj4gKwkJYiA9IChjb2xvcl9rZXkgJiAweGZmKTsKPiArCQlyIDw8PSAy Owo+ICsJCWcgPDw9IDI7Cj4gKwkJYiA8PD0gMjsKPiArCQljb2xvcl9rZXlfZW4gPSAxOwo+ICsJ CWJyZWFrOwo+ICsJfQo+ICsKPiArCXZvcDJfd2luX3dyaXRlKHdpbiwgVk9QMl9XSU5fQ09MT1Jf S0VZX0VOLCBjb2xvcl9rZXlfZW4pOwo+ICsJdm9wMl93aW5fd3JpdGUod2luLCBWT1AyX1dJTl9D T0xPUl9LRVksIChyIDw8IDIwKSB8IChnIDw8IDEwKSB8IGIpOwo+ICt9Cj4gKwo+ICtzdGF0aWMg dm9pZCB2b3AyX3BsYW5lX2F0b21pY191cGRhdGUoc3RydWN0IGRybV9wbGFuZSAqcGxhbmUsIHN0 cnVjdCBkcm1fYXRvbWljX3N0YXRlICpzdGF0ZSkKPiArewo+ICsJc3RydWN0IGRybV9wbGFuZV9z dGF0ZSAqcHN0YXRlID0gcGxhbmUtPnN0YXRlOwo+ICsJc3RydWN0IGRybV9jcnRjICpjcnRjID0g cHN0YXRlLT5jcnRjOwo+ICsJc3RydWN0IHZvcDJfd2luICp3aW4gPSB0b192b3AyX3dpbihwbGFu ZSk7Cj4gKwlzdHJ1Y3Qgdm9wMl92aWRlb19wb3J0ICp2cCA9IHRvX3ZvcDJfdmlkZW9fcG9ydChj cnRjKTsKPiArCXN0cnVjdCBkcm1fZGlzcGxheV9tb2RlICphZGp1c3RlZF9tb2RlID0gJmNydGMt PnN0YXRlLT5hZGp1c3RlZF9tb2RlOwo+ICsJc3RydWN0IHZvcDIgKnZvcDIgPSB3aW4tPnZvcDI7 Cj4gKwlzdHJ1Y3QgZHJtX2ZyYW1lYnVmZmVyICpmYiA9IHBzdGF0ZS0+ZmI7Cj4gKwl1aW50MzJf dCBicHAgPSBmYi0+Zm9ybWF0LT5jcHBbMF0gKiA4Owo+ICsJdWludDMyX3QgYWN0dWFsX3csIGFj dHVhbF9oLCBkc3BfdywgZHNwX2g7Cj4gKwl1aW50MzJfdCBhY3RfaW5mbywgZHNwX2luZm87Cj4g Kwl1aW50MzJfdCBmb3JtYXQ7Cj4gKwl1aW50MzJfdCBhZmJjX2Zvcm1hdDsKPiArCXVpbnQzMl90 IHJiX3N3YXA7Cj4gKwl1aW50MzJfdCB1dl9zd2FwOwo+ICsJc3RydWN0IGRybV9yZWN0ICpzcmMg PSAmcHN0YXRlLT5zcmM7Cj4gKwlzdHJ1Y3QgZHJtX3JlY3QgKmRlc3QgPSAmcHN0YXRlLT5kc3Q7 Cj4gKwl1aW50MzJfdCBhZmJjX3RpbGVfbnVtOwo+ICsJdWludDMyX3QgYWZiY19oYWxmX2Jsb2Nr X2VuOwo+ICsJdWludDMyX3QgdHJhbnNmb3JtX29mZnNldDsKPiArCWJvb2wgZGl0aGVyX3VwOwo+ ICsJYm9vbCB4bWlycm9yID0gcHN0YXRlLT5yb3RhdGlvbiAmIERSTV9NT0RFX1JFRkxFQ1RfWDsK PiArCWJvb2wgeW1pcnJvciA9IHBzdGF0ZS0+cm90YXRpb24gJiBEUk1fTU9ERV9SRUZMRUNUX1k7 Cj4gKwlib29sIHJvdGF0ZV8yNzAgPSBwc3RhdGUtPnJvdGF0aW9uICYgRFJNX01PREVfUk9UQVRF XzI3MDsKPiArCWJvb2wgcm90YXRlXzkwID0gcHN0YXRlLT5yb3RhdGlvbiAmIERSTV9NT0RFX1JP VEFURV85MDsKPiArCXN0cnVjdCByb2NrY2hpcF9nZW1fb2JqZWN0ICpya19vYmo7Cj4gKwl1bnNp Z25lZCBsb25nIG9mZnNldDsKPiArCWJvb2wgYWZiY19lbjsKPiArCWRtYV9hZGRyX3QgeXJnYl9t c3Q7Cj4gKwlkbWFfYWRkcl90IHV2X21zdDsKPiArCj4gKwkvKgo+ICsJICogY2FuJ3QgdXBkYXRl IHBsYW5lIHdoZW4gdm9wMiBpcyBkaXNhYmxlZC4KPiArCSAqLwo+ICsJaWYgKFdBUk5fT04oIWNy dGMpKQo+ICsJCXJldHVybjsKPiArCj4gKwlpZiAoIXBzdGF0ZS0+dmlzaWJsZSkgewo+ICsJCXZv cDJfcGxhbmVfYXRvbWljX2Rpc2FibGUocGxhbmUsIHN0YXRlKTsKPiArCQlyZXR1cm47Cj4gKwl9 Cj4gKwo+ICsJYWZiY19lbiA9IHJvY2tjaGlwX2FmYmMocGxhbmUsIGZiLT5tb2RpZmllcik7Cj4g Kwo+ICsJb2Zmc2V0ID0gKHNyYy0+eDEgPj4gMTYpICogZmItPmZvcm1hdC0+Y3BwWzBdOwo+ICsK PiArCS8qCj4gKwkgKiBBRkJDIEhEUl9QVFIgbXVzdCBzZXQgdG8gdGhlIHplcm8gb2Zmc2V0IG9m IHRoZSBmcmFtZWJ1ZmZlci4KPiArCSAqLwo+ICsJaWYgKGFmYmNfZW4pCj4gKwkJb2Zmc2V0ID0g MDsKPiArCWVsc2UgaWYgKHBzdGF0ZS0+cm90YXRpb24gJiBEUk1fTU9ERV9SRUZMRUNUX1kpCj4g KwkJb2Zmc2V0ICs9ICgoc3JjLT55MiA+PiAxNikgLSAxKSAqIGZiLT5waXRjaGVzWzBdOwo+ICsJ ZWxzZQo+ICsJCW9mZnNldCArPSAoc3JjLT55MSA+PiAxNikgKiBmYi0+cGl0Y2hlc1swXTsKPiAr Cj4gKwlya19vYmogPSB0b19yb2NrY2hpcF9vYmooZmItPm9ialswXSk7Cj4gKwo+ICsJeXJnYl9t c3QgPSBya19vYmotPmRtYV9hZGRyICsgb2Zmc2V0ICsgZmItPm9mZnNldHNbMF07Cj4gKwlpZiAo ZmItPmZvcm1hdC0+aXNfeXV2KSB7Cj4gKwkJaW50IGhzdWIgPSBmYi0+Zm9ybWF0LT5oc3ViOwo+ ICsJCWludCB2c3ViID0gZmItPmZvcm1hdC0+dnN1YjsKPiArCj4gKwkJb2Zmc2V0ID0gKHNyYy0+ eDEgPj4gMTYpICogZmItPmZvcm1hdC0+Y3BwWzFdIC8gaHN1YjsKPiArCQlvZmZzZXQgKz0gKHNy Yy0+eTEgPj4gMTYpICogZmItPnBpdGNoZXNbMV0gLyB2c3ViOwo+ICsKPiArCQlpZiAoKHBzdGF0 ZS0+cm90YXRpb24gJiBEUk1fTU9ERV9SRUZMRUNUX1kpICYmICFhZmJjX2VuKQo+ICsJCQlvZmZz ZXQgKz0gZmItPnBpdGNoZXNbMV0gKiAoKHBzdGF0ZS0+c3JjX2ggPj4gMTYpIC0gMikgIC8gdnN1 YjsKPiArCj4gKwkJcmtfb2JqID0gdG9fcm9ja2NoaXBfb2JqKGZiLT5vYmpbMF0pOwo+ICsJCXV2 X21zdCA9IHJrX29iai0+ZG1hX2FkZHIgKyBvZmZzZXQgKyBmYi0+b2Zmc2V0c1sxXTsKPiArCX0K PiArCj4gKwlhY3R1YWxfdyA9IGRybV9yZWN0X3dpZHRoKHNyYykgPj4gMTY7Cj4gKwlhY3R1YWxf aCA9IGRybV9yZWN0X2hlaWdodChzcmMpID4+IDE2Owo+ICsJZHNwX3cgPSBkcm1fcmVjdF93aWR0 aChkZXN0KTsKPiArCj4gKwlpZiAoZGVzdC0+eDEgKyBkc3BfdyA+IGFkanVzdGVkX21vZGUtPmhk aXNwbGF5KSB7Cj4gKwkJZHJtX2Vycih2b3AyLT5kcm0sICJ2cCVkICVzIGRlc3QtPngxWyVkXSAr IGRzcF93WyVkXSBleGNlZWQgbW9kZSBoZGlzcGxheVslZF1cbiIsCj4gKwkJCSAgdnAtPmlkLCB3 aW4tPmRhdGEtPm5hbWUsIGRlc3QtPngxLCBkc3BfdywgYWRqdXN0ZWRfbW9kZS0+aGRpc3BsYXkp Owo+ICsJCWRzcF93ID0gYWRqdXN0ZWRfbW9kZS0+aGRpc3BsYXkgLSBkZXN0LT54MTsKPiArCQlp ZiAoZHNwX3cgPCA0KQo+ICsJCQlkc3BfdyA9IDQ7Cj4gKwkJYWN0dWFsX3cgPSBkc3BfdyAqIGFj dHVhbF93IC8gZHJtX3JlY3Rfd2lkdGgoZGVzdCk7Cj4gKwl9Cj4gKwo+ICsJZHNwX2ggPSBkcm1f cmVjdF9oZWlnaHQoZGVzdCk7Cj4gKwo+ICsJaWYgKGRlc3QtPnkxICsgZHNwX2ggPiBhZGp1c3Rl ZF9tb2RlLT52ZGlzcGxheSkgewo+ICsJCWRybV9lcnIodm9wMi0+ZHJtLCAidnAlZCAlcyBkZXN0 LT55MVslZF0gKyBkc3BfaFslZF0gZXhjZWVkIG1vZGUgdmRpc3BsYXlbJWRdXG4iLAo+ICsJCQkg IHZwLT5pZCwgd2luLT5kYXRhLT5uYW1lLCBkZXN0LT55MSwgZHNwX2gsIGFkanVzdGVkX21vZGUt PnZkaXNwbGF5KTsKPiArCQlkc3BfaCA9IGFkanVzdGVkX21vZGUtPnZkaXNwbGF5IC0gZGVzdC0+ eTE7Cj4gKwkJaWYgKGRzcF9oIDwgNCkKPiArCQkJZHNwX2ggPSA0Owo+ICsJCWFjdHVhbF9oID0g ZHNwX2ggKiBhY3R1YWxfaCAvIGRybV9yZWN0X2hlaWdodChkZXN0KTsKPiArCX0KPiArCj4gKwkv Kgo+ICsJICogVGhpcyBpcyB3b3JrYXJvdW5kIHNvbHV0aW9uIGZvciBJQyBkZXNpZ246Cj4gKwkg KiBlc21hcnQgY2FuJ3Qgc3VwcG9ydCBzY2FsZSBkb3duIHdoZW4gYWN0dWFsX3cgJSAxNiA9PSAx Lgo+ICsJICovCj4gKwlpZiAoISh3aW4tPmRhdGEtPmZlYXR1cmUgJiBXSU5fRkVBVFVSRV9BRkJE QykpIHsKPiArCQlpZiAoYWN0dWFsX3cgPiBkc3BfdyAmJiAoYWN0dWFsX3cgJiAweGYpID09IDEp IHsKPiArCQkJZHJtX2Vycih2b3AyLT5kcm0sICJ2cCVkICVzIGFjdF93WyVkXSBNT0RFIDE2ID09 IDFcbiIsIHZwLT5pZCwgd2luLT5kYXRhLT5uYW1lLCBhY3R1YWxfdyk7Cj4gKwkJCWFjdHVhbF93 IC09IDE7Cj4gKwkJfQo+ICsJfQo+ICsKPiArCWlmIChhZmJjX2VuICYmIGFjdHVhbF93ICUgNCkg ewo+ICsJCWRybV9lcnIodm9wMi0+ZHJtLCAidnAlZCAlcyBhY3R1YWxfd1slZF0gc2hvdWxkIGFs aWduIGFzIDQgcGl4ZWwgd2hlbiBlbmFibGUgYWZiY1xuIiwKPiArCQkJICB2cC0+aWQsIHdpbi0+ ZGF0YS0+bmFtZSwgYWN0dWFsX3cpOwo+ICsJCWFjdHVhbF93ID0gQUxJR05fRE9XTihhY3R1YWxf dywgNCk7Cj4gKwl9Cj4gKwo+ICsJYWN0X2luZm8gPSAoYWN0dWFsX2ggLSAxKSA8PCAxNiB8ICgo YWN0dWFsX3cgLSAxKSAmIDB4ZmZmZik7Cj4gKwlkc3BfaW5mbyA9IChkc3BfaCAtIDEpIDw8IDE2 IHwgKChkc3BfdyAtIDEpICYgMHhmZmZmKTsKPiArCj4gKwlmb3JtYXQgPSB2b3AyX2NvbnZlcnRf Zm9ybWF0KGZiLT5mb3JtYXQtPmZvcm1hdCk7Cj4gKwo+ICsJc3Bpbl9sb2NrKCZ2b3AyLT5yZWdf bG9jayk7Cj4gKwlkcm1fZGJnKHZvcDItPmRybSwgInZwJWQgdXBkYXRlICVzWyVkeCVkLT4lZHgl ZEAlZHglZF0gZm10WyVwNGNjXyVzXSBhZGRyWyVwYWRdXG4iLAo+ICsJCSAgICAgIHZwLT5pZCwg d2luLT5kYXRhLT5uYW1lLCBhY3R1YWxfdywgYWN0dWFsX2gsIGRzcF93LCBkc3BfaCwKPiArCQkg ICAgICBkZXN0LT54MSwgZGVzdC0+eTEsCj4gKwkJICAgICAgJmZiLT5mb3JtYXQtPmZvcm1hdCwK PiArCQkgICAgICBhZmJjX2VuID8gIkFGQkMiIDogIiIsICZ5cmdiX21zdCk7Cj4gKwo+ICsJaWYg KGFmYmNfZW4pIHsKPiArCQl1aW50MzJfdCBzdHJpZGU7Cj4gKwo+ICsJCS8qIHRoZSBhZmJjIHN1 cGVyYmxvY2sgaXMgMTYgeCAxNiAqLwo+ICsJCWFmYmNfZm9ybWF0ID0gdm9wMl9jb252ZXJ0X2Fm YmNfZm9ybWF0KGZiLT5mb3JtYXQtPmZvcm1hdCk7Cj4gKwo+ICsJCS8qIEVuYWJsZSBjb2xvciB0 cmFuc2Zvcm0gZm9yIFlUUiAqLwo+ICsJCWlmIChmYi0+bW9kaWZpZXIgJiBBRkJDX0ZPUk1BVF9N T0RfWVRSKQo+ICsJCQlhZmJjX2Zvcm1hdCB8PSAoMSA8PCA0KTsKPiArCj4gKwkJYWZiY190aWxl X251bSA9IEFMSUdOKGFjdHVhbF93LCAxNikgPj4gNDsKPiArCj4gKwkJLyoKPiArCQkgKiBBRkJD IHBpY192aXJfd2lkdGggaXMgY291bnQgYnkgcGl4ZWwsIHRoaXMgaXMgZGlmZmVyZW50Cj4gKwkJ ICogd2l0aCBXSU5fVklSX1NUUklERS4KPiArCQkgKi8KPiArCQlzdHJpZGUgPSAoZmItPnBpdGNo ZXNbMF0gPDwgMykgLyBicHA7Cj4gKwkJaWYgKChzdHJpZGUgJiAweDNmKSAmJiAoeG1pcnJvciB8 fCByb3RhdGVfOTAgfHwgcm90YXRlXzI3MCkpCj4gKwkJCWRybV9lcnIodm9wMi0+ZHJtLCAidnAl ZCAlcyBzdHJpZGVbJWRdIG11c3QgYWxpZ24gYXMgNjQgcGl4ZWwgd2hlbiBlbmFibGUgeG1pcnJv ci9yb3RhdGVfOTAvcm90YXRlXzI3MFsweCV4XVxuIiwKPiArCQkJCSAgdnAtPmlkLCB3aW4tPmRh dGEtPm5hbWUsIHN0cmlkZSwgcHN0YXRlLT5yb3RhdGlvbik7Cj4gKwo+ICsJCXJiX3N3YXAgPSB2 b3AyX2FmYmNfcmJfc3dhcChmYi0+Zm9ybWF0LT5mb3JtYXQpOwo+ICsJCXV2X3N3YXAgPSB2b3Ay X2FmYmNfdXZfc3dhcChmYi0+Zm9ybWF0LT5mb3JtYXQpOwo+ICsJCS8qCj4gKwkJICogVGhpcyBp cyBhIHdvcmthcm91bmQgZm9yIGNyYXp5IElDIGRlc2lnbiwgQ2x1c3Rlcgo+ICsJCSAqIGFuZCBF c21hcnQvU21hcnQgdXNlIGRpZmZlcmVudCBmb3JtYXQgY29uZmlndXJhdGlvbiBtYXA6Cj4gKwkJ ICogWVVWNDIwXzEwQklUOiAweDEwIGZvciBDbHVzdGVyLCAweDE0IGZvciBFc21hcnQvU21hcnQu Cj4gKwkJICoKPiArCQkgKiBUaGlzIGlzIG9uZSB0aGluZyB3ZSBjYW4gbWFrZSB0aGUgY29udmVy dCBzaW1wbGU6Cj4gKwkJICogQUZCQ0QgZGVjb2RlIGFsbCB0aGUgWVVWIGRhdGEgdG8gWVVWNDQ0 LiBTbyB3ZSBqdXN0Cj4gKwkJICogc2V0IGFsbCB0aGUgeXV2IDEwIGJpdCB0byBZVVY0NDRfMTAu Cj4gKwkJICovCj4gKwkJaWYgKGZiLT5mb3JtYXQtPmlzX3l1diAmJiAoYnBwID09IDEwKSkKPiAr CQkJZm9ybWF0ID0gVk9QMl9DTFVTVEVSX1lVVjQ0NF8xMDsKPiArCj4gKwkJYWZiY19oYWxmX2Js b2NrX2VuID0gdm9wMl9hZmJjX2hhbGZfYmxvY2tfZW5hYmxlKHBzdGF0ZSk7Cj4gKwkJdHJhbnNm b3JtX29mZnNldCA9IHZvcDJfYWZiY190cmFuc2Zvcm1fb2Zmc2V0KHBzdGF0ZSwgYWZiY19oYWxm X2Jsb2NrX2VuKTsKPiArCQlpZiAodm9wMl9jbHVzdGVyX3dpbmRvdyh3aW4pKQo+ICsJCQl2b3Ay X3dpbl93cml0ZSh3aW4sIFZPUDJfV0lOX0FGQkNfRU5BQkxFLCAxKTsKPiArCQl2b3AyX3dpbl93 cml0ZSh3aW4sIFZPUDJfV0lOX0FGQkNfRk9STUFULCBhZmJjX2Zvcm1hdCk7Cj4gKwkJdm9wMl93 aW5fd3JpdGUod2luLCBWT1AyX1dJTl9BRkJDX1JCX1NXQVAsIHJiX3N3YXApOwo+ICsJCXZvcDJf d2luX3dyaXRlKHdpbiwgVk9QMl9XSU5fQUZCQ19VVl9TV0FQLCB1dl9zd2FwKTsKPiArCQl2b3Ay X3dpbl93cml0ZSh3aW4sIFZPUDJfV0lOX0FGQkNfQVVUT19HQVRJTkdfRU4sIDApOwo+ICsJCXZv cDJfd2luX3dyaXRlKHdpbiwgVk9QMl9XSU5fQUZCQ19CTE9DS19TUExJVF9FTiwgMCk7Cj4gKwkJ dm9wMl93aW5fd3JpdGUod2luLCBWT1AyX1dJTl9BRkJDX0hBTEZfQkxPQ0tfRU4sIGFmYmNfaGFs Zl9ibG9ja19lbik7Cj4gKwkJdm9wMl93aW5fd3JpdGUod2luLCBWT1AyX1dJTl9BRkJDX0hEUl9Q VFIsIHlyZ2JfbXN0KTsKPiArCQl2b3AyX3dpbl93cml0ZSh3aW4sIFZPUDJfV0lOX0FGQkNfUElD X1NJWkUsIGFjdF9pbmZvKTsKPiArCQl2b3AyX3dpbl93cml0ZSh3aW4sIFZPUDJfV0lOX0FGQkNf VFJBTlNGT1JNX09GRlNFVCwgdHJhbnNmb3JtX29mZnNldCk7Cj4gKwkJdm9wMl93aW5fd3JpdGUo d2luLCBWT1AyX1dJTl9BRkJDX1BJQ19PRkZTRVQsICgoc3JjLT54MSA+PiAxNikgfCBzcmMtPnkx KSk7Cj4gKwkJdm9wMl93aW5fd3JpdGUod2luLCBWT1AyX1dJTl9BRkJDX0RTUF9PRkZTRVQsIChk ZXN0LT54MSB8IChkZXN0LT55MSA8PCAxNikpKTsKPiArCQl2b3AyX3dpbl93cml0ZSh3aW4sIFZP UDJfV0lOX0FGQkNfUElDX1ZJUl9XSURUSCwgc3RyaWRlKTsKPiArCQl2b3AyX3dpbl93cml0ZSh3 aW4sIFZPUDJfV0lOX0FGQkNfVElMRV9OVU0sIGFmYmNfdGlsZV9udW0pOwo+ICsJCXZvcDJfd2lu X3dyaXRlKHdpbiwgVk9QMl9XSU5fWE1JUlJPUiwgeG1pcnJvcik7Cj4gKwkJdm9wMl93aW5fd3Jp dGUod2luLCBWT1AyX1dJTl9BRkJDX1JPVEFURV8yNzAsIHJvdGF0ZV8yNzApOwo+ICsJCXZvcDJf d2luX3dyaXRlKHdpbiwgVk9QMl9XSU5fQUZCQ19ST1RBVEVfOTAsIHJvdGF0ZV85MCk7Cj4gKwl9 IGVsc2Ugewo+ICsJCXZvcDJfd2luX3dyaXRlKHdpbiwgVk9QMl9XSU5fWVJHQl9WSVIsIERJVl9S T1VORF9VUChmYi0+cGl0Y2hlc1swXSwgNCkpOwo+ICsJfQo+ICsKPiArCXZvcDJfd2luX3dyaXRl KHdpbiwgVk9QMl9XSU5fWU1JUlJPUiwgeW1pcnJvcik7Cj4gKwo+ICsJaWYgKHJvdGF0ZV85MCB8 fCByb3RhdGVfMjcwKSB7Cj4gKwkJYWN0X2luZm8gPSBzd2FodzMyKGFjdF9pbmZvKTsKPiArCQlh Y3R1YWxfdyA9IGRybV9yZWN0X2hlaWdodChzcmMpID4+IDE2Owo+ICsJCWFjdHVhbF9oID0gZHJt X3JlY3Rfd2lkdGgoc3JjKSA+PiAxNjsKPiArCX0KPiArCj4gKwl2b3AyX3dpbl93cml0ZSh3aW4s IFZPUDJfV0lOX0ZPUk1BVCwgZm9ybWF0KTsKPiArCXZvcDJfd2luX3dyaXRlKHdpbiwgVk9QMl9X SU5fWVJHQl9NU1QsIHlyZ2JfbXN0KTsKPiArCj4gKwlyYl9zd2FwID0gdm9wMl93aW5fcmJfc3dh cChmYi0+Zm9ybWF0LT5mb3JtYXQpOwo+ICsJdm9wMl93aW5fd3JpdGUod2luLCBWT1AyX1dJTl9S Ql9TV0FQLCByYl9zd2FwKTsKPiArCWlmICghdm9wMl9jbHVzdGVyX3dpbmRvdyh3aW4pKSB7Cj4g KwkJdXZfc3dhcCA9IHZvcDJfd2luX3V2X3N3YXAoZmItPmZvcm1hdC0+Zm9ybWF0KTsKPiArCQl2 b3AyX3dpbl93cml0ZSh3aW4sIFZPUDJfV0lOX1VWX1NXQVAsIHV2X3N3YXApOwo+ICsJfQo+ICsK PiArCWlmIChmYi0+Zm9ybWF0LT5pc195dXYpIHsKPiArCQl2b3AyX3dpbl93cml0ZSh3aW4sIFZP UDJfV0lOX1VWX1ZJUiwgRElWX1JPVU5EX1VQKGZiLT5waXRjaGVzWzFdLCA0KSk7Cj4gKwkJdm9w Ml93aW5fd3JpdGUod2luLCBWT1AyX1dJTl9VVl9NU1QsIHV2X21zdCk7Cj4gKwl9Cj4gKwo+ICsJ dm9wMl9zZXR1cF9zY2FsZSh2b3AyLCB3aW4sIGFjdHVhbF93LCBhY3R1YWxfaCwgZHNwX3csIGRz cF9oLCBmYi0+Zm9ybWF0LT5mb3JtYXQpOwo+ICsJaWYgKCF2b3AyX2NsdXN0ZXJfd2luZG93KHdp bikpCj4gKwkJdm9wMl9wbGFuZV9zZXR1cF9jb2xvcl9rZXkocGxhbmUsIDApOwo+ICsJdm9wMl93 aW5fd3JpdGUod2luLCBWT1AyX1dJTl9BQ1RfSU5GTywgYWN0X2luZm8pOwo+ICsJdm9wMl93aW5f d3JpdGUod2luLCBWT1AyX1dJTl9EU1BfSU5GTywgZHNwX2luZm8pOwo+ICsJdm9wMl93aW5fd3Jp dGUod2luLCBWT1AyX1dJTl9EU1BfU1QsIGRlc3QtPnkxIDw8IDE2IHwgKGRlc3QtPngxICYgMHhm ZmZmKSk7Cj4gKwo+ICsJdm9wMl9zZXR1cF9jc2NfbW9kZSh2cCwgd2luLCBwc3RhdGUpOwo+ICsK PiArCWRpdGhlcl91cCA9IHZvcDJfd2luX2RpdGhlcl91cChmYi0+Zm9ybWF0LT5mb3JtYXQpOwo+ ICsJdm9wMl93aW5fd3JpdGUod2luLCBWT1AyX1dJTl9ESVRIRVJfVVAsIGRpdGhlcl91cCk7Cj4g Kwo+ICsJdm9wMl93aW5fd3JpdGUod2luLCBWT1AyX1dJTl9FTkFCTEUsIDEpOwo+ICsKPiArCWlm ICh2b3AyX2NsdXN0ZXJfd2luZG93KHdpbikpIHsKPiArCQlpbnQgbGJfbW9kZSA9IHZvcDJfZ2V0 X2NsdXN0ZXJfbGJfbW9kZSh3aW4sIHBzdGF0ZSk7Cj4gKwo+ICsJCXZvcDJfd2luX3dyaXRlKHdp biwgVk9QMl9XSU5fQ0xVU1RFUl9MQl9NT0RFLCBsYl9tb2RlKTsKPiArCQl2b3AyX3dpbl93cml0 ZSh3aW4sIFZPUDJfV0lOX0NMVVNURVJfRU5BQkxFLCAxKTsKPiArCX0KPiArCj4gKwlzcGluX3Vu bG9jaygmdm9wMi0+cmVnX2xvY2spOwo+ICt9Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGRy bV9wbGFuZV9oZWxwZXJfZnVuY3Mgdm9wMl9wbGFuZV9oZWxwZXJfZnVuY3MgPSB7Cj4gKwkuYXRv bWljX2NoZWNrID0gdm9wMl9wbGFuZV9hdG9taWNfY2hlY2ssCj4gKwkuYXRvbWljX3VwZGF0ZSA9 IHZvcDJfcGxhbmVfYXRvbWljX3VwZGF0ZSwKPiArCS5hdG9taWNfZGlzYWJsZSA9IHZvcDJfcGxh bmVfYXRvbWljX2Rpc2FibGUsCj4gK307Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGRybV9w bGFuZV9mdW5jcyB2b3AyX3BsYW5lX2Z1bmNzID0gewo+ICsJLnVwZGF0ZV9wbGFuZQk9IGRybV9h dG9taWNfaGVscGVyX3VwZGF0ZV9wbGFuZSwKPiArCS5kaXNhYmxlX3BsYW5lCT0gZHJtX2F0b21p Y19oZWxwZXJfZGlzYWJsZV9wbGFuZSwKPiArCS5kZXN0cm95ID0gZHJtX3BsYW5lX2NsZWFudXAs Cj4gKwkucmVzZXQgPSBkcm1fYXRvbWljX2hlbHBlcl9wbGFuZV9yZXNldCwKPiArCS5hdG9taWNf ZHVwbGljYXRlX3N0YXRlID0gZHJtX2F0b21pY19oZWxwZXJfcGxhbmVfZHVwbGljYXRlX3N0YXRl LAo+ICsJLmF0b21pY19kZXN0cm95X3N0YXRlID0gZHJtX2F0b21pY19oZWxwZXJfcGxhbmVfZGVz dHJveV9zdGF0ZSwKPiArCS5mb3JtYXRfbW9kX3N1cHBvcnRlZCA9IHJvY2tjaGlwX3ZvcDJfbW9k X3N1cHBvcnRlZCwKPiArfTsKPiArCj4gK3N0YXRpYyBpbnQgdm9wMl9jcnRjX2VuYWJsZV92Ymxh bmsoc3RydWN0IGRybV9jcnRjICpjcnRjKQo+ICt7Cj4gKwlzdHJ1Y3Qgdm9wMl92aWRlb19wb3J0 ICp2cCA9IHRvX3ZvcDJfdmlkZW9fcG9ydChjcnRjKTsKPiArCj4gKwl2b3AyX2NydGNfZW5hYmxl X2lycSh2cCwgVlBfSU5UX0ZTX0ZJRUxEKTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiAr c3RhdGljIHZvaWQgdm9wMl9jcnRjX2Rpc2FibGVfdmJsYW5rKHN0cnVjdCBkcm1fY3J0YyAqY3J0 YykKPiArewo+ICsJc3RydWN0IHZvcDJfdmlkZW9fcG9ydCAqdnAgPSB0b192b3AyX3ZpZGVvX3Bv cnQoY3J0Yyk7Cj4gKwo+ICsJdm9wMl9jcnRjX2Rpc2FibGVfaXJxKHZwLCBWUF9JTlRfRlNfRklF TEQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgYm9vbCB2b3AyX2NydGNfbW9kZV9maXh1cChzdHJ1Y3Qg ZHJtX2NydGMgKmNydGMsCj4gKwkJCQkgY29uc3Qgc3RydWN0IGRybV9kaXNwbGF5X21vZGUgKm1v ZGUsCj4gKwkJCQkgc3RydWN0IGRybV9kaXNwbGF5X21vZGUgKmFkal9tb2RlKQo+ICt7Cj4gKwlk cm1fbW9kZV9zZXRfY3J0Y2luZm8oYWRqX21vZGUsIENSVENfSU5URVJMQUNFX0hBTFZFX1YgfCBD UlRDX1NURVJFT19ET1VCTEUpOwo+ICsKPiArCXJldHVybiB0cnVlOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgdm9pZCB2b3AyX2RpdGhlcl9zZXR1cChzdHJ1Y3QgZHJtX2NydGMgKmNydGMsIHVpbnQzMl90 ICpkc3BfY3RybCkKPiArewo+ICsJc3RydWN0IHJvY2tjaGlwX2NydGNfc3RhdGUgKnZjc3RhdGUg PSB0b19yb2NrY2hpcF9jcnRjX3N0YXRlKGNydGMtPnN0YXRlKTsKPiArCj4gKwlzd2l0Y2ggKHZj c3RhdGUtPmJ1c19mb3JtYXQpIHsKPiArCWNhc2UgTUVESUFfQlVTX0ZNVF9SR0I1NjVfMVgxNjoK PiArCQkqZHNwX2N0cmwgfD0gUkszNTY4X1ZQX0RTUF9DVFJMX19ESVRIRVJfRE9XTl9FTjsKPiAr CQlicmVhazsKPiArCWNhc2UgTUVESUFfQlVTX0ZNVF9SR0I2NjZfMVgxODoKPiArCWNhc2UgTUVE SUFfQlVTX0ZNVF9SR0I2NjZfMVgyNF9DUEFESEk6Cj4gKwljYXNlIE1FRElBX0JVU19GTVRfUkdC NjY2XzFYN1gzX1NQV0c6Cj4gKwkJKmRzcF9jdHJsIHw9IFJLMzU2OF9WUF9EU1BfQ1RSTF9fRElU SEVSX0RPV05fRU47Cj4gKwkJKmRzcF9jdHJsIHw9IFJHQjg4OF9UT19SR0I2NjY7Cj4gKwkJYnJl YWs7Cj4gKwljYXNlIE1FRElBX0JVU19GTVRfWVVWOF8xWDI0Ogo+ICsJY2FzZSBNRURJQV9CVVNf Rk1UX1VZWVZZWThfMF81WDI0Ogo+ICsJCSpkc3BfY3RybCB8PSBSSzM1NjhfVlBfRFNQX0NUUkxf X1BSRV9ESVRIRVJfRE9XTl9FTjsKPiArCQlicmVhazsKPiArCWRlZmF1bHQ6Cj4gKwkJYnJlYWs7 Cj4gKwl9Cj4gKwo+ICsJaWYgKHZjc3RhdGUtPm91dHB1dF9tb2RlICE9IFJPQ0tDSElQX09VVF9N T0RFX0FBQUEpCj4gKwkJKmRzcF9jdHJsIHw9IFJLMzU2OF9WUF9EU1BfQ1RSTF9fUFJFX0RJVEhF Ul9ET1dOX0VOOwo+ICsKPiArCSpkc3BfY3RybCB8PSBGSUVMRF9QUkVQKFJLMzU2OF9WUF9EU1Bf Q1RSTF9fRElUSEVSX0RPV05fU0VMLAo+ICsJCQkJRElUSEVSX0RPV05fQUxMRUdSTyk7Cj4gK30K PiArCj4gK3N0YXRpYyB2b2lkIHZvcDJfcG9zdF9jb25maWcoc3RydWN0IGRybV9jcnRjICpjcnRj KQo+ICt7Cj4gKwlzdHJ1Y3Qgdm9wMl92aWRlb19wb3J0ICp2cCA9IHRvX3ZvcDJfdmlkZW9fcG9y dChjcnRjKTsKPiArCXN0cnVjdCB2b3AyICp2b3AyID0gdnAtPnZvcDI7Cj4gKwlzdHJ1Y3QgZHJt X2Rpc3BsYXlfbW9kZSAqbW9kZSA9ICZjcnRjLT5zdGF0ZS0+YWRqdXN0ZWRfbW9kZTsKPiArCXVp bnQxNl90IHZ0b3RhbCA9IG1vZGUtPmNydGNfdnRvdGFsOwo+ICsJdWludDE2X3QgaGRpc3BsYXkg PSBtb2RlLT5jcnRjX2hkaXNwbGF5Owo+ICsJdWludDE2X3QgaGFjdF9zdCA9IG1vZGUtPmNydGNf aHRvdGFsIC0gbW9kZS0+Y3J0Y19oc3luY19zdGFydDsKPiArCXVpbnQxNl90IHZkaXNwbGF5ID0g bW9kZS0+Y3J0Y192ZGlzcGxheTsKPiArCXVpbnQxNl90IHZhY3Rfc3QgPSBtb2RlLT5jcnRjX3Z0 b3RhbCAtIG1vZGUtPmNydGNfdnN5bmNfc3RhcnQ7Cj4gKwl1aW50MzJfdCBsZWZ0X21hcmdpbiA9 IDEwMCwgcmlnaHRfbWFyZ2luID0gMTAwLCB0b3BfbWFyZ2luID0gMTAwLCBib3R0b21fbWFyZ2lu ID0gMTAwOwo+ICsJdWludDE2X3QgaHNpemUgPSBoZGlzcGxheSAqIChsZWZ0X21hcmdpbiArIHJp Z2h0X21hcmdpbikgLyAyMDA7Cj4gKwl1aW50MTZfdCB2c2l6ZSA9IHZkaXNwbGF5ICogKHRvcF9t YXJnaW4gKyBib3R0b21fbWFyZ2luKSAvIDIwMDsKPiArCXVpbnQxNl90IGhhY3RfZW5kLCB2YWN0 X2VuZDsKPiArCXVpbnQzMl90IHZhbDsKPiArCj4gKwl2c2l6ZSA9IHJvdW5kZG93bih2c2l6ZSwg Mik7Cj4gKwloc2l6ZSA9IHJvdW5kZG93bihoc2l6ZSwgMik7Cj4gKwloYWN0X3N0ICs9IGhkaXNw bGF5ICogKDEwMCAtIGxlZnRfbWFyZ2luKSAvIDIwMDsKPiArCWhhY3RfZW5kID0gaGFjdF9zdCAr IGhzaXplOwo+ICsJdmFsID0gaGFjdF9zdCA8PCAxNjsKPiArCXZhbCB8PSBoYWN0X2VuZDsKPiAr CXZvcDJfdnBfd3JpdGUodnAsIFJLMzU2OF9WUF9QT1NUX0RTUF9IQUNUX0lORk8sIHZhbCk7Cj4g Kwl2YWN0X3N0ICs9IHZkaXNwbGF5ICogKDEwMCAtIHRvcF9tYXJnaW4pIC8gMjAwOwo+ICsJdmFj dF9lbmQgPSB2YWN0X3N0ICsgdnNpemU7Cj4gKwl2YWwgPSB2YWN0X3N0IDw8IDE2Owo+ICsJdmFs IHw9IHZhY3RfZW5kOwo+ICsJdm9wMl92cF93cml0ZSh2cCwgUkszNTY4X1ZQX1BPU1RfRFNQX1ZB Q1RfSU5GTywgdmFsKTsKPiArCXZhbCA9IHNjbF9jYWxfc2NhbGUyKHZkaXNwbGF5LCB2c2l6ZSkg PDwgMTY7Cj4gKwl2YWwgfD0gc2NsX2NhbF9zY2FsZTIoaGRpc3BsYXksIGhzaXplKTsKPiArCXZv cDJfdnBfd3JpdGUodnAsIFJLMzU2OF9WUF9QT1NUX1NDTF9GQUNUT1JfWVJHQiwgdmFsKTsKPiAr Cj4gKwl2YWwgPSAwOwo+ICsJaWYgKGhkaXNwbGF5ICE9IGhzaXplKQo+ICsJCXZhbCB8PSBSSzM1 NjhfVlBfUE9TVF9TQ0xfQ1RSTF9fSFNDQUxFRE9XTjsKPiArCWlmICh2ZGlzcGxheSAhPSB2c2l6 ZSkKPiArCQl2YWwgfD0gUkszNTY4X1ZQX1BPU1RfU0NMX0NUUkxfX1ZTQ0FMRURPV047Cj4gKwl2 b3AyX3dyaXRlbCh2b3AyLCBSSzM1NjhfVlBfUE9TVF9TQ0xfQ1RSTCwgdmFsKTsKPiArCj4gKwlp ZiAobW9kZS0+ZmxhZ3MgJiBEUk1fTU9ERV9GTEFHX0lOVEVSTEFDRSkgewo+ICsJCXVpbnQxNl90 IHZhY3Rfc3RfZjEgPSB2dG90YWwgKyB2YWN0X3N0ICsgMTsKPiArCQl1aW50MTZfdCB2YWN0X2Vu ZF9mMSA9IHZhY3Rfc3RfZjEgKyB2c2l6ZTsKPiArCj4gKwkJdmFsID0gdmFjdF9zdF9mMSA8PCAx NiB8IHZhY3RfZW5kX2YxOwo+ICsJCXZvcDJfdnBfd3JpdGUodnAsIFJLMzU2OF9WUF9QT1NUX0RT UF9WQUNUX0lORk9fRjEsIHZhbCk7Cj4gKwl9Cj4gKwo+ICsJdm9wMl92cF93cml0ZSh2cCwgUksz NTY4X1ZQX0RTUF9CRywgMCk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHJrMzU2OF9zZXRfaW50 Zl9tdXgoc3RydWN0IHZvcDJfdmlkZW9fcG9ydCAqdnAsIGludCBpZCwKPiArCQkJCXVpbnQzMl90 IHBvbGZsYWdzKQo+ICt7Cj4gKwlzdHJ1Y3Qgdm9wMiAqdm9wMiA9IHZwLT52b3AyOwo+ICsJdWlu dDMyX3QgZGllLCBkaXA7Cj4gKwo+ICsJZGllID0gdm9wMl9yZWFkbCh2b3AyLCBSSzM1NjhfRFNQ X0lGX0VOKTsKPiArCWRpcCA9IHZvcDJfcmVhZGwodm9wMiwgUkszNTY4X0RTUF9JRl9QT0wpOwo+ ICsKPiArCXN3aXRjaCAoaWQpIHsKPiArCWNhc2UgUkszNTY4X1ZPUDJfRVBfUkdCOgo+ICsJCWRp ZSAmPSB+UkszNTY4X1NZU19EU1BfSU5GQUNFX0VOX1JHQl9NVVg7Cj4gKwkJZGllIHw9IFJLMzU2 OF9TWVNfRFNQX0lORkFDRV9FTl9SR0IgfAo+ICsJCQkgICBGSUVMRF9QUkVQKFJLMzU2OF9TWVNf RFNQX0lORkFDRV9FTl9SR0JfTVVYLCB2cC0+aWQpOwo+ICsJCWlmIChwb2xmbGFncyAmIFBPTEZM QUdfRENMS19JTlYpCj4gKwkJCXJlZ21hcF93cml0ZSh2b3AyLT5ncmYsIFJLMzU2OF9HUkZfVk9f Q09OMSwgQklUKDMgKyAxNikgfCBCSVQoMykpOwo+ICsJCWVsc2UKPiArCQkJcmVnbWFwX3dyaXRl KHZvcDItPmdyZiwgUkszNTY4X0dSRl9WT19DT04xLCBCSVQoMyArIDE2KSk7Cj4gKwkJYnJlYWs7 Cj4gKwljYXNlIFJLMzU2OF9WT1AyX0VQX0hETUk6Cj4gKwkJZGllICY9IH5SSzM1NjhfU1lTX0RT UF9JTkZBQ0VfRU5fSERNSV9NVVg7Cj4gKwkJZGllIHw9IFJLMzU2OF9TWVNfRFNQX0lORkFDRV9F Tl9IRE1JIHwKPiArCQkJICAgRklFTERfUFJFUChSSzM1NjhfU1lTX0RTUF9JTkZBQ0VfRU5fSERN SV9NVVgsIHZwLT5pZCk7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFJLMzU2OF9WT1AyX0VQX0VEUDoK PiArCQlkaWUgJj0gflJLMzU2OF9TWVNfRFNQX0lORkFDRV9FTl9FRFBfTVVYOwo+ICsJCWRpZSB8 PSBSSzM1NjhfU1lTX0RTUF9JTkZBQ0VfRU5fRURQIHwKPiArCQkJICAgRklFTERfUFJFUChSSzM1 NjhfU1lTX0RTUF9JTkZBQ0VfRU5fRURQX01VWCwgdnAtPmlkKTsKPiArCQlicmVhazsKPiArCWNh c2UgUkszNTY4X1ZPUDJfRVBfTUlQSTA6Cj4gKwkJZGllICY9IH5SSzM1NjhfU1lTX0RTUF9JTkZB Q0VfRU5fTUlQSTBfTVVYOwo+ICsJCWRpZSB8PSBSSzM1NjhfU1lTX0RTUF9JTkZBQ0VfRU5fTUlQ STAgfAo+ICsJCQkgICBGSUVMRF9QUkVQKFJLMzU2OF9TWVNfRFNQX0lORkFDRV9FTl9NSVBJMF9N VVgsIHZwLT5pZCk7Cj4gKwkJZGlwICY9IH5SSzM1NjhfRFNQX0lGX1BPTF9fTUlQSV9QSU5fUE9M Owo+ICsJCWRpcCB8PSBGSUVMRF9QUkVQKFJLMzU2OF9EU1BfSUZfUE9MX19NSVBJX1BJTl9QT0ws IHBvbGZsYWdzKTsKPiArCQlicmVhazsKPiArCWNhc2UgUkszNTY4X1ZPUDJfRVBfTUlQSTE6Cj4g KwkJZGllICY9IH5SSzM1NjhfU1lTX0RTUF9JTkZBQ0VfRU5fTUlQSTFfTVVYOwo+ICsJCWRpZSB8 PSBSSzM1NjhfU1lTX0RTUF9JTkZBQ0VfRU5fTUlQSTEgfAo+ICsJCQkgICBGSUVMRF9QUkVQKFJL MzU2OF9TWVNfRFNQX0lORkFDRV9FTl9NSVBJMV9NVVgsIHZwLT5pZCk7Cj4gKwkJZGlwICY9IH5S SzM1NjhfRFNQX0lGX1BPTF9fTUlQSV9QSU5fUE9MOwo+ICsJCWRpcCB8PSBGSUVMRF9QUkVQKFJL MzU2OF9EU1BfSUZfUE9MX19NSVBJX1BJTl9QT0wsIHBvbGZsYWdzKTsKPiArCQlicmVhazsKPiAr CWNhc2UgUkszNTY4X1ZPUDJfRVBfTFZEUzA6Cj4gKwkJZGllICY9IH5SSzM1NjhfU1lTX0RTUF9J TkZBQ0VfRU5fTFZEUzBfTVVYOwo+ICsJCWRpZSB8PSBSSzM1NjhfU1lTX0RTUF9JTkZBQ0VfRU5f TFZEUzAgfAo+ICsJCQkgICBGSUVMRF9QUkVQKFJLMzU2OF9TWVNfRFNQX0lORkFDRV9FTl9MVkRT MF9NVVgsIHZwLT5pZCk7Cj4gKwkJZGlwICY9IH5SSzM1NjhfRFNQX0lGX1BPTF9fUkdCX0xWRFNf UElOX1BPTDsKPiArCQlkaXAgfD0gRklFTERfUFJFUChSSzM1NjhfRFNQX0lGX1BPTF9fUkdCX0xW RFNfUElOX1BPTCwgcG9sZmxhZ3MpOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBSSzM1NjhfVk9QMl9F UF9MVkRTMToKPiArCQlkaWUgJj0gflJLMzU2OF9TWVNfRFNQX0lORkFDRV9FTl9MVkRTMV9NVVg7 Cj4gKwkJZGllIHw9IFJLMzU2OF9TWVNfRFNQX0lORkFDRV9FTl9MVkRTMSB8Cj4gKwkJCSAgIEZJ RUxEX1BSRVAoUkszNTY4X1NZU19EU1BfSU5GQUNFX0VOX0xWRFMxX01VWCwgdnAtPmlkKTsKPiAr CQlkaXAgJj0gflJLMzU2OF9EU1BfSUZfUE9MX19SR0JfTFZEU19QSU5fUE9MOwo+ICsJCWRpcCB8 PSBGSUVMRF9QUkVQKFJLMzU2OF9EU1BfSUZfUE9MX19SR0JfTFZEU19QSU5fUE9MLCBwb2xmbGFn cyk7Cj4gKwkJYnJlYWs7Cj4gKwlkZWZhdWx0Ogo+ICsJCXJldHVybjsKPiArCX07Cj4gKwo+ICsJ ZGlwIHw9IFJLMzU2OF9EU1BfSUZfUE9MX19DRkdfRE9ORV9JTUQ7Cj4gKwo+ICsJdm9wMl93cml0 ZWwodm9wMiwgUkszNTY4X0RTUF9JRl9FTiwgZGllKTsKPiArCXZvcDJfd3JpdGVsKHZvcDIsIFJL MzU2OF9EU1BfSUZfUE9MLCBkaXApOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHVzX3RvX3ZlcnRp Y2FsX2xpbmUoc3RydWN0IGRybV9kaXNwbGF5X21vZGUgKm1vZGUsIGludCB1cykKPiArewo+ICsJ cmV0dXJuIHVzICogbW9kZS0+Y2xvY2sgLyBtb2RlLT5odG90YWwgLyAxMDAwOwo+ICt9Cj4gKwo+ ICtzdGF0aWMgdm9pZCB2b3AyX2NydGNfYXRvbWljX2VuYWJsZShzdHJ1Y3QgZHJtX2NydGMgKmNy dGMsIHN0cnVjdCBkcm1fYXRvbWljX3N0YXRlICpzdGF0ZSkKPiArewo+ICsJc3RydWN0IHZvcDJf dmlkZW9fcG9ydCAqdnAgPSB0b192b3AyX3ZpZGVvX3BvcnQoY3J0Yyk7Cj4gKwlzdHJ1Y3Qgdm9w MiAqdm9wMiA9IHZwLT52b3AyOwo+ICsJY29uc3Qgc3RydWN0IHZvcDJfZGF0YSAqdm9wMl9kYXRh ID0gdm9wMi0+ZGF0YTsKPiArCWNvbnN0IHN0cnVjdCB2b3AyX3ZpZGVvX3BvcnRfZGF0YSAqdnBf ZGF0YSA9ICZ2b3AyX2RhdGEtPnZwW3ZwLT5pZF07Cj4gKwlzdHJ1Y3QgZHJtX2NydGNfc3RhdGUg KmNydGNfc3RhdGUgPSBkcm1fYXRvbWljX2dldF9uZXdfY3J0Y19zdGF0ZShzdGF0ZSwgY3J0Yyk7 Cj4gKwlzdHJ1Y3Qgcm9ja2NoaXBfY3J0Y19zdGF0ZSAqdmNzdGF0ZSA9IHRvX3JvY2tjaGlwX2Ny dGNfc3RhdGUoY3J0Yy0+c3RhdGUpOwo+ICsJc3RydWN0IGRybV9kaXNwbGF5X21vZGUgKm1vZGUg PSAmY3J0Yy0+c3RhdGUtPmFkanVzdGVkX21vZGU7Cj4gKwl1bnNpZ25lZCBsb25nIGNsb2NrID0g bW9kZS0+Y3J0Y19jbG9jayAqIDEwMDA7Cj4gKwl1aW50MTZfdCBoc3luY19sZW4gPSBtb2RlLT5j cnRjX2hzeW5jX2VuZCAtIG1vZGUtPmNydGNfaHN5bmNfc3RhcnQ7Cj4gKwl1aW50MTZfdCBoZGlz cGxheSA9IG1vZGUtPmNydGNfaGRpc3BsYXk7Cj4gKwl1aW50MTZfdCBodG90YWwgPSBtb2RlLT5j cnRjX2h0b3RhbDsKPiArCXVpbnQxNl90IGhhY3Rfc3QgPSBtb2RlLT5jcnRjX2h0b3RhbCAtIG1v ZGUtPmNydGNfaHN5bmNfc3RhcnQ7Cj4gKwl1aW50MTZfdCBoYWN0X2VuZCA9IGhhY3Rfc3QgKyBo ZGlzcGxheTsKPiArCXVpbnQxNl90IHZkaXNwbGF5ID0gbW9kZS0+Y3J0Y192ZGlzcGxheTsKPiAr CXVpbnQxNl90IHZ0b3RhbCA9IG1vZGUtPmNydGNfdnRvdGFsOwo+ICsJdWludDE2X3QgdnN5bmNf bGVuID0gbW9kZS0+Y3J0Y192c3luY19lbmQgLSBtb2RlLT5jcnRjX3ZzeW5jX3N0YXJ0Owo+ICsJ dWludDE2X3QgdmFjdF9zdCA9IG1vZGUtPmNydGNfdnRvdGFsIC0gbW9kZS0+Y3J0Y192c3luY19z dGFydDsKPiArCXVpbnQxNl90IHZhY3RfZW5kID0gdmFjdF9zdCArIHZkaXNwbGF5Owo+ICsJdWlu dDhfdCBvdXRfbW9kZTsKPiArCXVpbnQzMl90IGRzcF9jdHJsID0gMDsKPiArCWludCBhY3RfZW5k Owo+ICsJdWludDMyX3QgdmFsLCBwb2xmbGFnczsKPiArCWludCByZXQ7Cj4gKwlzdHJ1Y3QgZHJt X2VuY29kZXIgKmVuY29kZXI7Cj4gKwo+ICsJZHJtX2RiZyh2b3AyLT5kcm0sICJVcGRhdGUgbW9k ZSB0byAlZHglZCVzJWQsIHR5cGU6ICVkIGZvciB2cCVkXG4iLAo+ICsJCWhkaXNwbGF5LCB2ZGlz cGxheSwgbW9kZS0+ZmxhZ3MgJiBEUk1fTU9ERV9GTEFHX0lOVEVSTEFDRSA/ICJpIiA6ICJwIiwK PiArCQlkcm1fbW9kZV92cmVmcmVzaChtb2RlKSwgdmNzdGF0ZS0+b3V0cHV0X3R5cGUsIHZwLT5p ZCk7Cj4gKwo+ICsJdm9wMl9sb2NrKHZvcDIpOwo+ICsKPiArCXJldCA9IGNsa19wcmVwYXJlX2Vu YWJsZSh2cC0+ZGNsayk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCWRybV9lcnIodm9wMi0+ZHJt LCAiZmFpbGVkIHRvIGVuYWJsZSBkY2xrIGZvciB2aWRlbyBwb3J0JWQgLSAlZFxuIiwKPiArCQkJ ICAgICAgdnAtPmlkLCByZXQpOwo+ICsJCXJldHVybjsKPiArCX0KPiArCj4gKwlpZiAoIXZvcDIt PmVuYWJsZV9jb3VudCkKPiArCQl2b3AyX2VuYWJsZSh2b3AyKTsKPiArCj4gKwl2b3AyLT5lbmFi bGVfY291bnQrKzsKPiArCj4gKwl2b3AyX2NydGNfZW5hYmxlX2lycSh2cCwgVlBfSU5UX1BPU1Rf QlVGX0VNUFRZKTsKPiArCj4gKwlwb2xmbGFncyA9IDA7Cj4gKwlpZiAodmNzdGF0ZS0+YnVzX2Zs YWdzICYgRFJNX0JVU19GTEFHX1BJWERBVEFfRFJJVkVfTkVHRURHRSkKPiArCQlwb2xmbGFncyB8 PSBQT0xGTEFHX0RDTEtfSU5WOwo+ICsJaWYgKG1vZGUtPmZsYWdzICYgRFJNX01PREVfRkxBR19Q SFNZTkMpCj4gKwkJcG9sZmxhZ3MgfD0gQklUKEhTWU5DX1BPU0lUSVZFKTsKPiArCWlmIChtb2Rl LT5mbGFncyAmIERSTV9NT0RFX0ZMQUdfUFZTWU5DKQo+ICsJCXBvbGZsYWdzIHw9IEJJVChWU1lO Q19QT1NJVElWRSk7Cj4gKwo+ICsJZHJtX2Zvcl9lYWNoX2VuY29kZXJfbWFzayhlbmNvZGVyLCBj cnRjLT5kZXYsIGNydGNfc3RhdGUtPmVuY29kZXJfbWFzaykgewo+ICsJCXN0cnVjdCBkZXZpY2Vf bm9kZSAqbm9kZSwgKnBhcmVudDsKPiArCj4gKwkJcGFyZW50ID0gb2ZfZ2V0X3BhcmVudChlbmNv ZGVyLT5wb3J0KTsKPiArCj4gKwkJZm9yX2VhY2hfZW5kcG9pbnRfb2Zfbm9kZShwYXJlbnQsIG5v ZGUpIHsKPiArCQkJc3RydWN0IGRldmljZV9ub2RlICpjcnRjX3BvcnQgPSBvZl9ncmFwaF9nZXRf cmVtb3RlX3BvcnQobm9kZSk7Cj4gKwkJCXN0cnVjdCBkZXZpY2Vfbm9kZSAqZXBuOwo+ICsJCQlz dHJ1Y3Qgb2ZfZW5kcG9pbnQgZW5kcG9pbnQ7Cj4gKwo+ICsJCQlpZiAoY3J0Yy0+cG9ydCAhPSBj cnRjX3BvcnQpIHsKPiArCQkJCW9mX25vZGVfcHV0KGNydGNfcG9ydCk7Cj4gKwkJCQljb250aW51 ZTsKPiArCQkJfQo+ICsKPiArCQkJb2Zfbm9kZV9wdXQoY3J0Y19wb3J0KTsKPiArCj4gKwkJCWVw biA9IG9mX2dyYXBoX2dldF9yZW1vdGVfZW5kcG9pbnQobm9kZSk7Cj4gKwkJCW9mX2dyYXBoX3Bh cnNlX2VuZHBvaW50KGVwbiwgJmVuZHBvaW50KTsKPiArCQkJb2Zfbm9kZV9wdXQoZXBuKTsKPiAr Cj4gKwkJCWRybV9kYmcodm9wMi0+ZHJtLCAidnAlZCBpcyBjb25uZWN0ZWQgdG8gJXMsIGlkICVk XG4iLAo+ICsJCQkJCSAgIHZwLT5pZCwgZW5jb2Rlci0+bmFtZSwgZW5kcG9pbnQuaWQpOwo+ICsJ CQlyazM1Njhfc2V0X2ludGZfbXV4KHZwLCBlbmRwb2ludC5pZCwgcG9sZmxhZ3MpOwo+ICsJCX0K PiArCQlvZl9ub2RlX3B1dChwYXJlbnQpOwo+ICsJfQo+ICsKPiArCWlmICh2Y3N0YXRlLT5vdXRw dXRfbW9kZSA9PSBST0NLQ0hJUF9PVVRfTU9ERV9BQUFBICYmCj4gKwkgICAgICEodnBfZGF0YS0+ ZmVhdHVyZSAmIFZPUF9GRUFUVVJFX09VVFBVVF8xMEJJVCkpCj4gKwkJb3V0X21vZGUgPSBST0NL Q0hJUF9PVVRfTU9ERV9QODg4Owo+ICsJZWxzZQo+ICsJCW91dF9tb2RlID0gdmNzdGF0ZS0+b3V0 cHV0X21vZGU7Cj4gKwo+ICsJZHNwX2N0cmwgfD0gRklFTERfUFJFUChSSzM1NjhfVlBfRFNQX0NU UkxfX09VVF9NT0RFLCBvdXRfbW9kZSk7Cj4gKwo+ICsJaWYgKHZvcDJfb3V0cHV0X3V2X3N3YXAo dmNzdGF0ZS0+YnVzX2Zvcm1hdCwgdmNzdGF0ZS0+b3V0cHV0X21vZGUpKQo+ICsJCWRzcF9jdHJs IHw9IFJLMzU2OF9WUF9EU1BfQ1RSTF9fRFNQX1JCX1NXQVA7Cj4gKwo+ICsJaWYgKGlzX3l1dl9v dXRwdXQodmNzdGF0ZS0+YnVzX2Zvcm1hdCkpCj4gKwkJZHNwX2N0cmwgfD0gUkszNTY4X1ZQX0RT UF9DVFJMX19QT1NUX0RTUF9PVVRfUjJZOwo+ICsKPiArCXZvcDJfZGl0aGVyX3NldHVwKGNydGMs ICZkc3BfY3RybCk7Cj4gKwo+ICsJdm9wMl92cF93cml0ZSh2cCwgUkszNTY4X1ZQX0RTUF9IVE9U QUxfSFNfRU5ELCAoaHRvdGFsIDw8IDE2KSB8IGhzeW5jX2xlbik7Cj4gKwl2YWwgPSBoYWN0X3N0 IDw8IDE2Owo+ICsJdmFsIHw9IGhhY3RfZW5kOwo+ICsJdm9wMl92cF93cml0ZSh2cCwgUkszNTY4 X1ZQX0RTUF9IQUNUX1NUX0VORCwgdmFsKTsKPiArCj4gKwl2YWwgPSB2YWN0X3N0IDw8IDE2Owo+ ICsJdmFsIHw9IHZhY3RfZW5kOwo+ICsJdm9wMl92cF93cml0ZSh2cCwgUkszNTY4X1ZQX0RTUF9W QUNUX1NUX0VORCwgdmFsKTsKPiArCj4gKwlpZiAobW9kZS0+ZmxhZ3MgJiBEUk1fTU9ERV9GTEFH X0lOVEVSTEFDRSkgewo+ICsJCXVpbnQxNl90IHZhY3Rfc3RfZjEgPSB2dG90YWwgKyB2YWN0X3N0 ICsgMTsKPiArCQl1aW50MTZfdCB2YWN0X2VuZF9mMSA9IHZhY3Rfc3RfZjEgKyB2ZGlzcGxheTsK PiArCj4gKwkJdmFsID0gdmFjdF9zdF9mMSA8PCAxNiB8IHZhY3RfZW5kX2YxOwo+ICsJCXZvcDJf dnBfd3JpdGUodnAsIFJLMzU2OF9WUF9EU1BfVkFDVF9TVF9FTkRfRjEsIHZhbCk7Cj4gKwo+ICsJ CXZhbCA9IHZ0b3RhbCA8PCAxNiB8ICh2dG90YWwgKyB2c3luY19sZW4pOwo+ICsJCXZvcDJfdnBf d3JpdGUodnAsIFJLMzU2OF9WUF9EU1BfVlNfU1RfRU5EX0YxLCB2YWwpOwo+ICsJCWRzcF9jdHJs IHw9IFJLMzU2OF9WUF9EU1BfQ1RSTF9fRFNQX0lOVEVSTEFDRTsKPiArCQlkc3BfY3RybCB8PSBS SzM1NjhfVlBfRFNQX0NUUkxfX0RTUF9GSUxFRF9QT0w7Cj4gKwkJZHNwX2N0cmwgfD0gUkszNTY4 X1ZQX0RTUF9DVFJMX19QMklfRU47Cj4gKwkJdnRvdGFsICs9IHZ0b3RhbCArIDE7Cj4gKwkJYWN0 X2VuZCA9IHZhY3RfZW5kX2YxOwo+ICsJfSBlbHNlIHsKPiArCQlhY3RfZW5kID0gdmFjdF9lbmQ7 Cj4gKwl9Cj4gKwo+ICsJdm9wMl93cml0ZWwodm9wMiwgUkszNTY4X1ZQX0xJTkVfRkxBRyh2cC0+ aWQpLAo+ICsJCSAgICAoYWN0X2VuZCAtIHVzX3RvX3ZlcnRpY2FsX2xpbmUobW9kZSwgMCkpIDw8 IDE2IHwgYWN0X2VuZCk7Cj4gKwo+ICsJdm9wMl92cF93cml0ZSh2cCwgUkszNTY4X1ZQX0RTUF9W VE9UQUxfVlNfRU5ELCB2dG90YWwgPDwgMTYgfCB2c3luY19sZW4pOwo+ICsKPiArCWlmIChtb2Rl LT5mbGFncyAmIERSTV9NT0RFX0ZMQUdfREJMQ0xLKSB7Cj4gKwkJZHNwX2N0cmwgfD0gUkszNTY4 X1ZQX0RTUF9DVFJMX19DT1JFX0RDTEtfRElWOwo+ICsJCWNsb2NrICo9IDI7Cj4gKwl9Cj4gKwo+ ICsJdm9wMl92cF93cml0ZSh2cCwgUkszNTY4X1ZQX01JUElfQ1RSTCwgMCk7Cj4gKwo+ICsJY2xr X3NldF9yYXRlKHZwLT5kY2xrLCBjbG9jayk7Cj4gKwo+ICsJdm9wMl9wb3N0X2NvbmZpZyhjcnRj KTsKPiArCj4gKwl2b3AyX2NmZ19kb25lKHZwKTsKPiArCj4gKwl2b3AyX3ZwX3dyaXRlKHZwLCBS SzM1NjhfVlBfRFNQX0NUUkwsIGRzcF9jdHJsKTsKPiArCj4gKwlkcm1fY3J0Y192Ymxhbmtfb24o Y3J0Yyk7Cj4gKwo+ICsJdm9wMl91bmxvY2sodm9wMik7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQg dm9wMl9jcnRjX2F0b21pY19jaGVjayhzdHJ1Y3QgZHJtX2NydGMgKmNydGMsCj4gKwkJCQkgIHN0 cnVjdCBkcm1fYXRvbWljX3N0YXRlICpzdGF0ZSkKPiArewo+ICsJc3RydWN0IHZvcDJfdmlkZW9f cG9ydCAqdnAgPSB0b192b3AyX3ZpZGVvX3BvcnQoY3J0Yyk7Cj4gKwlzdHJ1Y3QgZHJtX3BsYW5l ICpwbGFuZTsKPiArCWludCBucGxhbmVzID0gMDsKPiArCXN0cnVjdCBkcm1fY3J0Y19zdGF0ZSAq Y3J0Y19zdGF0ZSA9IGRybV9hdG9taWNfZ2V0X25ld19jcnRjX3N0YXRlKHN0YXRlLCBjcnRjKTsK PiArCj4gKwlkcm1fYXRvbWljX2NydGNfc3RhdGVfZm9yX2VhY2hfcGxhbmUocGxhbmUsIGNydGNf c3RhdGUpCj4gKwkJbnBsYW5lcysrOwo+ICsKPiArCWlmIChucGxhbmVzID4gdnAtPm5sYXllcnMp Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRp YyBib29sIGlzX29wYXF1ZSh1aW50MTZfdCBhbHBoYSkKPiArewo+ICsJcmV0dXJuIChhbHBoYSA+ PiA4KSA9PSAweGZmOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2b3AyX3BhcnNlX2FscGhhKHN0 cnVjdCB2b3AyX2FscGhhX2NvbmZpZyAqYWxwaGFfY29uZmlnLAo+ICsJCQkgICAgIHN0cnVjdCB2 b3AyX2FscGhhICphbHBoYSkKPiArewo+ICsJaW50IHNyY19nbGJfYWxwaGFfZW4gPSBpc19vcGFx dWUoYWxwaGFfY29uZmlnLT5zcmNfZ2xiX2FscGhhX3ZhbHVlKSA/IDAgOiAxOwo+ICsJaW50IGRz dF9nbGJfYWxwaGFfZW4gPSBpc19vcGFxdWUoYWxwaGFfY29uZmlnLT5kc3RfZ2xiX2FscGhhX3Zh bHVlKSA/IDAgOiAxOwo+ICsJaW50IHNyY19jb2xvcl9tb2RlID0gYWxwaGFfY29uZmlnLT5zcmNf cHJlbXVsdGlfZW4gPyBBTFBIQV9TUkNfUFJFX01VTCA6IEFMUEhBX1NSQ19OT19QUkVfTVVMOwo+ ICsJaW50IGRzdF9jb2xvcl9tb2RlID0gYWxwaGFfY29uZmlnLT5kc3RfcHJlbXVsdGlfZW4gPyBB TFBIQV9TUkNfUFJFX01VTCA6IEFMUEhBX1NSQ19OT19QUkVfTVVMOwo+ICsKPiArCWFscGhhLT5z cmNfY29sb3JfY3RybC52YWwgPSAwOwo+ICsJYWxwaGEtPmRzdF9jb2xvcl9jdHJsLnZhbCA9IDA7 Cj4gKwlhbHBoYS0+c3JjX2FscGhhX2N0cmwudmFsID0gMDsKPiArCWFscGhhLT5kc3RfYWxwaGFf Y3RybC52YWwgPSAwOwo+ICsKPiArCWlmICghYWxwaGFfY29uZmlnLT5zcmNfcGl4ZWxfYWxwaGFf ZW4pCj4gKwkJYWxwaGEtPnNyY19jb2xvcl9jdHJsLmJpdHMuYmxlbmRfbW9kZSA9IEFMUEhBX0dM T0JBTDsKPiArCWVsc2UgaWYgKGFscGhhX2NvbmZpZy0+c3JjX3BpeGVsX2FscGhhX2VuICYmICFz cmNfZ2xiX2FscGhhX2VuKQo+ICsJCWFscGhhLT5zcmNfY29sb3JfY3RybC5iaXRzLmJsZW5kX21v ZGUgPSBBTFBIQV9QRVJfUElYOwo+ICsJZWxzZQo+ICsJCWFscGhhLT5zcmNfY29sb3JfY3RybC5i aXRzLmJsZW5kX21vZGUgPSBBTFBIQV9QRVJfUElYX0dMT0JBTDsKPiArCj4gKwlhbHBoYS0+c3Jj X2NvbG9yX2N0cmwuYml0cy5hbHBoYV9lbiA9IDE7Cj4gKwo+ICsJaWYgKGFscGhhLT5zcmNfY29s b3JfY3RybC5iaXRzLmJsZW5kX21vZGUgPT0gQUxQSEFfR0xPQkFMKSB7Cj4gKwkJYWxwaGEtPnNy Y19jb2xvcl9jdHJsLmJpdHMuY29sb3JfbW9kZSA9IHNyY19jb2xvcl9tb2RlOwo+ICsJCWFscGhh LT5zcmNfY29sb3JfY3RybC5iaXRzLmZhY3Rvcl9tb2RlID0gU1JDX0ZBQ19BTFBIQV9TUkNfR0xP QkFMOwo+ICsJfSBlbHNlIGlmIChhbHBoYS0+c3JjX2NvbG9yX2N0cmwuYml0cy5ibGVuZF9tb2Rl ID09IEFMUEhBX1BFUl9QSVgpIHsKPiArCQlhbHBoYS0+c3JjX2NvbG9yX2N0cmwuYml0cy5jb2xv cl9tb2RlID0gc3JjX2NvbG9yX21vZGU7Cj4gKwkJYWxwaGEtPnNyY19jb2xvcl9jdHJsLmJpdHMu ZmFjdG9yX21vZGUgPSBTUkNfRkFDX0FMUEhBX09ORTsKPiArCX0gZWxzZSB7Cj4gKwkJYWxwaGEt PnNyY19jb2xvcl9jdHJsLmJpdHMuY29sb3JfbW9kZSA9IEFMUEhBX1NSQ19QUkVfTVVMOwo+ICsJ CWFscGhhLT5zcmNfY29sb3JfY3RybC5iaXRzLmZhY3Rvcl9tb2RlID0gU1JDX0ZBQ19BTFBIQV9T UkNfR0xPQkFMOwo+ICsJfQo+ICsJYWxwaGEtPnNyY19jb2xvcl9jdHJsLmJpdHMuZ2xiX2FscGhh ID0gYWxwaGFfY29uZmlnLT5zcmNfZ2xiX2FscGhhX3ZhbHVlID4+IDg7Cj4gKwlhbHBoYS0+c3Jj X2NvbG9yX2N0cmwuYml0cy5hbHBoYV9tb2RlID0gQUxQSEFfU1RSQUlHSFQ7Cj4gKwlhbHBoYS0+ c3JjX2NvbG9yX2N0cmwuYml0cy5hbHBoYV9jYWxfbW9kZSA9IEFMUEhBX1NBVFVSQVRJT047Cj4g Kwo+ICsJYWxwaGEtPmRzdF9jb2xvcl9jdHJsLmJpdHMuYWxwaGFfbW9kZSA9IEFMUEhBX1NUUkFJ R0hUOwo+ICsJYWxwaGEtPmRzdF9jb2xvcl9jdHJsLmJpdHMuYWxwaGFfY2FsX21vZGUgPSBBTFBI QV9TQVRVUkFUSU9OOwo+ICsJYWxwaGEtPmRzdF9jb2xvcl9jdHJsLmJpdHMuYmxlbmRfbW9kZSA9 IEFMUEhBX0dMT0JBTDsKPiArCWFscGhhLT5kc3RfY29sb3JfY3RybC5iaXRzLmdsYl9hbHBoYSA9 IGFscGhhX2NvbmZpZy0+ZHN0X2dsYl9hbHBoYV92YWx1ZSA+PiA4Owo+ICsJYWxwaGEtPmRzdF9j b2xvcl9jdHJsLmJpdHMuY29sb3JfbW9kZSA9IGRzdF9jb2xvcl9tb2RlOwo+ICsJYWxwaGEtPmRz dF9jb2xvcl9jdHJsLmJpdHMuZmFjdG9yX21vZGUgPSBBTFBIQV9TUkNfSU5WRVJTRTsKPiArCj4g KwlhbHBoYS0+c3JjX2FscGhhX2N0cmwuYml0cy5hbHBoYV9tb2RlID0gQUxQSEFfU1RSQUlHSFQ7 Cj4gKwlhbHBoYS0+c3JjX2FscGhhX2N0cmwuYml0cy5ibGVuZF9tb2RlID0gYWxwaGEtPnNyY19j b2xvcl9jdHJsLmJpdHMuYmxlbmRfbW9kZTsKPiArCWFscGhhLT5zcmNfYWxwaGFfY3RybC5iaXRz LmFscGhhX2NhbF9tb2RlID0gQUxQSEFfU0FUVVJBVElPTjsKPiArCWFscGhhLT5zcmNfYWxwaGFf Y3RybC5iaXRzLmZhY3Rvcl9tb2RlID0gQUxQSEFfT05FOwo+ICsKPiArCWFscGhhLT5kc3RfYWxw aGFfY3RybC5iaXRzLmFscGhhX21vZGUgPSBBTFBIQV9TVFJBSUdIVDsKPiArCWlmIChhbHBoYV9j b25maWctPmRzdF9waXhlbF9hbHBoYV9lbiAmJiAhZHN0X2dsYl9hbHBoYV9lbikKPiArCQlhbHBo YS0+ZHN0X2FscGhhX2N0cmwuYml0cy5ibGVuZF9tb2RlID0gQUxQSEFfUEVSX1BJWDsKPiArCWVs c2UKPiArCQlhbHBoYS0+ZHN0X2FscGhhX2N0cmwuYml0cy5ibGVuZF9tb2RlID0gQUxQSEFfUEVS X1BJWF9HTE9CQUw7Cj4gKwlhbHBoYS0+ZHN0X2FscGhhX2N0cmwuYml0cy5hbHBoYV9jYWxfbW9k ZSA9IEFMUEhBX05PX1NBVFVSQVRJT047Cj4gKwlhbHBoYS0+ZHN0X2FscGhhX2N0cmwuYml0cy5m YWN0b3JfbW9kZSA9IEFMUEhBX1NSQ19JTlZFUlNFOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHZv cDJfZmluZF9zdGFydF9taXhlcl9pZF9mb3JfdnAoc3RydWN0IHZvcDIgKnZvcDIsIHVpbnQ4X3Qg cG9ydF9pZCkKPiArewo+ICsJc3RydWN0IHZvcDJfdmlkZW9fcG9ydCAqdnA7Cj4gKwlpbnQgdXNl ZF9sYXllciA9IDA7Cj4gKwlpbnQgaTsKPiArCj4gKwlmb3IgKGkgPSAwOyBpIDwgcG9ydF9pZDsg aSsrKSB7Cj4gKwkJdnAgPSAmdm9wMi0+dnBzW2ldOwo+ICsJCXVzZWRfbGF5ZXIgKz0gaHdlaWdo dDMyKHZwLT53aW5fbWFzayk7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIHVzZWRfbGF5ZXI7Cj4gK30K PiArCj4gK3N0YXRpYyB2b2lkIHZvcDJfc2V0dXBfY2x1c3Rlcl9hbHBoYShzdHJ1Y3Qgdm9wMiAq dm9wMiwgc3RydWN0IHZvcDJfd2luICptYWluX3dpbikKPiArewo+ICsJdWludDMyX3Qgb2Zmc2V0 ID0gKG1haW5fd2luLT5kYXRhLT5waHlzX2lkICogMHgxMCk7Cj4gKwlzdHJ1Y3Qgdm9wMl9hbHBo YV9jb25maWcgYWxwaGFfY29uZmlnOwo+ICsJc3RydWN0IHZvcDJfYWxwaGEgYWxwaGE7Cj4gKwlz dHJ1Y3QgZHJtX3BsYW5lX3N0YXRlICpib3R0b21fd2luX3BzdGF0ZTsKPiArCWJvb2wgc3JjX3Bp eGVsX2FscGhhX2VuID0gZmFsc2U7Cj4gKwl1aW50MTZfdCBzcmNfZ2xiX2FscGhhX3ZhbCwgZHN0 X2dsYl9hbHBoYV92YWw7Cj4gKwlib29sIHByZW11bHRpX2VuID0gZmFsc2U7Cj4gKwlib29sIHN3 YXAgPSBmYWxzZTsKPiArCj4gKwkvKiBBdCBvbmUgd2luIG1vZGUsIHdpbjAgaXMgZHN0L2JvdHRv bSB3aW4sIGFuZCB3aW4xIGlzIGEgYWxsIHplcm8gc3JjL3RvcCB3aW4gKi8KPiArCWJvdHRvbV93 aW5fcHN0YXRlID0gbWFpbl93aW4tPmJhc2Uuc3RhdGU7Cj4gKwlzcmNfZ2xiX2FscGhhX3ZhbCA9 IDA7Cj4gKwlkc3RfZ2xiX2FscGhhX3ZhbCA9IG1haW5fd2luLT5iYXNlLnN0YXRlLT5hbHBoYTsK PiArCj4gKwlpZiAoIWJvdHRvbV93aW5fcHN0YXRlLT5mYikKPiArCQlyZXR1cm47Cj4gKwo+ICsJ YWxwaGFfY29uZmlnLnNyY19wcmVtdWx0aV9lbiA9IHByZW11bHRpX2VuOwo+ICsJYWxwaGFfY29u ZmlnLmRzdF9wcmVtdWx0aV9lbiA9IGZhbHNlOwo+ICsJYWxwaGFfY29uZmlnLnNyY19waXhlbF9h bHBoYV9lbiA9IHNyY19waXhlbF9hbHBoYV9lbjsKPiArCWFscGhhX2NvbmZpZy5kc3RfcGl4ZWxf YWxwaGFfZW4gPSB0cnVlOyAvKiBhbHBoYSB2YWx1ZSBuZWVkIHRyYW5zZmVyIHRvIG5leHQgbWl4 ICovCj4gKwlhbHBoYV9jb25maWcuc3JjX2dsYl9hbHBoYV92YWx1ZSA9IHNyY19nbGJfYWxwaGFf dmFsOwo+ICsJYWxwaGFfY29uZmlnLmRzdF9nbGJfYWxwaGFfdmFsdWUgPSBkc3RfZ2xiX2FscGhh X3ZhbDsKPiArCXZvcDJfcGFyc2VfYWxwaGEoJmFscGhhX2NvbmZpZywgJmFscGhhKTsKPiArCj4g KwlhbHBoYS5zcmNfY29sb3JfY3RybC5iaXRzLnNyY19kc3Rfc3dhcCA9IHN3YXA7Cj4gKwl2b3Ay X3dyaXRlbCh2b3AyLCBSSzM1NjhfQ0xVU1RFUjBfTUlYX1NSQ19DT0xPUl9DVFJMICsgb2Zmc2V0 LAo+ICsJCSAgICBhbHBoYS5zcmNfY29sb3JfY3RybC52YWwpOwo+ICsJdm9wMl93cml0ZWwodm9w MiwgUkszNTY4X0NMVVNURVIwX01JWF9EU1RfQ09MT1JfQ1RSTCArIG9mZnNldCwKPiArCQkgICAg YWxwaGEuZHN0X2NvbG9yX2N0cmwudmFsKTsKPiArCXZvcDJfd3JpdGVsKHZvcDIsIFJLMzU2OF9D TFVTVEVSMF9NSVhfU1JDX0FMUEhBX0NUUkwgKyBvZmZzZXQsCj4gKwkJICAgIGFscGhhLnNyY19h bHBoYV9jdHJsLnZhbCk7Cj4gKwl2b3AyX3dyaXRlbCh2b3AyLCBSSzM1NjhfQ0xVU1RFUjBfTUlY X0RTVF9BTFBIQV9DVFJMICsgb2Zmc2V0LAo+ICsJCSAgICBhbHBoYS5kc3RfYWxwaGFfY3RybC52 YWwpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2b3AyX3NldHVwX2FscGhhKHN0cnVjdCB2b3Ay X3ZpZGVvX3BvcnQgKnZwKQo+ICt7Cj4gKwlzdHJ1Y3Qgdm9wMiAqdm9wMiA9IHZwLT52b3AyOwo+ ICsJc3RydWN0IGRybV9mcmFtZWJ1ZmZlciAqZmI7Cj4gKwlzdHJ1Y3Qgdm9wMl9hbHBoYV9jb25m aWcgYWxwaGFfY29uZmlnOwo+ICsJc3RydWN0IHZvcDJfYWxwaGEgYWxwaGE7Cj4gKwlzdHJ1Y3Qg ZHJtX3BsYW5lICpwbGFuZTsKPiArCWludCBwaXhlbF9hbHBoYV9lbjsKPiArCWludCBwcmVtdWx0 aV9lbiwgZ3ByZW11bHRpX2VuID0gMDsKPiArCWludCBtaXhlcl9pZDsKPiArCXVpbnQzMl90IG9m ZnNldDsKPiArCWJvb2wgYm90dG9tX2xheWVyX2FscGhhX2VuID0gZmFsc2U7Cj4gKwl1aW50MzJf dCBkc3RfZ2xvYmFsX2FscGhhID0gRFJNX0JMRU5EX0FMUEhBX09QQVFVRTsKPiArCj4gKwltaXhl cl9pZCA9IHZvcDJfZmluZF9zdGFydF9taXhlcl9pZF9mb3JfdnAodm9wMiwgdnAtPmlkKTsKPiAr CWFscGhhX2NvbmZpZy5kc3RfcGl4ZWxfYWxwaGFfZW4gPSB0cnVlOyAvKiBhbHBoYSB2YWx1ZSBu ZWVkIHRyYW5zZmVyIHRvIG5leHQgbWl4ICovCj4gKwo+ICsJZHJtX2F0b21pY19jcnRjX2Zvcl9l YWNoX3BsYW5lKHBsYW5lLCAmdnAtPmNydGMpIHsKPiArCQlzdHJ1Y3Qgdm9wMl93aW4gKndpbiA9 IHRvX3ZvcDJfd2luKHBsYW5lKTsKPiArCj4gKwkJaWYgKHBsYW5lLT5zdGF0ZS0+bm9ybWFsaXpl ZF96cG9zID09IDAgJiYKPiArCQkgICAgIWlzX29wYXF1ZShwbGFuZS0+c3RhdGUtPmFscGhhKSAm Jgo+ICsJCSAgICAhdm9wMl9jbHVzdGVyX3dpbmRvdyh3aW4pKSB7Cj4gKwkJCS8qCj4gKwkJCSAq IElmIGJvdHRvbSBsYXllciBoYXZlIGdsb2JhbCBhbHBoYSBlZmZlY3QgW2V4Y2VwdCBjbHVzdGVy IGxheWVyLAo+ICsJCQkgKiBiZWNhdXNlIGNsdXN0ZXIgaGF2ZSBkZWFsIHdpdGggYm90dG9tIGxh eWVyIGdsb2JhbCBhbHBoYSB2YWx1ZQo+ICsJCQkgKiBhdCBjbHVzdGVyIG1peF0sIGJvdHRvbSBs YXllciBtaXggbmVlZCBkZWFsIHdpdGggZ2xvYmFsIGFscGhhLgo+ICsJCQkgKi8KPiArCQkJYm90 dG9tX2xheWVyX2FscGhhX2VuID0gdHJ1ZTsKPiArCQkJZHN0X2dsb2JhbF9hbHBoYSA9IHBsYW5l LT5zdGF0ZS0+YWxwaGE7Cj4gKwkJfQo+ICsJfQo+ICsKPiArCWRybV9hdG9taWNfY3J0Y19mb3Jf ZWFjaF9wbGFuZShwbGFuZSwgJnZwLT5jcnRjKSB7Cj4gKwkJc3RydWN0IHZvcDJfd2luICp3aW4g PSB0b192b3AyX3dpbihwbGFuZSk7Cj4gKwkJaW50IHpwb3MgPSBwbGFuZS0+c3RhdGUtPm5vcm1h bGl6ZWRfenBvczsKPiArCj4gKwkJaWYgKHBsYW5lLT5zdGF0ZS0+cGl4ZWxfYmxlbmRfbW9kZSA9 PSBEUk1fTU9ERV9CTEVORF9QUkVNVUxUSSkKPiArCQkJcHJlbXVsdGlfZW4gPSAxOwo+ICsJCWVs c2UKPiArCQkJcHJlbXVsdGlfZW4gPSAwOwo+ICsKPiArCQlwbGFuZSA9ICZ3aW4tPmJhc2U7Cj4g KwkJZmIgPSBwbGFuZS0+c3RhdGUtPmZiOwo+ICsKPiArCQlwaXhlbF9hbHBoYV9lbiA9IGZiLT5m b3JtYXQtPmhhc19hbHBoYTsKPiArCj4gKwkJYWxwaGFfY29uZmlnLnNyY19wcmVtdWx0aV9lbiA9 IHByZW11bHRpX2VuOwo+ICsKPiArCQlpZiAoYm90dG9tX2xheWVyX2FscGhhX2VuICYmIHpwb3Mg PT0gMSkgewo+ICsJCQlncHJlbXVsdGlfZW4gPSBwcmVtdWx0aV9lbjsKPiArCQkJLyogQ2QgPSBD cyArICgxIC0gQXMpICogQ2QgKiBBZ2QgKi8KPiArCQkJYWxwaGFfY29uZmlnLmRzdF9wcmVtdWx0 aV9lbiA9IGZhbHNlOwo+ICsJCQlhbHBoYV9jb25maWcuc3JjX3BpeGVsX2FscGhhX2VuID0gcGl4 ZWxfYWxwaGFfZW47Cj4gKwkJCWFscGhhX2NvbmZpZy5zcmNfZ2xiX2FscGhhX3ZhbHVlID0gcGxh bmUtPnN0YXRlLT5hbHBoYTsKPiArCQkJYWxwaGFfY29uZmlnLmRzdF9nbGJfYWxwaGFfdmFsdWUg PSBkc3RfZ2xvYmFsX2FscGhhOwo+ICsJCX0gZWxzZSBpZiAodm9wMl9jbHVzdGVyX3dpbmRvdyh3 aW4pKSB7Cj4gKwkJCS8qIE1peCBvdXRwdXQgZGF0YSBvbmx5IGhhdmUgcGl4ZWwgYWxwaGEgKi8K PiArCQkJYWxwaGFfY29uZmlnLmRzdF9wcmVtdWx0aV9lbiA9IHRydWU7Cj4gKwkJCWFscGhhX2Nv bmZpZy5zcmNfcGl4ZWxfYWxwaGFfZW4gPSB0cnVlOwo+ICsJCQlhbHBoYV9jb25maWcuc3JjX2ds Yl9hbHBoYV92YWx1ZSA9IERSTV9CTEVORF9BTFBIQV9PUEFRVUU7Cj4gKwkJCWFscGhhX2NvbmZp Zy5kc3RfZ2xiX2FscGhhX3ZhbHVlID0gRFJNX0JMRU5EX0FMUEhBX09QQVFVRTsKPiArCQl9IGVs c2Ugewo+ICsJCQkvKiBDZCA9IENzICsgKDEgLSBBcykgKiBDZCAqLwo+ICsJCQlhbHBoYV9jb25m aWcuZHN0X3ByZW11bHRpX2VuID0gdHJ1ZTsKPiArCQkJYWxwaGFfY29uZmlnLnNyY19waXhlbF9h bHBoYV9lbiA9IHBpeGVsX2FscGhhX2VuOwo+ICsJCQlhbHBoYV9jb25maWcuc3JjX2dsYl9hbHBo YV92YWx1ZSA9IHBsYW5lLT5zdGF0ZS0+YWxwaGE7Cj4gKwkJCWFscGhhX2NvbmZpZy5kc3RfZ2xi X2FscGhhX3ZhbHVlID0gRFJNX0JMRU5EX0FMUEhBX09QQVFVRTsKPiArCQl9Cj4gKwo+ICsJCXZv cDJfcGFyc2VfYWxwaGEoJmFscGhhX2NvbmZpZywgJmFscGhhKTsKPiArCj4gKwkJb2Zmc2V0ID0g KG1peGVyX2lkICsgenBvcyAtIDEpICogMHgxMDsKPiArCQl2b3AyX3dyaXRlbCh2b3AyLCBSSzM1 NjhfTUlYMF9TUkNfQ09MT1JfQ1RSTCArIG9mZnNldCwKPiArCQkJICAgIGFscGhhLnNyY19jb2xv cl9jdHJsLnZhbCk7Cj4gKwkJdm9wMl93cml0ZWwodm9wMiwgUkszNTY4X01JWDBfRFNUX0NPTE9S X0NUUkwgKyBvZmZzZXQsCj4gKwkJCSAgICBhbHBoYS5kc3RfY29sb3JfY3RybC52YWwpOwo+ICsJ CXZvcDJfd3JpdGVsKHZvcDIsIFJLMzU2OF9NSVgwX1NSQ19BTFBIQV9DVFJMICsgb2Zmc2V0LAo+ ICsJCQkgICAgYWxwaGEuc3JjX2FscGhhX2N0cmwudmFsKTsKPiArCQl2b3AyX3dyaXRlbCh2b3Ay LCBSSzM1NjhfTUlYMF9EU1RfQUxQSEFfQ1RSTCArIG9mZnNldCwKPiArCQkJICAgIGFscGhhLmRz dF9hbHBoYV9jdHJsLnZhbCk7Cj4gKwl9Cj4gKwo+ICsJaWYgKHZwLT5pZCA9PSAwKSB7Cj4gKwkJ aWYgKGJvdHRvbV9sYXllcl9hbHBoYV9lbikgewo+ICsJCQkvKiBUcmFuc2ZlciBwaXhlbCBhbHBo YSB0byBoZHIgbWl4ICovCj4gKwkJCWFscGhhX2NvbmZpZy5zcmNfcHJlbXVsdGlfZW4gPSBncHJl bXVsdGlfZW47Cj4gKwkJCWFscGhhX2NvbmZpZy5kc3RfcHJlbXVsdGlfZW4gPSB0cnVlOwo+ICsJ CQlhbHBoYV9jb25maWcuc3JjX3BpeGVsX2FscGhhX2VuID0gdHJ1ZTsKPiArCQkJYWxwaGFfY29u ZmlnLnNyY19nbGJfYWxwaGFfdmFsdWUgPSBEUk1fQkxFTkRfQUxQSEFfT1BBUVVFOwo+ICsJCQlh bHBoYV9jb25maWcuZHN0X2dsYl9hbHBoYV92YWx1ZSA9IERSTV9CTEVORF9BTFBIQV9PUEFRVUU7 Cj4gKwkJCXZvcDJfcGFyc2VfYWxwaGEoJmFscGhhX2NvbmZpZywgJmFscGhhKTsKPiArCj4gKwkJ CXZvcDJfd3JpdGVsKHZvcDIsIFJLMzU2OF9IRFIwX1NSQ19DT0xPUl9DVFJMLAo+ICsJCQkJYWxw aGEuc3JjX2NvbG9yX2N0cmwudmFsKTsKPiArCQkJdm9wMl93cml0ZWwodm9wMiwgUkszNTY4X0hE UjBfRFNUX0NPTE9SX0NUUkwsCj4gKwkJCQlhbHBoYS5kc3RfY29sb3JfY3RybC52YWwpOwo+ICsJ CQl2b3AyX3dyaXRlbCh2b3AyLCBSSzM1NjhfSERSMF9TUkNfQUxQSEFfQ1RSTCwKPiArCQkJCWFs cGhhLnNyY19hbHBoYV9jdHJsLnZhbCk7Cj4gKwkJCXZvcDJfd3JpdGVsKHZvcDIsIFJLMzU2OF9I RFIwX0RTVF9BTFBIQV9DVFJMLAo+ICsJCQkJYWxwaGEuZHN0X2FscGhhX2N0cmwudmFsKTsKPiAr CQl9IGVsc2Ugewo+ICsJCQl2b3AyX3dyaXRlbCh2b3AyLCBSSzM1NjhfSERSMF9TUkNfQ09MT1Jf Q1RSTCwgMCk7Cj4gKwkJfQo+ICsJfQo+ICt9Cj4gKwo+ICsjZGVmaW5lIE5SX1ZQUwkJMwo+ICsj ZGVmaW5lIE5SX01JWEVSUwk2Cj4gKwo+ICtzdGF0aWMgdm9pZCB2b3AyX3NldHVwX2xheWVyX21p eGVyKHN0cnVjdCB2b3AyX3ZpZGVvX3BvcnQgKnZwKQo+ICt7Cj4gKwlzdHJ1Y3Qgdm9wMiAqdm9w MiA9IHZwLT52b3AyOwo+ICsJc3RydWN0IGRybV9wbGFuZSAqcGxhbmU7Cj4gKwl1aW50MzJfdCBs YXllcl9zZWwgPSAwOwo+ICsJdWludDMyX3QgcG9ydF9zZWw7Cj4gKwlpbnQgbmxheWVyLCBvZnM7 Cj4gKwlzdHJ1Y3QgZHJtX2Rpc3BsYXlfbW9kZSAqYWRqdXN0ZWRfbW9kZTsKPiArCXVpbnQxNl90 IGhzeW5jX2xlbjsKPiArCXVpbnQxNl90IGhkaXNwbGF5Owo+ICsJdWludDMyX3QgYmdfZGx5Owo+ ICsJdWludDMyX3QgcHJlX3NjYW5fZGx5Owo+ICsJaW50IGk7Cj4gKwlzdHJ1Y3Qgdm9wMl92aWRl b19wb3J0ICp2cDAgPSAmdm9wMi0+dnBzWzBdOwo+ICsJc3RydWN0IHZvcDJfdmlkZW9fcG9ydCAq dnAxID0gJnZvcDItPnZwc1sxXTsKPiArCXN0cnVjdCB2b3AyX3ZpZGVvX3BvcnQgKnZwMiA9ICZ2 b3AyLT52cHNbMl07Cj4gKwo+ICsJYWRqdXN0ZWRfbW9kZSA9ICZ2cC0+Y3J0Yy5zdGF0ZS0+YWRq dXN0ZWRfbW9kZTsKPiArCWhzeW5jX2xlbiA9IGFkanVzdGVkX21vZGUtPmNydGNfaHN5bmNfZW5k IC0gYWRqdXN0ZWRfbW9kZS0+Y3J0Y19oc3luY19zdGFydDsKPiArCWhkaXNwbGF5ID0gYWRqdXN0 ZWRfbW9kZS0+Y3J0Y19oZGlzcGxheTsKPiArCj4gKwliZ19kbHkgPSB2cC0+ZGF0YS0+cHJlX3Nj YW5fbWF4X2RseVszXTsKPiArCXZvcDJfd3JpdGVsKHZvcDIsIFJLMzU2OF9WUF9CR19NSVhfQ1RS TCh2cC0+aWQpLAo+ICsJCQkgICAgRklFTERfUFJFUChSSzM1NjhfVlBfQkdfTUlYX0NUUkxfX0JH X0RMWSwgYmdfZGx5KSk7Cj4gKwo+ICsJcHJlX3NjYW5fZGx5ID0gKChiZ19kbHkgKyAoaGRpc3Bs YXkgPj4gMSkgLSAxKSA8PCAxNikgfCBoc3luY19sZW47Cj4gKwl2b3AyX3ZwX3dyaXRlKHZwLCBS SzM1NjhfVlBfUFJFX1NDQU5fSFRJTUlORywgcHJlX3NjYW5fZGx5KTsKPiArCj4gKwl2b3AyX3dy aXRlbCh2b3AyLCBSSzM1NjhfT1ZMX0NUUkwsIDApOwo+ICsJcG9ydF9zZWwgPSB2b3AyX3JlYWRs KHZvcDIsIFJLMzU2OF9PVkxfUE9SVF9TRUwpOwo+ICsJcG9ydF9zZWwgJj0gUkszNTY4X09WTF9Q T1JUX1NFTF9fU0VMX1BPUlQ7Cj4gKwo+ICsJaWYgKHZwMC0+bmxheWVycykKPiArCQlwb3J0X3Nl bCB8PSBGSUVMRF9QUkVQKFJLMzU2OF9PVkxfUE9SVF9TRVRfX1BPUlQwX01VWCwKPiArCQkJCSAg ICAgdnAwLT5ubGF5ZXJzIC0gMSk7Cj4gKwllbHNlCj4gKwkJcG9ydF9zZWwgfD0gRklFTERfUFJF UChSSzM1NjhfT1ZMX1BPUlRfU0VUX19QT1JUMF9NVVgsIDgpOwo+ICsKPiArCWlmICh2cDEtPm5s YXllcnMpCj4gKwkJcG9ydF9zZWwgfD0gRklFTERfUFJFUChSSzM1NjhfT1ZMX1BPUlRfU0VUX19Q T1JUMV9NVVgsCj4gKwkJCQkgICAgICh2cDAtPm5sYXllcnMgKyB2cDEtPm5sYXllcnMgLSAxKSk7 Cj4gKwllbHNlCj4gKwkJcG9ydF9zZWwgfD0gRklFTERfUFJFUChSSzM1NjhfT1ZMX1BPUlRfU0VU X19QT1JUMV9NVVgsIDgpOwo+ICsKPiArCWlmICh2cDItPm5sYXllcnMpCj4gKwkJcG9ydF9zZWwg fD0gRklFTERfUFJFUChSSzM1NjhfT1ZMX1BPUlRfU0VUX19QT1JUMl9NVVgsCj4gKwkJCSh2cDIt Pm5sYXllcnMgKyB2cDEtPm5sYXllcnMgKyB2cDAtPm5sYXllcnMgLSAxKSk7Cj4gKwllbHNlCj4g KwkJcG9ydF9zZWwgfD0gRklFTERfUFJFUChSSzM1NjhfT1ZMX1BPUlRfU0VUX19QT1JUMV9NVVgs IDgpOwo+ICsKPiArCWxheWVyX3NlbCA9IHZvcDJfcmVhZGwodm9wMiwgUkszNTY4X09WTF9MQVlF Ul9TRUwpOwo+ICsKPiArCW9mcyA9IDA7Cj4gKwlmb3IgKGkgPSAwOyBpIDwgdnAtPmlkOyBpKysp Cj4gKwkJb2ZzICs9IHZvcDItPnZwc1tpXS5ubGF5ZXJzOwo+ICsKPiArCW5sYXllciA9IDA7Cj4g Kwlkcm1fYXRvbWljX2NydGNfZm9yX2VhY2hfcGxhbmUocGxhbmUsICZ2cC0+Y3J0Yykgewo+ICsJ CXN0cnVjdCB2b3AyX3dpbiAqd2luID0gdG9fdm9wMl93aW4ocGxhbmUpOwo+ICsKPiArCQlzd2l0 Y2ggKHdpbi0+ZGF0YS0+cGh5c19pZCkgewo+ICsJCWNhc2UgUk9DS0NISVBfVk9QMl9DTFVTVEVS MDoKPiArCQkJcG9ydF9zZWwgJj0gflJLMzU2OF9PVkxfUE9SVF9TRUxfX0NMVVNURVIwOwo+ICsJ CQlwb3J0X3NlbCB8PSBGSUVMRF9QUkVQKFJLMzU2OF9PVkxfUE9SVF9TRUxfX0NMVVNURVIwLCB2 cC0+aWQpOwo+ICsJCQlicmVhazsKPiArCQljYXNlIFJPQ0tDSElQX1ZPUDJfQ0xVU1RFUjE6Cj4g KwkJCXBvcnRfc2VsICY9IH5SSzM1NjhfT1ZMX1BPUlRfU0VMX19DTFVTVEVSMTsKPiArCQkJcG9y dF9zZWwgfD0gRklFTERfUFJFUChSSzM1NjhfT1ZMX1BPUlRfU0VMX19DTFVTVEVSMSwgdnAtPmlk KTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSBST0NLQ0hJUF9WT1AyX0VTTUFSVDA6Cj4gKwkJCXBv cnRfc2VsICY9IH5SSzM1NjhfT1ZMX1BPUlRfU0VMX19FU01BUlQwOwo+ICsJCQlwb3J0X3NlbCB8 PSBGSUVMRF9QUkVQKFJLMzU2OF9PVkxfUE9SVF9TRUxfX0VTTUFSVDAsIHZwLT5pZCk7Cj4gKwkJ CWJyZWFrOwo+ICsJCWNhc2UgUk9DS0NISVBfVk9QMl9FU01BUlQxOgo+ICsJCQlwb3J0X3NlbCAm PSB+UkszNTY4X09WTF9QT1JUX1NFTF9fRVNNQVJUMTsKPiArCQkJcG9ydF9zZWwgfD0gRklFTERf UFJFUChSSzM1NjhfT1ZMX1BPUlRfU0VMX19FU01BUlQxLCB2cC0+aWQpOwo+ICsJCQlicmVhazsK PiArCQljYXNlIFJPQ0tDSElQX1ZPUDJfU01BUlQwOgo+ICsJCQlwb3J0X3NlbCAmPSB+UkszNTY4 X09WTF9QT1JUX1NFTF9fU01BUlQwOwo+ICsJCQlwb3J0X3NlbCB8PSBGSUVMRF9QUkVQKFJLMzU2 OF9PVkxfUE9SVF9TRUxfX1NNQVJUMCwgdnAtPmlkKTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSBS T0NLQ0hJUF9WT1AyX1NNQVJUMToKPiArCQkJcG9ydF9zZWwgJj0gflJLMzU2OF9PVkxfUE9SVF9T RUxfX1NNQVJUMTsKPiArCQkJcG9ydF9zZWwgfD0gRklFTERfUFJFUChSSzM1NjhfT1ZMX1BPUlRf U0VMX19TTUFSVDEsIHZwLT5pZCk7Cj4gKwkJCWJyZWFrOwo+ICsJCX0KPiArCj4gKwkJbGF5ZXJf c2VsICY9IH5SSzM1NjhfT1ZMX0xBWUVSX1NFTF9fTEFZRVIobmxheWVyICsgb2ZzLCAweDcpOwo+ ICsJCWxheWVyX3NlbCB8PSBSSzM1NjhfT1ZMX0xBWUVSX1NFTF9fTEFZRVIobmxheWVyICsgb2Zz LCB3aW4tPmRhdGEtPmxheWVyX3NlbF9pZCk7Cj4gKwkJbmxheWVyKys7Cj4gKwl9Cj4gKwo+ICsJ LyogY29uZmlndXJlIHVudXNlZCBsYXllcnMgdG8gMHg1IChyZXNlcnZlZCkgKi8KPiArCWZvciAo OyBubGF5ZXIgPCAzOyBubGF5ZXIrKykgewo+ICsJCWxheWVyX3NlbCAmPSB+UkszNTY4X09WTF9M QVlFUl9TRUxfX0xBWUVSKG5sYXllciArIG9mcywgMHg3KTsKPiArCQlsYXllcl9zZWwgfD0gUksz NTY4X09WTF9MQVlFUl9TRUxfX0xBWUVSKG5sYXllciArIG9mcywgNSk7Cj4gKwl9Cj4gKwo+ICsJ dm9wMl93cml0ZWwodm9wMiwgUkszNTY4X09WTF9MQVlFUl9TRUwsIGxheWVyX3NlbCk7Cj4gKwl2 b3AyX3dyaXRlbCh2b3AyLCBSSzM1NjhfT1ZMX1BPUlRfU0VMLCBwb3J0X3NlbCk7Cj4gKwl2b3Ay X3dyaXRlbCh2b3AyLCBSSzM1NjhfT1ZMX0NUUkwsIFJLMzU2OF9PVkxfQ1RSTF9fTEFZRVJTRUxf UkVHRE9ORV9JTUQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2b3AyX3NldHVwX2RseV9mb3Jf d2luZG93cyhzdHJ1Y3Qgdm9wMiAqdm9wMikKPiArewo+ICsJc3RydWN0IHZvcDJfd2luICp3aW47 Cj4gKwlpbnQgaSA9IDA7Cj4gKwl1aW50MzJfdCBjZGx5ID0gMCwgc2RseSA9IDA7Cj4gKwo+ICsJ Zm9yIChpID0gMDsgaSA8IHZvcDItPmRhdGEtPndpbl9zaXplOyBpKyspIHsKPiArCQl1aW50MzJf dCBkbHk7Cj4gKwo+ICsJCXdpbiA9ICZ2b3AyLT53aW5baV07Cj4gKwkJZGx5ID0gd2luLT5kZWxh eTsKPiArCj4gKwkJc3dpdGNoICh3aW4tPmRhdGEtPnBoeXNfaWQpIHsKPiArCQljYXNlIFJPQ0tD SElQX1ZPUDJfQ0xVU1RFUjA6Cj4gKwkJCWNkbHkgfD0gRklFTERfUFJFUChSSzM1NjhfQ0xVU1RF Ul9ETFlfTlVNX19DTFVTVEVSMF8wLCBkbHkpOwo+ICsJCQljZGx5IHw9IEZJRUxEX1BSRVAoUksz NTY4X0NMVVNURVJfRExZX05VTV9fQ0xVU1RFUjBfMSwgZGx5KTsKPiArCQkJYnJlYWs7Cj4gKwkJ Y2FzZSBST0NLQ0hJUF9WT1AyX0NMVVNURVIxOgo+ICsJCQljZGx5IHw9IEZJRUxEX1BSRVAoUksz NTY4X0NMVVNURVJfRExZX05VTV9fQ0xVU1RFUjFfMCwgZGx5KTsKPiArCQkJY2RseSB8PSBGSUVM RF9QUkVQKFJLMzU2OF9DTFVTVEVSX0RMWV9OVU1fX0NMVVNURVIxXzEsIGRseSk7Cj4gKwkJCWJy ZWFrOwo+ICsJCWNhc2UgUk9DS0NISVBfVk9QMl9FU01BUlQwOgo+ICsJCQlzZGx5IHw9IEZJRUxE X1BSRVAoUkszNTY4X1NNQVJUX0RMWV9OVU1fX0VTTUFSVDAsIGRseSk7Cj4gKwkJCWJyZWFrOwo+ ICsJCWNhc2UgUk9DS0NISVBfVk9QMl9FU01BUlQxOgo+ICsJCQlzZGx5IHw9IEZJRUxEX1BSRVAo UkszNTY4X1NNQVJUX0RMWV9OVU1fX0VTTUFSVDEsIGRseSk7Cj4gKwkJCWJyZWFrOwo+ICsJCWNh c2UgUk9DS0NISVBfVk9QMl9TTUFSVDA6Cj4gKwkJCXNkbHkgfD0gRklFTERfUFJFUChSSzM1Njhf U01BUlRfRExZX05VTV9fU01BUlQxLCBkbHkpOwo+ICsJCQlicmVhazsKPiArCQljYXNlIFJPQ0tD SElQX1ZPUDJfU01BUlQxOgo+ICsJCQlzZGx5IHw9IEZJRUxEX1BSRVAoUkszNTY4X1NNQVJUX0RM WV9OVU1fX1NNQVJUMCwgZGx5KTsKPiArCQkJYnJlYWs7Cj4gKwkJfQo+ICsJfQo+ICsKPiArCXZv cDJfd3JpdGVsKHZvcDIsIFJLMzU2OF9DTFVTVEVSX0RMWV9OVU0sIGNkbHkpOwo+ICsJdm9wMl93 cml0ZWwodm9wMiwgUkszNTY4X1NNQVJUX0RMWV9OVU0sIHNkbHkpOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgdm9pZCB2b3AyX2NydGNfYXRvbWljX2JlZ2luKHN0cnVjdCBkcm1fY3J0YyAqY3J0Yywgc3Ry dWN0IGRybV9hdG9taWNfc3RhdGUgKnN0YXRlKQo+ICt7Cj4gKwlzdHJ1Y3Qgdm9wMl92aWRlb19w b3J0ICp2cCA9IHRvX3ZvcDJfdmlkZW9fcG9ydChjcnRjKTsKPiArCXN0cnVjdCB2b3AyICp2b3Ay ID0gdnAtPnZvcDI7Cj4gKwlzdHJ1Y3QgZHJtX3BsYW5lICpwbGFuZTsKPiArCj4gKwl2cC0+d2lu X21hc2sgPSAwOwo+ICsKPiArCWRybV9hdG9taWNfY3J0Y19mb3JfZWFjaF9wbGFuZShwbGFuZSwg Y3J0Yykgewo+ICsJCXN0cnVjdCB2b3AyX3dpbiAqd2luID0gdG9fdm9wMl93aW4ocGxhbmUpOwo+ ICsKPiArCQl3aW4tPmRlbGF5ID0gd2luLT5kYXRhLT5kbHlbVk9QMl9ETFlfTU9ERV9ERUZBVUxU XTsKPiArCj4gKwkJdnAtPndpbl9tYXNrIHw9IEJJVCh3aW4tPmRhdGEtPnBoeXNfaWQpOwo+ICsK PiArCQlpZiAodm9wMl9jbHVzdGVyX3dpbmRvdyh3aW4pKQo+ICsJCQl2b3AyX3NldHVwX2NsdXN0 ZXJfYWxwaGEodm9wMiwgd2luKTsKPiArCX0KPiArCj4gKwlpZiAoIXZwLT53aW5fbWFzaykKPiAr CQlyZXR1cm47Cj4gKwo+ICsJdm9wMl9zZXR1cF9sYXllcl9taXhlcih2cCk7Cj4gKwl2b3AyX3Nl dHVwX2FscGhhKHZwKTsKPiArCXZvcDJfc2V0dXBfZGx5X2Zvcl93aW5kb3dzKHZvcDIpOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgdm9pZCB2b3AyX2NydGNfYXRvbWljX2ZsdXNoKHN0cnVjdCBkcm1fY3J0 YyAqY3J0Yywgc3RydWN0IGRybV9hdG9taWNfc3RhdGUgKnN0YXRlKQo+ICt7Cj4gKwlzdHJ1Y3Qg dm9wMl92aWRlb19wb3J0ICp2cCA9IHRvX3ZvcDJfdmlkZW9fcG9ydChjcnRjKTsKPiArCXN0cnVj dCB2b3AyICp2b3AyID0gdnAtPnZvcDI7Cj4gKwo+ICsJc3Bpbl9sb2NrKCZ2b3AyLT5yZWdfbG9j ayk7Cj4gKwo+ICsJdm9wMl9wb3N0X2NvbmZpZyhjcnRjKTsKPiArCj4gKwlzcGluX3VubG9jaygm dm9wMi0+cmVnX2xvY2spOwo+ICsKPiArCXZvcDJfY2ZnX2RvbmUodnApOwo+ICsKPiArCXNwaW5f bG9ja19pcnEoJmNydGMtPmRldi0+ZXZlbnRfbG9jayk7Cj4gKwo+ICsJaWYgKGNydGMtPnN0YXRl LT5ldmVudCkgewo+ICsJCVdBUk5fT04oZHJtX2NydGNfdmJsYW5rX2dldChjcnRjKSk7Cj4gKwkJ dnAtPmV2ZW50ID0gY3J0Yy0+c3RhdGUtPmV2ZW50Owo+ICsJCWNydGMtPnN0YXRlLT5ldmVudCA9 IE5VTEw7Cj4gKwl9Cj4gKwo+ICsJc3Bpbl91bmxvY2tfaXJxKCZjcnRjLT5kZXYtPmV2ZW50X2xv Y2spOwo+ICt9Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGRybV9jcnRjX2hlbHBlcl9mdW5j cyB2b3AyX2NydGNfaGVscGVyX2Z1bmNzID0gewo+ICsJLm1vZGVfZml4dXAgPSB2b3AyX2NydGNf bW9kZV9maXh1cCwKPiArCS5hdG9taWNfY2hlY2sgPSB2b3AyX2NydGNfYXRvbWljX2NoZWNrLAo+ ICsJLmF0b21pY19iZWdpbiA9IHZvcDJfY3J0Y19hdG9taWNfYmVnaW4sCj4gKwkuYXRvbWljX2Zs dXNoID0gdm9wMl9jcnRjX2F0b21pY19mbHVzaCwKPiArCS5hdG9taWNfZW5hYmxlID0gdm9wMl9j cnRjX2F0b21pY19lbmFibGUsCj4gKwkuYXRvbWljX2Rpc2FibGUgPSB2b3AyX2NydGNfYXRvbWlj X2Rpc2FibGUsCj4gK307Cj4gKwo+ICtzdGF0aWMgdm9pZCB2b3AyX2NydGNfcmVzZXQoc3RydWN0 IGRybV9jcnRjICpjcnRjKQo+ICt7Cj4gKwlzdHJ1Y3Qgcm9ja2NoaXBfY3J0Y19zdGF0ZSAqdmNz dGF0ZSA9IHRvX3JvY2tjaGlwX2NydGNfc3RhdGUoY3J0Yy0+c3RhdGUpOwo+ICsKPiArCWlmIChj cnRjLT5zdGF0ZSkgewo+ICsJCV9fZHJtX2F0b21pY19oZWxwZXJfY3J0Y19kZXN0cm95X3N0YXRl KGNydGMtPnN0YXRlKTsKPiArCQlrZnJlZSh2Y3N0YXRlKTsKPiArCX0KPiArCj4gKwl2Y3N0YXRl ID0ga3phbGxvYyhzaXplb2YoKnZjc3RhdGUpLCBHRlBfS0VSTkVMKTsKPiArCWlmICghdmNzdGF0 ZSkKPiArCQlyZXR1cm47Cj4gKwo+ICsJY3J0Yy0+c3RhdGUgPSAmdmNzdGF0ZS0+YmFzZTsKPiAr CWNydGMtPnN0YXRlLT5jcnRjID0gY3J0YzsKPiArfQo+ICsKPiArc3RhdGljIHN0cnVjdCBkcm1f Y3J0Y19zdGF0ZSAqdm9wMl9jcnRjX2R1cGxpY2F0ZV9zdGF0ZShzdHJ1Y3QgZHJtX2NydGMgKmNy dGMpCj4gK3sKPiArCXN0cnVjdCByb2NrY2hpcF9jcnRjX3N0YXRlICp2Y3N0YXRlLCAqb2xkX3Zj c3RhdGU7Cj4gKwo+ICsJb2xkX3Zjc3RhdGUgPSB0b19yb2NrY2hpcF9jcnRjX3N0YXRlKGNydGMt PnN0YXRlKTsKPiArCj4gKwl2Y3N0YXRlID0ga21lbWR1cChvbGRfdmNzdGF0ZSwgc2l6ZW9mKCpv bGRfdmNzdGF0ZSksIEdGUF9LRVJORUwpOwo+ICsJaWYgKCF2Y3N0YXRlKQo+ICsJCXJldHVybiBO VUxMOwo+ICsKPiArCV9fZHJtX2F0b21pY19oZWxwZXJfY3J0Y19kdXBsaWNhdGVfc3RhdGUoY3J0 YywgJnZjc3RhdGUtPmJhc2UpOwo+ICsKPiArCXJldHVybiAmdmNzdGF0ZS0+YmFzZTsKPiArfQo+ ICsKPiArc3RhdGljIHZvaWQgdm9wMl9jcnRjX2Rlc3Ryb3lfc3RhdGUoc3RydWN0IGRybV9jcnRj ICpjcnRjLAo+ICsJCQkJICAgIHN0cnVjdCBkcm1fY3J0Y19zdGF0ZSAqc3RhdGUpCj4gK3sKPiAr CXN0cnVjdCByb2NrY2hpcF9jcnRjX3N0YXRlICp2Y3N0YXRlID0gdG9fcm9ja2NoaXBfY3J0Y19z dGF0ZShzdGF0ZSk7Cj4gKwo+ICsJX19kcm1fYXRvbWljX2hlbHBlcl9jcnRjX2Rlc3Ryb3lfc3Rh dGUoJnZjc3RhdGUtPmJhc2UpOwo+ICsJa2ZyZWUodmNzdGF0ZSk7Cj4gK30KPiArCj4gK3N0YXRp YyBjb25zdCBzdHJ1Y3QgZHJtX2NydGNfZnVuY3Mgdm9wMl9jcnRjX2Z1bmNzID0gewo+ICsJLnNl dF9jb25maWcgPSBkcm1fYXRvbWljX2hlbHBlcl9zZXRfY29uZmlnLAo+ICsJLnBhZ2VfZmxpcCA9 IGRybV9hdG9taWNfaGVscGVyX3BhZ2VfZmxpcCwKPiArCS5kZXN0cm95ID0gZHJtX2NydGNfY2xl YW51cCwKPiArCS5yZXNldCA9IHZvcDJfY3J0Y19yZXNldCwKPiArCS5hdG9taWNfZHVwbGljYXRl X3N0YXRlID0gdm9wMl9jcnRjX2R1cGxpY2F0ZV9zdGF0ZSwKPiArCS5hdG9taWNfZGVzdHJveV9z dGF0ZSA9IHZvcDJfY3J0Y19kZXN0cm95X3N0YXRlLAo+ICsJLmVuYWJsZV92YmxhbmsgPSB2b3Ay X2NydGNfZW5hYmxlX3ZibGFuaywKPiArCS5kaXNhYmxlX3ZibGFuayA9IHZvcDJfY3J0Y19kaXNh YmxlX3ZibGFuaywKPiArfTsKPiArCj4gK3N0YXRpYyBpcnFyZXR1cm5fdCB2b3AyX2lzcihpbnQg aXJxLCB2b2lkICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3Qgdm9wMiAqdm9wMiA9IGRhdGE7Cj4gKwlj b25zdCBzdHJ1Y3Qgdm9wMl9kYXRhICp2b3AyX2RhdGEgPSB2b3AyLT5kYXRhOwo+ICsJdWludDMy X3QgYXhpX2lycXNbVk9QMl9TWVNfQVhJX0JVU19OVU1dOwo+ICsJaW50IHJldCA9IElSUV9OT05F Owo+ICsJaW50IGk7Cj4gKwo+ICsJLyoKPiArCSAqIFRoZSBpcnEgaXMgc2hhcmVkIHdpdGggdGhl IGlvbW11LiBJZiB0aGUgcnVudGltZS1wbSBzdGF0ZSBvZiB0aGUKPiArCSAqIHZvcDItZGV2aWNl IGlzIGRpc2FibGVkIHRoZSBpcnEgaGFzIHRvIGJlIHRhcmdldGVkIGF0IHRoZSBpb21tdS4KPiAr CSAqLwo+ICsJaWYgKCFwbV9ydW50aW1lX2dldF9pZl9pbl91c2Uodm9wMi0+ZGV2KSkKPiArCQly ZXR1cm4gSVJRX05PTkU7Cj4gKwo+ICsJZm9yIChpID0gMDsgaSA8IHZvcDJfZGF0YS0+bnJfdnBz OyBpKyspIHsKPiArCQlzdHJ1Y3Qgdm9wMl92aWRlb19wb3J0ICp2cCA9ICZ2b3AyLT52cHNbaV07 Cj4gKwkJc3RydWN0IGRybV9jcnRjICpjcnRjID0gJnZwLT5jcnRjOwo+ICsJCXVpbnQzMl90IGly cXM7Cj4gKwo+ICsJCWlycXMgPSB2b3AyX3JlYWRsKHZvcDIsIFJLMzU2OF9WUF9JTlRfU1RBVFVT KHZwLT5pZCkpOwo+ICsJCXZvcDJfd3JpdGVsKHZvcDIsIFJLMzU2OF9WUF9JTlRfQ0xSKHZwLT5p ZCksIGlycXMgPDwgMTYgfCBpcnFzKTsKPiArCj4gKwkJaWYgKGlycXMgJiBWUF9JTlRfRFNQX0hP TERfVkFMSUQpIHsKPiArCQkJY29tcGxldGUoJnZwLT5kc3BfaG9sZF9jb21wbGV0aW9uKTsKPiAr CQkJcmV0ID0gSVJRX0hBTkRMRUQ7Cj4gKwkJfQo+ICsKPiArCQlpZiAoaXJxcyAmIFZQX0lOVF9G U19GSUVMRCkgewo+ICsJCQl1bnNpZ25lZCBsb25nIGZsYWdzOwo+ICsKPiArCQkJZHJtX2NydGNf aGFuZGxlX3ZibGFuayhjcnRjKTsKPiArCQkJc3Bpbl9sb2NrX2lycXNhdmUoJmNydGMtPmRldi0+ ZXZlbnRfbG9jaywgZmxhZ3MpOwo+ICsJCQlpZiAodnAtPmV2ZW50KSB7Cj4gKwkJCQl1aW50MzJf dCB2YWwgPSB2b3AyX3JlYWRsKHZvcDIsIFJLMzU2OF9SRUdfQ0ZHX0RPTkUpOwo+ICsJCQkJaWYg KCEodmFsICYgQklUKHZwLT5pZCkpKSB7Cj4gKwkJCQkJZHJtX2NydGNfc2VuZF92YmxhbmtfZXZl bnQoY3J0YywgdnAtPmV2ZW50KTsKPiArCQkJCQl2cC0+ZXZlbnQgPSBOVUxMOwo+ICsJCQkJCWRy bV9jcnRjX3ZibGFua19wdXQoY3J0Yyk7Cj4gKwkJCQl9Cj4gKwkJCX0KPiArCQkJc3Bpbl91bmxv Y2tfaXJxcmVzdG9yZSgmY3J0Yy0+ZGV2LT5ldmVudF9sb2NrLCBmbGFncyk7Cj4gKwo+ICsJCQly ZXQgPSBJUlFfSEFORExFRDsKPiArCQl9Cj4gKwo+ICsJCWlmIChpcnFzICYgVlBfSU5UX1BPU1Rf QlVGX0VNUFRZKSB7Cj4gKwkJCWRybV9lcnJfcmF0ZWxpbWl0ZWQodm9wMi0+ZHJtLAo+ICsJCQkJ CSAgICAiUE9TVF9CVUZfRU1QVFkgaXJxIGVyciBhdCB2cCVkXG4iLAo+ICsJCQkJCSAgICB2cC0+ aWQpOwo+ICsJCQlyZXQgPSBJUlFfSEFORExFRDsKPiArCQl9Cj4gKwl9Cj4gKwo+ICsJYXhpX2ly cXNbMF0gPSB2b3AyX3JlYWRsKHZvcDIsIFJLMzU2OF9TWVMwX0lOVF9TVEFUVVMpOwo+ICsJdm9w Ml93cml0ZWwodm9wMiwgUkszNTY4X1NZUzBfSU5UX0NMUiwgYXhpX2lycXNbMF0gPDwgMTYgfCBh eGlfaXJxc1swXSk7Cj4gKwlheGlfaXJxc1sxXSA9IHZvcDJfcmVhZGwodm9wMiwgUkszNTY4X1NZ UzFfSU5UX1NUQVRVUyk7Cj4gKwl2b3AyX3dyaXRlbCh2b3AyLCBSSzM1NjhfU1lTMV9JTlRfQ0xS LCBheGlfaXJxc1sxXSA8PCAxNiB8IGF4aV9pcnFzWzFdKTsKPiArCj4gKwlmb3IgKGkgPSAwOyBp IDwgQVJSQVlfU0laRShheGlfaXJxcyk7IGkrKykgewo+ICsJCWlmIChheGlfaXJxc1tpXSAmIFZP UDJfSU5UX0JVU19FUlJQUikgewo+ICsJCQlkcm1fZXJyX3JhdGVsaW1pdGVkKHZvcDItPmRybSwg IkJVU19FUlJPUiBpcnEgZXJyXG4iKTsKPiArCQkJcmV0ID0gSVJRX0hBTkRMRUQ7Cj4gKwkJfQo+ ICsJfQo+ICsKPiArCXBtX3J1bnRpbWVfcHV0KHZvcDItPmRldik7Cj4gKwo+ICsJcmV0dXJuIHJl dDsKPiArfQo+ICsKPiArc3RhdGljIGludCB2b3AyX3BsYW5lX2luaXQoc3RydWN0IHZvcDIgKnZv cDIsIHN0cnVjdCB2b3AyX3dpbiAqd2luLCB1bnNpZ25lZCBsb25nIHBvc3NpYmxlX2NydGNzKQo+ ICt7Cj4gKwljb25zdCBzdHJ1Y3Qgdm9wMl93aW5fZGF0YSAqd2luX2RhdGEgPSB3aW4tPmRhdGE7 Cj4gKwl1bnNpZ25lZCBpbnQgYmxlbmRfY2FwcyA9IEJJVChEUk1fTU9ERV9CTEVORF9QSVhFTF9O T05FKSB8IEJJVChEUk1fTU9ERV9CTEVORF9QUkVNVUxUSSkgfAo+ICsJCQkJICBCSVQoRFJNX01P REVfQkxFTkRfQ09WRVJBR0UpOwo+ICsJaW50IHJldDsKPiArCj4gKwlyZXQgPSBkcm1fdW5pdmVy c2FsX3BsYW5lX2luaXQodm9wMi0+ZHJtLCAmd2luLT5iYXNlLCBwb3NzaWJsZV9jcnRjcywKPiAr CQkJCSAgICAgICAmdm9wMl9wbGFuZV9mdW5jcywgd2luX2RhdGEtPmZvcm1hdHMsIHdpbl9kYXRh LT5uZm9ybWF0cywKPiArCQkJCSAgICAgICB3aW5fZGF0YS0+Zm9ybWF0X21vZGlmaWVycywgd2lu LT50eXBlLCB3aW5fZGF0YS0+bmFtZSk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZHJtX2Vycih2b3Ay LT5kcm0sICJmYWlsZWQgdG8gaW5pdGlhbGl6ZSBwbGFuZSAlZFxuIiwgcmV0KTsKPiArCQlyZXR1 cm4gcmV0Owo+ICsJfQo+ICsKPiArCWRybV9wbGFuZV9oZWxwZXJfYWRkKCZ3aW4tPmJhc2UsICZ2 b3AyX3BsYW5lX2hlbHBlcl9mdW5jcyk7Cj4gKwo+ICsJaWYgKHdpbi0+ZGF0YS0+c3VwcG9ydGVk X3JvdGF0aW9ucykKPiArCQlkcm1fcGxhbmVfY3JlYXRlX3JvdGF0aW9uX3Byb3BlcnR5KCZ3aW4t PmJhc2UsIERSTV9NT0RFX1JPVEFURV8wLAo+ICsJCQkJCQkgICBEUk1fTU9ERV9ST1RBVEVfMCB8 Cj4gKwkJCQkJCSAgIHdpbi0+ZGF0YS0+c3VwcG9ydGVkX3JvdGF0aW9ucyk7Cj4gKwlkcm1fcGxh bmVfY3JlYXRlX2FscGhhX3Byb3BlcnR5KCZ3aW4tPmJhc2UpOwo+ICsJZHJtX3BsYW5lX2NyZWF0 ZV9ibGVuZF9tb2RlX3Byb3BlcnR5KCZ3aW4tPmJhc2UsIGJsZW5kX2NhcHMpOwo+ICsJZHJtX3Bs YW5lX2NyZWF0ZV96cG9zX3Byb3BlcnR5KCZ3aW4tPmJhc2UsIHdpbi0+d2luX2lkLCAwLAo+ICsJ CQkJICAgICAgIHZvcDItPnJlZ2lzdGVyZWRfbnVtX3dpbnMgLSAxKTsKPiArCj4gKwlyZXR1cm4g MDsKPiArfQo+ICsKPiArc3RhdGljIHN0cnVjdCB2b3AyX3ZpZGVvX3BvcnQgKmdldF9hY3RpdmF0 ZWRfdnAoc3RydWN0IHZvcDIgKnZvcDIsIGludCBuKQo+ICt7Cj4gKwlpbnQgaSwgaWQgPSAwOwo+ ICsKPiArCWZvciAoaSA9IDA7IGkgPCB2b3AyLT5kYXRhLT5ucl92cHM7IGkrKykgewo+ICsJCXN0 cnVjdCB2b3AyX3ZpZGVvX3BvcnQgKnZwID0gJnZvcDItPnZwc1tpXTsKPiArCj4gKwkJaWYgKCF2 cC0+Y3J0Yy5wb3J0KQo+ICsJCQljb250aW51ZTsKPiArCj4gKwkJaWYgKG4gPT0gaWQpCj4gKwkJ CXJldHVybiB2cDsKPiArCQlpZCsrOwo+ICsJfQo+ICsKPiArCXJldHVybiBOVUxMOwo+ICt9Cj4g Kwo+ICtzdGF0aWMgaW50IHZvcDJfY3JlYXRlX2NydGMoc3RydWN0IHZvcDIgKnZvcDIpCj4gK3sK PiArCWNvbnN0IHN0cnVjdCB2b3AyX2RhdGEgKnZvcDJfZGF0YSA9IHZvcDItPmRhdGE7Cj4gKwlz dHJ1Y3QgZHJtX2RldmljZSAqZHJtID0gdm9wMi0+ZHJtOwo+ICsJc3RydWN0IGRldmljZSAqZGV2 ID0gdm9wMi0+ZGV2Owo+ICsJc3RydWN0IGRybV9wbGFuZSAqcGxhbmU7Cj4gKwlzdHJ1Y3QgZGV2 aWNlX25vZGUgKnBvcnQ7Cj4gKwlzdHJ1Y3Qgdm9wMl92aWRlb19wb3J0ICp2cDsKPiArCXVpbnQz Ml90IHBvc3NpYmxlX2NydGNzOwo+ICsJaW50IGksIG52cCwgbnZwcyA9IDA7Cj4gKwlpbnQgcmV0 Owo+ICsKPiArCWZvciAoaSA9IDA7IGkgPCB2b3AyX2RhdGEtPm5yX3ZwczsgaSsrKSB7Cj4gKwkJ Y29uc3Qgc3RydWN0IHZvcDJfdmlkZW9fcG9ydF9kYXRhICp2cF9kYXRhOwo+ICsJCXN0cnVjdCBk ZXZpY2Vfbm9kZSAqbnA7Cj4gKwkJY2hhciBkY2xrX25hbWVbOV07Cj4gKwo+ICsJCXZwX2RhdGEg PSAmdm9wMl9kYXRhLT52cFtpXTsKPiArCQl2cCA9ICZ2b3AyLT52cHNbaV07Cj4gKwkJdnAtPnZv cDIgPSB2b3AyOwo+ICsJCXZwLT5pZCA9IHZwX2RhdGEtPmlkOwo+ICsJCXZwLT5yZWdzID0gdnBf ZGF0YS0+cmVnczsKPiArCQl2cC0+ZGF0YSA9IHZwX2RhdGE7Cj4gKwo+ICsJCXNucHJpbnRmKGRj bGtfbmFtZSwgc2l6ZW9mKGRjbGtfbmFtZSksICJkY2xrX3ZwJWQiLCB2cC0+aWQpOwo+ICsJCXZw LT5kY2xrID0gZGV2bV9jbGtfZ2V0KHZvcDItPmRldiwgZGNsa19uYW1lKTsKPiArCQlpZiAoSVNf RVJSKHZwLT5kY2xrKSkgewo+ICsJCQlkcm1fZXJyKHZvcDItPmRybSwgImZhaWxlZCB0byBnZXQg JXNcbiIsIGRjbGtfbmFtZSk7Cj4gKwkJCXJldHVybiBQVFJfRVJSKHZwLT5kY2xrKTsKPiArCQl9 Cj4gKwo+ICsJCW5wID0gb2ZfZ3JhcGhfZ2V0X3JlbW90ZV9ub2RlKGRldi0+b2Zfbm9kZSwgaSwg LTEpOwo+ICsJCWlmICghbnApIHsKPiArCQkJcHJpbnRrKCIlczogTm8gcmVtb3RlIGZvciB2cCVk XG4iLCBfX2Z1bmNfXywgaSk7Cj4gKwkJCWNvbnRpbnVlOwo+ICsJCX0KPiArCQlvZl9ub2RlX3B1 dChucCk7Cj4gKwo+ICsJCXBvcnQgPSBvZl9ncmFwaF9nZXRfcG9ydF9ieV9pZChkZXYtPm9mX25v ZGUsIGkpOwo+ICsJCWlmICghcG9ydCkgewo+ICsJCQlkcm1fZXJyKHZvcDItPmRybSwgIm5vIHBv cnQgbm9kZSBmb3VuZCBmb3IgdmlkZW9fcG9ydCVkXG4iLCBpKTsKPiArCQkJcmV0dXJuIC1FTk9F TlQ7Cj4gKwkJfQo+ICsKPiArCQl2cC0+Y3J0Yy5wb3J0ID0gcG9ydDsKPiArCQludnBzKys7Cj4g Kwl9Cj4gKwo+ICsJbnZwID0gMDsKPiArCWZvciAoaSA9IDA7IGkgPCB2b3AyLT5yZWdpc3RlcmVk X251bV93aW5zOyBpKyspIHsKPiArCQlzdHJ1Y3Qgdm9wMl93aW4gKndpbiA9ICZ2b3AyLT53aW5b aV07Cj4gKwo+ICsJCWlmICh3aW4tPnR5cGUgPT0gRFJNX1BMQU5FX1RZUEVfUFJJTUFSWSkgewo+ ICsJCQl2cCA9IGdldF9hY3RpdmF0ZWRfdnAodm9wMiwgbnZwKTsKPiArCj4gKwkJCWlmICh2cCkg ewo+ICsJCQkJcG9zc2libGVfY3J0Y3MgPSBCSVQobnZwKTsKPiArCQkJCXZwLT5wcmltYXJ5X3Bs YW5lID0gd2luOwo+ICsKPiArCQkJCW52cCsrOwo+ICsJCQl9IGVsc2Ugewo+ICsJCQkJLyogY2hh bmdlIHRoZSB1bnVzZWQgcHJpbWFyeSB3aW5kb3cgdG8gb3ZlcmxheSB3aW5kb3cgKi8KPiArCQkJ CXdpbi0+dHlwZSA9IERSTV9QTEFORV9UWVBFX09WRVJMQVk7Cj4gKwkJCX0KPiArCQl9Cj4gKwo+ ICsJCWlmICh3aW4tPnR5cGUgPT0gRFJNX1BMQU5FX1RZUEVfT1ZFUkxBWSkKPiArCQkJcG9zc2li bGVfY3J0Y3MgPSAoMSA8PCB2b3AyX2RhdGEtPm5yX3ZwcykgLSAxOwo+ICsKPiArCQlyZXQgPSB2 b3AyX3BsYW5lX2luaXQodm9wMiwgd2luLCBwb3NzaWJsZV9jcnRjcyk7Cj4gKwo+ICsJCWlmIChy ZXQpIHsKPiArCQkJZHJtX2Vycih2b3AyLT5kcm0sICJmYWlsZWQgdG8gaW5pdCBwbGFuZSAlczog JWRcbiIsIHdpbi0+ZGF0YS0+bmFtZSwgcmV0KTsKPiArCQkJcmV0dXJuIHJldDsKPiArCQl9Cj4g Kwl9Cj4gKwo+ICsJZm9yIChpID0gMDsgaSA8IHZvcDJfZGF0YS0+bnJfdnBzOyBpKyspIHsKPiAr CQl2cCA9ICZ2b3AyLT52cHNbaV07Cj4gKwo+ICsJCWlmICghdnAtPmNydGMucG9ydCkKPiArCQkJ Y29udGludWU7Cj4gKwo+ICsJCXBsYW5lID0gJnZwLT5wcmltYXJ5X3BsYW5lLT5iYXNlOwo+ICsK PiArCQlyZXQgPSBkcm1fY3J0Y19pbml0X3dpdGhfcGxhbmVzKGRybSwgJnZwLT5jcnRjLCBwbGFu ZSwgTlVMTCwgJnZvcDJfY3J0Y19mdW5jcywKPiArCQkJCQkJInZpZGVvX3BvcnQlZCIsIHZwLT5p ZCk7Cj4gKwkJaWYgKHJldCkgewo+ICsJCQlkcm1fZXJyKHZvcDItPmRybSwgImNydGMgaW5pdCBm b3IgdmlkZW9fcG9ydCVkIGZhaWxlZFxuIiwgaSk7Cj4gKwkJCXJldHVybiByZXQ7Cj4gKwkJfQo+ ICsKPiArCQlkcm1fY3J0Y19oZWxwZXJfYWRkKCZ2cC0+Y3J0YywgJnZvcDJfY3J0Y19oZWxwZXJf ZnVuY3MpOwo+ICsKPiArCQlpbml0X2NvbXBsZXRpb24oJnZwLT5kc3BfaG9sZF9jb21wbGV0aW9u KTsKPiArCX0KPiArCj4gKwlmb3IgKGkgPSAwOyBpIDwgdm9wMi0+ZGF0YS0+bnJfdnBzOyBpKysp IHsKPiArCQlzdHJ1Y3Qgdm9wMl92aWRlb19wb3J0ICp2cCA9ICZ2b3AyLT52cHNbaV07Cj4gKwkJ aWYgKHZwLT5jcnRjLnBvcnQpCj4gKwkJCXZwLT5ubGF5ZXJzID0gTlJfTUlYRVJTIC8gbnZwczsK PiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgdm9wMl9kZXN0 cm95X2NydGMoc3RydWN0IGRybV9jcnRjICpjcnRjKQo+ICt7Cj4gKwlvZl9ub2RlX3B1dChjcnRj LT5wb3J0KTsKPiArCj4gKwkvKgo+ICsJICogRGVzdHJveSBDUlRDIGFmdGVyIHZvcDJfcGxhbmVf ZGVzdHJveSgpIHNpbmNlIHZvcDJfZGlzYWJsZV9wbGFuZSgpCj4gKwkgKiByZWZlcmVuY2VzIHRo ZSBDUlRDLgo+ICsJICovCj4gKwlkcm1fY3J0Y19jbGVhbnVwKGNydGMpOwo+ICt9Cj4gKwo+ICtz dGF0aWMgaW50IHZvcDJfY2x1c3Rlcl9pbml0KHN0cnVjdCB2b3AyX3dpbiAqd2luKQo+ICt7Cj4g KwlzdHJ1Y3Qgdm9wMiAqdm9wMiA9IHdpbi0+dm9wMjsKPiArCWludCBpOwo+ICsJc3RydWN0IHJl Z19maWVsZCB2b3AyX2NsdXN0ZXJfcmVnc1tWT1AyX1dJTl9NQVhfUkVHXSA9IHsKPiArCQlbVk9Q Ml9XSU5fRU5BQkxFXSA9IFJFR19GSUVMRChSSzM1NjhfQ0xVU1RFUl9XSU5fQ1RSTDAsIDAsIDAp LAo+ICsJCVtWT1AyX1dJTl9GT1JNQVRdID0gUkVHX0ZJRUxEKFJLMzU2OF9DTFVTVEVSX1dJTl9D VFJMMCwgMSwgNSksCj4gKwkJW1ZPUDJfV0lOX1JCX1NXQVBdID0gUkVHX0ZJRUxEKFJLMzU2OF9D TFVTVEVSX1dJTl9DVFJMMCwgMTQsIDE0KSwKPiArCQlbVk9QMl9XSU5fRElUSEVSX1VQXSA9IFJF R19GSUVMRChSSzM1NjhfQ0xVU1RFUl9XSU5fQ1RSTDAsIDE4LCAxOCksCj4gKwkJW1ZPUDJfV0lO X0FDVF9JTkZPXSA9IFJFR19GSUVMRChSSzM1NjhfQ0xVU1RFUl9XSU5fQUNUX0lORk8sIDAsIDMx KSwKPiArCQlbVk9QMl9XSU5fRFNQX0lORk9dID0gUkVHX0ZJRUxEKFJLMzU2OF9DTFVTVEVSX1dJ Tl9EU1BfSU5GTywgMCwgMzEpLAo+ICsJCVtWT1AyX1dJTl9EU1BfU1RdID0gUkVHX0ZJRUxEKFJL MzU2OF9DTFVTVEVSX1dJTl9EU1BfU1QsIDAsIDMxKSwKPiArCQlbVk9QMl9XSU5fWVJHQl9NU1Rd ID0gUkVHX0ZJRUxEKFJLMzU2OF9DTFVTVEVSX1dJTl9ZUkdCX01TVCwgMCwgMzEpLAo+ICsJCVtW T1AyX1dJTl9VVl9NU1RdID0gUkVHX0ZJRUxEKFJLMzU2OF9DTFVTVEVSX1dJTl9DQlJfTVNULCAw LCAzMSksCj4gKwkJW1ZPUDJfV0lOX1lVVl9DTElQXSA9IFJFR19GSUVMRChSSzM1NjhfQ0xVU1RF Ul9XSU5fQ1RSTDAsIDE5LCAxOSksCj4gKwkJW1ZPUDJfV0lOX1lSR0JfVklSXSA9IFJFR19GSUVM RChSSzM1NjhfQ0xVU1RFUl9XSU5fVklSLCAwLCAxNSksCj4gKwkJW1ZPUDJfV0lOX1VWX1ZJUl0g PSBSRUdfRklFTEQoUkszNTY4X0NMVVNURVJfV0lOX1ZJUiwgMTYsIDMxKSwKPiArCQlbVk9QMl9X SU5fWTJSX0VOXSA9IFJFR19GSUVMRChSSzM1NjhfQ0xVU1RFUl9XSU5fQ1RSTDAsIDgsIDgpLAo+ ICsJCVtWT1AyX1dJTl9SMllfRU5dID0gUkVHX0ZJRUxEKFJLMzU2OF9DTFVTVEVSX1dJTl9DVFJM MCwgOSwgOSksCj4gKwkJW1ZPUDJfV0lOX0NTQ19NT0RFXSA9IFJFR19GSUVMRChSSzM1NjhfQ0xV U1RFUl9XSU5fQ1RSTDAsIDEwLCAxMSksCj4gKwo+ICsJCS8qIFNjYWxlICovCj4gKwkJW1ZPUDJf V0lOX1NDQUxFX1lSR0JfWF0gPSBSRUdfRklFTEQoUkszNTY4X0NMVVNURVJfV0lOX1NDTF9GQUNU T1JfWVJHQiwgMCwgMTUpLAo+ICsJCVtWT1AyX1dJTl9TQ0FMRV9ZUkdCX1ldID0gUkVHX0ZJRUxE KFJLMzU2OF9DTFVTVEVSX1dJTl9TQ0xfRkFDVE9SX1lSR0IsIDE2LCAzMSksCj4gKwkJW1ZPUDJf V0lOX1lSR0JfVkVSX1NDTF9NT0RFXSA9IFJFR19GSUVMRChSSzM1NjhfQ0xVU1RFUl9XSU5fQ1RS TDEsIDE0LCAxNSksCj4gKwkJW1ZPUDJfV0lOX1lSR0JfSE9SX1NDTF9NT0RFXSA9IFJFR19GSUVM RChSSzM1NjhfQ0xVU1RFUl9XSU5fQ1RSTDEsIDEyLCAxMyksCj4gKwkJW1ZPUDJfV0lOX0JJQ19D T0VfU0VMXSA9IFJFR19GSUVMRChSSzM1NjhfQ0xVU1RFUl9XSU5fQ1RSTDEsIDIsIDMpLAo+ICsJ CVtWT1AyX1dJTl9WU0RfWVJHQl9HVDJdID0gUkVHX0ZJRUxEKFJLMzU2OF9DTFVTVEVSX1dJTl9D VFJMMSwgMjgsIDI4KSwKPiArCQlbVk9QMl9XSU5fVlNEX1lSR0JfR1Q0XSA9IFJFR19GSUVMRChS SzM1NjhfQ0xVU1RFUl9XSU5fQ1RSTDEsIDI5LCAyOSksCj4gKwo+ICsJCS8qIGNsdXN0ZXIgcmVn cyAqLwo+ICsJCVtWT1AyX1dJTl9BRkJDX0VOQUJMRV0gPSBSRUdfRklFTEQoUkszNTY4X0NMVVNU RVJfQ1RSTCwgMSwgMSksCj4gKwkJW1ZPUDJfV0lOX0NMVVNURVJfRU5BQkxFXSA9IFJFR19GSUVM RChSSzM1NjhfQ0xVU1RFUl9DVFJMLCAwLCAwKSwKPiArCQlbVk9QMl9XSU5fQ0xVU1RFUl9MQl9N T0RFXSA9IFJFR19GSUVMRChSSzM1NjhfQ0xVU1RFUl9DVFJMLCA0LCA3KSwKPiArCj4gKwkJLyog YWZiYyByZWdzICovCj4gKwkJW1ZPUDJfV0lOX0FGQkNfRk9STUFUXSA9IFJFR19GSUVMRChSSzM1 NjhfQ0xVU1RFUl9XSU5fQUZCQ0RfQ1RSTCwgMiwgNiksCj4gKwkJW1ZPUDJfV0lOX0FGQkNfUkJf U1dBUF0gPSBSRUdfRklFTEQoUkszNTY4X0NMVVNURVJfV0lOX0FGQkNEX0NUUkwsIDksIDkpLAo+ ICsJCVtWT1AyX1dJTl9BRkJDX1VWX1NXQVBdID0gUkVHX0ZJRUxEKFJLMzU2OF9DTFVTVEVSX1dJ Tl9BRkJDRF9DVFJMLCAxMCwgMTApLAo+ICsJCVtWT1AyX1dJTl9BRkJDX0FVVE9fR0FUSU5HX0VO XSA9IFJFR19GSUVMRChSSzM1NjhfQ0xVU1RFUl9XSU5fQUZCQ0RfT1VUUFVUX0NUUkwsIDQsIDQp LAo+ICsJCVtWT1AyX1dJTl9BRkJDX0hBTEZfQkxPQ0tfRU5dID0gUkVHX0ZJRUxEKFJLMzU2OF9D TFVTVEVSX1dJTl9BRkJDRF9DVFJMLCA3LCA3KSwKPiArCQlbVk9QMl9XSU5fQUZCQ19CTE9DS19T UExJVF9FTl0gPSBSRUdfRklFTEQoUkszNTY4X0NMVVNURVJfV0lOX0FGQkNEX0NUUkwsIDgsIDgp LAo+ICsJCVtWT1AyX1dJTl9BRkJDX0hEUl9QVFJdID0gUkVHX0ZJRUxEKFJLMzU2OF9DTFVTVEVS X1dJTl9BRkJDRF9IRFJfUFRSLCAwLCAzMSksCj4gKwkJW1ZPUDJfV0lOX0FGQkNfUElDX1NJWkVd ID0gUkVHX0ZJRUxEKFJLMzU2OF9DTFVTVEVSX1dJTl9BRkJDRF9QSUNfU0laRSwgMCwgMzEpLAo+ ICsJCVtWT1AyX1dJTl9BRkJDX1BJQ19WSVJfV0lEVEhdID0gUkVHX0ZJRUxEKFJLMzU2OF9DTFVT VEVSX1dJTl9BRkJDRF9WSVJfV0lEVEgsIDAsIDE1KSwKPiArCQlbVk9QMl9XSU5fQUZCQ19USUxF X05VTV0gPSBSRUdfRklFTEQoUkszNTY4X0NMVVNURVJfV0lOX0FGQkNEX1ZJUl9XSURUSCwgMTYs IDMxKSwKPiArCQlbVk9QMl9XSU5fQUZCQ19QSUNfT0ZGU0VUXSA9IFJFR19GSUVMRChSSzM1Njhf Q0xVU1RFUl9XSU5fQUZCQ0RfUElDX09GRlNFVCwgMCwgMzEpLAo+ICsJCVtWT1AyX1dJTl9BRkJD X0RTUF9PRkZTRVRdID0gUkVHX0ZJRUxEKFJLMzU2OF9DTFVTVEVSX1dJTl9BRkJDRF9EU1BfT0ZG U0VULCAwLCAzMSksCj4gKwkJW1ZPUDJfV0lOX0FGQkNfVFJBTlNGT1JNX09GRlNFVF0gPSBSRUdf RklFTEQoUkszNTY4X0NMVVNURVJfV0lOX0FGQkNEX1RSQU5TRk9STV9PRkZTRVQsIDAsIDMxKSwK PiArCQlbVk9QMl9XSU5fQUZCQ19ST1RBVEVfOTBdID0gUkVHX0ZJRUxEKFJLMzU2OF9DTFVTVEVS X1dJTl9BRkJDRF9ST1RBVEVfTU9ERSwgMCwgMCksCj4gKwkJW1ZPUDJfV0lOX0FGQkNfUk9UQVRF XzI3MF0gPSBSRUdfRklFTEQoUkszNTY4X0NMVVNURVJfV0lOX0FGQkNEX1JPVEFURV9NT0RFLCAx LCAxKSwKPiArCQlbVk9QMl9XSU5fWE1JUlJPUl0gPSBSRUdfRklFTEQoUkszNTY4X0NMVVNURVJf V0lOX0FGQkNEX1JPVEFURV9NT0RFLCAyLCAyKSwKPiArCQlbVk9QMl9XSU5fWU1JUlJPUl0gPSBS RUdfRklFTEQoUkszNTY4X0NMVVNURVJfV0lOX0FGQkNEX1JPVEFURV9NT0RFLCAzLCAzKSwKPiAr CQlbVk9QMl9XSU5fVVZfU1dBUF0gPSB7IC5yZWcgPSAweGZmZmZmZmZmIH0sCj4gKwkJW1ZPUDJf V0lOX0NPTE9SX0tFWV0gPSB7IC5yZWcgPSAweGZmZmZmZmZmIH0sCj4gKwkJW1ZPUDJfV0lOX0NP TE9SX0tFWV9FTl0gPSB7IC5yZWcgPSAweGZmZmZmZmZmIH0sCj4gKwkJW1ZPUDJfV0lOX1NDQUxF X0NCQ1JfWF0gPSB7IC5yZWcgPSAweGZmZmZmZmZmIH0sCj4gKwkJW1ZPUDJfV0lOX1NDQUxFX0NC Q1JfWV0gPSB7IC5yZWcgPSAweGZmZmZmZmZmIH0sCj4gKwkJW1ZPUDJfV0lOX1lSR0JfSFNDTF9G SUxURVJfTU9ERV0gPSB7IC5yZWcgPSAweGZmZmZmZmZmIH0sCj4gKwkJW1ZPUDJfV0lOX1lSR0Jf VlNDTF9GSUxURVJfTU9ERV0gPSB7IC5yZWcgPSAweGZmZmZmZmZmIH0sCj4gKwkJW1ZPUDJfV0lO X0NCQ1JfVkVSX1NDTF9NT0RFXSA9IHsgLnJlZyA9IDB4ZmZmZmZmZmYgfSwKPiArCQlbVk9QMl9X SU5fQ0JDUl9IU0NMX0ZJTFRFUl9NT0RFXSA9IHsgLnJlZyA9IDB4ZmZmZmZmZmYgfSwKPiArCQlb Vk9QMl9XSU5fQ0JDUl9IT1JfU0NMX01PREVdID0geyAucmVnID0gMHhmZmZmZmZmZiB9LAo+ICsJ CVtWT1AyX1dJTl9DQkNSX1ZTQ0xfRklMVEVSX01PREVdID0geyAucmVnID0gMHhmZmZmZmZmZiB9 LAo+ICsJCVtWT1AyX1dJTl9WU0RfQ0JDUl9HVDJdID0geyAucmVnID0gMHhmZmZmZmZmZiB9LAo+ ICsJCVtWT1AyX1dJTl9WU0RfQ0JDUl9HVDRdID0geyAucmVnID0gMHhmZmZmZmZmZiB9LAo+ICsJ fTsKPiArCj4gKwlmb3IgKGkgPSAwOyBpIDwgQVJSQVlfU0laRSh2b3AyX2NsdXN0ZXJfcmVncyk7 IGkrKykKPiArCQl2b3AyX2NsdXN0ZXJfcmVnc1tpXS5yZWcgKz0gd2luLT5vZmZzZXQ7Cj4gKwo+ ICsJcmV0dXJuIGRldm1fcmVnbWFwX2ZpZWxkX2J1bGtfYWxsb2Modm9wMi0+ZGV2LCB2b3AyLT5t YXAsIHdpbi0+cmVnLAo+ICsJCQkJCSAgICB2b3AyX2NsdXN0ZXJfcmVncywKPiArCQkJCQkgICAg QVJSQVlfU0laRSh2b3AyX2NsdXN0ZXJfcmVncykpOwo+ICt9Owo+ICsKPiArc3RhdGljIGludCB2 b3AyX2VzbWFydF9pbml0KHN0cnVjdCB2b3AyX3dpbiAqd2luKQo+ICt7Cj4gKwlzdHJ1Y3Qgdm9w MiAqdm9wMiA9IHdpbi0+dm9wMjsKPiArCWludCBpOwo+ICsJc3RydWN0IHJlZ19maWVsZCB2b3Ay X2VzbWFydF9yZWdzW1ZPUDJfV0lOX01BWF9SRUddID0gewo+ICsJCVtWT1AyX1dJTl9FTkFCTEVd ID0gUkVHX0ZJRUxEKFJLMzU2OF9TTUFSVF9SRUdJT04wX0NUUkwsIDAsIDApLAo+ICsJCVtWT1Ay X1dJTl9GT1JNQVRdID0gUkVHX0ZJRUxEKFJLMzU2OF9TTUFSVF9SRUdJT04wX0NUUkwsIDEsIDUp LAo+ICsJCVtWT1AyX1dJTl9ESVRIRVJfVVBdID0gUkVHX0ZJRUxEKFJLMzU2OF9TTUFSVF9SRUdJ T04wX0NUUkwsIDEyLCAxMiksCj4gKwkJW1ZPUDJfV0lOX1JCX1NXQVBdID0gUkVHX0ZJRUxEKFJL MzU2OF9TTUFSVF9SRUdJT04wX0NUUkwsIDE0LCAxNCksCj4gKwkJW1ZPUDJfV0lOX1VWX1NXQVBd ID0gUkVHX0ZJRUxEKFJLMzU2OF9TTUFSVF9SRUdJT04wX0NUUkwsIDE2LCAxNiksCj4gKwkJW1ZP UDJfV0lOX0FDVF9JTkZPXSA9IFJFR19GSUVMRChSSzM1NjhfU01BUlRfUkVHSU9OMF9BQ1RfSU5G TywgMCwgMzEpLAo+ICsJCVtWT1AyX1dJTl9EU1BfSU5GT10gPSBSRUdfRklFTEQoUkszNTY4X1NN QVJUX1JFR0lPTjBfRFNQX0lORk8sIDAsIDMxKSwKPiArCQlbVk9QMl9XSU5fRFNQX1NUXSA9IFJF R19GSUVMRChSSzM1NjhfU01BUlRfUkVHSU9OMF9EU1BfU1QsIDAsIDI4KSwKPiArCQlbVk9QMl9X SU5fWVJHQl9NU1RdID0gUkVHX0ZJRUxEKFJLMzU2OF9TTUFSVF9SRUdJT04wX1lSR0JfTVNULCAw LCAzMSksCj4gKwkJW1ZPUDJfV0lOX1VWX01TVF0gPSBSRUdfRklFTEQoUkszNTY4X1NNQVJUX1JF R0lPTjBfQ0JSX01TVCwgMCwgMzEpLAo+ICsJCVtWT1AyX1dJTl9ZVVZfQ0xJUF0gPSBSRUdfRklF TEQoUkszNTY4X1NNQVJUX1JFR0lPTjBfQ1RSTCwgMTcsIDE3KSwKPiArCQlbVk9QMl9XSU5fWVJH Ql9WSVJdID0gUkVHX0ZJRUxEKFJLMzU2OF9TTUFSVF9SRUdJT04wX1ZJUiwgMCwgMTUpLAo+ICsJ CVtWT1AyX1dJTl9VVl9WSVJdID0gUkVHX0ZJRUxEKFJLMzU2OF9TTUFSVF9SRUdJT04wX1ZJUiwg MTYsIDMxKSwKPiArCQlbVk9QMl9XSU5fWTJSX0VOXSA9IFJFR19GSUVMRChSSzM1NjhfU01BUlRf Q1RSTDAsIDAsIDApLAo+ICsJCVtWT1AyX1dJTl9SMllfRU5dID0gUkVHX0ZJRUxEKFJLMzU2OF9T TUFSVF9DVFJMMCwgMSwgMSksCj4gKwkJW1ZPUDJfV0lOX0NTQ19NT0RFXSA9IFJFR19GSUVMRChS SzM1NjhfU01BUlRfQ1RSTDAsIDIsIDMpLAo+ICsJCVtWT1AyX1dJTl9ZTUlSUk9SXSA9IFJFR19G SUVMRChSSzM1NjhfU01BUlRfQ1RSTDEsIDMxLCAzMSksCj4gKwkJW1ZPUDJfV0lOX0NPTE9SX0tF WV0gPSBSRUdfRklFTEQoUkszNTY4X1NNQVJUX0NPTE9SX0tFWV9DVFJMLCAwLCAyOSksCj4gKwkJ W1ZPUDJfV0lOX0NPTE9SX0tFWV9FTl0gPSBSRUdfRklFTEQoUkszNTY4X1NNQVJUX0NPTE9SX0tF WV9DVFJMLCAzMSwgMzEpLAo+ICsKPiArCQkvKiBTY2FsZSAqLwo+ICsJCVtWT1AyX1dJTl9TQ0FM RV9ZUkdCX1hdID0gUkVHX0ZJRUxEKFJLMzU2OF9TTUFSVF9SRUdJT04wX1NDTF9GQUNUT1JfWVJH QiwgMCwgMTUpLAo+ICsJCVtWT1AyX1dJTl9TQ0FMRV9ZUkdCX1ldID0gUkVHX0ZJRUxEKFJLMzU2 OF9TTUFSVF9SRUdJT04wX1NDTF9GQUNUT1JfWVJHQiwgMTYsIDMxKSwKPiArCQlbVk9QMl9XSU5f U0NBTEVfQ0JDUl9YXSA9IFJFR19GSUVMRChSSzM1NjhfU01BUlRfUkVHSU9OMF9TQ0xfRkFDVE9S X0NCUiwgMCwgMTUpLAo+ICsJCVtWT1AyX1dJTl9TQ0FMRV9DQkNSX1ldID0gUkVHX0ZJRUxEKFJL MzU2OF9TTUFSVF9SRUdJT04wX1NDTF9GQUNUT1JfQ0JSLCAxNiwgMzEpLAo+ICsJCVtWT1AyX1dJ Tl9ZUkdCX0hPUl9TQ0xfTU9ERV0gPSBSRUdfRklFTEQoUkszNTY4X1NNQVJUX1JFR0lPTjBfU0NM X0NUUkwsIDAsIDEpLAo+ICsJCVtWT1AyX1dJTl9ZUkdCX0hTQ0xfRklMVEVSX01PREVdID0gUkVH X0ZJRUxEKFJLMzU2OF9TTUFSVF9SRUdJT04wX1NDTF9DVFJMLCAyLCAzKSwKPiArCQlbVk9QMl9X SU5fWVJHQl9WRVJfU0NMX01PREVdID0gUkVHX0ZJRUxEKFJLMzU2OF9TTUFSVF9SRUdJT04wX1ND TF9DVFJMLCA0LCA1KSwKPiArCQlbVk9QMl9XSU5fWVJHQl9WU0NMX0ZJTFRFUl9NT0RFXSA9IFJF R19GSUVMRChSSzM1NjhfU01BUlRfUkVHSU9OMF9TQ0xfQ1RSTCwgNiwgNyksCj4gKwkJW1ZPUDJf V0lOX0NCQ1JfSE9SX1NDTF9NT0RFXSA9IFJFR19GSUVMRChSSzM1NjhfU01BUlRfUkVHSU9OMF9T Q0xfQ1RSTCwgOCwgOSksCj4gKwkJW1ZPUDJfV0lOX0NCQ1JfSFNDTF9GSUxURVJfTU9ERV0gPSBS RUdfRklFTEQoUkszNTY4X1NNQVJUX1JFR0lPTjBfU0NMX0NUUkwsIDEwLCAxMSksCj4gKwkJW1ZP UDJfV0lOX0NCQ1JfVkVSX1NDTF9NT0RFXSA9IFJFR19GSUVMRChSSzM1NjhfU01BUlRfUkVHSU9O MF9TQ0xfQ1RSTCwgMTIsIDEzKSwKPiArCQlbVk9QMl9XSU5fQ0JDUl9WU0NMX0ZJTFRFUl9NT0RF XSA9IFJFR19GSUVMRChSSzM1NjhfU01BUlRfUkVHSU9OMF9TQ0xfQ1RSTCwgMTQsIDE1KSwKPiAr CQlbVk9QMl9XSU5fQklDX0NPRV9TRUxdID0gUkVHX0ZJRUxEKFJLMzU2OF9TTUFSVF9SRUdJT04w X1NDTF9DVFJMLCAxNiwgMTcpLAo+ICsJCVtWT1AyX1dJTl9WU0RfWVJHQl9HVDJdID0gUkVHX0ZJ RUxEKFJLMzU2OF9TTUFSVF9SRUdJT04wX0NUUkwsIDgsIDgpLAo+ICsJCVtWT1AyX1dJTl9WU0Rf WVJHQl9HVDRdID0gUkVHX0ZJRUxEKFJLMzU2OF9TTUFSVF9SRUdJT04wX0NUUkwsIDksIDkpLAo+ ICsJCVtWT1AyX1dJTl9WU0RfQ0JDUl9HVDJdID0gUkVHX0ZJRUxEKFJLMzU2OF9TTUFSVF9SRUdJ T04wX0NUUkwsIDEwLCAxMCksCj4gKwkJW1ZPUDJfV0lOX1ZTRF9DQkNSX0dUNF0gPSBSRUdfRklF TEQoUkszNTY4X1NNQVJUX1JFR0lPTjBfQ1RSTCwgMTEsIDExKSwKPiArCQlbVk9QMl9XSU5fWE1J UlJPUl0gPSB7IC5yZWcgPSAweGZmZmZmZmZmIH0sCj4gKwkJW1ZPUDJfV0lOX0NMVVNURVJfRU5B QkxFXSA9IHsgLnJlZyA9IDB4ZmZmZmZmZmYgfSwKPiArCQlbVk9QMl9XSU5fQUZCQ19FTkFCTEVd ID0geyAucmVnID0gMHhmZmZmZmZmZiB9LAo+ICsJCVtWT1AyX1dJTl9DTFVTVEVSX0xCX01PREVd ID0geyAucmVnID0gMHhmZmZmZmZmZiB9LAo+ICsJCVtWT1AyX1dJTl9BRkJDX0ZPUk1BVF0gPSB7 IC5yZWcgPSAweGZmZmZmZmZmIH0sCj4gKwkJW1ZPUDJfV0lOX0FGQkNfUkJfU1dBUF0gPSB7IC5y ZWcgPSAweGZmZmZmZmZmIH0sCj4gKwkJW1ZPUDJfV0lOX0FGQkNfVVZfU1dBUF0gPSB7IC5yZWcg PSAweGZmZmZmZmZmIH0sCj4gKwkJW1ZPUDJfV0lOX0FGQkNfQVVUT19HQVRJTkdfRU5dID0geyAu cmVnID0gMHhmZmZmZmZmZiB9LAo+ICsJCVtWT1AyX1dJTl9BRkJDX0JMT0NLX1NQTElUX0VOXSA9 IHsgLnJlZyA9IDB4ZmZmZmZmZmYgfSwKPiArCQlbVk9QMl9XSU5fQUZCQ19QSUNfVklSX1dJRFRI XSA9IHsgLnJlZyA9IDB4ZmZmZmZmZmYgfSwKPiArCQlbVk9QMl9XSU5fQUZCQ19USUxFX05VTV0g PSB7IC5yZWcgPSAweGZmZmZmZmZmIH0sCj4gKwkJW1ZPUDJfV0lOX0FGQkNfUElDX09GRlNFVF0g PSB7IC5yZWcgPSAweGZmZmZmZmZmIH0sCj4gKwkJW1ZPUDJfV0lOX0FGQkNfUElDX1NJWkVdID0g eyAucmVnID0gMHhmZmZmZmZmZiB9LAo+ICsJCVtWT1AyX1dJTl9BRkJDX0RTUF9PRkZTRVRdID0g eyAucmVnID0gMHhmZmZmZmZmZiB9LAo+ICsJCVtWT1AyX1dJTl9BRkJDX1RSQU5TRk9STV9PRkZT RVRdID0geyAucmVnID0gMHhmZmZmZmZmZiB9LAo+ICsJCVtWT1AyX1dJTl9BRkJDX0hEUl9QVFJd ID0geyAucmVnID0gMHhmZmZmZmZmZiB9LAo+ICsJCVtWT1AyX1dJTl9BRkJDX0hBTEZfQkxPQ0tf RU5dID0geyAucmVnID0gMHhmZmZmZmZmZiB9LAo+ICsJCVtWT1AyX1dJTl9BRkJDX1JPVEFURV8y NzBdID0geyAucmVnID0gMHhmZmZmZmZmZiB9LAo+ICsJCVtWT1AyX1dJTl9BRkJDX1JPVEFURV85 MF0gPSB7IC5yZWcgPSAweGZmZmZmZmZmIH0sCj4gKwl9Owo+ICsKPiArCWZvciAoaSA9IDA7IGkg PCBBUlJBWV9TSVpFKHZvcDJfZXNtYXJ0X3JlZ3MpOyBpKyspCj4gKwkJdm9wMl9lc21hcnRfcmVn c1tpXS5yZWcgKz0gd2luLT5vZmZzZXQ7Cj4gKwo+ICsJcmV0dXJuIGRldm1fcmVnbWFwX2ZpZWxk X2J1bGtfYWxsb2Modm9wMi0+ZGV2LCB2b3AyLT5tYXAsIHdpbi0+cmVnLAo+ICsJCQkJCSAgICB2 b3AyX2VzbWFydF9yZWdzLAo+ICsJCQkJCSAgICBBUlJBWV9TSVpFKHZvcDJfZXNtYXJ0X3JlZ3Mp KTsKPiArfTsKPiArCj4gK3N0YXRpYyBpbnQgdm9wMl93aW5faW5pdChzdHJ1Y3Qgdm9wMiAqdm9w MikKPiArewo+ICsJY29uc3Qgc3RydWN0IHZvcDJfZGF0YSAqdm9wMl9kYXRhID0gdm9wMi0+ZGF0 YTsKPiArCXN0cnVjdCB2b3AyX3dpbiAqd2luOwo+ICsJaW50IGksIHJldDsKPiArCj4gKwlmb3Ig KGkgPSAwOyBpIDwgdm9wMl9kYXRhLT53aW5fc2l6ZTsgaSsrKSB7Cj4gKwkJY29uc3Qgc3RydWN0 IHZvcDJfd2luX2RhdGEgKndpbl9kYXRhID0gJnZvcDJfZGF0YS0+d2luW2ldOwo+ICsKPiArCQl3 aW4gPSAmdm9wMi0+d2luW2ldOwo+ICsJCXdpbi0+ZGF0YSA9IHdpbl9kYXRhOwo+ICsJCXdpbi0+ dHlwZSA9IHdpbl9kYXRhLT50eXBlOwo+ICsJCXdpbi0+b2Zmc2V0ID0gd2luX2RhdGEtPmJhc2U7 Cj4gKwkJd2luLT53aW5faWQgPSBpOwo+ICsJCXdpbi0+dm9wMiA9IHZvcDI7Cj4gKwkJaWYgKHZv cDJfY2x1c3Rlcl93aW5kb3cod2luKSkKPiArCQkJcmV0ID0gdm9wMl9jbHVzdGVyX2luaXQod2lu KTsKPiArCQllbHNlCj4gKwkJCXJldCA9IHZvcDJfZXNtYXJ0X2luaXQod2luKTsKPiArCQlpZiAo cmV0KQo+ICsJCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXZvcDItPnJlZ2lzdGVyZWRfbnVt X3dpbnMgPSB2b3AyX2RhdGEtPndpbl9zaXplOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ ICsvKgo+ICsgKiBUaGUgd2luZG93IHJlZ2lzdGVycyBhcmUgb25seSB1cGRhdGVkIHdoZW4gY29u ZmlnIGRvbmUgaXMgd3JpdHRlbi4KPiArICogVW50aWwgdGhhdCB0aGV5IHJlYWQgYmFjayB0aGUg b2xkIHZhbHVlLiBBcyB3ZSByZWFkLW1vZGlmeS13cml0ZQo+ICsgKiB0aGVzZSByZWdpc3RlcnMg bWFyayB0aGVtIGFzIG5vbi12b2xhdGlsZS4gVGhpcyBtYWtlcyBzdXJlIHdlIHJlYWQKPiArICog dGhlIG5ldyB2YWx1ZXMgZnJvbSB0aGUgcmVnbWFwIHJlZ2lzdGVyIGNhY2hlLgo+ICsgKi8KCgoK SSB0aGlua3Mgd2Ugc2hvdWxkIGJlIHZlcnkgY2FyZWZ1bGx5IGFib3V0IHN3aXRjaCB0byByZWdt YXAuCgpNb3N0IG9mIHRoZSByZWdpc3RlcnMgYXJlIHRha2UgZWZmZWN0IGJ5IGZyYW1lIHN5bmMo dGhhdCBpcyB5b3Ugd3JpdGUgCnRoZSBjb25maWcgZG9uZSBiaXQgYW5kIHdoZW4gdnN5bmMgaW50 ZXJydXB0IGNvbWUpLAoKTm90IG9ubHkgd2luZG93cyByZWdpc3RlciwgYnV0IGFsc28gdGhlIFNZ U19DVFJMLCBwb3N0IApwcm9jZXNzb3IoVlAwLzEvMikswqAgT1ZFUkxBWSwgaGRyIGFuZCBzbyBv bi4KCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgcmVnbWFwX3JhbmdlIHZvcDJfbm9udm9sYXRpbGVf cmFuZ2VbXSA9IHsKPiArCXJlZ21hcF9yZWdfcmFuZ2UoMHgxMDAwLCAweDIzZmYpLAo+ICt9Owo+ ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCByZWdtYXBfYWNjZXNzX3RhYmxlIHZvcDJfdm9sYXRp bGVfdGFibGUgPSB7Cj4gKwkubm9fcmFuZ2VzID0gdm9wMl9ub252b2xhdGlsZV9yYW5nZSwKPiAr CS5uX25vX3JhbmdlcyA9IEFSUkFZX1NJWkUodm9wMl9ub252b2xhdGlsZV9yYW5nZSksCj4gK307 Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IHJlZ21hcF9jb25maWcgdm9wMl9yZWdtYXBfY29u ZmlnID0gewo+ICsJLnJlZ19iaXRzCT0gMzIsCj4gKwkudmFsX2JpdHMJPSAzMiwKPiArCS5yZWdf c3RyaWRlCT0gNCwKPiArCS5tYXhfcmVnaXN0ZXIJPSAweDMwMDAsCj4gKwkubmFtZQkJPSAidm9w MiIsCj4gKwkudm9sYXRpbGVfdGFibGUJPSAmdm9wMl92b2xhdGlsZV90YWJsZSwKPiArCS5jYWNo ZV90eXBlCT0gUkVHQ0FDSEVfUkJUUkVFLAo+ICt9Owo+ICsKPiArc3RhdGljIGludCB2b3AyX2Jp bmQoc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgZGV2aWNlICptYXN0ZXIsIHZvaWQgKmRhdGEp Cj4gK3sKPiArCXN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYgPSB0b19wbGF0Zm9ybV9kZXZp Y2UoZGV2KTsKPiArCWNvbnN0IHN0cnVjdCB2b3AyX2RhdGEgKnZvcDJfZGF0YTsKPiArCXN0cnVj dCBkcm1fZGV2aWNlICpkcm0gPSBkYXRhOwo+ICsJc3RydWN0IHZvcDIgKnZvcDI7Cj4gKwlzdHJ1 Y3QgcmVzb3VyY2UgKnJlczsKPiArCXNpemVfdCBhbGxvY19zaXplOwo+ICsJaW50IHJldDsKPiAr Cj4gKwl2b3AyX2RhdGEgPSBvZl9kZXZpY2VfZ2V0X21hdGNoX2RhdGEoZGV2KTsKPiArCWlmICgh dm9wMl9kYXRhKQo+ICsJCXJldHVybiAtRU5PREVWOwo+ICsKPiArCS8qIEFsbG9jYXRlIHZvcDIg c3RydWN0IGFuZCBpdHMgdm9wMl93aW4gYXJyYXkgKi8KPiArCWFsbG9jX3NpemUgPSBzaXplb2Yo KnZvcDIpICsgc2l6ZW9mKCp2b3AyLT53aW4pICogdm9wMl9kYXRhLT53aW5fc2l6ZTsKPiArCXZv cDIgPSBkZXZtX2t6YWxsb2MoZGV2LCBhbGxvY19zaXplLCBHRlBfS0VSTkVMKTsKPiArCWlmICgh dm9wMikKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwl2b3AyLT5kZXYgPSBkZXY7Cj4gKwl2 b3AyLT5kYXRhID0gdm9wMl9kYXRhOwo+ICsJdm9wMi0+ZHJtID0gZHJtOwo+ICsKPiArCWRldl9z ZXRfZHJ2ZGF0YShkZXYsIHZvcDIpOwo+ICsKPiArCXJlcyA9IHBsYXRmb3JtX2dldF9yZXNvdXJj ZV9ieW5hbWUocGRldiwgSU9SRVNPVVJDRV9NRU0sICJyZWdzIik7Cj4gKwlpZiAoIXJlcykgewo+ ICsJCWRybV9lcnIodm9wMi0+ZHJtLCAiZmFpbGVkIHRvIGdldCB2b3AyIHJlZ2lzdGVyIGJ5bmFt ZVxuIik7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJdm9wMi0+cmVncyA9IGRl dm1faW9yZW1hcF9yZXNvdXJjZShkZXYsIHJlcyk7Cj4gKwlpZiAoSVNfRVJSKHZvcDItPnJlZ3Mp KQo+ICsJCXJldHVybiBQVFJfRVJSKHZvcDItPnJlZ3MpOwo+ICsJdm9wMi0+bGVuID0gcmVzb3Vy Y2Vfc2l6ZShyZXMpOwo+ICsKPiArCXZvcDItPm1hcCA9IGRldm1fcmVnbWFwX2luaXRfbW1pbyhk ZXYsIHZvcDItPnJlZ3MsICZ2b3AyX3JlZ21hcF9jb25maWcpOwo+ICsKPiArCXJldCA9IHZvcDJf d2luX2luaXQodm9wMik7Cj4gKwlpZiAocmV0KQo+ICsJCXJldHVybiByZXQ7CkRvIHlvdSBoYXZl IGEgY291bnQgYWJvdXQgaG93IG11Y2ggdGltZSB0aGUgZnVuY3Rpb24gdm9wMl93aW5faW5pdCBj b3N0ID8KPiArCj4gKwlyZXMgPSBwbGF0Zm9ybV9nZXRfcmVzb3VyY2VfYnluYW1lKHBkZXYsIElP UkVTT1VSQ0VfTUVNLCAiZ2FtbWFfbHV0Iik7Cj4gKwlpZiAocmVzKSB7Cj4gKwkJdm9wMi0+bHV0 X3JlZ3MgPSBkZXZtX2lvcmVtYXBfcmVzb3VyY2UoZGV2LCByZXMpOwo+ICsJCWlmIChJU19FUlIo dm9wMi0+bHV0X3JlZ3MpKQo+ICsJCQlyZXR1cm4gUFRSX0VSUih2b3AyLT5sdXRfcmVncyk7Cj4g Kwl9Cj4gKwo+ICsJdm9wMi0+Z3JmID0gc3lzY29uX3JlZ21hcF9sb29rdXBfYnlfcGhhbmRsZShk ZXYtPm9mX25vZGUsICJyb2NrY2hpcCxncmYiKTsKPiArCj4gKwl2b3AyLT5oY2xrID0gZGV2bV9j bGtfZ2V0KHZvcDItPmRldiwgImhjbGtfdm9wIik7Cj4gKwlpZiAoSVNfRVJSKHZvcDItPmhjbGsp KSB7Cj4gKwkJZHJtX2Vycih2b3AyLT5kcm0sICJmYWlsZWQgdG8gZ2V0IGhjbGsgc291cmNlXG4i KTsKPiArCQlyZXR1cm4gUFRSX0VSUih2b3AyLT5oY2xrKTsKPiArCX0KPiArCj4gKwl2b3AyLT5h Y2xrID0gZGV2bV9jbGtfZ2V0KHZvcDItPmRldiwgImFjbGtfdm9wIik7Cj4gKwlpZiAoSVNfRVJS KHZvcDItPmFjbGspKSB7Cj4gKwkJZHJtX2Vycih2b3AyLT5kcm0sICJmYWlsZWQgdG8gZ2V0IGFj bGsgc291cmNlXG4iKTsKPiArCQlyZXR1cm4gUFRSX0VSUih2b3AyLT5hY2xrKTsKPiArCX0KPiAr Cj4gKwl2b3AyLT5pcnEgPSBwbGF0Zm9ybV9nZXRfaXJxKHBkZXYsIDApOwo+ICsJaWYgKHZvcDIt PmlycSA8IDApIHsKPiArCQlkcm1fZXJyKHZvcDItPmRybSwgImNhbm5vdCBmaW5kIGlycSBmb3Ig dm9wMlxuIik7Cj4gKwkJcmV0dXJuIHZvcDItPmlycTsKPiArCX0KPiArCj4gKwlzcGluX2xvY2tf aW5pdCgmdm9wMi0+cmVnX2xvY2spOwo+ICsJbXV0ZXhfaW5pdCgmdm9wMi0+dm9wMl9sb2NrKTsK PiArCj4gKwlyZXQgPSBkZXZtX3JlcXVlc3RfaXJxKGRldiwgdm9wMi0+aXJxLCB2b3AyX2lzciwg SVJRRl9TSEFSRUQsIGRldl9uYW1lKGRldiksIHZvcDIpOwo+ICsJaWYgKHJldCkKPiArCQlyZXR1 cm4gcmV0Owo+ICsKPiArCXJldCA9IHJvY2tjaGlwX2RybV9kbWFfYXR0YWNoX2RldmljZSh2b3Ay LT5kcm0sIHZvcDItPmRldik7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZHJtX2Vycih2b3AyLT5kcm0s ICJmYWlsZWQgdG8gYXR0YWNoIGRtYSBtYXBwaW5nLCAlZFxuIiwgcmV0KTsKPiArCQlyZXR1cm4g cmV0Owo+ICsJfQo+ICsKPiArCXJldCA9IHZvcDJfY3JlYXRlX2NydGModm9wMik7Cj4gKwlpZiAo cmV0KQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJcG1fcnVudGltZV9lbmFibGUoJnBkZXYtPmRl dik7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHZvcDJfdW5iaW5k KHN0cnVjdCBkZXZpY2UgKmRldiwgc3RydWN0IGRldmljZSAqbWFzdGVyLCB2b2lkICpkYXRhKQo+ ICt7Cj4gKwlzdHJ1Y3Qgdm9wMiAqdm9wMiA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsJc3Ry dWN0IGRybV9kZXZpY2UgKmRybSA9IHZvcDItPmRybTsKPiArCXN0cnVjdCBsaXN0X2hlYWQgKnBs YW5lX2xpc3QgPSAmZHJtLT5tb2RlX2NvbmZpZy5wbGFuZV9saXN0Owo+ICsJc3RydWN0IGxpc3Rf aGVhZCAqY3J0Y19saXN0ID0gJmRybS0+bW9kZV9jb25maWcuY3J0Y19saXN0Owo+ICsJc3RydWN0 IGRybV9jcnRjICpjcnRjLCAqdG1wYzsKPiArCXN0cnVjdCBkcm1fcGxhbmUgKnBsYW5lLCAqdG1w cDsKPiArCj4gKwlyb2NrY2hpcF9kcm1fZG1hX2RldGFjaF9kZXZpY2Uodm9wMi0+ZHJtLCB2b3Ay LT5kZXYpOwo+ICsKPiArCXBtX3J1bnRpbWVfZGlzYWJsZShkZXYpOwo+ICsKPiArCWxpc3RfZm9y X2VhY2hfZW50cnlfc2FmZShwbGFuZSwgdG1wcCwgcGxhbmVfbGlzdCwgaGVhZCkKPiArCQlkcm1f cGxhbmVfY2xlYW51cChwbGFuZSk7Cj4gKwo+ICsJbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZlKGNy dGMsIHRtcGMsIGNydGNfbGlzdCwgaGVhZCkKPiArCQl2b3AyX2Rlc3Ryb3lfY3J0YyhjcnRjKTsK PiArfQo+ICsKPiArY29uc3Qgc3RydWN0IGNvbXBvbmVudF9vcHMgdm9wMl9jb21wb25lbnRfb3Bz ID0gewo+ICsJLmJpbmQgPSB2b3AyX2JpbmQsCj4gKwkudW5iaW5kID0gdm9wMl91bmJpbmQsCj4g K307Cj4gK0VYUE9SVF9TWU1CT0xfR1BMKHZvcDJfY29tcG9uZW50X29wcyk7Cj4gZGlmZiAtLWdp dCBhL2RyaXZlcnMvZ3B1L2RybS9yb2NrY2hpcC9yb2NrY2hpcF9kcm1fdm9wMi5oIGIvZHJpdmVy cy9ncHUvZHJtL3JvY2tjaGlwL3JvY2tjaGlwX2RybV92b3AyLmgKPiBuZXcgZmlsZSBtb2RlIDEw MDY0NAo+IGluZGV4IDAwMDAwMDAwMDAwMDAuLmJiNTY3N2ZmMDBlOTMKPiAtLS0gL2Rldi9udWxs Cj4gKysrIGIvZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlwL3JvY2tjaGlwX2RybV92b3AyLmgKPiBA QCAtMCwwICsxLDQ4MCBAQAo+ICsvKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMC1v bmx5ICovCj4gKy8qCj4gKyAqIENvcHlyaWdodCAoQykgRnV6aG91IFJvY2tjaGlwIEVsZWN0cm9u aWNzIENvLkx0ZAo+ICsgKiBBdXRob3I6TWFyayBZYW8gPG1hcmsueWFvQHJvY2stY2hpcHMuY29t Pgo+ICsgKi8KPiArCj4gKyNpZm5kZWYgX1JPQ0tDSElQX0RSTV9WT1AyX0gKPiArI2RlZmluZSBf Uk9DS0NISVBfRFJNX1ZPUDJfSAo+ICsKPiArI2luY2x1ZGUgInJvY2tjaGlwX2RybV92b3AuaCIK PiArCj4gKyNpbmNsdWRlIDxsaW51eC9yZWdtYXAuaD4KPiArI2luY2x1ZGUgPGRybS9kcm1fbW9k ZXMuaD4KPiArCj4gKyNkZWZpbmUgVk9QX0ZFQVRVUkVfT1VUUFVUXzEwQklUICAgICAgICBCSVQo MCkKPiArCj4gKyNkZWZpbmUgV0lOX0ZFQVRVUkVfQUZCREMJCUJJVCgwKQo+ICsjZGVmaW5lIFdJ Tl9GRUFUVVJFX0NMVVNURVIJCUJJVCgxKQo+ICsKPiArLyoKPiArICogIHRoZSBkZWxheSBudW1i ZXIgb2YgYSB3aW5kb3cgaW4gZGlmZmVyZW50IG1vZGUuCj4gKyAqLwo+ICtlbnVtIHdpbl9kbHlf bW9kZSB7Cj4gKwlWT1AyX0RMWV9NT0RFX0RFRkFVTFQsICAgLyoqPCBkZWZhdWx0IG1vZGUgKi8K PiArCVZPUDJfRExZX01PREVfSElTT19TLCAgICAvKiogSERSIGluIFNEUiBvdXQgbW9kZSwgYXMg YSBTRFIgd2luZG93ICovCj4gKwlWT1AyX0RMWV9NT0RFX0hJSE9fSCwgICAgLyoqIEhEUiBpbiBI RFIgb3V0IG1vZGUsIGFzIGEgSERSIHdpbmRvdyAqLwo+ICsJVk9QMl9ETFlfTU9ERV9NQVgsCj4g K307Cj4gKwo+ICtzdHJ1Y3Qgdm9wX3JlY3Qgewo+ICsJaW50IHdpZHRoOwo+ICsJaW50IGhlaWdo dDsKPiArfTsKPiArCj4gK2VudW0gdm9wMl9zY2FsZV91cF9tb2RlIHsKPiArCVZPUDJfU0NBTEVf VVBfTlJTVF9OQk9SLAo+ICsJVk9QMl9TQ0FMRV9VUF9CSUwsCj4gKwlWT1AyX1NDQUxFX1VQX0JJ QywKPiArfTsKPiArCj4gK2VudW0gdm9wMl9zY2FsZV9kb3duX21vZGUgewo+ICsJVk9QMl9TQ0FM RV9ET1dOX05SU1RfTkJPUiwKPiArCVZPUDJfU0NBTEVfRE9XTl9CSUwsCj4gKwlWT1AyX1NDQUxF X0RPV05fQVZHLAo+ICt9Owo+ICsKPiArZW51bSB2b3AyX3dpbl9yZWdzIHsKPiArCVZPUDJfV0lO X0VOQUJMRSwKPiArCVZPUDJfV0lOX0ZPUk1BVCwKPiArCVZPUDJfV0lOX0NTQ19NT0RFLAo+ICsJ Vk9QMl9XSU5fWE1JUlJPUiwKPiArCVZPUDJfV0lOX1lNSVJST1IsCj4gKwlWT1AyX1dJTl9SQl9T V0FQLAo+ICsJVk9QMl9XSU5fVVZfU1dBUCwKPiArCVZPUDJfV0lOX0FDVF9JTkZPLAo+ICsJVk9Q Ml9XSU5fRFNQX0lORk8sCj4gKwlWT1AyX1dJTl9EU1BfU1QsCj4gKwlWT1AyX1dJTl9ZUkdCX01T VCwKPiArCVZPUDJfV0lOX1VWX01TVCwKPiArCVZPUDJfV0lOX1lSR0JfVklSLAo+ICsJVk9QMl9X SU5fVVZfVklSLAo+ICsJVk9QMl9XSU5fWVVWX0NMSVAsCj4gKwlWT1AyX1dJTl9ZMlJfRU4sCj4g KwlWT1AyX1dJTl9SMllfRU4sCj4gKwlWT1AyX1dJTl9DT0xPUl9LRVksCj4gKwlWT1AyX1dJTl9D T0xPUl9LRVlfRU4sCj4gKwlWT1AyX1dJTl9ESVRIRVJfVVAsCj4gKwo+ICsJLyogc2NhbGUgcmVn cyAqLwo+ICsJVk9QMl9XSU5fU0NBTEVfWVJHQl9YLAo+ICsJVk9QMl9XSU5fU0NBTEVfWVJHQl9Z LAo+ICsJVk9QMl9XSU5fU0NBTEVfQ0JDUl9YLAo+ICsJVk9QMl9XSU5fU0NBTEVfQ0JDUl9ZLAo+ ICsJVk9QMl9XSU5fWVJHQl9IT1JfU0NMX01PREUsCj4gKwlWT1AyX1dJTl9ZUkdCX0hTQ0xfRklM VEVSX01PREUsCj4gKwlWT1AyX1dJTl9ZUkdCX1ZFUl9TQ0xfTU9ERSwKPiArCVZPUDJfV0lOX1lS R0JfVlNDTF9GSUxURVJfTU9ERSwKPiArCVZPUDJfV0lOX0NCQ1JfVkVSX1NDTF9NT0RFLAo+ICsJ Vk9QMl9XSU5fQ0JDUl9IU0NMX0ZJTFRFUl9NT0RFLAo+ICsJVk9QMl9XSU5fQ0JDUl9IT1JfU0NM X01PREUsCj4gKwlWT1AyX1dJTl9DQkNSX1ZTQ0xfRklMVEVSX01PREUsCj4gKwlWT1AyX1dJTl9W U0RfQ0JDUl9HVDIsCj4gKwlWT1AyX1dJTl9WU0RfQ0JDUl9HVDQsCj4gKwlWT1AyX1dJTl9WU0Rf WVJHQl9HVDIsCj4gKwlWT1AyX1dJTl9WU0RfWVJHQl9HVDQsCj4gKwlWT1AyX1dJTl9CSUNfQ09F X1NFTCwKPiArCj4gKwkvKiBjbHVzdGVyIHJlZ3MgKi8KPiArCVZPUDJfV0lOX0NMVVNURVJfRU5B QkxFLAo+ICsJVk9QMl9XSU5fQUZCQ19FTkFCTEUsCj4gKwlWT1AyX1dJTl9DTFVTVEVSX0xCX01P REUsCj4gKwo+ICsJLyogYWZiYyByZWdzICovCj4gKwlWT1AyX1dJTl9BRkJDX0ZPUk1BVCwKPiAr CVZPUDJfV0lOX0FGQkNfUkJfU1dBUCwKPiArCVZPUDJfV0lOX0FGQkNfVVZfU1dBUCwKPiArCVZP UDJfV0lOX0FGQkNfQVVUT19HQVRJTkdfRU4sCj4gKwlWT1AyX1dJTl9BRkJDX0JMT0NLX1NQTElU X0VOLAo+ICsJVk9QMl9XSU5fQUZCQ19QSUNfVklSX1dJRFRILAo+ICsJVk9QMl9XSU5fQUZCQ19U SUxFX05VTSwKPiArCVZPUDJfV0lOX0FGQkNfUElDX09GRlNFVCwKPiArCVZPUDJfV0lOX0FGQkNf UElDX1NJWkUsCj4gKwlWT1AyX1dJTl9BRkJDX0RTUF9PRkZTRVQsCj4gKwlWT1AyX1dJTl9BRkJD X1RSQU5TRk9STV9PRkZTRVQsCj4gKwlWT1AyX1dJTl9BRkJDX0hEUl9QVFIsCj4gKwlWT1AyX1dJ Tl9BRkJDX0hBTEZfQkxPQ0tfRU4sCj4gKwlWT1AyX1dJTl9BRkJDX1JPVEFURV8yNzAsCj4gKwlW T1AyX1dJTl9BRkJDX1JPVEFURV85MCwKPiArCVZPUDJfV0lOX01BWF9SRUcsCj4gK307Cj4gKwo+ ICtzdHJ1Y3Qgdm9wMl93aW5fZGF0YSB7Cj4gKwljb25zdCBjaGFyICpuYW1lOwo+ICsJdWludDhf dCBwaHlzX2lkOwo+ICsKPiArCXVpbnQzMl90IGJhc2U7Cj4gKwllbnVtIGRybV9wbGFuZV90eXBl IHR5cGU7Cj4gKwo+ICsJdWludDMyX3QgbmZvcm1hdHM7Cj4gKwljb25zdCB1aW50MzJfdCAqZm9y bWF0czsKPiArCWNvbnN0IHVpbnQ2NF90ICpmb3JtYXRfbW9kaWZpZXJzOwo+ICsJY29uc3QgdW5z aWduZWQgaW50IHN1cHBvcnRlZF9yb3RhdGlvbnM7Cj4gKwo+ICsJLyoqCj4gKwkgKiBAbGF5ZXJf c2VsX2lkOiBkZWZpbmVkIGJ5IHJlZ2lzdGVyIE9WRVJMQVlfTEFZRVJfU0VMIG9mIFZPUDIKPiAr CSAqLwo+ICsJaW50IGxheWVyX3NlbF9pZDsKPiArCXVpbnQ2NF90IGZlYXR1cmU7Cj4gKwo+ICsJ dW5zaWduZWQgaW50IG1heF91cHNjYWxlX2ZhY3RvcjsKPiArCXVuc2lnbmVkIGludCBtYXhfZG93 bnNjYWxlX2ZhY3RvcjsKPiArCWNvbnN0IHVpbnQ4X3QgZGx5W1ZPUDJfRExZX01PREVfTUFYXTsK PiArfTsKPiArCj4gK3N0cnVjdCB2b3AyX3ZpZGVvX3BvcnRfZGF0YSB7Cj4gKwljaGFyIGlkOwo+ ICsJdWludDMyX3QgZmVhdHVyZTsKPiArCXVpbnQxNl90IGdhbW1hX2x1dF9sZW47Cj4gKwl1aW50 MTZfdCBjdWJpY19sdXRfbGVuOwo+ICsJc3RydWN0IHZvcF9yZWN0IG1heF9vdXRwdXQ7Cj4gKwlj b25zdCB1OCBwcmVfc2Nhbl9tYXhfZGx5WzRdOwo+ICsJY29uc3Qgc3RydWN0IHZvcDJfdmlkZW9f cG9ydF9yZWdzICpyZWdzOwo+ICsJaW50IG9mZnNldDsKPiArfTsKPiArCj4gK3N0cnVjdCB2b3Ay X2RhdGEgewo+ICsJdWludDhfdCBucl92cHM7Cj4gKwl1aW50OF90IG5yX21peGVyczsKPiArCXVp bnQ4X3QgbnJfbGF5ZXJzOwo+ICsJdWludDhfdCBucl9nYW1tYXM7Cj4gKwljb25zdCBzdHJ1Y3Qg dm9wMl9jdHJsICpjdHJsOwo+ICsJY29uc3Qgc3RydWN0IHZvcDJfd2luX2RhdGEgKndpbjsKPiAr CWNvbnN0IHN0cnVjdCB2b3AyX3ZpZGVvX3BvcnRfZGF0YSAqdnA7Cj4gKwljb25zdCBzdHJ1Y3Qg dm9wX2NzY190YWJsZSAqY3NjX3RhYmxlOwo+ICsJc3RydWN0IHZvcF9yZWN0IG1heF9pbnB1dDsK PiArCXN0cnVjdCB2b3BfcmVjdCBtYXhfb3V0cHV0Owo+ICsKPiArCXVuc2lnbmVkIGludCB3aW5f c2l6ZTsKPiArCXVuc2lnbmVkIGludCBzb2NfaWQ7Cj4gK307Cj4gKwo+ICsvKiBpbnRlcnJ1cHQg ZGVmaW5lICovCj4gKyNkZWZpbmUgRlNfTkVXX0lOVFIJCQlCSVQoNCkKPiArI2RlZmluZSBBRERS X1NBTUVfSU5UUgkJCUJJVCg1KQo+ICsjZGVmaW5lIExJTkVfRkxBRzFfSU5UUgkJCUJJVCg2KQo+ ICsjZGVmaW5lIFdJTjBfRU1QVFlfSU5UUgkJCUJJVCg3KQo+ICsjZGVmaW5lIFdJTjFfRU1QVFlf SU5UUgkJCUJJVCg4KQo+ICsjZGVmaW5lIFdJTjJfRU1QVFlfSU5UUgkJCUJJVCg5KQo+ICsjZGVm aW5lIFdJTjNfRU1QVFlfSU5UUgkJCUJJVCgxMCkKPiArI2RlZmluZSBIV0NfRU1QVFlfSU5UUgkJ CUJJVCgxMSkKPiArI2RlZmluZSBQT1NUX0JVRl9FTVBUWV9JTlRSCQlCSVQoMTIpCj4gKyNkZWZp bmUgUFdNX0dFTl9JTlRSCQkJQklUKDEzKQo+ICsjZGVmaW5lIERNQV9GSU5JU0hfSU5UUgkJCUJJ VCgxNCkKPiArI2RlZmluZSBGU19GSUVMRF9JTlRSCQkJQklUKDE1KQo+ICsjZGVmaW5lIEZFX0lO VFIJCQkJQklUKDE2KQo+ICsjZGVmaW5lIFdCX1VWX0ZJRk9fRlVMTF9JTlRSCQlCSVQoMTcpCj4g KyNkZWZpbmUgV0JfWVJHQl9GSUZPX0ZVTExfSU5UUgkJQklUKDE4KQo+ICsjZGVmaW5lIFdCX0NP TVBMRVRFX0lOVFIJCUJJVCgxOSkKPiArCj4gKy8qCj4gKyAqIGRpc3BsYXkgb3V0cHV0IGludGVy ZmFjZSBzdXBwb3J0ZWQgYnkgcm9ja2NoaXAgbGNkYwo+ICsgKi8KPiArI2RlZmluZSBST0NLQ0hJ UF9PVVRfTU9ERV9QODg4CQkwCj4gKyNkZWZpbmUgUk9DS0NISVBfT1VUX01PREVfQlQxMTIwCTAK PiArI2RlZmluZSBST0NLQ0hJUF9PVVRfTU9ERV9QNjY2CQkxCj4gKyNkZWZpbmUgUk9DS0NISVBf T1VUX01PREVfUDU2NQkJMgo+ICsjZGVmaW5lIFJPQ0tDSElQX09VVF9NT0RFX0JUNjU2CQk1Cj4g KyNkZWZpbmUgUk9DS0NISVBfT1VUX01PREVfUzg4OAkJOAo+ICsjZGVmaW5lIFJPQ0tDSElQX09V VF9NT0RFX1M4ODhfRFVNTVkJMTIKPiArI2RlZmluZSBST0NLQ0hJUF9PVVRfTU9ERV9ZVVY0MjAJ MTQKPiArLyogZm9yIHVzZSBzcGVjaWFsIG91dGZhY2UgKi8KPiArI2RlZmluZSBST0NLQ0hJUF9P VVRfTU9ERV9BQUFBCQkxNQo+ICsKPiArZW51bSB2b3BfY3NjX2Zvcm1hdCB7Cj4gKwlDU0NfQlQ2 MDFMLAo+ICsJQ1NDX0JUNzA5TCwKPiArCUNTQ19CVDYwMUYsCj4gKwlDU0NfQlQyMDIwLAo+ICt9 Owo+ICsKPiArZW51bSBzcmNfZmFjdG9yX21vZGUgewo+ICsJU1JDX0ZBQ19BTFBIQV9aRVJPLAo+ ICsJU1JDX0ZBQ19BTFBIQV9PTkUsCj4gKwlTUkNfRkFDX0FMUEhBX0RTVCwKPiArCVNSQ19GQUNf QUxQSEFfRFNUX0lOVkVSU0UsCj4gKwlTUkNfRkFDX0FMUEhBX1NSQywKPiArCVNSQ19GQUNfQUxQ SEFfU1JDX0dMT0JBTCwKPiArfTsKPiArCj4gK2VudW0gZHN0X2ZhY3Rvcl9tb2RlIHsKPiArCURT VF9GQUNfQUxQSEFfWkVSTywKPiArCURTVF9GQUNfQUxQSEFfT05FLAo+ICsJRFNUX0ZBQ19BTFBI QV9TUkMsCj4gKwlEU1RfRkFDX0FMUEhBX1NSQ19JTlZFUlNFLAo+ICsJRFNUX0ZBQ19BTFBIQV9E U1QsCj4gKwlEU1RfRkFDX0FMUEhBX0RTVF9HTE9CQUwsCj4gK307Cj4gKwo+ICsjZGVmaW5lIFJL MzU2OF9HUkZfVk9fQ09OMQkJCTB4MDM2NAo+ICsvKiBTeXN0ZW0gcmVnaXN0ZXJzIGRlZmluaXRp b24gKi8KPiArI2RlZmluZSBSSzM1NjhfUkVHX0NGR19ET05FCQkJMHgwMDAKPiArI2RlZmluZSBS SzM1NjhfVkVSU0lPTl9JTkZPCQkJMHgwMDQKPiArI2RlZmluZSBSSzM1NjhfU1lTX0FVVE9fR0FU SU5HX0NUUkwJCTB4MDA4Cj4gKyNkZWZpbmUgUkszNTY4X1NZU19BWElfTFVUX0NUUkwJCQkweDAy NAo+ICsjZGVmaW5lIFJLMzU2OF9EU1BfSUZfRU4JCQkweDAyOAo+ICsjZGVmaW5lIFJLMzU2OF9E U1BfSUZfQ1RSTAkJCTB4MDJjCj4gKyNkZWZpbmUgUkszNTY4X0RTUF9JRl9QT0wJCQkweDAzMAo+ ICsjZGVmaW5lIFJLMzU2OF9XQl9DVFJMCQkJCTB4NDAKPiArI2RlZmluZSBSSzM1NjhfV0JfWFND QUxfRkFDVE9SCQkJMHg0NAo+ICsjZGVmaW5lIFJLMzU2OF9XQl9ZUkdCX01TVAkJCTB4NDgKPiAr I2RlZmluZSBSSzM1NjhfV0JfQ0JSX01TVAkJCTB4NEMKPiArI2RlZmluZSBSSzM1NjhfT1RQX1dJ Tl9FTgkJCTB4MDUwCj4gKyNkZWZpbmUgUkszNTY4X0xVVF9QT1JUX1NFTAkJCTB4MDU4Cj4gKyNk ZWZpbmUgUkszNTY4X1NZU19TVEFUVVMwCQkJMHgwNjAKPiArI2RlZmluZSBSSzM1NjhfVlBfTElO RV9GTEFHKHZwKQkJCSgweDcwICsgKHZwKSAqIDB4NCkKPiArI2RlZmluZSBSSzM1NjhfU1lTMF9J TlRfRU4JCQkweDgwCj4gKyNkZWZpbmUgUkszNTY4X1NZUzBfSU5UX0NMUgkJCTB4ODQKPiArI2Rl ZmluZSBSSzM1NjhfU1lTMF9JTlRfU1RBVFVTCQkJMHg4OAo+ICsjZGVmaW5lIFJLMzU2OF9TWVMx X0lOVF9FTgkJCTB4OTAKPiArI2RlZmluZSBSSzM1NjhfU1lTMV9JTlRfQ0xSCQkJMHg5NAo+ICsj ZGVmaW5lIFJLMzU2OF9TWVMxX0lOVF9TVEFUVVMJCQkweDk4Cj4gKyNkZWZpbmUgUkszNTY4X1ZQ X0lOVF9FTih2cCkJCQkoMHhBMCArICh2cCkgKiAweDEwKQo+ICsjZGVmaW5lIFJLMzU2OF9WUF9J TlRfQ0xSKHZwKQkJCSgweEE0ICsgKHZwKSAqIDB4MTApCj4gKyNkZWZpbmUgUkszNTY4X1ZQX0lO VF9TVEFUVVModnApCQkoMHhBOCArICh2cCkgKiAweDEwKQo+ICsjZGVmaW5lIFJLMzU2OF9WUF9J TlRfUkFXX1NUQVRVUyh2cCkJCSgweEFDICsgKHZwKSAqIDB4MTApCj4gKwo+ICsvKiBWaWRlbyBQ b3J0IHJlZ2lzdGVycyBkZWZpbml0aW9uICovCj4gKyNkZWZpbmUgUkszNTY4X1ZQX0RTUF9DVFJM CQkJMHgwMAo+ICsjZGVmaW5lIFJLMzU2OF9WUF9NSVBJX0NUUkwJCQkweDA0Cj4gKyNkZWZpbmUg UkszNTY4X1ZQX0NPTE9SX0JBUl9DVFJMCQkweDA4Cj4gKyNkZWZpbmUgUkszNTY4X1ZQXzNEX0xV VF9DVFJMCQkJMHgxMAo+ICsjZGVmaW5lIFJLMzU2OF9WUF8zRF9MVVRfTVNUCQkJMHgyMAo+ICsj ZGVmaW5lIFJLMzU2OF9WUF9EU1BfQkcJCQkweDJDCj4gKyNkZWZpbmUgUkszNTY4X1ZQX1BSRV9T Q0FOX0hUSU1JTkcJCTB4MzAKPiArI2RlZmluZSBSSzM1NjhfVlBfUE9TVF9EU1BfSEFDVF9JTkZP CQkweDM0Cj4gKyNkZWZpbmUgUkszNTY4X1ZQX1BPU1RfRFNQX1ZBQ1RfSU5GTwkJMHgzOAo+ICsj ZGVmaW5lIFJLMzU2OF9WUF9QT1NUX1NDTF9GQUNUT1JfWVJHQgkJMHgzQwo+ICsjZGVmaW5lIFJL MzU2OF9WUF9QT1NUX1NDTF9DVFJMCQkJMHg0MAo+ICsjZGVmaW5lIFJLMzU2OF9WUF9QT1NUX0RT UF9WQUNUX0lORk9fRjEJCTB4NDQKPiArI2RlZmluZSBSSzM1NjhfVlBfRFNQX0hUT1RBTF9IU19F TkQJCTB4NDgKPiArI2RlZmluZSBSSzM1NjhfVlBfRFNQX0hBQ1RfU1RfRU5ECQkweDRDCj4gKyNk ZWZpbmUgUkszNTY4X1ZQX0RTUF9WVE9UQUxfVlNfRU5ECQkweDUwCj4gKyNkZWZpbmUgUkszNTY4 X1ZQX0RTUF9WQUNUX1NUX0VORAkJMHg1NAo+ICsjZGVmaW5lIFJLMzU2OF9WUF9EU1BfVlNfU1Rf RU5EX0YxCQkweDU4Cj4gKyNkZWZpbmUgUkszNTY4X1ZQX0RTUF9WQUNUX1NUX0VORF9GMQkJMHg1 Qwo+ICsjZGVmaW5lIFJLMzU2OF9WUF9CQ1NIX0NUUkwJCQkweDYwCj4gKyNkZWZpbmUgUkszNTY4 X1ZQX0JDU0hfQkNTCQkJMHg2NAo+ICsjZGVmaW5lIFJLMzU2OF9WUF9CQ1NIX0gJCQkweDY4Cj4g KyNkZWZpbmUgUkszNTY4X1ZQX0JDU0hfQ09MT1JfQkFSCQkweDZDCj4gKwo+ICsvKiBPdmVybGF5 IHJlZ2lzdGVycyBkZWZpbml0aW9uICAgICovCj4gKyNkZWZpbmUgUkszNTY4X09WTF9DVFJMCQkJ CTB4NjAwCj4gKyNkZWZpbmUgUkszNTY4X09WTF9MQVlFUl9TRUwJCQkweDYwNAo+ICsjZGVmaW5l IFJLMzU2OF9PVkxfUE9SVF9TRUwJCQkweDYwOAo+ICsjZGVmaW5lIFJLMzU2OF9DTFVTVEVSMF9N SVhfU1JDX0NPTE9SX0NUUkwJMHg2MTAKPiArI2RlZmluZSBSSzM1NjhfQ0xVU1RFUjBfTUlYX0RT VF9DT0xPUl9DVFJMCTB4NjE0Cj4gKyNkZWZpbmUgUkszNTY4X0NMVVNURVIwX01JWF9TUkNfQUxQ SEFfQ1RSTAkweDYxOAo+ICsjZGVmaW5lIFJLMzU2OF9DTFVTVEVSMF9NSVhfRFNUX0FMUEhBX0NU UkwJMHg2MUMKPiArI2RlZmluZSBSSzM1NjhfTUlYMF9TUkNfQ09MT1JfQ1RSTAkJMHg2NTAKPiAr I2RlZmluZSBSSzM1NjhfTUlYMF9EU1RfQ09MT1JfQ1RSTAkJMHg2NTQKPiArI2RlZmluZSBSSzM1 NjhfTUlYMF9TUkNfQUxQSEFfQ1RSTAkJMHg2NTgKPiArI2RlZmluZSBSSzM1NjhfTUlYMF9EU1Rf QUxQSEFfQ1RSTAkJMHg2NUMKPiArI2RlZmluZSBSSzM1NjhfSERSMF9TUkNfQ09MT1JfQ1RSTAkJ MHg2QzAKPiArI2RlZmluZSBSSzM1NjhfSERSMF9EU1RfQ09MT1JfQ1RSTAkJMHg2QzQKPiArI2Rl ZmluZSBSSzM1NjhfSERSMF9TUkNfQUxQSEFfQ1RSTAkJMHg2QzgKPiArI2RlZmluZSBSSzM1Njhf SERSMF9EU1RfQUxQSEFfQ1RSTAkJMHg2Q0MKPiArI2RlZmluZSBSSzM1NjhfVlBfQkdfTUlYX0NU UkwodnApCQkoMHg2RTAgKyAodnApICogNCkKPiArI2RlZmluZSBSSzM1NjhfQ0xVU1RFUl9ETFlf TlVNCQkJMHg2RjAKPiArI2RlZmluZSBSSzM1NjhfU01BUlRfRExZX05VTQkJCTB4NkY4Cj4gKwo+ ICsvKiBDbHVzdGVyIHJlZ2lzdGVyIGRlZmluaXRpb24sIG9mZnNldCByZWxhdGl2ZSB0byB3aW5k b3cgYmFzZSAqLwo+ICsjZGVmaW5lIFJLMzU2OF9DTFVTVEVSX1dJTl9DVFJMMAkJMHgwMAo+ICsj ZGVmaW5lIFJLMzU2OF9DTFVTVEVSX1dJTl9DVFJMMQkJMHgwNAo+ICsjZGVmaW5lIFJLMzU2OF9D TFVTVEVSX1dJTl9ZUkdCX01TVAkJMHgxMAo+ICsjZGVmaW5lIFJLMzU2OF9DTFVTVEVSX1dJTl9D QlJfTVNUCQkweDE0Cj4gKyNkZWZpbmUgUkszNTY4X0NMVVNURVJfV0lOX1ZJUgkJCTB4MTgKPiAr I2RlZmluZSBSSzM1NjhfQ0xVU1RFUl9XSU5fQUNUX0lORk8JCTB4MjAKPiArI2RlZmluZSBSSzM1 NjhfQ0xVU1RFUl9XSU5fRFNQX0lORk8JCTB4MjQKPiArI2RlZmluZSBSSzM1NjhfQ0xVU1RFUl9X SU5fRFNQX1NUCQkweDI4Cj4gKyNkZWZpbmUgUkszNTY4X0NMVVNURVJfV0lOX1NDTF9GQUNUT1Jf WVJHQgkweDMwCj4gKyNkZWZpbmUgUkszNTY4X0NMVVNURVJfV0lOX0FGQkNEX1RSQU5TRk9STV9P RkZTRVQJMHgzQwo+ICsjZGVmaW5lIFJLMzU2OF9DTFVTVEVSX1dJTl9BRkJDRF9PVVRQVVRfQ1RS TAkweDUwCj4gKyNkZWZpbmUgUkszNTY4X0NMVVNURVJfV0lOX0FGQkNEX1JPVEFURV9NT0RFCTB4 NTQKPiArI2RlZmluZSBSSzM1NjhfQ0xVU1RFUl9XSU5fQUZCQ0RfSERSX1BUUgkweDU4Cj4gKyNk ZWZpbmUgUkszNTY4X0NMVVNURVJfV0lOX0FGQkNEX1ZJUl9XSURUSAkweDVDCj4gKyNkZWZpbmUg UkszNTY4X0NMVVNURVJfV0lOX0FGQkNEX1BJQ19TSVpFCTB4NjAKPiArI2RlZmluZSBSSzM1Njhf Q0xVU1RFUl9XSU5fQUZCQ0RfUElDX09GRlNFVAkweDY0Cj4gKyNkZWZpbmUgUkszNTY4X0NMVVNU RVJfV0lOX0FGQkNEX0RTUF9PRkZTRVQJMHg2OAo+ICsjZGVmaW5lIFJLMzU2OF9DTFVTVEVSX1dJ Tl9BRkJDRF9DVFJMCQkweDZDCj4gKwo+ICsjZGVmaW5lIFJLMzU2OF9DTFVTVEVSX0NUUkwJCQkw eDEwMAo+ICsKPiArLyogKEUpc21hcnQgcmVnaXN0ZXIgZGVmaW5pdGlvbiwgb2Zmc2V0IHJlbGF0 aXZlIHRvIHdpbmRvdyBiYXNlICovCj4gKyNkZWZpbmUgUkszNTY4X1NNQVJUX0NUUkwwCQkJMHgw MAo+ICsjZGVmaW5lIFJLMzU2OF9TTUFSVF9DVFJMMQkJCTB4MDQKPiArI2RlZmluZSBSSzM1Njhf U01BUlRfUkVHSU9OMF9DVFJMCQkweDEwCj4gKyNkZWZpbmUgUkszNTY4X1NNQVJUX1JFR0lPTjBf WVJHQl9NU1QJCTB4MTQKPiArI2RlZmluZSBSSzM1NjhfU01BUlRfUkVHSU9OMF9DQlJfTVNUCQkw eDE4Cj4gKyNkZWZpbmUgUkszNTY4X1NNQVJUX1JFR0lPTjBfVklSCQkweDFDCj4gKyNkZWZpbmUg UkszNTY4X1NNQVJUX1JFR0lPTjBfQUNUX0lORk8JCTB4MjAKPiArI2RlZmluZSBSSzM1NjhfU01B UlRfUkVHSU9OMF9EU1BfSU5GTwkJMHgyNAo+ICsjZGVmaW5lIFJLMzU2OF9TTUFSVF9SRUdJT04w X0RTUF9TVAkJMHgyOAo+ICsjZGVmaW5lIFJLMzU2OF9TTUFSVF9SRUdJT04wX1NDTF9DVFJMCQkw eDMwCj4gKyNkZWZpbmUgUkszNTY4X1NNQVJUX1JFR0lPTjBfU0NMX0ZBQ1RPUl9ZUkdCCTB4MzQK PiArI2RlZmluZSBSSzM1NjhfU01BUlRfUkVHSU9OMF9TQ0xfRkFDVE9SX0NCUgkweDM4Cj4gKyNk ZWZpbmUgUkszNTY4X1NNQVJUX1JFR0lPTjBfU0NMX09GRlNFVAkJMHgzQwo+ICsjZGVmaW5lIFJL MzU2OF9TTUFSVF9SRUdJT04xX0NUUkwJCTB4NDAKPiArI2RlZmluZSBSSzM1NjhfU01BUlRfUkVH SU9OMV9ZUkdCX01TVAkJMHg0NAo+ICsjZGVmaW5lIFJLMzU2OF9TTUFSVF9SRUdJT04xX0NCUl9N U1QJCTB4NDgKPiArI2RlZmluZSBSSzM1NjhfU01BUlRfUkVHSU9OMV9WSVIJCTB4NEMKPiArI2Rl ZmluZSBSSzM1NjhfU01BUlRfUkVHSU9OMV9BQ1RfSU5GTwkJMHg1MAo+ICsjZGVmaW5lIFJLMzU2 OF9TTUFSVF9SRUdJT04xX0RTUF9JTkZPCQkweDU0Cj4gKyNkZWZpbmUgUkszNTY4X1NNQVJUX1JF R0lPTjFfRFNQX1NUCQkweDU4Cj4gKyNkZWZpbmUgUkszNTY4X1NNQVJUX1JFR0lPTjFfU0NMX0NU UkwJCTB4NjAKPiArI2RlZmluZSBSSzM1NjhfU01BUlRfUkVHSU9OMV9TQ0xfRkFDVE9SX1lSR0IJ MHg2NAo+ICsjZGVmaW5lIFJLMzU2OF9TTUFSVF9SRUdJT04xX1NDTF9GQUNUT1JfQ0JSCTB4NjgK PiArI2RlZmluZSBSSzM1NjhfU01BUlRfUkVHSU9OMV9TQ0xfT0ZGU0VUCQkweDZDCj4gKyNkZWZp bmUgUkszNTY4X1NNQVJUX1JFR0lPTjJfQ1RSTAkJMHg3MAo+ICsjZGVmaW5lIFJLMzU2OF9TTUFS VF9SRUdJT04yX1lSR0JfTVNUCQkweDc0Cj4gKyNkZWZpbmUgUkszNTY4X1NNQVJUX1JFR0lPTjJf Q0JSX01TVAkJMHg3OAo+ICsjZGVmaW5lIFJLMzU2OF9TTUFSVF9SRUdJT04yX1ZJUgkJMHg3Qwo+ ICsjZGVmaW5lIFJLMzU2OF9TTUFSVF9SRUdJT04yX0FDVF9JTkZPCQkweDgwCj4gKyNkZWZpbmUg UkszNTY4X1NNQVJUX1JFR0lPTjJfRFNQX0lORk8JCTB4ODQKPiArI2RlZmluZSBSSzM1NjhfU01B UlRfUkVHSU9OMl9EU1BfU1QJCTB4ODgKPiArI2RlZmluZSBSSzM1NjhfU01BUlRfUkVHSU9OMl9T Q0xfQ1RSTAkJMHg5MAo+ICsjZGVmaW5lIFJLMzU2OF9TTUFSVF9SRUdJT04yX1NDTF9GQUNUT1Jf WVJHQgkweDk0Cj4gKyNkZWZpbmUgUkszNTY4X1NNQVJUX1JFR0lPTjJfU0NMX0ZBQ1RPUl9DQlIJ MHg5OAo+ICsjZGVmaW5lIFJLMzU2OF9TTUFSVF9SRUdJT04yX1NDTF9PRkZTRVQJCTB4OUMKPiAr I2RlZmluZSBSSzM1NjhfU01BUlRfUkVHSU9OM19DVFJMCQkweEEwCj4gKyNkZWZpbmUgUkszNTY4 X1NNQVJUX1JFR0lPTjNfWVJHQl9NU1QJCTB4QTQKPiArI2RlZmluZSBSSzM1NjhfU01BUlRfUkVH SU9OM19DQlJfTVNUCQkweEE4Cj4gKyNkZWZpbmUgUkszNTY4X1NNQVJUX1JFR0lPTjNfVklSCQkw eEFDCj4gKyNkZWZpbmUgUkszNTY4X1NNQVJUX1JFR0lPTjNfQUNUX0lORk8JCTB4QjAKPiArI2Rl ZmluZSBSSzM1NjhfU01BUlRfUkVHSU9OM19EU1BfSU5GTwkJMHhCNAo+ICsjZGVmaW5lIFJLMzU2 OF9TTUFSVF9SRUdJT04zX0RTUF9TVAkJMHhCOAo+ICsjZGVmaW5lIFJLMzU2OF9TTUFSVF9SRUdJ T04zX1NDTF9DVFJMCQkweEMwCj4gKyNkZWZpbmUgUkszNTY4X1NNQVJUX1JFR0lPTjNfU0NMX0ZB Q1RPUl9ZUkdCCTB4QzQKPiArI2RlZmluZSBSSzM1NjhfU01BUlRfUkVHSU9OM19TQ0xfRkFDVE9S X0NCUgkweEM4Cj4gKyNkZWZpbmUgUkszNTY4X1NNQVJUX1JFR0lPTjNfU0NMX09GRlNFVAkJMHhD Qwo+ICsjZGVmaW5lIFJLMzU2OF9TTUFSVF9DT0xPUl9LRVlfQ1RSTAkJMHhEMAo+ICsKPiArLyog SERSIHJlZ2lzdGVyIGRlZmluaXRpb24gKi8KPiArI2RlZmluZSBSSzM1NjhfSERSX0xVVF9DVFJM CQkJMHgyMDAwCj4gKyNkZWZpbmUgUkszNTY4X0hEUl9MVVRfTVNUCQkJMHgyMDA0Cj4gKyNkZWZp bmUgUkszNTY4X1NEUjJIRFJfQ1RSTAkJCTB4MjAxMAo+ICsjZGVmaW5lIFJLMzU2OF9IRFIyU0RS X0NUUkwJCQkweDIwMjAKPiArI2RlZmluZSBSSzM1NjhfSERSMlNEUl9TUkNfUkFOR0UJCTB4MjAy NAo+ICsjZGVmaW5lIFJLMzU2OF9IRFIyU0RSX05PUk1GQUNFRVRGCQkweDIwMjgKPiArI2RlZmlu ZSBSSzM1NjhfSERSMlNEUl9EU1RfUkFOR0UJCTB4MjAyQwo+ICsjZGVmaW5lIFJLMzU2OF9IRFIy U0RSX05PUk1GQUNDR0FNTUEJCTB4MjAzMAo+ICsjZGVmaW5lIFJLMzU2OF9IRFJfRUVURl9PRVRG X1kwCQkJMHgyMDNDCj4gKyNkZWZpbmUgUkszNTY4X0hEUl9TQVRfWTAJCQkweDIwQzAKPiArI2Rl ZmluZSBSSzM1NjhfSERSX0VPVEZfT0VURl9ZMAkJCTB4MjBGMAo+ICsjZGVmaW5lIFJLMzU2OF9I RFJfT0VURl9EWF9QT1cxCQkJMHgyMjAwCj4gKyNkZWZpbmUgUkszNTY4X0hEUl9PRVRGX1hOMQkJ CTB4MjMwMAo+ICsKPiArI2RlZmluZSBSSzM1NjhfUkVHX0NGR19ET05FX19HTEJfQ0ZHX0RPTkVf RU4JCUJJVCgxNSkKPiArCj4gKyNkZWZpbmUgUkszNTY4X1ZQX0RTUF9DVFJMX19TVEFOREJZCQkJ QklUKDMxKQo+ICsjZGVmaW5lIFJLMzU2OF9WUF9EU1BfQ1RSTF9fRElUSEVSX0RPV05fTU9ERQkJ QklUKDIwKQo+ICsjZGVmaW5lIFJLMzU2OF9WUF9EU1BfQ1RSTF9fRElUSEVSX0RPV05fU0VMCQlH RU5NQVNLKDE5LCAxOCkKPiArI2RlZmluZSBSSzM1NjhfVlBfRFNQX0NUUkxfX0RJVEhFUl9ET1dO X0VOCQlCSVQoMTcpCj4gKyNkZWZpbmUgUkszNTY4X1ZQX0RTUF9DVFJMX19QUkVfRElUSEVSX0RP V05fRU4JCUJJVCgxNikKPiArI2RlZmluZSBSSzM1NjhfVlBfRFNQX0NUUkxfX1BPU1RfRFNQX09V VF9SMlkJCUJJVCgxNSkKPiArI2RlZmluZSBSSzM1NjhfVlBfRFNQX0NUUkxfX0RTUF9SQl9TV0FQ CQkJQklUKDkpCj4gKyNkZWZpbmUgUkszNTY4X1ZQX0RTUF9DVFJMX19EU1BfSU5URVJMQUNFCQlC SVQoNykKPiArI2RlZmluZSBSSzM1NjhfVlBfRFNQX0NUUkxfX0RTUF9GSUxFRF9QT0wJCUJJVCg2 KQo+ICsjZGVmaW5lIFJLMzU2OF9WUF9EU1BfQ1RSTF9fUDJJX0VOCQkJQklUKDUpCj4gKyNkZWZp bmUgUkszNTY4X1ZQX0RTUF9DVFJMX19DT1JFX0RDTEtfRElWCQlCSVQoNCkKPiArI2RlZmluZSBS SzM1NjhfVlBfRFNQX0NUUkxfX09VVF9NT0RFCQkJR0VOTUFTSygzLCAwKQo+ICsKPiArI2RlZmlu ZSBSSzM1NjhfVlBfUE9TVF9TQ0xfQ1RSTF9fVlNDQUxFRE9XTgkJQklUKDEpCj4gKyNkZWZpbmUg UkszNTY4X1ZQX1BPU1RfU0NMX0NUUkxfX0hTQ0FMRURPV04JCUJJVCgwKQo+ICsKPiArI2RlZmlu ZSBSSzM1NjhfU1lTX0RTUF9JTkZBQ0VfRU5fTFZEUzFfTVVYCQlHRU5NQVNLKDI2LCAyNSkKPiAr I2RlZmluZSBSSzM1NjhfU1lTX0RTUF9JTkZBQ0VfRU5fTFZEUzEJCQlCSVQoMjQpCj4gKyNkZWZp bmUgUkszNTY4X1NZU19EU1BfSU5GQUNFX0VOX01JUEkxX01VWAkJR0VOTUFTSygyMiwgMjEpCj4g KyNkZWZpbmUgUkszNTY4X1NZU19EU1BfSU5GQUNFX0VOX01JUEkxCQkJQklUKDIwKQo+ICsjZGVm aW5lIFJLMzU2OF9TWVNfRFNQX0lORkFDRV9FTl9MVkRTMF9NVVgJCUdFTk1BU0soMTksIDE4KQo+ ICsjZGVmaW5lIFJLMzU2OF9TWVNfRFNQX0lORkFDRV9FTl9NSVBJMF9NVVgJCUdFTk1BU0soMTcs IDE2KQo+ICsjZGVmaW5lIFJLMzU2OF9TWVNfRFNQX0lORkFDRV9FTl9FRFBfTVVYCQlHRU5NQVNL KDE1LCAxNCkKPiArI2RlZmluZSBSSzM1NjhfU1lTX0RTUF9JTkZBQ0VfRU5fSERNSV9NVVgJCUdF Tk1BU0soMTEsIDEwKQo+ICsjZGVmaW5lIFJLMzU2OF9TWVNfRFNQX0lORkFDRV9FTl9SR0JfTVVY CQlHRU5NQVNLKDksIDgpCj4gKyNkZWZpbmUgUkszNTY4X1NZU19EU1BfSU5GQUNFX0VOX0xWRFMw CQkJQklUKDUpCj4gKyNkZWZpbmUgUkszNTY4X1NZU19EU1BfSU5GQUNFX0VOX01JUEkwCQkJQklU KDQpCj4gKyNkZWZpbmUgUkszNTY4X1NZU19EU1BfSU5GQUNFX0VOX0VEUAkJCUJJVCgzKQo+ICsj ZGVmaW5lIFJLMzU2OF9TWVNfRFNQX0lORkFDRV9FTl9IRE1JCQkJQklUKDEpCj4gKyNkZWZpbmUg UkszNTY4X1NZU19EU1BfSU5GQUNFX0VOX1JHQgkJCUJJVCgwKQo+ICsKPiArI2RlZmluZSBSSzM1 NjhfRFNQX0lGX1BPTF9fTUlQSV9QSU5fUE9MCQkJR0VOTUFTSygxOSwgMTYpCj4gKyNkZWZpbmUg UkszNTY4X0RTUF9JRl9QT0xfX0VEUF9QSU5fUE9MCQkJR0VOTUFTSygxNSwgMTIpCj4gKyNkZWZp bmUgUkszNTY4X0RTUF9JRl9QT0xfX0hETUlfUElOX1BPTAkJCUdFTk1BU0soNywgNCkKPiArI2Rl ZmluZSBSSzM1NjhfRFNQX0lGX1BPTF9fUkdCX0xWRFNfUElOX1BPTAkJR0VOTUFTSygzLCAwKQo+ ICsKPiArI2RlZmluZSBSSzM1NjhfVlAwX01JUElfQ1RSTF9fRENMS19ESVYyX1BIQVNFX0xPQ0sJ QklUKDUpCj4gKyNkZWZpbmUgUkszNTY4X1ZQMF9NSVBJX0NUUkxfX0RDTEtfRElWMgkJCUJJVCg0 KQo+ICsKPiArI2RlZmluZSBSSzM1NjhfU1lTX0FVVE9fR0FUSU5HX0NUUkxfX0FVVE9fR0FUSU5H X0VOCUJJVCgzMSkKPiArCj4gKyNkZWZpbmUgUkszNTY4X0RTUF9JRl9QT0xfX0NGR19ET05FX0lN RAkJCUJJVCgyOCkKPiArCj4gKyNkZWZpbmUgVk9QMl9TWVNfQVhJX0JVU19OVU0JCQkJMgo+ICsK PiArI2RlZmluZSBWT1AyX0NMVVNURVJfWVVWNDQ0XzEwCQkJCTB4MTIKPiArCj4gKyNkZWZpbmUg Vk9QMl9DT0xPUl9LRVlfTUFTSwkJCQlCSVQoMzEpCj4gKwo+ICsjZGVmaW5lIFJLMzU2OF9PVkxf Q1RSTF9fTEFZRVJTRUxfUkVHRE9ORV9JTUQJCUJJVCgyOCkKPiArCj4gKyNkZWZpbmUgUkszNTY4 X1ZQX0JHX01JWF9DVFJMX19CR19ETFkJCQlHRU5NQVNLKDMxLCAyNCkKPiArCj4gKyNkZWZpbmUg UkszNTY4X09WTF9QT1JUX1NFTF9fU0VMX1BPUlQJCQlHRU5NQVNLKDMxLCAxNikKPiArI2RlZmlu ZSBSSzM1NjhfT1ZMX1BPUlRfU0VMX19TTUFSVDEJCQlHRU5NQVNLKDMxLCAzMCkKPiArI2RlZmlu ZSBSSzM1NjhfT1ZMX1BPUlRfU0VMX19TTUFSVDAJCQlHRU5NQVNLKDI5LCAyOCkKPiArI2RlZmlu ZSBSSzM1NjhfT1ZMX1BPUlRfU0VMX19FU01BUlQxCQkJR0VOTUFTSygyNywgMjYpCj4gKyNkZWZp bmUgUkszNTY4X09WTF9QT1JUX1NFTF9fRVNNQVJUMAkJCUdFTk1BU0soMjUsIDI0KQo+ICsjZGVm aW5lIFJLMzU2OF9PVkxfUE9SVF9TRUxfX0NMVVNURVIxCQkJR0VOTUFTSygxOSwgMTgpCj4gKyNk ZWZpbmUgUkszNTY4X09WTF9QT1JUX1NFTF9fQ0xVU1RFUjAJCQlHRU5NQVNLKDE3LCAxNikKPiAr I2RlZmluZSBSSzM1NjhfT1ZMX1BPUlRfU0VUX19QT1JUMl9NVVgJCQlHRU5NQVNLKDExLCA4KQo+ ICsjZGVmaW5lIFJLMzU2OF9PVkxfUE9SVF9TRVRfX1BPUlQxX01VWAkJCUdFTk1BU0soNywgNCkK PiArI2RlZmluZSBSSzM1NjhfT1ZMX1BPUlRfU0VUX19QT1JUMF9NVVgJCQlHRU5NQVNLKDMsIDAp Cj4gKyNkZWZpbmUgUkszNTY4X09WTF9MQVlFUl9TRUxfX0xBWUVSKGxheWVyLCB4KQkJKCh4KSA8 PCAoKGxheWVyKSAqIDQpKQo+ICsKPiArI2RlZmluZSBSSzM1NjhfQ0xVU1RFUl9ETFlfTlVNX19D TFVTVEVSMV8xCQlHRU5NQVNLKDMxLCAyNCkKPiArI2RlZmluZSBSSzM1NjhfQ0xVU1RFUl9ETFlf TlVNX19DTFVTVEVSMV8wCQlHRU5NQVNLKDIzLCAxNikKPiArI2RlZmluZSBSSzM1NjhfQ0xVU1RF Ul9ETFlfTlVNX19DTFVTVEVSMF8xCQlHRU5NQVNLKDE1LCA4KQo+ICsjZGVmaW5lIFJLMzU2OF9D TFVTVEVSX0RMWV9OVU1fX0NMVVNURVIwXzAJCUdFTk1BU0soNywgMCkKPiArCj4gKyNkZWZpbmUg UkszNTY4X1NNQVJUX0RMWV9OVU1fX1NNQVJUMQkJCUdFTk1BU0soMzEsIDI0KQo+ICsjZGVmaW5l IFJLMzU2OF9TTUFSVF9ETFlfTlVNX19TTUFSVDAJCQlHRU5NQVNLKDIzLCAxNikKPiArI2RlZmlu ZSBSSzM1NjhfU01BUlRfRExZX05VTV9fRVNNQVJUMQkJCUdFTk1BU0soMTUsIDgpCj4gKyNkZWZp bmUgUkszNTY4X1NNQVJUX0RMWV9OVU1fX0VTTUFSVDAJCQlHRU5NQVNLKDcsIDApCj4gKwo+ICsj ZGVmaW5lIFZQX0lOVF9EU1BfSE9MRF9WQUxJRAlCSVQoNikKPiArI2RlZmluZSBWUF9JTlRfRlNf RklFTEQJCUJJVCg1KQo+ICsjZGVmaW5lIFZQX0lOVF9QT1NUX0JVRl9FTVBUWQlCSVQoNCkKPiAr I2RlZmluZSBWUF9JTlRfTElORV9GTEFHMQlCSVQoMykKPiArI2RlZmluZSBWUF9JTlRfTElORV9G TEFHMAlCSVQoMikKPiArI2RlZmluZSBWT1AyX0lOVF9CVVNfRVJSUFIJQklUKDEpCj4gKyNkZWZp bmUgVlBfSU5UX0ZTCQlCSVQoMCkKPiArCj4gKyNkZWZpbmUgUE9MRkxBR19EQ0xLX0lOVglCSVQo MykKPiArCj4gK2VudW0gdm9wMl9sYXllcl9waHlfaWQgewo+ICsJUk9DS0NISVBfVk9QMl9DTFVT VEVSMCA9IDAsCj4gKwlST0NLQ0hJUF9WT1AyX0NMVVNURVIxLAo+ICsJUk9DS0NISVBfVk9QMl9F U01BUlQwLAo+ICsJUk9DS0NISVBfVk9QMl9FU01BUlQxLAo+ICsJUk9DS0NISVBfVk9QMl9TTUFS VDAsCj4gKwlST0NLQ0hJUF9WT1AyX1NNQVJUMSwKPiArCVJPQ0tDSElQX1ZPUDJfQ0xVU1RFUjIs Cj4gKwlST0NLQ0hJUF9WT1AyX0NMVVNURVIzLAo+ICsJUk9DS0NISVBfVk9QMl9FU01BUlQyLAo+ ICsJUk9DS0NISVBfVk9QMl9FU01BUlQzLAo+ICsJUk9DS0NISVBfVk9QMl9QSFlfSURfSU5WQUxJ RCA9IC0xLAo+ICt9Owo+ICsKPiArZXh0ZXJuIGNvbnN0IHN0cnVjdCBjb21wb25lbnRfb3BzIHZv cDJfY29tcG9uZW50X29wczsKPiArCj4gKyNlbmRpZiAvKiBfUk9DS0NISVBfRFJNX1ZPUDJfSCAq Lwo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vcm9ja2NoaXAvcm9ja2NoaXBfdm9wMl9y ZWcuYyBiL2RyaXZlcnMvZ3B1L2RybS9yb2NrY2hpcC9yb2NrY2hpcF92b3AyX3JlZy5jCj4gbmV3 IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAwMDAwLi4yMzc2ZTYzZDk0NzhmCj4g LS0tIC9kZXYvbnVsbAo+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9yb2NrY2hpcC9yb2NrY2hpcF92 b3AyX3JlZy5jCj4gQEAgLTAsMCArMSwyODUgQEAKPiArLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZp ZXI6IEdQTC0yLjAtb25seQo+ICsvKgo+ICsgKiBDb3B5cmlnaHQgKEMpIFJvY2tjaGlwIEVsZWN0 cm9uaWNzIENvLkx0ZAo+ICsgKiBBdXRob3I6IEFuZHkgWWFuIDxhbmR5LnlhbkByb2NrLWNoaXBz LmNvbT4KPiArICovCj4gKwo+ICsjaW5jbHVkZSA8bGludXgva2VybmVsLmg+Cj4gKyNpbmNsdWRl IDxsaW51eC9jb21wb25lbnQuaD4KPiArI2luY2x1ZGUgPGxpbnV4L21vZF9kZXZpY2V0YWJsZS5o Pgo+ICsjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+Cj4gKyNpbmNsdWRlIDxsaW51 eC9vZi5oPgo+ICsjaW5jbHVkZSA8ZHJtL2RybV9mb3VyY2MuaD4KPiArI2luY2x1ZGUgPGRybS9k cm1fcGxhbmUuaD4KPiArI2luY2x1ZGUgPGRybS9kcm1fcHJpbnQuaD4KPiArCj4gKyNpbmNsdWRl ICJyb2NrY2hpcF9kcm1fdm9wMi5oIgo+ICsKPiArc3RhdGljIGNvbnN0IHVpbnQzMl90IGZvcm1h dHNfd2luX2Z1bGxfMTBiaXRbXSA9IHsKPiArCURSTV9GT1JNQVRfWFJHQjg4ODgsCj4gKwlEUk1f Rk9STUFUX0FSR0I4ODg4LAo+ICsJRFJNX0ZPUk1BVF9YQkdSODg4OCwKPiArCURSTV9GT1JNQVRf QUJHUjg4ODgsCj4gKwlEUk1fRk9STUFUX1JHQjg4OCwKPiArCURSTV9GT1JNQVRfQkdSODg4LAo+ ICsJRFJNX0ZPUk1BVF9SR0I1NjUsCj4gKwlEUk1fRk9STUFUX0JHUjU2NSwKPiArCURSTV9GT1JN QVRfTlYxMiwKPiArCURSTV9GT1JNQVRfTlYxNiwKPiArCURSTV9GT1JNQVRfTlYyNCwKPiArfTsK PiArCj4gK3N0YXRpYyBjb25zdCB1aW50MzJfdCBmb3JtYXRzX3dpbl9mdWxsXzEwYml0X3l1eXZb XSA9IHsKPiArCURSTV9GT1JNQVRfWFJHQjg4ODgsCj4gKwlEUk1fRk9STUFUX0FSR0I4ODg4LAo+ ICsJRFJNX0ZPUk1BVF9YQkdSODg4OCwKPiArCURSTV9GT1JNQVRfQUJHUjg4ODgsCj4gKwlEUk1f Rk9STUFUX1JHQjg4OCwKPiArCURSTV9GT1JNQVRfQkdSODg4LAo+ICsJRFJNX0ZPUk1BVF9SR0I1 NjUsCj4gKwlEUk1fRk9STUFUX0JHUjU2NSwKPiArCURSTV9GT1JNQVRfTlYxMiwKPiArCURSTV9G T1JNQVRfTlYxNiwKPiArCURSTV9GT1JNQVRfTlYyNCwKPiArCURSTV9GT1JNQVRfWVZZVSwKPiAr CURSTV9GT1JNQVRfVllVWSwKPiArfTsKPiArCj4gK3N0YXRpYyBjb25zdCB1aW50MzJfdCBmb3Jt YXRzX3dpbl9saXRlW10gPSB7Cj4gKwlEUk1fRk9STUFUX1hSR0I4ODg4LAo+ICsJRFJNX0ZPUk1B VF9BUkdCODg4OCwKPiArCURSTV9GT1JNQVRfWEJHUjg4ODgsCj4gKwlEUk1fRk9STUFUX0FCR1I4 ODg4LAo+ICsJRFJNX0ZPUk1BVF9SR0I4ODgsCj4gKwlEUk1fRk9STUFUX0JHUjg4OCwKPiArCURS TV9GT1JNQVRfUkdCNTY1LAo+ICsJRFJNX0ZPUk1BVF9CR1I1NjUsCj4gK307Cj4gKwo+ICtzdGF0 aWMgY29uc3QgdWludDY0X3QgZm9ybWF0X21vZGlmaWVyc1tdID0gewo+ICsJRFJNX0ZPUk1BVF9N T0RfTElORUFSLAo+ICsJRFJNX0ZPUk1BVF9NT0RfSU5WQUxJRCwKPiArfTsKPiArCj4gK3N0YXRp YyBjb25zdCB1aW50NjRfdCBmb3JtYXRfbW9kaWZpZXJzX2FmYmNbXSA9IHsKPiArCURSTV9GT1JN QVRfTU9EX0FSTV9BRkJDKEFGQkNfRk9STUFUX01PRF9CTE9DS19TSVpFXzE2eDE2KSwKPiArCj4g KwlEUk1fRk9STUFUX01PRF9BUk1fQUZCQyhBRkJDX0ZPUk1BVF9NT0RfQkxPQ0tfU0laRV8xNngx NiB8Cj4gKwkJCQlBRkJDX0ZPUk1BVF9NT0RfU1BBUlNFKSwKPiArCj4gKwlEUk1fRk9STUFUX01P RF9BUk1fQUZCQyhBRkJDX0ZPUk1BVF9NT0RfQkxPQ0tfU0laRV8xNngxNiB8Cj4gKwkJCQlBRkJD X0ZPUk1BVF9NT0RfWVRSKSwKPiArCj4gKwlEUk1fRk9STUFUX01PRF9BUk1fQUZCQyhBRkJDX0ZP Uk1BVF9NT0RfQkxPQ0tfU0laRV8xNngxNiB8Cj4gKwkJCQlBRkJDX0ZPUk1BVF9NT0RfQ0JSKSwK PiArCj4gKwlEUk1fRk9STUFUX01PRF9BUk1fQUZCQyhBRkJDX0ZPUk1BVF9NT0RfQkxPQ0tfU0la RV8xNngxNiB8Cj4gKwkJCQlBRkJDX0ZPUk1BVF9NT0RfWVRSIHwKPiArCQkJCUFGQkNfRk9STUFU X01PRF9TUEFSU0UpLAo+ICsKPiArCURSTV9GT1JNQVRfTU9EX0FSTV9BRkJDKEFGQkNfRk9STUFU X01PRF9CTE9DS19TSVpFXzE2eDE2IHwKPiArCQkJCUFGQkNfRk9STUFUX01PRF9DQlIgfAo+ICsJ CQkJQUZCQ19GT1JNQVRfTU9EX1NQQVJTRSksCj4gKwo+ICsJRFJNX0ZPUk1BVF9NT0RfQVJNX0FG QkMoQUZCQ19GT1JNQVRfTU9EX0JMT0NLX1NJWkVfMTZ4MTYgfAo+ICsJCQkJQUZCQ19GT1JNQVRf TU9EX1lUUiB8Cj4gKwkJCQlBRkJDX0ZPUk1BVF9NT0RfQ0JSKSwKPiArCj4gKwlEUk1fRk9STUFU X01PRF9BUk1fQUZCQyhBRkJDX0ZPUk1BVF9NT0RfQkxPQ0tfU0laRV8xNngxNiB8Cj4gKwkJCQlB RkJDX0ZPUk1BVF9NT0RfWVRSIHwKPiArCQkJCUFGQkNfRk9STUFUX01PRF9DQlIgfAo+ICsJCQkJ QUZCQ19GT1JNQVRfTU9EX1NQQVJTRSksCj4gKwo+ICsJLyogU1BMSVQgbWFuZGF0ZXMgU1BBUlNF LCBSR0IgbW9kZXMgbWFuZGF0ZXMgWVRSICovCj4gKwlEUk1fRk9STUFUX01PRF9BUk1fQUZCQyhB RkJDX0ZPUk1BVF9NT0RfQkxPQ0tfU0laRV8xNngxNiB8Cj4gKwkJCQlBRkJDX0ZPUk1BVF9NT0Rf WVRSIHwKPiArCQkJCUFGQkNfRk9STUFUX01PRF9TUEFSU0UgfAo+ICsJCQkJQUZCQ19GT1JNQVRf TU9EX1NQTElUKSwKPiArCURSTV9GT1JNQVRfTU9EX0lOVkFMSUQsCj4gK307Cj4gKwo+ICtzdGF0 aWMgY29uc3Qgc3RydWN0IHZvcDJfdmlkZW9fcG9ydF9kYXRhIHJrMzU2OF92b3BfdmlkZW9fcG9y dHNbXSA9IHsKPiArCXsKPiArCQkuaWQgPSAwLAo+ICsJCS5mZWF0dXJlID0gVk9QX0ZFQVRVUkVf T1VUUFVUXzEwQklULAo+ICsJCS5nYW1tYV9sdXRfbGVuID0gMTAyNCwKPiArCQkuY3ViaWNfbHV0 X2xlbiA9IDkgKiA5ICogOSwKPiArCQkubWF4X291dHB1dCA9IHsgNDA5NiwgMjMwNCB9LAo+ICsJ CS5wcmVfc2Nhbl9tYXhfZGx5ID0geyA2OSwgNTMsIDUzLCA0MiB9LAo+ICsJCS5vZmZzZXQgPSAw eGMwMCwKPiArCX0sIHsKPiArCQkuaWQgPSAxLAo+ICsJCS5nYW1tYV9sdXRfbGVuID0gMTAyNCwK PiArCQkubWF4X291dHB1dCA9IHsgMjA0OCwgMTUzNiB9LAo+ICsJCS5wcmVfc2Nhbl9tYXhfZGx5 ID0geyA0MCwgNDAsIDQwLCA0MCB9LAo+ICsJCS5vZmZzZXQgPSAweGQwMCwKPiArCX0sIHsKPiAr CQkuaWQgPSAyLAo+ICsJCS5nYW1tYV9sdXRfbGVuID0gMTAyNCwKPiArCQkubWF4X291dHB1dCA9 IHsgMTkyMCwgMTA4MCB9LAo+ICsJCS5wcmVfc2Nhbl9tYXhfZGx5ID0geyA0MCwgNDAsIDQwLCA0 MCB9LAo+ICsJCS5vZmZzZXQgPSAweGUwMCwKPiArCX0sCj4gK307Cj4gKwo+ICsvKgo+ICsgKiBy azM1Njggdm9wIHdpdGggMiBjbHVzdGVyLCAyIGVzbWFydCB3aW4sIDIgc21hcnQgd2luLgo+ICsg KiBFdmVyeSBjbHVzdGVyIGNhbiB3b3JrIGFzIDRLIHdpbiBvciBzcGxpdCBpbnRvIHR3byB3aW4u Cj4gKyAqIEFsbCB3aW4gaW4gY2x1c3RlciBzdXBwb3J0IEFGQkNELgo+ICsgKgo+ICsgKiBFdmVy eSBlc21hcnQgd2luIGFuZCBzbWFydCB3aW4gc3VwcG9ydCA0IE11bHRpLXJlZ2lvbi4KPiArICoK PiArICogU2NhbGUgZmlsdGVyIG1vZGU6Cj4gKyAqCj4gKyAqICogQ2x1c3RlcjogIGJpY3ViaWMg Zm9yIGhvcml6b250YWwgc2NhbGUgdXAsIG90aGVycyB1c2UgYmlsaW5lYXIKPiArICogKiBFU21h cnQ6Cj4gKyAqICAgICogbmVhcmVzdC1uZWlnaGJvci9iaWxpbmVhci9iaWN1YmljIGZvciBzY2Fs ZSB1cAo+ICsgKiAgICAqIG5lYXJlc3QtbmVpZ2hib3IvYmlsaW5lYXIvYXZlcmFnZSBmb3Igc2Nh bGUgZG93bgo+ICsgKgo+ICsgKgo+ICsgKiBAVE9ETyBkZXNjcmliZSB0aGUgd2luZCBsaWtlIGNw dS1tYXAgZHQgbm9kZXM7Cj4gKyAqLwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IHZvcDJfd2luX2Rh dGEgcmszNTY4X3ZvcF93aW5fZGF0YVtdID0gewo+ICsJewo+ICsJCS5uYW1lID0gIlNtYXJ0MC13 aW4wIiwKPiArCQkucGh5c19pZCA9IFJPQ0tDSElQX1ZPUDJfU01BUlQwLAo+ICsJCS5iYXNlID0g MHgxYzAwLAo+ICsJCS5mb3JtYXRzID0gZm9ybWF0c193aW5fbGl0ZSwKPiArCQkubmZvcm1hdHMg PSBBUlJBWV9TSVpFKGZvcm1hdHNfd2luX2xpdGUpLAo+ICsJCS5mb3JtYXRfbW9kaWZpZXJzID0g Zm9ybWF0X21vZGlmaWVycywKPiArCQkubGF5ZXJfc2VsX2lkID0gMywKPiArCQkuc3VwcG9ydGVk X3JvdGF0aW9ucyA9IERSTV9NT0RFX1JFRkxFQ1RfWSwKPiArCQkudHlwZSA9IERSTV9QTEFORV9U WVBFX1BSSU1BUlksCj4gKwkJLm1heF91cHNjYWxlX2ZhY3RvciA9IDgsCj4gKwkJLm1heF9kb3du c2NhbGVfZmFjdG9yID0gOCwKPiArCQkuZGx5ID0geyAyMCwgNDcsIDQxIH0sCj4gKwl9LCB7Cj4g KwkJLm5hbWUgPSAiU21hcnQxLXdpbjAiLAo+ICsJCS5waHlzX2lkID0gUk9DS0NISVBfVk9QMl9T TUFSVDEsCj4gKwkJLmZvcm1hdHMgPSBmb3JtYXRzX3dpbl9saXRlLAo+ICsJCS5uZm9ybWF0cyA9 IEFSUkFZX1NJWkUoZm9ybWF0c193aW5fbGl0ZSksCj4gKwkJLmZvcm1hdF9tb2RpZmllcnMgPSBm b3JtYXRfbW9kaWZpZXJzLAo+ICsJCS5iYXNlID0gMHgxZTAwLAo+ICsJCS5sYXllcl9zZWxfaWQg PSA3LAo+ICsJCS5zdXBwb3J0ZWRfcm90YXRpb25zID0gRFJNX01PREVfUkVGTEVDVF9ZLAo+ICsJ CS50eXBlID0gRFJNX1BMQU5FX1RZUEVfUFJJTUFSWSwKPiArCQkubWF4X3Vwc2NhbGVfZmFjdG9y ID0gOCwKPiArCQkubWF4X2Rvd25zY2FsZV9mYWN0b3IgPSA4LAo+ICsJCS5kbHkgPSB7IDIwLCA0 NywgNDEgfSwKPiArCX0sIHsKPiArCQkubmFtZSA9ICJFc21hcnQxLXdpbjAiLAo+ICsJCS5waHlz X2lkID0gUk9DS0NISVBfVk9QMl9FU01BUlQxLAo+ICsJCS5mb3JtYXRzID0gZm9ybWF0c193aW5f ZnVsbF8xMGJpdF95dXl2LAo+ICsJCS5uZm9ybWF0cyA9IEFSUkFZX1NJWkUoZm9ybWF0c193aW5f ZnVsbF8xMGJpdF95dXl2KSwKPiArCQkuZm9ybWF0X21vZGlmaWVycyA9IGZvcm1hdF9tb2RpZmll cnMsCj4gKwkJLmJhc2UgPSAweDFhMDAsCj4gKwkJLmxheWVyX3NlbF9pZCA9IDYsCj4gKwkJLnN1 cHBvcnRlZF9yb3RhdGlvbnMgPSBEUk1fTU9ERV9SRUZMRUNUX1ksCj4gKwkJLnR5cGUgPSBEUk1f UExBTkVfVFlQRV9QUklNQVJZLAo+ICsJCS5tYXhfdXBzY2FsZV9mYWN0b3IgPSA4LAo+ICsJCS5t YXhfZG93bnNjYWxlX2ZhY3RvciA9IDgsCj4gKwkJLmRseSA9IHsgMjAsIDQ3LCA0MSB9LAo+ICsJ fSwgewo+ICsJCS5uYW1lID0gIkVzbWFydDAtd2luMCIsCj4gKwkJLnBoeXNfaWQgPSBST0NLQ0hJ UF9WT1AyX0VTTUFSVDAsCj4gKwkJLmZvcm1hdHMgPSBmb3JtYXRzX3dpbl9mdWxsXzEwYml0X3l1 eXYsCj4gKwkJLm5mb3JtYXRzID0gQVJSQVlfU0laRShmb3JtYXRzX3dpbl9mdWxsXzEwYml0X3l1 eXYpLAo+ICsJCS5mb3JtYXRfbW9kaWZpZXJzID0gZm9ybWF0X21vZGlmaWVycywKPiArCQkuYmFz ZSA9IDB4MTgwMCwKPiArCQkubGF5ZXJfc2VsX2lkID0gMiwKPiArCQkuc3VwcG9ydGVkX3JvdGF0 aW9ucyA9IERSTV9NT0RFX1JFRkxFQ1RfWSwKPiArCQkudHlwZSA9IERSTV9QTEFORV9UWVBFX09W RVJMQVksCj4gKwkJLm1heF91cHNjYWxlX2ZhY3RvciA9IDgsCj4gKwkJLm1heF9kb3duc2NhbGVf ZmFjdG9yID0gOCwKPiArCQkuZGx5ID0geyAyMCwgNDcsIDQxIH0sCj4gKwl9LCB7Cj4gKwkJLm5h bWUgPSAiQ2x1c3RlcjAtd2luMCIsCj4gKwkJLnBoeXNfaWQgPSBST0NLQ0hJUF9WT1AyX0NMVVNU RVIwLAo+ICsJCS5iYXNlID0gMHgxMDAwLAo+ICsJCS5mb3JtYXRzID0gZm9ybWF0c193aW5fZnVs bF8xMGJpdCwKPiArCQkubmZvcm1hdHMgPSBBUlJBWV9TSVpFKGZvcm1hdHNfd2luX2Z1bGxfMTBi aXQpLAo+ICsJCS5mb3JtYXRfbW9kaWZpZXJzID0gZm9ybWF0X21vZGlmaWVyc19hZmJjLAo+ICsJ CS5sYXllcl9zZWxfaWQgPSAwLAo+ICsJCS5zdXBwb3J0ZWRfcm90YXRpb25zID0gRFJNX01PREVf Uk9UQVRFXzkwIHwgRFJNX01PREVfUk9UQVRFXzI3MCB8Cj4gKwkJCQkJRFJNX01PREVfUkVGTEVD VF9YIHwgRFJNX01PREVfUkVGTEVDVF9ZLAo+ICsJCS5tYXhfdXBzY2FsZV9mYWN0b3IgPSA0LAo+ ICsJCS5tYXhfZG93bnNjYWxlX2ZhY3RvciA9IDQsCj4gKwkJLmRseSA9IHsgMCwgMjcsIDIxIH0s Cj4gKwkJLnR5cGUgPSBEUk1fUExBTkVfVFlQRV9PVkVSTEFZLAo+ICsJCS5mZWF0dXJlID0gV0lO X0ZFQVRVUkVfQUZCREMgfCBXSU5fRkVBVFVSRV9DTFVTVEVSLAo+ICsJfSwgewo+ICsJCS5uYW1l ID0gIkNsdXN0ZXIxLXdpbjAiLAo+ICsJCS5waHlzX2lkID0gUk9DS0NISVBfVk9QMl9DTFVTVEVS MSwKPiArCQkuYmFzZSA9IDB4MTIwMCwKPiArCQkuZm9ybWF0cyA9IGZvcm1hdHNfd2luX2Z1bGxf MTBiaXQsCj4gKwkJLm5mb3JtYXRzID0gQVJSQVlfU0laRShmb3JtYXRzX3dpbl9mdWxsXzEwYml0 KSwKPiArCQkuZm9ybWF0X21vZGlmaWVycyA9IGZvcm1hdF9tb2RpZmllcnNfYWZiYywKPiArCQku bGF5ZXJfc2VsX2lkID0gMSwKPiArCQkuc3VwcG9ydGVkX3JvdGF0aW9ucyA9IERSTV9NT0RFX1JP VEFURV85MCB8IERSTV9NT0RFX1JPVEFURV8yNzAgfAo+ICsJCQkJCURSTV9NT0RFX1JFRkxFQ1Rf WCB8IERSTV9NT0RFX1JFRkxFQ1RfWSwKPiArCQkudHlwZSA9IERSTV9QTEFORV9UWVBFX09WRVJM QVksCj4gKwkJLm1heF91cHNjYWxlX2ZhY3RvciA9IDQsCj4gKwkJLm1heF9kb3duc2NhbGVfZmFj dG9yID0gNCwKPiArCQkuZGx5ID0geyAwLCAyNywgMjEgfSwKPiArCQkuZmVhdHVyZSA9IFdJTl9G RUFUVVJFX0FGQkRDIHwgV0lOX0ZFQVRVUkVfQ0xVU1RFUiwKPiArCX0sCj4gK307Cj4gKwo+ICtz dGF0aWMgY29uc3Qgc3RydWN0IHZvcDJfZGF0YSByazM1NjZfdm9wID0gewo+ICsJLm5yX3ZwcyA9 IDMsCj4gKwkubnJfbWl4ZXJzID0gNSwKPiArCS5ucl9nYW1tYXMgPSAxLAo+ICsJLm1heF9pbnB1 dCA9IHsgNDA5NiwgMjMwNCB9LAo+ICsJLm1heF9vdXRwdXQgPSB7IDQwOTYsIDIzMDQgfSwKPiAr CS52cCA9IHJrMzU2OF92b3BfdmlkZW9fcG9ydHMsCj4gKwkud2luID0gcmszNTY4X3ZvcF93aW5f ZGF0YSwKPiArCS53aW5fc2l6ZSA9IEFSUkFZX1NJWkUocmszNTY4X3ZvcF93aW5fZGF0YSksCj4g Kwkuc29jX2lkID0gMzU2NiwKPiArfTsKPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgdm9wMl9k YXRhIHJrMzU2OF92b3AgPSB7Cj4gKwkubnJfdnBzID0gMywKPiArCS5ucl9taXhlcnMgPSA1LAo+ ICsJLm5yX2dhbW1hcyA9IDEsCj4gKwkubWF4X2lucHV0ID0geyA0MDk2LCAyMzA0IH0sCj4gKwku bWF4X291dHB1dCA9IHsgNDA5NiwgMjMwNCB9LAo+ICsJLnZwID0gcmszNTY4X3ZvcF92aWRlb19w b3J0cywKPiArCS53aW4gPSByazM1Njhfdm9wX3dpbl9kYXRhLAo+ICsJLndpbl9zaXplID0gQVJS QVlfU0laRShyazM1Njhfdm9wX3dpbl9kYXRhKSwKPiArCS5zb2NfaWQgPSAzNTY4LAo+ICt9Owo+ ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQgdm9wMl9kdF9tYXRjaFtdID0g ewo+ICsJewo+ICsJCS5jb21wYXRpYmxlID0gInJvY2tjaGlwLHJrMzU2Ni12b3AiLAo+ICsJCS5k YXRhID0gJnJrMzU2Nl92b3AsCj4gKwl9LCB7Cj4gKwkJLmNvbXBhdGlibGUgPSAicm9ja2NoaXAs cmszNTY4LXZvcCIsCj4gKwkJLmRhdGEgPSAmcmszNTY4X3ZvcCwKPiArCX0sIHsKPiArCX0sCj4g K307Cj4gK01PRFVMRV9ERVZJQ0VfVEFCTEUob2YsIHZvcDJfZHRfbWF0Y2gpOwo+ICsKPiArc3Rh dGljIGludCB2b3AyX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sKPiAr CXN0cnVjdCBkZXZpY2UgKmRldiA9ICZwZGV2LT5kZXY7Cj4gKwo+ICsJcmV0dXJuIGNvbXBvbmVu dF9hZGQoZGV2LCAmdm9wMl9jb21wb25lbnRfb3BzKTsKPiArfQo+ICsKPiArc3RhdGljIGludCB2 b3AyX3JlbW92ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+ICt7Cj4gKwljb21wb25l bnRfZGVsKCZwZGV2LT5kZXYsICZ2b3AyX2NvbXBvbmVudF9vcHMpOwo+ICsKPiArCXJldHVybiAw Owo+ICt9Cj4gKwo+ICtzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIHZvcDJfcGxhdGZvcm1fZHJpdmVy ID0gewo+ICsJLnByb2JlID0gdm9wMl9wcm9iZSwKPiArCS5yZW1vdmUgPSB2b3AyX3JlbW92ZSwK PiArCS5kcml2ZXIgPSB7Cj4gKwkJLm5hbWUgPSAicm9ja2NoaXAtdm9wMiIsCj4gKwkJLm9mX21h dGNoX3RhYmxlID0gb2ZfbWF0Y2hfcHRyKHZvcDJfZHRfbWF0Y2gpLAo+ICsJfSwKPiArfTsKCgoK X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KTGludXgtcm9j a2NoaXAgbWFpbGluZyBsaXN0CkxpbnV4LXJvY2tjaGlwQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0 cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1yb2NrY2hpcAo= 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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 61E2EC433F5 for ; Tue, 4 Jan 2022 11:14:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232049AbiADLOG (ORCPT ); Tue, 4 Jan 2022 06:14:06 -0500 Received: from regular1.263xmail.com ([211.150.70.204]:51332 "EHLO regular1.263xmail.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231834AbiADLOF (ORCPT ); Tue, 4 Jan 2022 06:14:05 -0500 X-Greylist: delayed 381 seconds by postgrey-1.27 at vger.kernel.org; Tue, 04 Jan 2022 06:14:03 EST Received: from localhost (unknown [192.168.167.16]) by regular1.263xmail.com (Postfix) with ESMTP id 58C5A503; Tue, 4 Jan 2022 19:07:25 +0800 (CST) X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-ADDR-CHECKED4: 1 X-SKE-CHECKED: 1 X-ABS-CHECKED: 1 X-ANTISPAM-LEVEL: 2 Received: from [172.16.12.89] (unknown [58.22.7.114]) by smtp.263.net (postfix) whith ESMTP id P12624T140276825810688S1641294444616683_; Tue, 04 Jan 2022 19:07:25 +0800 (CST) X-IP-DOMAINF: 1 X-RL-SENDER: andy.yan@rock-chips.com X-SENDER: yxj@rock-chips.com X-LOGIN-NAME: andy.yan@rock-chips.com X-FST-TO: kever.yang@rock-chips.com X-RCPT-COUNT: 12 X-LOCAL-RCPT-COUNT: 2 X-MUTI-DOMAIN-COUNT: 0 X-SENDER-IP: 58.22.7.114 X-ATTACHMENT-NUM: 0 X-UNIQUE-TAG: X-System-Flag: 0 Subject: Re: [PATCH 22/22] drm: rockchip: Add VOP2 driver To: Sascha Hauer , dri-devel@lists.freedesktop.org Cc: linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org, kernel@pengutronix.de, Benjamin Gaignard , Michael Riesch , Sandy Huang , =?UTF-8?Q?Heiko_St=c3=bcbner?= , Peter Geis , Kever Yang References: <20211220110630.3521121-1-s.hauer@pengutronix.de> <20211220110630.3521121-23-s.hauer@pengutronix.de> From: Andy Yan Message-ID: Date: Tue, 4 Jan 2022 19:07:23 +0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.14.0 MIME-Version: 1.0 In-Reply-To: <20211220110630.3521121-23-s.hauer@pengutronix.de> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Hi Sascha: Please add Series-version for all the patch series. add also Series-changes. I saw you have Series-changes in cover-letter, but we usually include them in patch. Here is a link you can take for reference[0] [0]https://source.denx.de/u-boot/u-boot/-/tree/master/tools/patman On 12/20/21 7:06 PM, Sascha Hauer wrote: > From: Andy Yan > > The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568. > It replaces the VOP unit found in the older Rockchip SoCs. > > This driver has been derived from the downstream Rockchip Kernel and > heavily modified: > > - All nonstandard DRM properties have been removed > - dropped struct vop2_plane_state and pass around less data between > functions > - Dropped all DRM_FORMAT_* not known on upstream > - rework register access to get rid of excessively used macros > - Drop all waiting for framesyncs > > The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB > board. Overlay support is tested with the modetest utility. AFBC support > on the cluster windows is tested with weston-simple-dmabuf-egl on > weston using the (yet to be upstreamed) panfrost driver support. > > Signed-off-by: Sascha Hauer > --- > drivers/gpu/drm/rockchip/Kconfig | 6 + > drivers/gpu/drm/rockchip/Makefile | 1 + > drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 1 + > drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 7 +- > drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 2 + > drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 15 + > drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 2768 ++++++++++++++++++ > drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 480 +++ > drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 285 ++ > 9 files changed, 3564 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > create mode 100644 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > > diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig > index b9b156308460a..4ff0043f0ee70 100644 > --- a/drivers/gpu/drm/rockchip/Kconfig > +++ b/drivers/gpu/drm/rockchip/Kconfig > @@ -28,6 +28,12 @@ config ROCKCHIP_VOP > This selects support for the VOP driver. You should enable it > on all older SoCs up to RK3399. > > +config ROCKCHIP_VOP2 > + bool "Rockchip VOP2 driver" > + help > + This selects support for the VOP2 driver. You should enable it > + on all newer SoCs beginning form RK3568. > + > config ROCKCHIP_ANALOGIX_DP > bool "Rockchip specific extensions for Analogix DP driver" > depends on ROCKCHIP_VOP > diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile > index cd6e7bb5ce9c5..29848caef5c21 100644 > --- a/drivers/gpu/drm/rockchip/Makefile > +++ b/drivers/gpu/drm/rockchip/Makefile > @@ -7,6 +7,7 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ > rockchip_drm_gem.o > rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o > > +rockchipdrm-$(CONFIG_ROCKCHIP_VOP2) += rockchip_drm_vop2.o rockchip_vop2_reg.o > rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o > rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o > rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c > index 64fa5fd62c01a..2bd9acb265e5a 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c > @@ -474,6 +474,7 @@ static int __init rockchip_drm_init(void) > > num_rockchip_sub_drivers = 0; > ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP); > + ADD_ROCKCHIP_SUB_DRIVER(vop2_platform_driver, CONFIG_ROCKCHIP_VOP2); > ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver, > CONFIG_ROCKCHIP_LVDS); > ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver, > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h > index aa0909e8edf93..fd6994f21817e 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h > @@ -18,7 +18,7 @@ > > #define ROCKCHIP_MAX_FB_BUFFER 3 > #define ROCKCHIP_MAX_CONNECTOR 2 > -#define ROCKCHIP_MAX_CRTC 2 > +#define ROCKCHIP_MAX_CRTC 4 > > struct drm_device; > struct drm_connector; > @@ -31,6 +31,9 @@ struct rockchip_crtc_state { > int output_bpc; > int output_flags; > bool enable_afbc; > + uint32_t bus_format; > + u32 bus_flags; > + int color_space; > }; > #define to_rockchip_crtc_state(s) \ > container_of(s, struct rockchip_crtc_state, base) > @@ -65,4 +68,6 @@ extern struct platform_driver rockchip_dp_driver; > extern struct platform_driver rockchip_lvds_driver; > extern struct platform_driver vop_platform_driver; > extern struct platform_driver rk3066_hdmi_driver; > +extern struct platform_driver vop2_platform_driver; > + > #endif /* _ROCKCHIP_DRM_DRV_H_ */ > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c > index 3aa37e177667e..0d2cb4f3922b8 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c > @@ -134,4 +134,6 @@ void rockchip_drm_mode_config_init(struct drm_device *dev) > > dev->mode_config.funcs = &rockchip_drm_mode_config_funcs; > dev->mode_config.helper_private = &rockchip_mode_config_helpers; > + > + dev->mode_config.normalize_zpos = true; > } > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h > index 857d97cdc67c6..1e364d7b50e69 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h > @@ -54,9 +54,23 @@ struct vop_afbc { > struct vop_reg enable; > struct vop_reg win_sel; > struct vop_reg format; > + struct vop_reg rb_swap; > + struct vop_reg uv_swap; > + struct vop_reg auto_gating_en; > + struct vop_reg block_split_en; > + struct vop_reg pic_vir_width; > + struct vop_reg tile_num; > struct vop_reg hreg_block_split; > + struct vop_reg pic_offset; > struct vop_reg pic_size; > + struct vop_reg dsp_offset; > + struct vop_reg transform_offset; > struct vop_reg hdr_ptr; > + struct vop_reg half_block_en; > + struct vop_reg xmirror; > + struct vop_reg ymirror; > + struct vop_reg rotate_270; > + struct vop_reg rotate_90; > struct vop_reg rstn; > }; > > @@ -410,4 +424,5 @@ static inline int scl_vop_cal_lb_mode(int width, bool is_yuv) > } > > extern const struct component_ops vop_component_ops; > + > #endif /* _ROCKCHIP_DRM_VOP_H */ > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > new file mode 100644 > index 0000000000000..7d39ba90061d1 > --- /dev/null > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > @@ -0,0 +1,2768 @@ > +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) > +/* > + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. > + * Author: Andy Yan > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include It seems that you removed the writeback code in the driver ? > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "rockchip_drm_drv.h" > +#include "rockchip_drm_gem.h" > +#include "rockchip_drm_fb.h" > +#include "rockchip_drm_vop2.h" > + > +/* > + * VOP2 architecture > + * > + +----------+ +-------------+ +-----------+ > + | Cluster | | Sel 1 from 6| | 1 from 3 | > + | window0 | | Layer0 | | RGB | > + +----------+ +-------------+ +---------------+ +-------------+ +-----------+ > + +----------+ +-------------+ |N from 6 layers| | | > + | Cluster | | Sel 1 from 6| | Overlay0 +--->| Video Port0 | +-----------+ > + | window1 | | Layer1 | | | | | | 1 from 3 | > + +----------+ +-------------+ +---------------+ +-------------+ | LVDS | > + +----------+ +-------------+ +-----------+ > + | Esmart | | Sel 1 from 6| > + | window0 | | Layer2 | +---------------+ +-------------+ +-----------+ > + +----------+ +-------------+ |N from 6 Layers| | | +--> | 1 from 3 | > + +----------+ +-------------+ --------> | Overlay1 +--->| Video Port1 | | MIPI | > + | Esmart | | Sel 1 from 6| --------> | | | | +-----------+ > + | Window1 | | Layer3 | +---------------+ +-------------+ > + +----------+ +-------------+ +-----------+ > + +----------+ +-------------+ | 1 from 3 | > + | Smart | | Sel 1 from 6| +---------------+ +-------------+ | HDMI | > + | Window0 | | Layer4 | |N from 6 Layers| | | +-----------+ > + +----------+ +-------------+ | Overlay2 +--->| Video Port2 | > + +----------+ +-------------+ | | | | +-----------+ > + | Smart | | Sel 1 from 6| +---------------+ +-------------+ | 1 from 3 | > + | Window1 | | Layer5 | | eDP | > + +----------+ +-------------+ +-----------+ > + * > + */ > + > +enum vop2_data_format { > + VOP2_FMT_ARGB8888 = 0, > + VOP2_FMT_RGB888, > + VOP2_FMT_RGB565, > + VOP2_FMT_XRGB101010, > + VOP2_FMT_YUV420SP, > + VOP2_FMT_YUV422SP, > + VOP2_FMT_YUV444SP, > + VOP2_FMT_YUYV422 = 8, > + VOP2_FMT_YUYV420, > + VOP2_FMT_VYUY422, > + VOP2_FMT_VYUY420, > + VOP2_FMT_YUV420SP_TILE_8x4 = 0x10, > + VOP2_FMT_YUV420SP_TILE_16x2, > + VOP2_FMT_YUV422SP_TILE_8x4, > + VOP2_FMT_YUV422SP_TILE_16x2, > + VOP2_FMT_YUV420SP_10, > + VOP2_FMT_YUV422SP_10, > + VOP2_FMT_YUV444SP_10, > +}; > + > +enum vop2_afbc_format { > + VOP2_AFBC_FMT_RGB565, > + VOP2_AFBC_FMT_ARGB2101010 = 2, > + VOP2_AFBC_FMT_YUV420_10BIT, > + VOP2_AFBC_FMT_RGB888, > + VOP2_AFBC_FMT_ARGB8888, > + VOP2_AFBC_FMT_YUV420 = 9, > + VOP2_AFBC_FMT_YUV422 = 0xb, > + VOP2_AFBC_FMT_YUV422_10BIT = 0xe, > + VOP2_AFBC_FMT_INVALID = -1, > +}; > + > +union vop2_alpha_ctrl { > + uint32_t val; > + struct { > + /* [0:1] */ > + uint32_t color_mode:1; > + uint32_t alpha_mode:1; > + /* [2:3] */ > + uint32_t blend_mode:2; > + uint32_t alpha_cal_mode:1; > + /* [5:7] */ > + uint32_t factor_mode:3; > + /* [8:9] */ > + uint32_t alpha_en:1; > + uint32_t src_dst_swap:1; > + uint32_t reserved:6; > + /* [16:23] */ > + uint32_t glb_alpha:8; > + } bits; > +}; > + > +struct vop2_alpha { > + union vop2_alpha_ctrl src_color_ctrl; > + union vop2_alpha_ctrl dst_color_ctrl; > + union vop2_alpha_ctrl src_alpha_ctrl; > + union vop2_alpha_ctrl dst_alpha_ctrl; > +}; > + > +struct vop2_alpha_config { > + bool src_premulti_en; > + bool dst_premulti_en; > + bool src_pixel_alpha_en; > + bool dst_pixel_alpha_en; > + uint16_t src_glb_alpha_value; > + uint16_t dst_glb_alpha_value; > +}; > + > +struct vop2_win { > + struct vop2 *vop2; > + struct drm_plane base; > + const struct vop2_win_data *data; > + struct regmap_field *reg[VOP2_WIN_MAX_REG]; > + > + /** > + * @win_id: graphic window id, a cluster maybe split into two > + * graphics windows. > + */ > + uint8_t win_id; > + > + uint32_t offset; > + > + uint8_t delay; > + enum drm_plane_type type; > +}; > + > +struct vop2_video_port { > + struct drm_crtc crtc; > + struct vop2 *vop2; > + struct clk *dclk; > + uint8_t id; > + const struct vop2_video_port_regs *regs; > + const struct vop2_video_port_data *data; > + > + struct completion dsp_hold_completion; > + > + /** > + * @win_mask: Bitmask of wins attached to the video port; > + */ > + uint32_t win_mask; > + > + struct vop2_win *primary_plane; > + struct drm_pending_vblank_event *event; > + > + int nlayers; > +}; > + > +struct vop2 { > + struct device *dev; > + struct drm_device *drm; > + struct vop2_video_port vps[ROCKCHIP_MAX_CRTC]; > + > + const struct vop2_data *data; > + /* Number of win that registered as plane, > + * maybe less than the total number of hardware > + * win. > + */ > + uint32_t registered_num_wins; > + > + void __iomem *regs; > + struct regmap *map; > + > + struct regmap *grf; > + > + /* physical map length of vop2 register */ > + uint32_t len; > + > + void __iomem *lut_regs; > + /* one time only one process allowed to config the register */ > + spinlock_t reg_lock; > + > + /* protects crtc enable/disable */ > + struct mutex vop2_lock; > + > + int irq; > + > + /* > + * Some globle resource are shared between all > + * the vidoe ports(crtcs), so we need a ref counter here. > + */ > + unsigned int enable_count; > + struct clk *hclk; > + struct clk *aclk; > + > + /* must put at the end of the struct */ > + struct vop2_win win[]; > +}; > + > +static struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc) > +{ > + return container_of(crtc, struct vop2_video_port, crtc); > +} > + > +static struct vop2_win *to_vop2_win(struct drm_plane *p) > +{ > + return container_of(p, struct vop2_win, base); > +} > + > +static void vop2_lock(struct vop2 *vop2) > +{ > + mutex_lock(&vop2->vop2_lock); > +} > + > +static void vop2_unlock(struct vop2 *vop2) > +{ > + mutex_unlock(&vop2->vop2_lock); > +} > + > +static void vop2_writel(struct vop2 *vop2, uint32_t offset, uint32_t v) > +{ > + regmap_write(vop2->map, offset, v); > +} > + > +static void vop2_vp_write(struct vop2_video_port *vp, uint32_t offset, > + uint32_t v) > +{ > + regmap_write(vp->vop2->map, vp->data->offset + offset, v); > +} > + > +static uint32_t vop2_readl(struct vop2 *vop2, uint32_t offset) > +{ > + uint32_t val; > + > + regmap_read(vop2->map, offset, &val); > + > + return val; > +} > + > +static void vop2_win_write(const struct vop2_win *win, unsigned int reg, > + uint32_t v) > +{ > + regmap_field_write(win->reg[reg], v); > +} > + > +static bool vop2_cluster_window(const struct vop2_win *win) > +{ > + return win->data->feature & WIN_FEATURE_CLUSTER; > +} > + > +static void vop2_cfg_done(struct vop2_video_port *vp) > +{ > + struct vop2 *vop2 = vp->vop2; > + uint32_t val; > + > + val = vop2_readl(vop2, RK3568_REG_CFG_DONE); > + > + val &= 0x7; > + > + vop2_writel(vop2, RK3568_REG_CFG_DONE, > + val | BIT(vp->id) | RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN); > +} > + > +static void vop2_win_disable(struct vop2_win *win) > +{ > + vop2_win_write(win, VOP2_WIN_ENABLE, 0); > + > + if (vop2_cluster_window(win)) > + vop2_win_write(win, VOP2_WIN_CLUSTER_ENABLE, 0); > +} > + > +static enum vop2_data_format vop2_convert_format(uint32_t format) > +{ > + switch (format) { > + case DRM_FORMAT_XRGB8888: > + case DRM_FORMAT_ARGB8888: > + case DRM_FORMAT_XBGR8888: > + case DRM_FORMAT_ABGR8888: > + return VOP2_FMT_ARGB8888; > + case DRM_FORMAT_RGB888: > + case DRM_FORMAT_BGR888: > + return VOP2_FMT_RGB888; > + case DRM_FORMAT_RGB565: > + case DRM_FORMAT_BGR565: > + return VOP2_FMT_RGB565; > + case DRM_FORMAT_NV12: > + return VOP2_FMT_YUV420SP; > + case DRM_FORMAT_NV16: > + return VOP2_FMT_YUV422SP; > + case DRM_FORMAT_NV24: > + return VOP2_FMT_YUV444SP; > + case DRM_FORMAT_YUYV: > + case DRM_FORMAT_YVYU: > + return VOP2_FMT_VYUY422; > + case DRM_FORMAT_VYUY: > + case DRM_FORMAT_UYVY: > + return VOP2_FMT_YUYV422; > + default: > + DRM_ERROR("unsupported format[%08x]\n", format); > + return -EINVAL; > + } > +} > + > +static enum vop2_afbc_format vop2_convert_afbc_format(uint32_t format) > +{ > + switch (format) { > + case DRM_FORMAT_XRGB8888: > + case DRM_FORMAT_ARGB8888: > + case DRM_FORMAT_XBGR8888: > + case DRM_FORMAT_ABGR8888: > + return VOP2_AFBC_FMT_ARGB8888; > + case DRM_FORMAT_RGB888: > + case DRM_FORMAT_BGR888: > + return VOP2_AFBC_FMT_RGB888; > + case DRM_FORMAT_RGB565: > + case DRM_FORMAT_BGR565: > + return VOP2_AFBC_FMT_RGB565; > + case DRM_FORMAT_NV12: > + return VOP2_AFBC_FMT_YUV420; > + case DRM_FORMAT_NV16: > + return VOP2_AFBC_FMT_YUV422; > + default: > + return VOP2_AFBC_FMT_INVALID; > + } > + > + return VOP2_AFBC_FMT_INVALID; > +} > + > +static bool vop2_win_rb_swap(uint32_t format) > +{ > + switch (format) { > + case DRM_FORMAT_XBGR8888: > + case DRM_FORMAT_ABGR8888: > + case DRM_FORMAT_BGR888: > + case DRM_FORMAT_BGR565: > + return true; > + default: > + return false; > + } > +} > + > +static bool vop2_afbc_rb_swap(uint32_t format) > +{ > + switch (format) { > + case DRM_FORMAT_NV24: > + return true; > + default: > + return false; > + } > +} > + > +static bool vop2_afbc_uv_swap(uint32_t format) > +{ > + switch (format) { > + case DRM_FORMAT_NV12: > + case DRM_FORMAT_NV16: > + return true; > + default: > + return false; > + } > +} > + > +static bool vop2_win_uv_swap(uint32_t format) > +{ > + switch (format) { > + case DRM_FORMAT_NV12: > + case DRM_FORMAT_NV16: > + case DRM_FORMAT_NV24: > + return true; > + default: > + return false; > + } > +} > + > +static bool vop2_win_dither_up(uint32_t format) > +{ > + switch (format) { > + case DRM_FORMAT_BGR565: > + case DRM_FORMAT_RGB565: > + return true; > + default: > + return false; > + } > +} > + > +static bool vop2_output_uv_swap(uint32_t bus_format, uint32_t output_mode) > +{ > + /* > + * FIXME: > + * > + * There is no media type for YUV444 output, > + * so when out_mode is AAAA or P888, assume output is YUV444 on > + * yuv format. > + * > + * From H/W testing, YUV444 mode need a rb swap. > + */ > + if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 || > + bus_format == MEDIA_BUS_FMT_VYUY8_1X16 || > + bus_format == MEDIA_BUS_FMT_YVYU8_2X8 || > + bus_format == MEDIA_BUS_FMT_VYUY8_2X8 || > + ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || > + bus_format == MEDIA_BUS_FMT_YUV10_1X30) && > + (output_mode == ROCKCHIP_OUT_MODE_AAAA || > + output_mode == ROCKCHIP_OUT_MODE_P888))) > + return true; > + else > + return false; > +} > + > +static bool is_yuv_output(uint32_t bus_format) > +{ > + switch (bus_format) { > + case MEDIA_BUS_FMT_YUV8_1X24: > + case MEDIA_BUS_FMT_YUV10_1X30: > + case MEDIA_BUS_FMT_UYYVYY8_0_5X24: > + case MEDIA_BUS_FMT_UYYVYY10_0_5X30: > + case MEDIA_BUS_FMT_YUYV8_2X8: > + case MEDIA_BUS_FMT_YVYU8_2X8: > + case MEDIA_BUS_FMT_UYVY8_2X8: > + case MEDIA_BUS_FMT_VYUY8_2X8: > + case MEDIA_BUS_FMT_YUYV8_1X16: > + case MEDIA_BUS_FMT_YVYU8_1X16: > + case MEDIA_BUS_FMT_UYVY8_1X16: > + case MEDIA_BUS_FMT_VYUY8_1X16: > + return true; > + default: > + return false; > + } > +} > + > +static bool rockchip_afbc(struct drm_plane *plane, u64 modifier) > +{ > + int i; > + > + if (modifier == DRM_FORMAT_MOD_LINEAR) > + return false; > + > + for (i = 0 ; i < plane->modifier_count; i++) > + if (plane->modifiers[i] == modifier) > + break; > + > + return (i < plane->modifier_count) ? true : false; > + > +} > + > +static bool rockchip_vop2_mod_supported(struct drm_plane *plane, uint32_t format, u64 modifier) > +{ > + struct vop2_win *win = to_vop2_win(plane); > + struct vop2 *vop2 = win->vop2; > + > + if (modifier == DRM_FORMAT_MOD_INVALID) > + return false; > + > + if (modifier == DRM_FORMAT_MOD_LINEAR) > + return true; > + > + if (!rockchip_afbc(plane, modifier)) { > + drm_err(vop2->drm, "Unsupported format modifier 0x%llx\n", modifier); > + > + return false; > + } > + > + return vop2_convert_afbc_format(format) >= 0; > +} > + > +static int vop2_afbc_half_block_enable(struct drm_plane_state *pstate) > +{ > + if ((pstate->rotation & DRM_MODE_ROTATE_270) || (pstate->rotation & DRM_MODE_ROTATE_90)) > + return 0; > + else > + return 1; > +} > + > +static uint32_t vop2_afbc_transform_offset(struct drm_plane_state *pstate, > + bool afbc_half_block_en) > +{ > + struct drm_rect *src = &pstate->src; > + struct drm_framebuffer *fb = pstate->fb; > + uint32_t bpp = fb->format->cpp[0] * 8; > + uint32_t vir_width = (fb->pitches[0] << 3) / bpp; > + uint32_t width = drm_rect_width(src) >> 16; > + uint32_t height = drm_rect_height(src) >> 16; > + uint32_t act_xoffset = src->x1 >> 16; > + uint32_t act_yoffset = src->y1 >> 16; > + uint32_t align16_crop = 0; > + uint32_t align64_crop = 0; > + uint32_t height_tmp = 0; > + uint32_t transform_tmp = 0; > + uint8_t transform_xoffset = 0; > + uint8_t transform_yoffset = 0; > + uint8_t top_crop = 0; > + uint8_t top_crop_line_num = 0; > + uint8_t bottom_crop_line_num = 0; > + > + /* 16 pixel align */ > + if (height & 0xf) > + align16_crop = 16 - (height & 0xf); > + > + height_tmp = height + align16_crop; > + > + /* 64 pixel align */ > + if (height_tmp & 0x3f) > + align64_crop = 64 - (height_tmp & 0x3f); > + > + top_crop_line_num = top_crop << 2; > + if (top_crop == 0) > + bottom_crop_line_num = align16_crop + align64_crop; > + else if (top_crop == 1) > + bottom_crop_line_num = align16_crop + align64_crop + 12; > + else if (top_crop == 2) > + bottom_crop_line_num = align16_crop + align64_crop + 8; > + > + switch (pstate->rotation & > + (DRM_MODE_REFLECT_X | > + DRM_MODE_REFLECT_Y | > + DRM_MODE_ROTATE_90 | > + DRM_MODE_ROTATE_270)) { > + case DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y: > + transform_tmp = act_xoffset + width; > + transform_xoffset = 16 - (transform_tmp & 0xf); > + transform_tmp = bottom_crop_line_num - act_yoffset; > + > + if (afbc_half_block_en) > + transform_yoffset = transform_tmp & 0x7; > + else > + transform_yoffset = (transform_tmp & 0xf); > + > + break; > + case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90: > + transform_tmp = bottom_crop_line_num - act_yoffset; > + transform_xoffset = transform_tmp & 0xf; > + transform_tmp = vir_width - width - act_xoffset; > + transform_yoffset = transform_tmp & 0xf; > + break; > + case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_270: > + transform_tmp = top_crop_line_num + act_yoffset; > + transform_xoffset = transform_tmp & 0xf; > + transform_tmp = act_xoffset; > + transform_yoffset = transform_tmp & 0xf; > + break; > + case DRM_MODE_REFLECT_X: > + transform_tmp = act_xoffset + width; > + transform_xoffset = 16 - (transform_tmp & 0xf); > + transform_tmp = top_crop_line_num + act_yoffset; > + > + if (afbc_half_block_en) > + transform_yoffset = transform_tmp & 0x7; > + else > + transform_yoffset = transform_tmp & 0xf; > + > + break; > + case DRM_MODE_REFLECT_Y: > + transform_tmp = act_xoffset; > + transform_xoffset = transform_tmp & 0xf; > + transform_tmp = bottom_crop_line_num - act_yoffset; > + > + if (afbc_half_block_en) > + transform_yoffset = transform_tmp & 0x7; > + else > + transform_yoffset = transform_tmp & 0xf; > + > + break; > + case DRM_MODE_ROTATE_90: > + transform_tmp = bottom_crop_line_num - act_yoffset; > + transform_xoffset = transform_tmp & 0xf; > + transform_tmp = act_xoffset; > + transform_yoffset = transform_tmp & 0xf; > + break; > + case DRM_MODE_ROTATE_270: > + transform_tmp = top_crop_line_num + act_yoffset; > + transform_xoffset = transform_tmp & 0xf; > + transform_tmp = vir_width - width - act_xoffset; > + transform_yoffset = transform_tmp & 0xf; > + break; > + case 0: > + transform_tmp = act_xoffset; > + transform_xoffset = transform_tmp & 0xf; > + transform_tmp = top_crop_line_num + act_yoffset; > + > + if (afbc_half_block_en) > + transform_yoffset = transform_tmp & 0x7; > + else > + transform_yoffset = transform_tmp & 0xf; > + > + break; > + } > + > + return (transform_xoffset & 0xf) | ((transform_yoffset & 0xf) << 16); > +} > + > +/* > + * A Cluster window has 2048 x 16 line buffer, which can > + * works at 2048 x 16(Full) or 4096 x 8 (Half) mode. > + * for Cluster_lb_mode register: > + * 0: half mode, for plane input width range 2048 ~ 4096 > + * 1: half mode, for cluster work at 2 * 2048 plane mode > + * 2: half mode, for rotate_90/270 mode > + * > + */ > +static int vop2_get_cluster_lb_mode(struct vop2_win *win, struct drm_plane_state *pstate) > +{ > + if ((pstate->rotation & DRM_MODE_ROTATE_270) || (pstate->rotation & DRM_MODE_ROTATE_90)) > + return 2; > + else > + return 0; > +} > + > +/* > + * bli_sd_factor = (src - 1) / (dst - 1) << 12; > + * avg_sd_factor: > + * bli_su_factor: > + * bic_su_factor: > + * = (src - 1) / (dst - 1) << 16; > + * > + * gt2 enable: dst get one line from two line of the src > + * gt4 enable: dst get one line from four line of the src. > + * > + */ > +static uint16_t vop2_scale_factor(enum scale_mode mode, > + int32_t filter_mode, > + uint32_t src, uint32_t dst) > +{ > + uint32_t fac; > + int i; > + > + if (mode == SCALE_NONE) > + return 0; > + > + /* > + * A workaround to avoid zero div. > + */ > + if (dst == 1 || src == 1) { > + dst++; > + src++; > + } > + > + if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) { > + fac = ((src - 1) << 12) / (dst - 1); > + for (i = 0; i < 100; i++) { > + if (fac * (dst - 1) >> 12 < (src - 1)) > + break; > + fac -= 1; > + DRM_DEBUG("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); > + } > + } else { > + fac = ((src - 1) << 16) / (dst - 1); > + for (i = 0; i < 100; i++) { > + if (fac * (dst - 1) >> 16 < (src - 1)) > + break; > + fac -= 1; > + DRM_DEBUG("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); > + } > + } > + > + return fac; > +} > + > +static void vop2_setup_scale(struct vop2 *vop2, const struct vop2_win *win, > + uint32_t src_w, uint32_t src_h, uint32_t dst_w, > + uint32_t dst_h, uint32_t pixel_format) > +{ > + const struct drm_format_info *info; > + uint16_t cbcr_src_w; > + uint16_t cbcr_src_h; > + uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode; > + uint16_t cbcr_hor_scl_mode, cbcr_ver_scl_mode; > + uint16_t hscl_filter_mode, vscl_filter_mode; > + uint8_t gt2 = 0; > + uint8_t gt4 = 0; > + uint32_t val; > + > + info = drm_format_info(pixel_format); > + > + cbcr_src_w = src_w / info->hsub; > + cbcr_src_h = src_h / info->vsub; > + > + if (src_h >= (4 * dst_h)) { > + gt4 = 1; > + src_h >>= 2; > + } else if (src_h >= (2 * dst_h)) { > + gt2 = 1; > + src_h >>= 1; > + } > + > + yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w); > + yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h); > + > + if (yrgb_hor_scl_mode == SCALE_UP) > + hscl_filter_mode = VOP2_SCALE_UP_BIC; > + else > + hscl_filter_mode = VOP2_SCALE_DOWN_BIL; > + > + if (yrgb_ver_scl_mode == SCALE_UP) > + vscl_filter_mode = VOP2_SCALE_UP_BIL; > + else > + vscl_filter_mode = VOP2_SCALE_DOWN_BIL; > + > + /* > + * RK3568 VOP Esmart/Smart dsp_w should be even pixel > + * at scale down mode > + */ > + if (!(win->data->feature & WIN_FEATURE_AFBDC)) { > + if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1)) { > + drm_dbg(vop2->drm, "%s dst_w[%d] should align as 2 pixel\n", > + win->data->name, dst_w); > + dst_w += 1; > + } > + } > + > + val = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, > + src_w, dst_w); > + vop2_win_write(win, VOP2_WIN_SCALE_YRGB_X, val); > + val = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, > + src_h, dst_h); > + vop2_win_write(win, VOP2_WIN_SCALE_YRGB_Y, val); > + > + vop2_win_write(win, VOP2_WIN_VSD_YRGB_GT4, gt4); > + vop2_win_write(win, VOP2_WIN_VSD_YRGB_GT2, gt2); > + > + vop2_win_write(win, VOP2_WIN_YRGB_HOR_SCL_MODE, yrgb_hor_scl_mode); > + vop2_win_write(win, VOP2_WIN_YRGB_VER_SCL_MODE, yrgb_ver_scl_mode); > + > + if (vop2_cluster_window(win)) > + return; > + > + vop2_win_write(win, VOP2_WIN_YRGB_HSCL_FILTER_MODE, hscl_filter_mode); > + vop2_win_write(win, VOP2_WIN_YRGB_VSCL_FILTER_MODE, vscl_filter_mode); > + > + if (info->is_yuv) { > + gt4 = gt2 = 0; > + > + if (cbcr_src_h >= (4 * dst_h)) > + gt4 = 1; > + else if (cbcr_src_h >= (2 * dst_h)) > + gt2 = 1; > + > + if (gt4) > + cbcr_src_h >>= 2; > + else if (gt2) > + cbcr_src_h >>= 1; > + > + cbcr_hor_scl_mode = scl_get_scl_mode(cbcr_src_w, dst_w); > + cbcr_ver_scl_mode = scl_get_scl_mode(cbcr_src_h, dst_h); > + > + val = vop2_scale_factor(cbcr_hor_scl_mode, hscl_filter_mode, > + cbcr_src_w, dst_w); > + vop2_win_write(win, VOP2_WIN_SCALE_CBCR_X, val); > + > + val = vop2_scale_factor(cbcr_ver_scl_mode, vscl_filter_mode, > + cbcr_src_h, dst_h); > + vop2_win_write(win, VOP2_WIN_SCALE_CBCR_Y, val); > + > + vop2_win_write(win, VOP2_WIN_VSD_CBCR_GT4, gt4); > + vop2_win_write(win, VOP2_WIN_VSD_CBCR_GT2, gt2); > + vop2_win_write(win, VOP2_WIN_CBCR_HOR_SCL_MODE, cbcr_hor_scl_mode); > + vop2_win_write(win, VOP2_WIN_CBCR_VER_SCL_MODE, cbcr_ver_scl_mode); > + vop2_win_write(win, VOP2_WIN_CBCR_HSCL_FILTER_MODE, hscl_filter_mode); > + vop2_win_write(win, VOP2_WIN_CBCR_VSCL_FILTER_MODE, vscl_filter_mode); > + } > +} > + > +static int vop2_convert_csc_mode(int csc_mode) > +{ > + switch (csc_mode) { > + case V4L2_COLORSPACE_SMPTE170M: > + case V4L2_COLORSPACE_470_SYSTEM_M: > + case V4L2_COLORSPACE_470_SYSTEM_BG: > + return CSC_BT601L; > + case V4L2_COLORSPACE_REC709: > + case V4L2_COLORSPACE_SMPTE240M: > + case V4L2_COLORSPACE_DEFAULT: > + return CSC_BT709L; > + case V4L2_COLORSPACE_JPEG: > + return CSC_BT601F; > + case V4L2_COLORSPACE_BT2020: > + return CSC_BT2020; > + default: > + return CSC_BT709L; > + } > +} > + > +/* > + * colorspace path: > + * Input Win csc Output > + * 1. YUV(2020) --> Y2R->2020To709->R2Y --> YUV_OUTPUT(601/709) > + * RGB --> R2Y __/ > + * > + * 2. YUV(2020) --> bypasss --> YUV_OUTPUT(2020) > + * RGB --> 709To2020->R2Y __/ > + * > + * 3. YUV(2020) --> Y2R->2020To709 --> RGB_OUTPUT(709) > + * RGB --> R2Y __/ > + * > + * 4. YUV(601/709)-> Y2R->709To2020->R2Y --> YUV_OUTPUT(2020) > + * RGB --> 709To2020->R2Y __/ > + * > + * 5. YUV(601/709)-> bypass --> YUV_OUTPUT(709) > + * RGB --> R2Y __/ > + * > + * 6. YUV(601/709)-> bypass --> YUV_OUTPUT(601) > + * RGB --> R2Y(601) __/ > + * > + * 7. YUV --> Y2R(709) --> RGB_OUTPUT(709) > + * RGB --> bypass __/ > + * > + * 8. RGB --> 709To2020->R2Y --> YUV_OUTPUT(2020) > + * > + * 9. RGB --> R2Y(709) --> YUV_OUTPUT(709) > + * > + * 10. RGB --> R2Y(601) --> YUV_OUTPUT(601) > + * > + * 11. RGB --> bypass --> RGB_OUTPUT(709) > + */ > + > +static void vop2_setup_csc_mode(struct vop2_video_port *vp, > + struct vop2_win *win, > + struct drm_plane_state *pstate) > +{ > + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); > + int is_input_yuv = pstate->fb->format->is_yuv; > + int is_output_yuv = is_yuv_output(vcstate->bus_format); > + int input_csc = V4L2_COLORSPACE_DEFAULT; > + int output_csc = vcstate->color_space; > + bool r2y_en, y2r_en; > + int csc_mode; > + > + if (is_input_yuv && !is_output_yuv) { > + y2r_en = 1; > + r2y_en = 0; > + csc_mode = vop2_convert_csc_mode(input_csc); > + } else if (!is_input_yuv && is_output_yuv) { > + y2r_en = 0; > + r2y_en = 1; > + csc_mode = vop2_convert_csc_mode(output_csc); > + } else { > + y2r_en = 0; > + r2y_en = 0; > + csc_mode = 0; > + } > + > + vop2_win_write(win, VOP2_WIN_Y2R_EN, y2r_en); > + vop2_win_write(win, VOP2_WIN_R2Y_EN, r2y_en); > + vop2_win_write(win, VOP2_WIN_CSC_MODE, csc_mode); > +} > + > +static void vop2_crtc_enable_irq(struct vop2_video_port *vp, uint32_t irq) > +{ > + struct vop2 *vop2 = vp->vop2; > + > + vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irq << 16 | irq); > + vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16 | irq); > +} > + > +static void vop2_crtc_disable_irq(struct vop2_video_port *vp, uint32_t irq) > +{ > + struct vop2 *vop2 = vp->vop2; > + > + vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16); > +} > + > +static int vop2_core_clks_prepare_enable(struct vop2 *vop2) > +{ > + int ret; > + > + ret = clk_prepare_enable(vop2->hclk); > + if (ret < 0) { > + drm_err(vop2->drm, "failed to enable hclk - %d\n", ret); > + return ret; > + } > + > + ret = clk_prepare_enable(vop2->aclk); > + if (ret < 0) { > + drm_err(vop2->drm, "failed to enable aclk - %d\n", ret); > + goto err; > + } > + > + return 0; > +err: > + clk_disable_unprepare(vop2->hclk); > + > + return ret; > +} > + > +static void vop2_enable(struct vop2 *vop2) > +{ > + int ret; > + uint32_t v; > + > + ret = pm_runtime_get_sync(vop2->dev); > + if (ret < 0) { > + drm_err(vop2->drm, "failed to get pm runtime: %d\n", ret); > + return; > + } > + > + ret = vop2_core_clks_prepare_enable(vop2); > + if (ret) { > + pm_runtime_put_sync(vop2->dev); > + return; > + } > + > + if (vop2->data->soc_id == 3566) > + vop2_writel(vop2, RK3568_OTP_WIN_EN, 1); > + > + vop2_writel(vop2, RK3568_REG_CFG_DONE, RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN); > + > + /* > + * Disable auto gating, this is a workaround to > + * avoid display image shift when a window enabled. > + */ > + v = vop2_readl(vop2, RK3568_SYS_AUTO_GATING_CTRL); > + v &= ~RK3568_SYS_AUTO_GATING_CTRL__AUTO_GATING_EN; > + vop2_writel(vop2, RK3568_SYS_AUTO_GATING_CTRL, v); > + > + vop2_writel(vop2, RK3568_SYS0_INT_CLR, > + VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR); > + vop2_writel(vop2, RK3568_SYS0_INT_EN, > + VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR); > + vop2_writel(vop2, RK3568_SYS1_INT_CLR, > + VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR); > + vop2_writel(vop2, RK3568_SYS1_INT_EN, > + VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR); > +} > + > +static void vop2_disable(struct vop2 *vop2) > +{ > + pm_runtime_put_sync(vop2->dev); > + > + clk_disable_unprepare(vop2->aclk); > + clk_disable_unprepare(vop2->hclk); > +} > + > +static void vop2_crtc_atomic_disable(struct drm_crtc *crtc, > + struct drm_atomic_state *state) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct vop2 *vop2 = vp->vop2; > + int ret; > + > + vop2_lock(vop2); > + > + drm_crtc_vblank_off(crtc); > + > + /* > + * Vop standby will take effect at end of current frame, > + * if dsp hold valid irq happen, it means standby complete. > + * > + * we must wait standby complete when we want to disable aclk, > + * if not, memory bus maybe dead. > + */ > + reinit_completion(&vp->dsp_hold_completion); > + > + vop2_crtc_enable_irq(vp, VP_INT_DSP_HOLD_VALID); > + spin_lock(&vop2->reg_lock); > + > + vop2_writel(vop2, RK3568_VP_DSP_CTRL, 1); > + > + spin_unlock(&vop2->reg_lock); > + > + ret = wait_for_completion_timeout(&vp->dsp_hold_completion, msecs_to_jiffies(50)); > + if (!ret) > + drm_info(vop2->drm, "wait for vp%d dsp_hold timeout\n", vp->id); > + > + vop2_crtc_disable_irq(vp, VP_INT_DSP_HOLD_VALID); > + > + clk_disable_unprepare(vp->dclk); > + > + vop2->enable_count--; > + > + if (!vop2->enable_count) > + vop2_disable(vop2); > + > + vop2_unlock(vop2); > + > + if (crtc->state->event && !crtc->state->active) { > + spin_lock_irq(&crtc->dev->event_lock); > + drm_crtc_send_vblank_event(crtc, crtc->state->event); > + spin_unlock_irq(&crtc->dev->event_lock); > + > + crtc->state->event = NULL; > + } > +} > + > +static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_state *astate) > +{ > + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(astate, plane); > + struct drm_framebuffer *fb = pstate->fb; > + struct drm_crtc *crtc = pstate->crtc; > + struct drm_crtc_state *cstate; > + struct vop2_video_port *vp; > + struct vop2 *vop2; > + const struct vop2_data *vop2_data; > + struct drm_rect *dest = &pstate->dst; > + struct drm_rect *src = &pstate->src; > + int min_scale = FRAC_16_16(1, 8); > + int max_scale = FRAC_16_16(8, 1); > + int format; > + int ret; > + > + if (!crtc) > + return 0; > + > + vp = to_vop2_video_port(crtc); > + vop2 = vp->vop2; > + vop2_data = vop2->data; > + > + cstate = drm_atomic_get_existing_crtc_state(pstate->state, crtc); > + if (WARN_ON(!cstate)) > + return -EINVAL; > + > + ret = drm_atomic_helper_check_plane_state(pstate, cstate, > + min_scale, max_scale, > + true, true); > + if (ret) > + return ret; > + > + if (!pstate->visible) > + return 0; > + > + format = vop2_convert_format(fb->format->format); > + if (format < 0) > + return format; > + > + if (drm_rect_width(src) >> 16 < 4 || drm_rect_height(src) >> 16 < 4 || > + drm_rect_width(dest) < 4 || drm_rect_width(dest) < 4) { > + drm_err(vop2->drm, "Invalid size: %dx%d->%dx%d, min size is 4x4\n", > + drm_rect_width(src) >> 16, drm_rect_height(src) >> 16, > + drm_rect_width(dest), drm_rect_height(dest)); > + pstate->visible = false; > + return 0; > + } > + > + if (drm_rect_width(src) >> 16 > vop2_data->max_input.width || > + drm_rect_height(src) >> 16 > vop2_data->max_input.height) { > + drm_err(vop2->drm, "Invalid source: %dx%d. max input: %dx%d\n", > + drm_rect_width(src) >> 16, > + drm_rect_height(src) >> 16, > + vop2_data->max_input.width, > + vop2_data->max_input.height); > + return -EINVAL; > + } > + > + /* > + * Src.x1 can be odd when do clip, but yuv plane start point > + * need align with 2 pixel. > + */ > + if (fb->format->is_yuv && ((pstate->src.x1 >> 16) % 2)) { > + drm_err(vop2->drm, "Invalid Source: Yuv format not support odd xpos\n"); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static void vop2_plane_atomic_disable(struct drm_plane *plane, struct drm_atomic_state *state) > +{ > + struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(state, plane); > + struct vop2_win *win = to_vop2_win(plane); > + struct vop2 *vop2 = win->vop2; > + > + drm_dbg(vop2->drm, "%s disable\n", win->data->name); > + > + if (!old_pstate->crtc) > + return; > + > + spin_lock(&vop2->reg_lock); > + > + vop2_win_disable(win); > + vop2_win_write(win, VOP2_WIN_YUV_CLIP, 0); > + > + spin_unlock(&vop2->reg_lock); > +} > + > +/* > + * The color key is 10 bit, so all format should > + * convert to 10 bit here. > + */ > +static void vop2_plane_setup_color_key(struct drm_plane *plane, uint32_t color_key) > +{ > + struct drm_plane_state *pstate = plane->state; > + struct drm_framebuffer *fb = pstate->fb; > + struct vop2_win *win = to_vop2_win(plane); > + uint32_t color_key_en = 0; > + uint32_t r = 0; > + uint32_t g = 0; > + uint32_t b = 0; > + > + if (!(color_key & VOP2_COLOR_KEY_MASK) || fb->format->is_yuv) { > + vop2_win_write(win, VOP2_WIN_COLOR_KEY_EN, 0); > + return; > + } > + > + switch (fb->format->format) { > + case DRM_FORMAT_RGB565: > + case DRM_FORMAT_BGR565: > + r = (color_key & 0xf800) >> 11; > + g = (color_key & 0x7e0) >> 5; > + b = (color_key & 0x1f); > + r <<= 5; > + g <<= 4; > + b <<= 5; > + color_key_en = 1; > + break; > + case DRM_FORMAT_XRGB8888: > + case DRM_FORMAT_ARGB8888: > + case DRM_FORMAT_XBGR8888: > + case DRM_FORMAT_ABGR8888: > + case DRM_FORMAT_RGB888: > + case DRM_FORMAT_BGR888: > + r = (color_key & 0xff0000) >> 16; > + g = (color_key & 0xff00) >> 8; > + b = (color_key & 0xff); > + r <<= 2; > + g <<= 2; > + b <<= 2; > + color_key_en = 1; > + break; > + } > + > + vop2_win_write(win, VOP2_WIN_COLOR_KEY_EN, color_key_en); > + vop2_win_write(win, VOP2_WIN_COLOR_KEY, (r << 20) | (g << 10) | b); > +} > + > +static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_atomic_state *state) > +{ > + struct drm_plane_state *pstate = plane->state; > + struct drm_crtc *crtc = pstate->crtc; > + struct vop2_win *win = to_vop2_win(plane); > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; > + struct vop2 *vop2 = win->vop2; > + struct drm_framebuffer *fb = pstate->fb; > + uint32_t bpp = fb->format->cpp[0] * 8; > + uint32_t actual_w, actual_h, dsp_w, dsp_h; > + uint32_t act_info, dsp_info; > + uint32_t format; > + uint32_t afbc_format; > + uint32_t rb_swap; > + uint32_t uv_swap; > + struct drm_rect *src = &pstate->src; > + struct drm_rect *dest = &pstate->dst; > + uint32_t afbc_tile_num; > + uint32_t afbc_half_block_en; > + uint32_t transform_offset; > + bool dither_up; > + bool xmirror = pstate->rotation & DRM_MODE_REFLECT_X; > + bool ymirror = pstate->rotation & DRM_MODE_REFLECT_Y; > + bool rotate_270 = pstate->rotation & DRM_MODE_ROTATE_270; > + bool rotate_90 = pstate->rotation & DRM_MODE_ROTATE_90; > + struct rockchip_gem_object *rk_obj; > + unsigned long offset; > + bool afbc_en; > + dma_addr_t yrgb_mst; > + dma_addr_t uv_mst; > + > + /* > + * can't update plane when vop2 is disabled. > + */ > + if (WARN_ON(!crtc)) > + return; > + > + if (!pstate->visible) { > + vop2_plane_atomic_disable(plane, state); > + return; > + } > + > + afbc_en = rockchip_afbc(plane, fb->modifier); > + > + offset = (src->x1 >> 16) * fb->format->cpp[0]; > + > + /* > + * AFBC HDR_PTR must set to the zero offset of the framebuffer. > + */ > + if (afbc_en) > + offset = 0; > + else if (pstate->rotation & DRM_MODE_REFLECT_Y) > + offset += ((src->y2 >> 16) - 1) * fb->pitches[0]; > + else > + offset += (src->y1 >> 16) * fb->pitches[0]; > + > + rk_obj = to_rockchip_obj(fb->obj[0]); > + > + yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0]; > + if (fb->format->is_yuv) { > + int hsub = fb->format->hsub; > + int vsub = fb->format->vsub; > + > + offset = (src->x1 >> 16) * fb->format->cpp[1] / hsub; > + offset += (src->y1 >> 16) * fb->pitches[1] / vsub; > + > + if ((pstate->rotation & DRM_MODE_REFLECT_Y) && !afbc_en) > + offset += fb->pitches[1] * ((pstate->src_h >> 16) - 2) / vsub; > + > + rk_obj = to_rockchip_obj(fb->obj[0]); > + uv_mst = rk_obj->dma_addr + offset + fb->offsets[1]; > + } > + > + actual_w = drm_rect_width(src) >> 16; > + actual_h = drm_rect_height(src) >> 16; > + dsp_w = drm_rect_width(dest); > + > + if (dest->x1 + dsp_w > adjusted_mode->hdisplay) { > + drm_err(vop2->drm, "vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n", > + vp->id, win->data->name, dest->x1, dsp_w, adjusted_mode->hdisplay); > + dsp_w = adjusted_mode->hdisplay - dest->x1; > + if (dsp_w < 4) > + dsp_w = 4; > + actual_w = dsp_w * actual_w / drm_rect_width(dest); > + } > + > + dsp_h = drm_rect_height(dest); > + > + if (dest->y1 + dsp_h > adjusted_mode->vdisplay) { > + drm_err(vop2->drm, "vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n", > + vp->id, win->data->name, dest->y1, dsp_h, adjusted_mode->vdisplay); > + dsp_h = adjusted_mode->vdisplay - dest->y1; > + if (dsp_h < 4) > + dsp_h = 4; > + actual_h = dsp_h * actual_h / drm_rect_height(dest); > + } > + > + /* > + * This is workaround solution for IC design: > + * esmart can't support scale down when actual_w % 16 == 1. > + */ > + if (!(win->data->feature & WIN_FEATURE_AFBDC)) { > + if (actual_w > dsp_w && (actual_w & 0xf) == 1) { > + drm_err(vop2->drm, "vp%d %s act_w[%d] MODE 16 == 1\n", vp->id, win->data->name, actual_w); > + actual_w -= 1; > + } > + } > + > + if (afbc_en && actual_w % 4) { > + drm_err(vop2->drm, "vp%d %s actual_w[%d] should align as 4 pixel when enable afbc\n", > + vp->id, win->data->name, actual_w); > + actual_w = ALIGN_DOWN(actual_w, 4); > + } > + > + act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); > + dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff); > + > + format = vop2_convert_format(fb->format->format); > + > + spin_lock(&vop2->reg_lock); > + drm_dbg(vop2->drm, "vp%d update %s[%dx%d->%dx%d@%dx%d] fmt[%p4cc_%s] addr[%pad]\n", > + vp->id, win->data->name, actual_w, actual_h, dsp_w, dsp_h, > + dest->x1, dest->y1, > + &fb->format->format, > + afbc_en ? "AFBC" : "", &yrgb_mst); > + > + if (afbc_en) { > + uint32_t stride; > + > + /* the afbc superblock is 16 x 16 */ > + afbc_format = vop2_convert_afbc_format(fb->format->format); > + > + /* Enable color transform for YTR */ > + if (fb->modifier & AFBC_FORMAT_MOD_YTR) > + afbc_format |= (1 << 4); > + > + afbc_tile_num = ALIGN(actual_w, 16) >> 4; > + > + /* > + * AFBC pic_vir_width is count by pixel, this is different > + * with WIN_VIR_STRIDE. > + */ > + stride = (fb->pitches[0] << 3) / bpp; > + if ((stride & 0x3f) && (xmirror || rotate_90 || rotate_270)) > + drm_err(vop2->drm, "vp%d %s stride[%d] must align as 64 pixel when enable xmirror/rotate_90/rotate_270[0x%x]\n", > + vp->id, win->data->name, stride, pstate->rotation); > + > + rb_swap = vop2_afbc_rb_swap(fb->format->format); > + uv_swap = vop2_afbc_uv_swap(fb->format->format); > + /* > + * This is a workaround for crazy IC design, Cluster > + * and Esmart/Smart use different format configuration map: > + * YUV420_10BIT: 0x10 for Cluster, 0x14 for Esmart/Smart. > + * > + * This is one thing we can make the convert simple: > + * AFBCD decode all the YUV data to YUV444. So we just > + * set all the yuv 10 bit to YUV444_10. > + */ > + if (fb->format->is_yuv && (bpp == 10)) > + format = VOP2_CLUSTER_YUV444_10; > + > + afbc_half_block_en = vop2_afbc_half_block_enable(pstate); > + transform_offset = vop2_afbc_transform_offset(pstate, afbc_half_block_en); > + if (vop2_cluster_window(win)) > + vop2_win_write(win, VOP2_WIN_AFBC_ENABLE, 1); > + vop2_win_write(win, VOP2_WIN_AFBC_FORMAT, afbc_format); > + vop2_win_write(win, VOP2_WIN_AFBC_RB_SWAP, rb_swap); > + vop2_win_write(win, VOP2_WIN_AFBC_UV_SWAP, uv_swap); > + vop2_win_write(win, VOP2_WIN_AFBC_AUTO_GATING_EN, 0); > + vop2_win_write(win, VOP2_WIN_AFBC_BLOCK_SPLIT_EN, 0); > + vop2_win_write(win, VOP2_WIN_AFBC_HALF_BLOCK_EN, afbc_half_block_en); > + vop2_win_write(win, VOP2_WIN_AFBC_HDR_PTR, yrgb_mst); > + vop2_win_write(win, VOP2_WIN_AFBC_PIC_SIZE, act_info); > + vop2_win_write(win, VOP2_WIN_AFBC_TRANSFORM_OFFSET, transform_offset); > + vop2_win_write(win, VOP2_WIN_AFBC_PIC_OFFSET, ((src->x1 >> 16) | src->y1)); > + vop2_win_write(win, VOP2_WIN_AFBC_DSP_OFFSET, (dest->x1 | (dest->y1 << 16))); > + vop2_win_write(win, VOP2_WIN_AFBC_PIC_VIR_WIDTH, stride); > + vop2_win_write(win, VOP2_WIN_AFBC_TILE_NUM, afbc_tile_num); > + vop2_win_write(win, VOP2_WIN_XMIRROR, xmirror); > + vop2_win_write(win, VOP2_WIN_AFBC_ROTATE_270, rotate_270); > + vop2_win_write(win, VOP2_WIN_AFBC_ROTATE_90, rotate_90); > + } else { > + vop2_win_write(win, VOP2_WIN_YRGB_VIR, DIV_ROUND_UP(fb->pitches[0], 4)); > + } > + > + vop2_win_write(win, VOP2_WIN_YMIRROR, ymirror); > + > + if (rotate_90 || rotate_270) { > + act_info = swahw32(act_info); > + actual_w = drm_rect_height(src) >> 16; > + actual_h = drm_rect_width(src) >> 16; > + } > + > + vop2_win_write(win, VOP2_WIN_FORMAT, format); > + vop2_win_write(win, VOP2_WIN_YRGB_MST, yrgb_mst); > + > + rb_swap = vop2_win_rb_swap(fb->format->format); > + vop2_win_write(win, VOP2_WIN_RB_SWAP, rb_swap); > + if (!vop2_cluster_window(win)) { > + uv_swap = vop2_win_uv_swap(fb->format->format); > + vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap); > + } > + > + if (fb->format->is_yuv) { > + vop2_win_write(win, VOP2_WIN_UV_VIR, DIV_ROUND_UP(fb->pitches[1], 4)); > + vop2_win_write(win, VOP2_WIN_UV_MST, uv_mst); > + } > + > + vop2_setup_scale(vop2, win, actual_w, actual_h, dsp_w, dsp_h, fb->format->format); > + if (!vop2_cluster_window(win)) > + vop2_plane_setup_color_key(plane, 0); > + vop2_win_write(win, VOP2_WIN_ACT_INFO, act_info); > + vop2_win_write(win, VOP2_WIN_DSP_INFO, dsp_info); > + vop2_win_write(win, VOP2_WIN_DSP_ST, dest->y1 << 16 | (dest->x1 & 0xffff)); > + > + vop2_setup_csc_mode(vp, win, pstate); > + > + dither_up = vop2_win_dither_up(fb->format->format); > + vop2_win_write(win, VOP2_WIN_DITHER_UP, dither_up); > + > + vop2_win_write(win, VOP2_WIN_ENABLE, 1); > + > + if (vop2_cluster_window(win)) { > + int lb_mode = vop2_get_cluster_lb_mode(win, pstate); > + > + vop2_win_write(win, VOP2_WIN_CLUSTER_LB_MODE, lb_mode); > + vop2_win_write(win, VOP2_WIN_CLUSTER_ENABLE, 1); > + } > + > + spin_unlock(&vop2->reg_lock); > +} > + > +static const struct drm_plane_helper_funcs vop2_plane_helper_funcs = { > + .atomic_check = vop2_plane_atomic_check, > + .atomic_update = vop2_plane_atomic_update, > + .atomic_disable = vop2_plane_atomic_disable, > +}; > + > +static const struct drm_plane_funcs vop2_plane_funcs = { > + .update_plane = drm_atomic_helper_update_plane, > + .disable_plane = drm_atomic_helper_disable_plane, > + .destroy = drm_plane_cleanup, > + .reset = drm_atomic_helper_plane_reset, > + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, > + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, > + .format_mod_supported = rockchip_vop2_mod_supported, > +}; > + > +static int vop2_crtc_enable_vblank(struct drm_crtc *crtc) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + > + vop2_crtc_enable_irq(vp, VP_INT_FS_FIELD); > + > + return 0; > +} > + > +static void vop2_crtc_disable_vblank(struct drm_crtc *crtc) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + > + vop2_crtc_disable_irq(vp, VP_INT_FS_FIELD); > +} > + > +static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc, > + const struct drm_display_mode *mode, > + struct drm_display_mode *adj_mode) > +{ > + drm_mode_set_crtcinfo(adj_mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE); > + > + return true; > +} > + > +static void vop2_dither_setup(struct drm_crtc *crtc, uint32_t *dsp_ctrl) > +{ > + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); > + > + switch (vcstate->bus_format) { > + case MEDIA_BUS_FMT_RGB565_1X16: > + *dsp_ctrl |= RK3568_VP_DSP_CTRL__DITHER_DOWN_EN; > + break; > + case MEDIA_BUS_FMT_RGB666_1X18: > + case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: > + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: > + *dsp_ctrl |= RK3568_VP_DSP_CTRL__DITHER_DOWN_EN; > + *dsp_ctrl |= RGB888_TO_RGB666; > + break; > + case MEDIA_BUS_FMT_YUV8_1X24: > + case MEDIA_BUS_FMT_UYYVYY8_0_5X24: > + *dsp_ctrl |= RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN; > + break; > + default: > + break; > + } > + > + if (vcstate->output_mode != ROCKCHIP_OUT_MODE_AAAA) > + *dsp_ctrl |= RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN; > + > + *dsp_ctrl |= FIELD_PREP(RK3568_VP_DSP_CTRL__DITHER_DOWN_SEL, > + DITHER_DOWN_ALLEGRO); > +} > + > +static void vop2_post_config(struct drm_crtc *crtc) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct vop2 *vop2 = vp->vop2; > + struct drm_display_mode *mode = &crtc->state->adjusted_mode; > + uint16_t vtotal = mode->crtc_vtotal; > + uint16_t hdisplay = mode->crtc_hdisplay; > + uint16_t hact_st = mode->crtc_htotal - mode->crtc_hsync_start; > + uint16_t vdisplay = mode->crtc_vdisplay; > + uint16_t vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; > + uint32_t left_margin = 100, right_margin = 100, top_margin = 100, bottom_margin = 100; > + uint16_t hsize = hdisplay * (left_margin + right_margin) / 200; > + uint16_t vsize = vdisplay * (top_margin + bottom_margin) / 200; > + uint16_t hact_end, vact_end; > + uint32_t val; > + > + vsize = rounddown(vsize, 2); > + hsize = rounddown(hsize, 2); > + hact_st += hdisplay * (100 - left_margin) / 200; > + hact_end = hact_st + hsize; > + val = hact_st << 16; > + val |= hact_end; > + vop2_vp_write(vp, RK3568_VP_POST_DSP_HACT_INFO, val); > + vact_st += vdisplay * (100 - top_margin) / 200; > + vact_end = vact_st + vsize; > + val = vact_st << 16; > + val |= vact_end; > + vop2_vp_write(vp, RK3568_VP_POST_DSP_VACT_INFO, val); > + val = scl_cal_scale2(vdisplay, vsize) << 16; > + val |= scl_cal_scale2(hdisplay, hsize); > + vop2_vp_write(vp, RK3568_VP_POST_SCL_FACTOR_YRGB, val); > + > + val = 0; > + if (hdisplay != hsize) > + val |= RK3568_VP_POST_SCL_CTRL__HSCALEDOWN; > + if (vdisplay != vsize) > + val |= RK3568_VP_POST_SCL_CTRL__VSCALEDOWN; > + vop2_writel(vop2, RK3568_VP_POST_SCL_CTRL, val); > + > + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { > + uint16_t vact_st_f1 = vtotal + vact_st + 1; > + uint16_t vact_end_f1 = vact_st_f1 + vsize; > + > + val = vact_st_f1 << 16 | vact_end_f1; > + vop2_vp_write(vp, RK3568_VP_POST_DSP_VACT_INFO_F1, val); > + } > + > + vop2_vp_write(vp, RK3568_VP_DSP_BG, 0); > +} > + > +static void rk3568_set_intf_mux(struct vop2_video_port *vp, int id, > + uint32_t polflags) > +{ > + struct vop2 *vop2 = vp->vop2; > + uint32_t die, dip; > + > + die = vop2_readl(vop2, RK3568_DSP_IF_EN); > + dip = vop2_readl(vop2, RK3568_DSP_IF_POL); > + > + switch (id) { > + case RK3568_VOP2_EP_RGB: > + die &= ~RK3568_SYS_DSP_INFACE_EN_RGB_MUX; > + die |= RK3568_SYS_DSP_INFACE_EN_RGB | > + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_RGB_MUX, vp->id); > + if (polflags & POLFLAG_DCLK_INV) > + regmap_write(vop2->grf, RK3568_GRF_VO_CON1, BIT(3 + 16) | BIT(3)); > + else > + regmap_write(vop2->grf, RK3568_GRF_VO_CON1, BIT(3 + 16)); > + break; > + case RK3568_VOP2_EP_HDMI: > + die &= ~RK3568_SYS_DSP_INFACE_EN_HDMI_MUX; > + die |= RK3568_SYS_DSP_INFACE_EN_HDMI | > + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_HDMI_MUX, vp->id); > + break; > + case RK3568_VOP2_EP_EDP: > + die &= ~RK3568_SYS_DSP_INFACE_EN_EDP_MUX; > + die |= RK3568_SYS_DSP_INFACE_EN_EDP | > + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_EDP_MUX, vp->id); > + break; > + case RK3568_VOP2_EP_MIPI0: > + die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX; > + die |= RK3568_SYS_DSP_INFACE_EN_MIPI0 | > + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX, vp->id); > + dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL; > + dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags); > + break; > + case RK3568_VOP2_EP_MIPI1: > + die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX; > + die |= RK3568_SYS_DSP_INFACE_EN_MIPI1 | > + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id); > + dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL; > + dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags); > + break; > + case RK3568_VOP2_EP_LVDS0: > + die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX; > + die |= RK3568_SYS_DSP_INFACE_EN_LVDS0 | > + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX, vp->id); > + dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; > + dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); > + break; > + case RK3568_VOP2_EP_LVDS1: > + die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX; > + die |= RK3568_SYS_DSP_INFACE_EN_LVDS1 | > + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX, vp->id); > + dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; > + dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); > + break; > + default: > + return; > + }; > + > + dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD; > + > + vop2_writel(vop2, RK3568_DSP_IF_EN, die); > + vop2_writel(vop2, RK3568_DSP_IF_POL, dip); > +} > + > +static int us_to_vertical_line(struct drm_display_mode *mode, int us) > +{ > + return us * mode->clock / mode->htotal / 1000; > +} > + > +static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct vop2 *vop2 = vp->vop2; > + const struct vop2_data *vop2_data = vop2->data; > + const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; > + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); > + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); > + struct drm_display_mode *mode = &crtc->state->adjusted_mode; > + unsigned long clock = mode->crtc_clock * 1000; > + uint16_t hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; > + uint16_t hdisplay = mode->crtc_hdisplay; > + uint16_t htotal = mode->crtc_htotal; > + uint16_t hact_st = mode->crtc_htotal - mode->crtc_hsync_start; > + uint16_t hact_end = hact_st + hdisplay; > + uint16_t vdisplay = mode->crtc_vdisplay; > + uint16_t vtotal = mode->crtc_vtotal; > + uint16_t vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; > + uint16_t vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; > + uint16_t vact_end = vact_st + vdisplay; > + uint8_t out_mode; > + uint32_t dsp_ctrl = 0; > + int act_end; > + uint32_t val, polflags; > + int ret; > + struct drm_encoder *encoder; > + > + drm_dbg(vop2->drm, "Update mode to %dx%d%s%d, type: %d for vp%d\n", > + hdisplay, vdisplay, mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", > + drm_mode_vrefresh(mode), vcstate->output_type, vp->id); > + > + vop2_lock(vop2); > + > + ret = clk_prepare_enable(vp->dclk); > + if (ret < 0) { > + drm_err(vop2->drm, "failed to enable dclk for video port%d - %d\n", > + vp->id, ret); > + return; > + } > + > + if (!vop2->enable_count) > + vop2_enable(vop2); > + > + vop2->enable_count++; > + > + vop2_crtc_enable_irq(vp, VP_INT_POST_BUF_EMPTY); > + > + polflags = 0; > + if (vcstate->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) > + polflags |= POLFLAG_DCLK_INV; > + if (mode->flags & DRM_MODE_FLAG_PHSYNC) > + polflags |= BIT(HSYNC_POSITIVE); > + if (mode->flags & DRM_MODE_FLAG_PVSYNC) > + polflags |= BIT(VSYNC_POSITIVE); > + > + drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) { > + struct device_node *node, *parent; > + > + parent = of_get_parent(encoder->port); > + > + for_each_endpoint_of_node(parent, node) { > + struct device_node *crtc_port = of_graph_get_remote_port(node); > + struct device_node *epn; > + struct of_endpoint endpoint; > + > + if (crtc->port != crtc_port) { > + of_node_put(crtc_port); > + continue; > + } > + > + of_node_put(crtc_port); > + > + epn = of_graph_get_remote_endpoint(node); > + of_graph_parse_endpoint(epn, &endpoint); > + of_node_put(epn); > + > + drm_dbg(vop2->drm, "vp%d is connected to %s, id %d\n", > + vp->id, encoder->name, endpoint.id); > + rk3568_set_intf_mux(vp, endpoint.id, polflags); > + } > + of_node_put(parent); > + } > + > + if (vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA && > + !(vp_data->feature & VOP_FEATURE_OUTPUT_10BIT)) > + out_mode = ROCKCHIP_OUT_MODE_P888; > + else > + out_mode = vcstate->output_mode; > + > + dsp_ctrl |= FIELD_PREP(RK3568_VP_DSP_CTRL__OUT_MODE, out_mode); > + > + if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode)) > + dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_RB_SWAP; > + > + if (is_yuv_output(vcstate->bus_format)) > + dsp_ctrl |= RK3568_VP_DSP_CTRL__POST_DSP_OUT_R2Y; > + > + vop2_dither_setup(crtc, &dsp_ctrl); > + > + vop2_vp_write(vp, RK3568_VP_DSP_HTOTAL_HS_END, (htotal << 16) | hsync_len); > + val = hact_st << 16; > + val |= hact_end; > + vop2_vp_write(vp, RK3568_VP_DSP_HACT_ST_END, val); > + > + val = vact_st << 16; > + val |= vact_end; > + vop2_vp_write(vp, RK3568_VP_DSP_VACT_ST_END, val); > + > + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { > + uint16_t vact_st_f1 = vtotal + vact_st + 1; > + uint16_t vact_end_f1 = vact_st_f1 + vdisplay; > + > + val = vact_st_f1 << 16 | vact_end_f1; > + vop2_vp_write(vp, RK3568_VP_DSP_VACT_ST_END_F1, val); > + > + val = vtotal << 16 | (vtotal + vsync_len); > + vop2_vp_write(vp, RK3568_VP_DSP_VS_ST_END_F1, val); > + dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_INTERLACE; > + dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_FILED_POL; > + dsp_ctrl |= RK3568_VP_DSP_CTRL__P2I_EN; > + vtotal += vtotal + 1; > + act_end = vact_end_f1; > + } else { > + act_end = vact_end; > + } > + > + vop2_writel(vop2, RK3568_VP_LINE_FLAG(vp->id), > + (act_end - us_to_vertical_line(mode, 0)) << 16 | act_end); > + > + vop2_vp_write(vp, RK3568_VP_DSP_VTOTAL_VS_END, vtotal << 16 | vsync_len); > + > + if (mode->flags & DRM_MODE_FLAG_DBLCLK) { > + dsp_ctrl |= RK3568_VP_DSP_CTRL__CORE_DCLK_DIV; > + clock *= 2; > + } > + > + vop2_vp_write(vp, RK3568_VP_MIPI_CTRL, 0); > + > + clk_set_rate(vp->dclk, clock); > + > + vop2_post_config(crtc); > + > + vop2_cfg_done(vp); > + > + vop2_vp_write(vp, RK3568_VP_DSP_CTRL, dsp_ctrl); > + > + drm_crtc_vblank_on(crtc); > + > + vop2_unlock(vop2); > +} > + > +static int vop2_crtc_atomic_check(struct drm_crtc *crtc, > + struct drm_atomic_state *state) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct drm_plane *plane; > + int nplanes = 0; > + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); > + > + drm_atomic_crtc_state_for_each_plane(plane, crtc_state) > + nplanes++; > + > + if (nplanes > vp->nlayers) > + return -EINVAL; > + > + return 0; > +} > + > +static bool is_opaque(uint16_t alpha) > +{ > + return (alpha >> 8) == 0xff; > +} > + > +static void vop2_parse_alpha(struct vop2_alpha_config *alpha_config, > + struct vop2_alpha *alpha) > +{ > + int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1; > + int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1; > + int src_color_mode = alpha_config->src_premulti_en ? ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL; > + int dst_color_mode = alpha_config->dst_premulti_en ? ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL; > + > + alpha->src_color_ctrl.val = 0; > + alpha->dst_color_ctrl.val = 0; > + alpha->src_alpha_ctrl.val = 0; > + alpha->dst_alpha_ctrl.val = 0; > + > + if (!alpha_config->src_pixel_alpha_en) > + alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; > + else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en) > + alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX; > + else > + alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; > + > + alpha->src_color_ctrl.bits.alpha_en = 1; > + > + if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) { > + alpha->src_color_ctrl.bits.color_mode = src_color_mode; > + alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; > + } else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) { > + alpha->src_color_ctrl.bits.color_mode = src_color_mode; > + alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE; > + } else { > + alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL; > + alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; > + } > + alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8; > + alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; > + alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; > + > + alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; > + alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; > + alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; > + alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8; > + alpha->dst_color_ctrl.bits.color_mode = dst_color_mode; > + alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; > + > + alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; > + alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode; > + alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; > + alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE; > + > + alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; > + if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en) > + alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX; > + else > + alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; > + alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION; > + alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; > +} > + > +static int vop2_find_start_mixer_id_for_vp(struct vop2 *vop2, uint8_t port_id) > +{ > + struct vop2_video_port *vp; > + int used_layer = 0; > + int i; > + > + for (i = 0; i < port_id; i++) { > + vp = &vop2->vps[i]; > + used_layer += hweight32(vp->win_mask); > + } > + > + return used_layer; > +} > + > +static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_win *main_win) > +{ > + uint32_t offset = (main_win->data->phys_id * 0x10); > + struct vop2_alpha_config alpha_config; > + struct vop2_alpha alpha; > + struct drm_plane_state *bottom_win_pstate; > + bool src_pixel_alpha_en = false; > + uint16_t src_glb_alpha_val, dst_glb_alpha_val; > + bool premulti_en = false; > + bool swap = false; > + > + /* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */ > + bottom_win_pstate = main_win->base.state; > + src_glb_alpha_val = 0; > + dst_glb_alpha_val = main_win->base.state->alpha; > + > + if (!bottom_win_pstate->fb) > + return; > + > + alpha_config.src_premulti_en = premulti_en; > + alpha_config.dst_premulti_en = false; > + alpha_config.src_pixel_alpha_en = src_pixel_alpha_en; > + alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ > + alpha_config.src_glb_alpha_value = src_glb_alpha_val; > + alpha_config.dst_glb_alpha_value = dst_glb_alpha_val; > + vop2_parse_alpha(&alpha_config, &alpha); > + > + alpha.src_color_ctrl.bits.src_dst_swap = swap; > + vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL + offset, > + alpha.src_color_ctrl.val); > + vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_COLOR_CTRL + offset, > + alpha.dst_color_ctrl.val); > + vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL + offset, > + alpha.src_alpha_ctrl.val); > + vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL + offset, > + alpha.dst_alpha_ctrl.val); > +} > + > +static void vop2_setup_alpha(struct vop2_video_port *vp) > +{ > + struct vop2 *vop2 = vp->vop2; > + struct drm_framebuffer *fb; > + struct vop2_alpha_config alpha_config; > + struct vop2_alpha alpha; > + struct drm_plane *plane; > + int pixel_alpha_en; > + int premulti_en, gpremulti_en = 0; > + int mixer_id; > + uint32_t offset; > + bool bottom_layer_alpha_en = false; > + uint32_t dst_global_alpha = DRM_BLEND_ALPHA_OPAQUE; > + > + mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id); > + alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ > + > + drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { > + struct vop2_win *win = to_vop2_win(plane); > + > + if (plane->state->normalized_zpos == 0 && > + !is_opaque(plane->state->alpha) && > + !vop2_cluster_window(win)) { > + /* > + * If bottom layer have global alpha effect [except cluster layer, > + * because cluster have deal with bottom layer global alpha value > + * at cluster mix], bottom layer mix need deal with global alpha. > + */ > + bottom_layer_alpha_en = true; > + dst_global_alpha = plane->state->alpha; > + } > + } > + > + drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { > + struct vop2_win *win = to_vop2_win(plane); > + int zpos = plane->state->normalized_zpos; > + > + if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) > + premulti_en = 1; > + else > + premulti_en = 0; > + > + plane = &win->base; > + fb = plane->state->fb; > + > + pixel_alpha_en = fb->format->has_alpha; > + > + alpha_config.src_premulti_en = premulti_en; > + > + if (bottom_layer_alpha_en && zpos == 1) { > + gpremulti_en = premulti_en; > + /* Cd = Cs + (1 - As) * Cd * Agd */ > + alpha_config.dst_premulti_en = false; > + alpha_config.src_pixel_alpha_en = pixel_alpha_en; > + alpha_config.src_glb_alpha_value = plane->state->alpha; > + alpha_config.dst_glb_alpha_value = dst_global_alpha; > + } else if (vop2_cluster_window(win)) { > + /* Mix output data only have pixel alpha */ > + alpha_config.dst_premulti_en = true; > + alpha_config.src_pixel_alpha_en = true; > + alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; > + alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; > + } else { > + /* Cd = Cs + (1 - As) * Cd */ > + alpha_config.dst_premulti_en = true; > + alpha_config.src_pixel_alpha_en = pixel_alpha_en; > + alpha_config.src_glb_alpha_value = plane->state->alpha; > + alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; > + } > + > + vop2_parse_alpha(&alpha_config, &alpha); > + > + offset = (mixer_id + zpos - 1) * 0x10; > + vop2_writel(vop2, RK3568_MIX0_SRC_COLOR_CTRL + offset, > + alpha.src_color_ctrl.val); > + vop2_writel(vop2, RK3568_MIX0_DST_COLOR_CTRL + offset, > + alpha.dst_color_ctrl.val); > + vop2_writel(vop2, RK3568_MIX0_SRC_ALPHA_CTRL + offset, > + alpha.src_alpha_ctrl.val); > + vop2_writel(vop2, RK3568_MIX0_DST_ALPHA_CTRL + offset, > + alpha.dst_alpha_ctrl.val); > + } > + > + if (vp->id == 0) { > + if (bottom_layer_alpha_en) { > + /* Transfer pixel alpha to hdr mix */ > + alpha_config.src_premulti_en = gpremulti_en; > + alpha_config.dst_premulti_en = true; > + alpha_config.src_pixel_alpha_en = true; > + alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; > + alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; > + vop2_parse_alpha(&alpha_config, &alpha); > + > + vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, > + alpha.src_color_ctrl.val); > + vop2_writel(vop2, RK3568_HDR0_DST_COLOR_CTRL, > + alpha.dst_color_ctrl.val); > + vop2_writel(vop2, RK3568_HDR0_SRC_ALPHA_CTRL, > + alpha.src_alpha_ctrl.val); > + vop2_writel(vop2, RK3568_HDR0_DST_ALPHA_CTRL, > + alpha.dst_alpha_ctrl.val); > + } else { > + vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, 0); > + } > + } > +} > + > +#define NR_VPS 3 > +#define NR_MIXERS 6 > + > +static void vop2_setup_layer_mixer(struct vop2_video_port *vp) > +{ > + struct vop2 *vop2 = vp->vop2; > + struct drm_plane *plane; > + uint32_t layer_sel = 0; > + uint32_t port_sel; > + int nlayer, ofs; > + struct drm_display_mode *adjusted_mode; > + uint16_t hsync_len; > + uint16_t hdisplay; > + uint32_t bg_dly; > + uint32_t pre_scan_dly; > + int i; > + struct vop2_video_port *vp0 = &vop2->vps[0]; > + struct vop2_video_port *vp1 = &vop2->vps[1]; > + struct vop2_video_port *vp2 = &vop2->vps[2]; > + > + adjusted_mode = &vp->crtc.state->adjusted_mode; > + hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; > + hdisplay = adjusted_mode->crtc_hdisplay; > + > + bg_dly = vp->data->pre_scan_max_dly[3]; > + vop2_writel(vop2, RK3568_VP_BG_MIX_CTRL(vp->id), > + FIELD_PREP(RK3568_VP_BG_MIX_CTRL__BG_DLY, bg_dly)); > + > + pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len; > + vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly); > + > + vop2_writel(vop2, RK3568_OVL_CTRL, 0); > + port_sel = vop2_readl(vop2, RK3568_OVL_PORT_SEL); > + port_sel &= RK3568_OVL_PORT_SEL__SEL_PORT; > + > + if (vp0->nlayers) > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, > + vp0->nlayers - 1); > + else > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, 8); > + > + if (vp1->nlayers) > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, > + (vp0->nlayers + vp1->nlayers - 1)); > + else > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8); > + > + if (vp2->nlayers) > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, > + (vp2->nlayers + vp1->nlayers + vp0->nlayers - 1)); > + else > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8); > + > + layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); > + > + ofs = 0; > + for (i = 0; i < vp->id; i++) > + ofs += vop2->vps[i].nlayers; > + > + nlayer = 0; > + drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { > + struct vop2_win *win = to_vop2_win(plane); > + > + switch (win->data->phys_id) { > + case ROCKCHIP_VOP2_CLUSTER0: > + port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER0; > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER0, vp->id); > + break; > + case ROCKCHIP_VOP2_CLUSTER1: > + port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER1; > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER1, vp->id); > + break; > + case ROCKCHIP_VOP2_ESMART0: > + port_sel &= ~RK3568_OVL_PORT_SEL__ESMART0; > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART0, vp->id); > + break; > + case ROCKCHIP_VOP2_ESMART1: > + port_sel &= ~RK3568_OVL_PORT_SEL__ESMART1; > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART1, vp->id); > + break; > + case ROCKCHIP_VOP2_SMART0: > + port_sel &= ~RK3568_OVL_PORT_SEL__SMART0; > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART0, vp->id); > + break; > + case ROCKCHIP_VOP2_SMART1: > + port_sel &= ~RK3568_OVL_PORT_SEL__SMART1; > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART1, vp->id); > + break; > + } > + > + layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(nlayer + ofs, 0x7); > + layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(nlayer + ofs, win->data->layer_sel_id); > + nlayer++; > + } > + > + /* configure unused layers to 0x5 (reserved) */ > + for (; nlayer < 3; nlayer++) { > + layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(nlayer + ofs, 0x7); > + layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(nlayer + ofs, 5); > + } > + > + vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel); > + vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel); > + vop2_writel(vop2, RK3568_OVL_CTRL, RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD); > +} > + > +static void vop2_setup_dly_for_windows(struct vop2 *vop2) > +{ > + struct vop2_win *win; > + int i = 0; > + uint32_t cdly = 0, sdly = 0; > + > + for (i = 0; i < vop2->data->win_size; i++) { > + uint32_t dly; > + > + win = &vop2->win[i]; > + dly = win->delay; > + > + switch (win->data->phys_id) { > + case ROCKCHIP_VOP2_CLUSTER0: > + cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_0, dly); > + cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_1, dly); > + break; > + case ROCKCHIP_VOP2_CLUSTER1: > + cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_0, dly); > + cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_1, dly); > + break; > + case ROCKCHIP_VOP2_ESMART0: > + sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART0, dly); > + break; > + case ROCKCHIP_VOP2_ESMART1: > + sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART1, dly); > + break; > + case ROCKCHIP_VOP2_SMART0: > + sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART1, dly); > + break; > + case ROCKCHIP_VOP2_SMART1: > + sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART0, dly); > + break; > + } > + } > + > + vop2_writel(vop2, RK3568_CLUSTER_DLY_NUM, cdly); > + vop2_writel(vop2, RK3568_SMART_DLY_NUM, sdly); > +} > + > +static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct vop2 *vop2 = vp->vop2; > + struct drm_plane *plane; > + > + vp->win_mask = 0; > + > + drm_atomic_crtc_for_each_plane(plane, crtc) { > + struct vop2_win *win = to_vop2_win(plane); > + > + win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT]; > + > + vp->win_mask |= BIT(win->data->phys_id); > + > + if (vop2_cluster_window(win)) > + vop2_setup_cluster_alpha(vop2, win); > + } > + > + if (!vp->win_mask) > + return; > + > + vop2_setup_layer_mixer(vp); > + vop2_setup_alpha(vp); > + vop2_setup_dly_for_windows(vop2); > +} > + > +static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct vop2 *vop2 = vp->vop2; > + > + spin_lock(&vop2->reg_lock); > + > + vop2_post_config(crtc); > + > + spin_unlock(&vop2->reg_lock); > + > + vop2_cfg_done(vp); > + > + spin_lock_irq(&crtc->dev->event_lock); > + > + if (crtc->state->event) { > + WARN_ON(drm_crtc_vblank_get(crtc)); > + vp->event = crtc->state->event; > + crtc->state->event = NULL; > + } > + > + spin_unlock_irq(&crtc->dev->event_lock); > +} > + > +static const struct drm_crtc_helper_funcs vop2_crtc_helper_funcs = { > + .mode_fixup = vop2_crtc_mode_fixup, > + .atomic_check = vop2_crtc_atomic_check, > + .atomic_begin = vop2_crtc_atomic_begin, > + .atomic_flush = vop2_crtc_atomic_flush, > + .atomic_enable = vop2_crtc_atomic_enable, > + .atomic_disable = vop2_crtc_atomic_disable, > +}; > + > +static void vop2_crtc_reset(struct drm_crtc *crtc) > +{ > + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); > + > + if (crtc->state) { > + __drm_atomic_helper_crtc_destroy_state(crtc->state); > + kfree(vcstate); > + } > + > + vcstate = kzalloc(sizeof(*vcstate), GFP_KERNEL); > + if (!vcstate) > + return; > + > + crtc->state = &vcstate->base; > + crtc->state->crtc = crtc; > +} > + > +static struct drm_crtc_state *vop2_crtc_duplicate_state(struct drm_crtc *crtc) > +{ > + struct rockchip_crtc_state *vcstate, *old_vcstate; > + > + old_vcstate = to_rockchip_crtc_state(crtc->state); > + > + vcstate = kmemdup(old_vcstate, sizeof(*old_vcstate), GFP_KERNEL); > + if (!vcstate) > + return NULL; > + > + __drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base); > + > + return &vcstate->base; > +} > + > +static void vop2_crtc_destroy_state(struct drm_crtc *crtc, > + struct drm_crtc_state *state) > +{ > + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(state); > + > + __drm_atomic_helper_crtc_destroy_state(&vcstate->base); > + kfree(vcstate); > +} > + > +static const struct drm_crtc_funcs vop2_crtc_funcs = { > + .set_config = drm_atomic_helper_set_config, > + .page_flip = drm_atomic_helper_page_flip, > + .destroy = drm_crtc_cleanup, > + .reset = vop2_crtc_reset, > + .atomic_duplicate_state = vop2_crtc_duplicate_state, > + .atomic_destroy_state = vop2_crtc_destroy_state, > + .enable_vblank = vop2_crtc_enable_vblank, > + .disable_vblank = vop2_crtc_disable_vblank, > +}; > + > +static irqreturn_t vop2_isr(int irq, void *data) > +{ > + struct vop2 *vop2 = data; > + const struct vop2_data *vop2_data = vop2->data; > + uint32_t axi_irqs[VOP2_SYS_AXI_BUS_NUM]; > + int ret = IRQ_NONE; > + int i; > + > + /* > + * The irq is shared with the iommu. If the runtime-pm state of the > + * vop2-device is disabled the irq has to be targeted at the iommu. > + */ > + if (!pm_runtime_get_if_in_use(vop2->dev)) > + return IRQ_NONE; > + > + for (i = 0; i < vop2_data->nr_vps; i++) { > + struct vop2_video_port *vp = &vop2->vps[i]; > + struct drm_crtc *crtc = &vp->crtc; > + uint32_t irqs; > + > + irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id)); > + vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs); > + > + if (irqs & VP_INT_DSP_HOLD_VALID) { > + complete(&vp->dsp_hold_completion); > + ret = IRQ_HANDLED; > + } > + > + if (irqs & VP_INT_FS_FIELD) { > + unsigned long flags; > + > + drm_crtc_handle_vblank(crtc); > + spin_lock_irqsave(&crtc->dev->event_lock, flags); > + if (vp->event) { > + uint32_t val = vop2_readl(vop2, RK3568_REG_CFG_DONE); > + if (!(val & BIT(vp->id))) { > + drm_crtc_send_vblank_event(crtc, vp->event); > + vp->event = NULL; > + drm_crtc_vblank_put(crtc); > + } > + } > + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); > + > + ret = IRQ_HANDLED; > + } > + > + if (irqs & VP_INT_POST_BUF_EMPTY) { > + drm_err_ratelimited(vop2->drm, > + "POST_BUF_EMPTY irq err at vp%d\n", > + vp->id); > + ret = IRQ_HANDLED; > + } > + } > + > + axi_irqs[0] = vop2_readl(vop2, RK3568_SYS0_INT_STATUS); > + vop2_writel(vop2, RK3568_SYS0_INT_CLR, axi_irqs[0] << 16 | axi_irqs[0]); > + axi_irqs[1] = vop2_readl(vop2, RK3568_SYS1_INT_STATUS); > + vop2_writel(vop2, RK3568_SYS1_INT_CLR, axi_irqs[1] << 16 | axi_irqs[1]); > + > + for (i = 0; i < ARRAY_SIZE(axi_irqs); i++) { > + if (axi_irqs[i] & VOP2_INT_BUS_ERRPR) { > + drm_err_ratelimited(vop2->drm, "BUS_ERROR irq err\n"); > + ret = IRQ_HANDLED; > + } > + } > + > + pm_runtime_put(vop2->dev); > + > + return ret; > +} > + > +static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win, unsigned long possible_crtcs) > +{ > + const struct vop2_win_data *win_data = win->data; > + unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | BIT(DRM_MODE_BLEND_PREMULTI) | > + BIT(DRM_MODE_BLEND_COVERAGE); > + int ret; > + > + ret = drm_universal_plane_init(vop2->drm, &win->base, possible_crtcs, > + &vop2_plane_funcs, win_data->formats, win_data->nformats, > + win_data->format_modifiers, win->type, win_data->name); > + if (ret) { > + drm_err(vop2->drm, "failed to initialize plane %d\n", ret); > + return ret; > + } > + > + drm_plane_helper_add(&win->base, &vop2_plane_helper_funcs); > + > + if (win->data->supported_rotations) > + drm_plane_create_rotation_property(&win->base, DRM_MODE_ROTATE_0, > + DRM_MODE_ROTATE_0 | > + win->data->supported_rotations); > + drm_plane_create_alpha_property(&win->base); > + drm_plane_create_blend_mode_property(&win->base, blend_caps); > + drm_plane_create_zpos_property(&win->base, win->win_id, 0, > + vop2->registered_num_wins - 1); > + > + return 0; > +} > + > +static struct vop2_video_port *get_activated_vp(struct vop2 *vop2, int n) > +{ > + int i, id = 0; > + > + for (i = 0; i < vop2->data->nr_vps; i++) { > + struct vop2_video_port *vp = &vop2->vps[i]; > + > + if (!vp->crtc.port) > + continue; > + > + if (n == id) > + return vp; > + id++; > + } > + > + return NULL; > +} > + > +static int vop2_create_crtc(struct vop2 *vop2) > +{ > + const struct vop2_data *vop2_data = vop2->data; > + struct drm_device *drm = vop2->drm; > + struct device *dev = vop2->dev; > + struct drm_plane *plane; > + struct device_node *port; > + struct vop2_video_port *vp; > + uint32_t possible_crtcs; > + int i, nvp, nvps = 0; > + int ret; > + > + for (i = 0; i < vop2_data->nr_vps; i++) { > + const struct vop2_video_port_data *vp_data; > + struct device_node *np; > + char dclk_name[9]; > + > + vp_data = &vop2_data->vp[i]; > + vp = &vop2->vps[i]; > + vp->vop2 = vop2; > + vp->id = vp_data->id; > + vp->regs = vp_data->regs; > + vp->data = vp_data; > + > + snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", vp->id); > + vp->dclk = devm_clk_get(vop2->dev, dclk_name); > + if (IS_ERR(vp->dclk)) { > + drm_err(vop2->drm, "failed to get %s\n", dclk_name); > + return PTR_ERR(vp->dclk); > + } > + > + np = of_graph_get_remote_node(dev->of_node, i, -1); > + if (!np) { > + printk("%s: No remote for vp%d\n", __func__, i); > + continue; > + } > + of_node_put(np); > + > + port = of_graph_get_port_by_id(dev->of_node, i); > + if (!port) { > + drm_err(vop2->drm, "no port node found for video_port%d\n", i); > + return -ENOENT; > + } > + > + vp->crtc.port = port; > + nvps++; > + } > + > + nvp = 0; > + for (i = 0; i < vop2->registered_num_wins; i++) { > + struct vop2_win *win = &vop2->win[i]; > + > + if (win->type == DRM_PLANE_TYPE_PRIMARY) { > + vp = get_activated_vp(vop2, nvp); > + > + if (vp) { > + possible_crtcs = BIT(nvp); > + vp->primary_plane = win; > + > + nvp++; > + } else { > + /* change the unused primary window to overlay window */ > + win->type = DRM_PLANE_TYPE_OVERLAY; > + } > + } > + > + if (win->type == DRM_PLANE_TYPE_OVERLAY) > + possible_crtcs = (1 << vop2_data->nr_vps) - 1; > + > + ret = vop2_plane_init(vop2, win, possible_crtcs); > + > + if (ret) { > + drm_err(vop2->drm, "failed to init plane %s: %d\n", win->data->name, ret); > + return ret; > + } > + } > + > + for (i = 0; i < vop2_data->nr_vps; i++) { > + vp = &vop2->vps[i]; > + > + if (!vp->crtc.port) > + continue; > + > + plane = &vp->primary_plane->base; > + > + ret = drm_crtc_init_with_planes(drm, &vp->crtc, plane, NULL, &vop2_crtc_funcs, > + "video_port%d", vp->id); > + if (ret) { > + drm_err(vop2->drm, "crtc init for video_port%d failed\n", i); > + return ret; > + } > + > + drm_crtc_helper_add(&vp->crtc, &vop2_crtc_helper_funcs); > + > + init_completion(&vp->dsp_hold_completion); > + } > + > + for (i = 0; i < vop2->data->nr_vps; i++) { > + struct vop2_video_port *vp = &vop2->vps[i]; > + if (vp->crtc.port) > + vp->nlayers = NR_MIXERS / nvps; > + } > + > + return 0; > +} > + > +static void vop2_destroy_crtc(struct drm_crtc *crtc) > +{ > + of_node_put(crtc->port); > + > + /* > + * Destroy CRTC after vop2_plane_destroy() since vop2_disable_plane() > + * references the CRTC. > + */ > + drm_crtc_cleanup(crtc); > +} > + > +static int vop2_cluster_init(struct vop2_win *win) > +{ > + struct vop2 *vop2 = win->vop2; > + int i; > + struct reg_field vop2_cluster_regs[VOP2_WIN_MAX_REG] = { > + [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0), > + [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5), > + [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 14, 14), > + [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 18, 18), > + [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_ACT_INFO, 0, 31), > + [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_INFO, 0, 31), > + [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_ST, 0, 31), > + [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_CLUSTER_WIN_YRGB_MST, 0, 31), > + [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_CLUSTER_WIN_CBR_MST, 0, 31), > + [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 19, 19), > + [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 0, 15), > + [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 16, 31), > + [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 8, 8), > + [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 9, 9), > + [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 10, 11), > + > + /* Scale */ > + [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0, 15), > + [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 16, 31), > + [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 14, 15), > + [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 12, 13), > + [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 2, 3), > + [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 28, 28), > + [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 29, 29), > + > + /* cluster regs */ > + [VOP2_WIN_AFBC_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 1, 1), > + [VOP2_WIN_CLUSTER_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 0, 0), > + [VOP2_WIN_CLUSTER_LB_MODE] = REG_FIELD(RK3568_CLUSTER_CTRL, 4, 7), > + > + /* afbc regs */ > + [VOP2_WIN_AFBC_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 2, 6), > + [VOP2_WIN_AFBC_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 9, 9), > + [VOP2_WIN_AFBC_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 10, 10), > + [VOP2_WIN_AFBC_AUTO_GATING_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 4, 4), > + [VOP2_WIN_AFBC_HALF_BLOCK_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 7, 7), > + [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 8, 8), > + [VOP2_WIN_AFBC_HDR_PTR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0, 31), > + [VOP2_WIN_AFBC_PIC_SIZE] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0, 31), > + [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0, 15), > + [VOP2_WIN_AFBC_TILE_NUM] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 16, 31), > + [VOP2_WIN_AFBC_PIC_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0, 31), > + [VOP2_WIN_AFBC_DSP_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0, 31), > + [VOP2_WIN_AFBC_TRANSFORM_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET, 0, 31), > + [VOP2_WIN_AFBC_ROTATE_90] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0, 0), > + [VOP2_WIN_AFBC_ROTATE_270] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 1, 1), > + [VOP2_WIN_XMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 2, 2), > + [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 3, 3), > + [VOP2_WIN_UV_SWAP] = { .reg = 0xffffffff }, > + [VOP2_WIN_COLOR_KEY] = { .reg = 0xffffffff }, > + [VOP2_WIN_COLOR_KEY_EN] = { .reg = 0xffffffff }, > + [VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff }, > + [VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff }, > + [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = { .reg = 0xffffffff }, > + [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = { .reg = 0xffffffff }, > + [VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff }, > + [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff }, > + [VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff }, > + [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff }, > + [VOP2_WIN_VSD_CBCR_GT2] = { .reg = 0xffffffff }, > + [VOP2_WIN_VSD_CBCR_GT4] = { .reg = 0xffffffff }, > + }; > + > + for (i = 0; i < ARRAY_SIZE(vop2_cluster_regs); i++) > + vop2_cluster_regs[i].reg += win->offset; > + > + return devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg, > + vop2_cluster_regs, > + ARRAY_SIZE(vop2_cluster_regs)); > +}; > + > +static int vop2_esmart_init(struct vop2_win *win) > +{ > + struct vop2 *vop2 = win->vop2; > + int i; > + struct reg_field vop2_esmart_regs[VOP2_WIN_MAX_REG] = { > + [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 0, 0), > + [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 1, 5), > + [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 12, 12), > + [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 14, 14), > + [VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 16, 16), > + [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_SMART_REGION0_ACT_INFO, 0, 31), > + [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_SMART_REGION0_DSP_INFO, 0, 31), > + [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_SMART_REGION0_DSP_ST, 0, 28), > + [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_SMART_REGION0_YRGB_MST, 0, 31), > + [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_SMART_REGION0_CBR_MST, 0, 31), > + [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 17, 17), > + [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 0, 15), > + [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 16, 31), > + [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_SMART_CTRL0, 0, 0), > + [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_SMART_CTRL0, 1, 1), > + [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_SMART_CTRL0, 2, 3), > + [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_SMART_CTRL1, 31, 31), > + [VOP2_WIN_COLOR_KEY] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 0, 29), > + [VOP2_WIN_COLOR_KEY_EN] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 31, 31), > + > + /* Scale */ > + [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0, 15), > + [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 16, 31), > + [VOP2_WIN_SCALE_CBCR_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0, 15), > + [VOP2_WIN_SCALE_CBCR_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 16, 31), > + [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 0, 1), > + [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 2, 3), > + [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 4, 5), > + [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 6, 7), > + [VOP2_WIN_CBCR_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 8, 9), > + [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 10, 11), > + [VOP2_WIN_CBCR_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 12, 13), > + [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 14, 15), > + [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 16, 17), > + [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 8, 8), > + [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 9, 9), > + [VOP2_WIN_VSD_CBCR_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 10, 10), > + [VOP2_WIN_VSD_CBCR_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 11, 11), > + [VOP2_WIN_XMIRROR] = { .reg = 0xffffffff }, > + [VOP2_WIN_CLUSTER_ENABLE] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_ENABLE] = { .reg = 0xffffffff }, > + [VOP2_WIN_CLUSTER_LB_MODE] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_FORMAT] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_RB_SWAP] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_UV_SWAP] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_AUTO_GATING_EN] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_TILE_NUM] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_PIC_OFFSET] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_PIC_SIZE] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_DSP_OFFSET] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_TRANSFORM_OFFSET] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_HDR_PTR] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_HALF_BLOCK_EN] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_ROTATE_270] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff }, > + }; > + > + for (i = 0; i < ARRAY_SIZE(vop2_esmart_regs); i++) > + vop2_esmart_regs[i].reg += win->offset; > + > + return devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg, > + vop2_esmart_regs, > + ARRAY_SIZE(vop2_esmart_regs)); > +}; > + > +static int vop2_win_init(struct vop2 *vop2) > +{ > + const struct vop2_data *vop2_data = vop2->data; > + struct vop2_win *win; > + int i, ret; > + > + for (i = 0; i < vop2_data->win_size; i++) { > + const struct vop2_win_data *win_data = &vop2_data->win[i]; > + > + win = &vop2->win[i]; > + win->data = win_data; > + win->type = win_data->type; > + win->offset = win_data->base; > + win->win_id = i; > + win->vop2 = vop2; > + if (vop2_cluster_window(win)) > + ret = vop2_cluster_init(win); > + else > + ret = vop2_esmart_init(win); > + if (ret) > + return ret; > + } > + > + vop2->registered_num_wins = vop2_data->win_size; > + > + return 0; > +} > + > +/* > + * The window registers are only updated when config done is written. > + * Until that they read back the old value. As we read-modify-write > + * these registers mark them as non-volatile. This makes sure we read > + * the new values from the regmap register cache. > + */ I thinks we should be very carefully about switch to regmap. Most of the registers are take effect by frame sync(that is you write the config done bit and when vsync interrupt come), Not only windows register, but also the SYS_CTRL, post processor(VP0/1/2),  OVERLAY, hdr and so on. > +static const struct regmap_range vop2_nonvolatile_range[] = { > + regmap_reg_range(0x1000, 0x23ff), > +}; > + > +static const struct regmap_access_table vop2_volatile_table = { > + .no_ranges = vop2_nonvolatile_range, > + .n_no_ranges = ARRAY_SIZE(vop2_nonvolatile_range), > +}; > + > +static const struct regmap_config vop2_regmap_config = { > + .reg_bits = 32, > + .val_bits = 32, > + .reg_stride = 4, > + .max_register = 0x3000, > + .name = "vop2", > + .volatile_table = &vop2_volatile_table, > + .cache_type = REGCACHE_RBTREE, > +}; > + > +static int vop2_bind(struct device *dev, struct device *master, void *data) > +{ > + struct platform_device *pdev = to_platform_device(dev); > + const struct vop2_data *vop2_data; > + struct drm_device *drm = data; > + struct vop2 *vop2; > + struct resource *res; > + size_t alloc_size; > + int ret; > + > + vop2_data = of_device_get_match_data(dev); > + if (!vop2_data) > + return -ENODEV; > + > + /* Allocate vop2 struct and its vop2_win array */ > + alloc_size = sizeof(*vop2) + sizeof(*vop2->win) * vop2_data->win_size; > + vop2 = devm_kzalloc(dev, alloc_size, GFP_KERNEL); > + if (!vop2) > + return -ENOMEM; > + > + vop2->dev = dev; > + vop2->data = vop2_data; > + vop2->drm = drm; > + > + dev_set_drvdata(dev, vop2); > + > + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); > + if (!res) { > + drm_err(vop2->drm, "failed to get vop2 register byname\n"); > + return -EINVAL; > + } > + > + vop2->regs = devm_ioremap_resource(dev, res); > + if (IS_ERR(vop2->regs)) > + return PTR_ERR(vop2->regs); > + vop2->len = resource_size(res); > + > + vop2->map = devm_regmap_init_mmio(dev, vop2->regs, &vop2_regmap_config); > + > + ret = vop2_win_init(vop2); > + if (ret) > + return ret; Do you have a count about how much time the function vop2_win_init cost ? > + > + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gamma_lut"); > + if (res) { > + vop2->lut_regs = devm_ioremap_resource(dev, res); > + if (IS_ERR(vop2->lut_regs)) > + return PTR_ERR(vop2->lut_regs); > + } > + > + vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf"); > + > + vop2->hclk = devm_clk_get(vop2->dev, "hclk_vop"); > + if (IS_ERR(vop2->hclk)) { > + drm_err(vop2->drm, "failed to get hclk source\n"); > + return PTR_ERR(vop2->hclk); > + } > + > + vop2->aclk = devm_clk_get(vop2->dev, "aclk_vop"); > + if (IS_ERR(vop2->aclk)) { > + drm_err(vop2->drm, "failed to get aclk source\n"); > + return PTR_ERR(vop2->aclk); > + } > + > + vop2->irq = platform_get_irq(pdev, 0); > + if (vop2->irq < 0) { > + drm_err(vop2->drm, "cannot find irq for vop2\n"); > + return vop2->irq; > + } > + > + spin_lock_init(&vop2->reg_lock); > + mutex_init(&vop2->vop2_lock); > + > + ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2); > + if (ret) > + return ret; > + > + ret = rockchip_drm_dma_attach_device(vop2->drm, vop2->dev); > + if (ret) { > + drm_err(vop2->drm, "failed to attach dma mapping, %d\n", ret); > + return ret; > + } > + > + ret = vop2_create_crtc(vop2); > + if (ret) > + return ret; > + > + pm_runtime_enable(&pdev->dev); > + > + return 0; > +} > + > +static void vop2_unbind(struct device *dev, struct device *master, void *data) > +{ > + struct vop2 *vop2 = dev_get_drvdata(dev); > + struct drm_device *drm = vop2->drm; > + struct list_head *plane_list = &drm->mode_config.plane_list; > + struct list_head *crtc_list = &drm->mode_config.crtc_list; > + struct drm_crtc *crtc, *tmpc; > + struct drm_plane *plane, *tmpp; > + > + rockchip_drm_dma_detach_device(vop2->drm, vop2->dev); > + > + pm_runtime_disable(dev); > + > + list_for_each_entry_safe(plane, tmpp, plane_list, head) > + drm_plane_cleanup(plane); > + > + list_for_each_entry_safe(crtc, tmpc, crtc_list, head) > + vop2_destroy_crtc(crtc); > +} > + > +const struct component_ops vop2_component_ops = { > + .bind = vop2_bind, > + .unbind = vop2_unbind, > +}; > +EXPORT_SYMBOL_GPL(vop2_component_ops); > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > new file mode 100644 > index 0000000000000..bb5677ff00e93 > --- /dev/null > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > @@ -0,0 +1,480 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd > + * Author:Mark Yao > + */ > + > +#ifndef _ROCKCHIP_DRM_VOP2_H > +#define _ROCKCHIP_DRM_VOP2_H > + > +#include "rockchip_drm_vop.h" > + > +#include > +#include > + > +#define VOP_FEATURE_OUTPUT_10BIT BIT(0) > + > +#define WIN_FEATURE_AFBDC BIT(0) > +#define WIN_FEATURE_CLUSTER BIT(1) > + > +/* > + * the delay number of a window in different mode. > + */ > +enum win_dly_mode { > + VOP2_DLY_MODE_DEFAULT, /**< default mode */ > + VOP2_DLY_MODE_HISO_S, /** HDR in SDR out mode, as a SDR window */ > + VOP2_DLY_MODE_HIHO_H, /** HDR in HDR out mode, as a HDR window */ > + VOP2_DLY_MODE_MAX, > +}; > + > +struct vop_rect { > + int width; > + int height; > +}; > + > +enum vop2_scale_up_mode { > + VOP2_SCALE_UP_NRST_NBOR, > + VOP2_SCALE_UP_BIL, > + VOP2_SCALE_UP_BIC, > +}; > + > +enum vop2_scale_down_mode { > + VOP2_SCALE_DOWN_NRST_NBOR, > + VOP2_SCALE_DOWN_BIL, > + VOP2_SCALE_DOWN_AVG, > +}; > + > +enum vop2_win_regs { > + VOP2_WIN_ENABLE, > + VOP2_WIN_FORMAT, > + VOP2_WIN_CSC_MODE, > + VOP2_WIN_XMIRROR, > + VOP2_WIN_YMIRROR, > + VOP2_WIN_RB_SWAP, > + VOP2_WIN_UV_SWAP, > + VOP2_WIN_ACT_INFO, > + VOP2_WIN_DSP_INFO, > + VOP2_WIN_DSP_ST, > + VOP2_WIN_YRGB_MST, > + VOP2_WIN_UV_MST, > + VOP2_WIN_YRGB_VIR, > + VOP2_WIN_UV_VIR, > + VOP2_WIN_YUV_CLIP, > + VOP2_WIN_Y2R_EN, > + VOP2_WIN_R2Y_EN, > + VOP2_WIN_COLOR_KEY, > + VOP2_WIN_COLOR_KEY_EN, > + VOP2_WIN_DITHER_UP, > + > + /* scale regs */ > + VOP2_WIN_SCALE_YRGB_X, > + VOP2_WIN_SCALE_YRGB_Y, > + VOP2_WIN_SCALE_CBCR_X, > + VOP2_WIN_SCALE_CBCR_Y, > + VOP2_WIN_YRGB_HOR_SCL_MODE, > + VOP2_WIN_YRGB_HSCL_FILTER_MODE, > + VOP2_WIN_YRGB_VER_SCL_MODE, > + VOP2_WIN_YRGB_VSCL_FILTER_MODE, > + VOP2_WIN_CBCR_VER_SCL_MODE, > + VOP2_WIN_CBCR_HSCL_FILTER_MODE, > + VOP2_WIN_CBCR_HOR_SCL_MODE, > + VOP2_WIN_CBCR_VSCL_FILTER_MODE, > + VOP2_WIN_VSD_CBCR_GT2, > + VOP2_WIN_VSD_CBCR_GT4, > + VOP2_WIN_VSD_YRGB_GT2, > + VOP2_WIN_VSD_YRGB_GT4, > + VOP2_WIN_BIC_COE_SEL, > + > + /* cluster regs */ > + VOP2_WIN_CLUSTER_ENABLE, > + VOP2_WIN_AFBC_ENABLE, > + VOP2_WIN_CLUSTER_LB_MODE, > + > + /* afbc regs */ > + VOP2_WIN_AFBC_FORMAT, > + VOP2_WIN_AFBC_RB_SWAP, > + VOP2_WIN_AFBC_UV_SWAP, > + VOP2_WIN_AFBC_AUTO_GATING_EN, > + VOP2_WIN_AFBC_BLOCK_SPLIT_EN, > + VOP2_WIN_AFBC_PIC_VIR_WIDTH, > + VOP2_WIN_AFBC_TILE_NUM, > + VOP2_WIN_AFBC_PIC_OFFSET, > + VOP2_WIN_AFBC_PIC_SIZE, > + VOP2_WIN_AFBC_DSP_OFFSET, > + VOP2_WIN_AFBC_TRANSFORM_OFFSET, > + VOP2_WIN_AFBC_HDR_PTR, > + VOP2_WIN_AFBC_HALF_BLOCK_EN, > + VOP2_WIN_AFBC_ROTATE_270, > + VOP2_WIN_AFBC_ROTATE_90, > + VOP2_WIN_MAX_REG, > +}; > + > +struct vop2_win_data { > + const char *name; > + uint8_t phys_id; > + > + uint32_t base; > + enum drm_plane_type type; > + > + uint32_t nformats; > + const uint32_t *formats; > + const uint64_t *format_modifiers; > + const unsigned int supported_rotations; > + > + /** > + * @layer_sel_id: defined by register OVERLAY_LAYER_SEL of VOP2 > + */ > + int layer_sel_id; > + uint64_t feature; > + > + unsigned int max_upscale_factor; > + unsigned int max_downscale_factor; > + const uint8_t dly[VOP2_DLY_MODE_MAX]; > +}; > + > +struct vop2_video_port_data { > + char id; > + uint32_t feature; > + uint16_t gamma_lut_len; > + uint16_t cubic_lut_len; > + struct vop_rect max_output; > + const u8 pre_scan_max_dly[4]; > + const struct vop2_video_port_regs *regs; > + int offset; > +}; > + > +struct vop2_data { > + uint8_t nr_vps; > + uint8_t nr_mixers; > + uint8_t nr_layers; > + uint8_t nr_gammas; > + const struct vop2_ctrl *ctrl; > + const struct vop2_win_data *win; > + const struct vop2_video_port_data *vp; > + const struct vop_csc_table *csc_table; > + struct vop_rect max_input; > + struct vop_rect max_output; > + > + unsigned int win_size; > + unsigned int soc_id; > +}; > + > +/* interrupt define */ > +#define FS_NEW_INTR BIT(4) > +#define ADDR_SAME_INTR BIT(5) > +#define LINE_FLAG1_INTR BIT(6) > +#define WIN0_EMPTY_INTR BIT(7) > +#define WIN1_EMPTY_INTR BIT(8) > +#define WIN2_EMPTY_INTR BIT(9) > +#define WIN3_EMPTY_INTR BIT(10) > +#define HWC_EMPTY_INTR BIT(11) > +#define POST_BUF_EMPTY_INTR BIT(12) > +#define PWM_GEN_INTR BIT(13) > +#define DMA_FINISH_INTR BIT(14) > +#define FS_FIELD_INTR BIT(15) > +#define FE_INTR BIT(16) > +#define WB_UV_FIFO_FULL_INTR BIT(17) > +#define WB_YRGB_FIFO_FULL_INTR BIT(18) > +#define WB_COMPLETE_INTR BIT(19) > + > +/* > + * display output interface supported by rockchip lcdc > + */ > +#define ROCKCHIP_OUT_MODE_P888 0 > +#define ROCKCHIP_OUT_MODE_BT1120 0 > +#define ROCKCHIP_OUT_MODE_P666 1 > +#define ROCKCHIP_OUT_MODE_P565 2 > +#define ROCKCHIP_OUT_MODE_BT656 5 > +#define ROCKCHIP_OUT_MODE_S888 8 > +#define ROCKCHIP_OUT_MODE_S888_DUMMY 12 > +#define ROCKCHIP_OUT_MODE_YUV420 14 > +/* for use special outface */ > +#define ROCKCHIP_OUT_MODE_AAAA 15 > + > +enum vop_csc_format { > + CSC_BT601L, > + CSC_BT709L, > + CSC_BT601F, > + CSC_BT2020, > +}; > + > +enum src_factor_mode { > + SRC_FAC_ALPHA_ZERO, > + SRC_FAC_ALPHA_ONE, > + SRC_FAC_ALPHA_DST, > + SRC_FAC_ALPHA_DST_INVERSE, > + SRC_FAC_ALPHA_SRC, > + SRC_FAC_ALPHA_SRC_GLOBAL, > +}; > + > +enum dst_factor_mode { > + DST_FAC_ALPHA_ZERO, > + DST_FAC_ALPHA_ONE, > + DST_FAC_ALPHA_SRC, > + DST_FAC_ALPHA_SRC_INVERSE, > + DST_FAC_ALPHA_DST, > + DST_FAC_ALPHA_DST_GLOBAL, > +}; > + > +#define RK3568_GRF_VO_CON1 0x0364 > +/* System registers definition */ > +#define RK3568_REG_CFG_DONE 0x000 > +#define RK3568_VERSION_INFO 0x004 > +#define RK3568_SYS_AUTO_GATING_CTRL 0x008 > +#define RK3568_SYS_AXI_LUT_CTRL 0x024 > +#define RK3568_DSP_IF_EN 0x028 > +#define RK3568_DSP_IF_CTRL 0x02c > +#define RK3568_DSP_IF_POL 0x030 > +#define RK3568_WB_CTRL 0x40 > +#define RK3568_WB_XSCAL_FACTOR 0x44 > +#define RK3568_WB_YRGB_MST 0x48 > +#define RK3568_WB_CBR_MST 0x4C > +#define RK3568_OTP_WIN_EN 0x050 > +#define RK3568_LUT_PORT_SEL 0x058 > +#define RK3568_SYS_STATUS0 0x060 > +#define RK3568_VP_LINE_FLAG(vp) (0x70 + (vp) * 0x4) > +#define RK3568_SYS0_INT_EN 0x80 > +#define RK3568_SYS0_INT_CLR 0x84 > +#define RK3568_SYS0_INT_STATUS 0x88 > +#define RK3568_SYS1_INT_EN 0x90 > +#define RK3568_SYS1_INT_CLR 0x94 > +#define RK3568_SYS1_INT_STATUS 0x98 > +#define RK3568_VP_INT_EN(vp) (0xA0 + (vp) * 0x10) > +#define RK3568_VP_INT_CLR(vp) (0xA4 + (vp) * 0x10) > +#define RK3568_VP_INT_STATUS(vp) (0xA8 + (vp) * 0x10) > +#define RK3568_VP_INT_RAW_STATUS(vp) (0xAC + (vp) * 0x10) > + > +/* Video Port registers definition */ > +#define RK3568_VP_DSP_CTRL 0x00 > +#define RK3568_VP_MIPI_CTRL 0x04 > +#define RK3568_VP_COLOR_BAR_CTRL 0x08 > +#define RK3568_VP_3D_LUT_CTRL 0x10 > +#define RK3568_VP_3D_LUT_MST 0x20 > +#define RK3568_VP_DSP_BG 0x2C > +#define RK3568_VP_PRE_SCAN_HTIMING 0x30 > +#define RK3568_VP_POST_DSP_HACT_INFO 0x34 > +#define RK3568_VP_POST_DSP_VACT_INFO 0x38 > +#define RK3568_VP_POST_SCL_FACTOR_YRGB 0x3C > +#define RK3568_VP_POST_SCL_CTRL 0x40 > +#define RK3568_VP_POST_DSP_VACT_INFO_F1 0x44 > +#define RK3568_VP_DSP_HTOTAL_HS_END 0x48 > +#define RK3568_VP_DSP_HACT_ST_END 0x4C > +#define RK3568_VP_DSP_VTOTAL_VS_END 0x50 > +#define RK3568_VP_DSP_VACT_ST_END 0x54 > +#define RK3568_VP_DSP_VS_ST_END_F1 0x58 > +#define RK3568_VP_DSP_VACT_ST_END_F1 0x5C > +#define RK3568_VP_BCSH_CTRL 0x60 > +#define RK3568_VP_BCSH_BCS 0x64 > +#define RK3568_VP_BCSH_H 0x68 > +#define RK3568_VP_BCSH_COLOR_BAR 0x6C > + > +/* Overlay registers definition */ > +#define RK3568_OVL_CTRL 0x600 > +#define RK3568_OVL_LAYER_SEL 0x604 > +#define RK3568_OVL_PORT_SEL 0x608 > +#define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610 > +#define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614 > +#define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618 > +#define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C > +#define RK3568_MIX0_SRC_COLOR_CTRL 0x650 > +#define RK3568_MIX0_DST_COLOR_CTRL 0x654 > +#define RK3568_MIX0_SRC_ALPHA_CTRL 0x658 > +#define RK3568_MIX0_DST_ALPHA_CTRL 0x65C > +#define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0 > +#define RK3568_HDR0_DST_COLOR_CTRL 0x6C4 > +#define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8 > +#define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC > +#define RK3568_VP_BG_MIX_CTRL(vp) (0x6E0 + (vp) * 4) > +#define RK3568_CLUSTER_DLY_NUM 0x6F0 > +#define RK3568_SMART_DLY_NUM 0x6F8 > + > +/* Cluster register definition, offset relative to window base */ > +#define RK3568_CLUSTER_WIN_CTRL0 0x00 > +#define RK3568_CLUSTER_WIN_CTRL1 0x04 > +#define RK3568_CLUSTER_WIN_YRGB_MST 0x10 > +#define RK3568_CLUSTER_WIN_CBR_MST 0x14 > +#define RK3568_CLUSTER_WIN_VIR 0x18 > +#define RK3568_CLUSTER_WIN_ACT_INFO 0x20 > +#define RK3568_CLUSTER_WIN_DSP_INFO 0x24 > +#define RK3568_CLUSTER_WIN_DSP_ST 0x28 > +#define RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB 0x30 > +#define RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET 0x3C > +#define RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL 0x50 > +#define RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE 0x54 > +#define RK3568_CLUSTER_WIN_AFBCD_HDR_PTR 0x58 > +#define RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH 0x5C > +#define RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE 0x60 > +#define RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET 0x64 > +#define RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET 0x68 > +#define RK3568_CLUSTER_WIN_AFBCD_CTRL 0x6C > + > +#define RK3568_CLUSTER_CTRL 0x100 > + > +/* (E)smart register definition, offset relative to window base */ > +#define RK3568_SMART_CTRL0 0x00 > +#define RK3568_SMART_CTRL1 0x04 > +#define RK3568_SMART_REGION0_CTRL 0x10 > +#define RK3568_SMART_REGION0_YRGB_MST 0x14 > +#define RK3568_SMART_REGION0_CBR_MST 0x18 > +#define RK3568_SMART_REGION0_VIR 0x1C > +#define RK3568_SMART_REGION0_ACT_INFO 0x20 > +#define RK3568_SMART_REGION0_DSP_INFO 0x24 > +#define RK3568_SMART_REGION0_DSP_ST 0x28 > +#define RK3568_SMART_REGION0_SCL_CTRL 0x30 > +#define RK3568_SMART_REGION0_SCL_FACTOR_YRGB 0x34 > +#define RK3568_SMART_REGION0_SCL_FACTOR_CBR 0x38 > +#define RK3568_SMART_REGION0_SCL_OFFSET 0x3C > +#define RK3568_SMART_REGION1_CTRL 0x40 > +#define RK3568_SMART_REGION1_YRGB_MST 0x44 > +#define RK3568_SMART_REGION1_CBR_MST 0x48 > +#define RK3568_SMART_REGION1_VIR 0x4C > +#define RK3568_SMART_REGION1_ACT_INFO 0x50 > +#define RK3568_SMART_REGION1_DSP_INFO 0x54 > +#define RK3568_SMART_REGION1_DSP_ST 0x58 > +#define RK3568_SMART_REGION1_SCL_CTRL 0x60 > +#define RK3568_SMART_REGION1_SCL_FACTOR_YRGB 0x64 > +#define RK3568_SMART_REGION1_SCL_FACTOR_CBR 0x68 > +#define RK3568_SMART_REGION1_SCL_OFFSET 0x6C > +#define RK3568_SMART_REGION2_CTRL 0x70 > +#define RK3568_SMART_REGION2_YRGB_MST 0x74 > +#define RK3568_SMART_REGION2_CBR_MST 0x78 > +#define RK3568_SMART_REGION2_VIR 0x7C > +#define RK3568_SMART_REGION2_ACT_INFO 0x80 > +#define RK3568_SMART_REGION2_DSP_INFO 0x84 > +#define RK3568_SMART_REGION2_DSP_ST 0x88 > +#define RK3568_SMART_REGION2_SCL_CTRL 0x90 > +#define RK3568_SMART_REGION2_SCL_FACTOR_YRGB 0x94 > +#define RK3568_SMART_REGION2_SCL_FACTOR_CBR 0x98 > +#define RK3568_SMART_REGION2_SCL_OFFSET 0x9C > +#define RK3568_SMART_REGION3_CTRL 0xA0 > +#define RK3568_SMART_REGION3_YRGB_MST 0xA4 > +#define RK3568_SMART_REGION3_CBR_MST 0xA8 > +#define RK3568_SMART_REGION3_VIR 0xAC > +#define RK3568_SMART_REGION3_ACT_INFO 0xB0 > +#define RK3568_SMART_REGION3_DSP_INFO 0xB4 > +#define RK3568_SMART_REGION3_DSP_ST 0xB8 > +#define RK3568_SMART_REGION3_SCL_CTRL 0xC0 > +#define RK3568_SMART_REGION3_SCL_FACTOR_YRGB 0xC4 > +#define RK3568_SMART_REGION3_SCL_FACTOR_CBR 0xC8 > +#define RK3568_SMART_REGION3_SCL_OFFSET 0xCC > +#define RK3568_SMART_COLOR_KEY_CTRL 0xD0 > + > +/* HDR register definition */ > +#define RK3568_HDR_LUT_CTRL 0x2000 > +#define RK3568_HDR_LUT_MST 0x2004 > +#define RK3568_SDR2HDR_CTRL 0x2010 > +#define RK3568_HDR2SDR_CTRL 0x2020 > +#define RK3568_HDR2SDR_SRC_RANGE 0x2024 > +#define RK3568_HDR2SDR_NORMFACEETF 0x2028 > +#define RK3568_HDR2SDR_DST_RANGE 0x202C > +#define RK3568_HDR2SDR_NORMFACCGAMMA 0x2030 > +#define RK3568_HDR_EETF_OETF_Y0 0x203C > +#define RK3568_HDR_SAT_Y0 0x20C0 > +#define RK3568_HDR_EOTF_OETF_Y0 0x20F0 > +#define RK3568_HDR_OETF_DX_POW1 0x2200 > +#define RK3568_HDR_OETF_XN1 0x2300 > + > +#define RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN BIT(15) > + > +#define RK3568_VP_DSP_CTRL__STANDBY BIT(31) > +#define RK3568_VP_DSP_CTRL__DITHER_DOWN_MODE BIT(20) > +#define RK3568_VP_DSP_CTRL__DITHER_DOWN_SEL GENMASK(19, 18) > +#define RK3568_VP_DSP_CTRL__DITHER_DOWN_EN BIT(17) > +#define RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN BIT(16) > +#define RK3568_VP_DSP_CTRL__POST_DSP_OUT_R2Y BIT(15) > +#define RK3568_VP_DSP_CTRL__DSP_RB_SWAP BIT(9) > +#define RK3568_VP_DSP_CTRL__DSP_INTERLACE BIT(7) > +#define RK3568_VP_DSP_CTRL__DSP_FILED_POL BIT(6) > +#define RK3568_VP_DSP_CTRL__P2I_EN BIT(5) > +#define RK3568_VP_DSP_CTRL__CORE_DCLK_DIV BIT(4) > +#define RK3568_VP_DSP_CTRL__OUT_MODE GENMASK(3, 0) > + > +#define RK3568_VP_POST_SCL_CTRL__VSCALEDOWN BIT(1) > +#define RK3568_VP_POST_SCL_CTRL__HSCALEDOWN BIT(0) > + > +#define RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX GENMASK(26, 25) > +#define RK3568_SYS_DSP_INFACE_EN_LVDS1 BIT(24) > +#define RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX GENMASK(22, 21) > +#define RK3568_SYS_DSP_INFACE_EN_MIPI1 BIT(20) > +#define RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX GENMASK(19, 18) > +#define RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX GENMASK(17, 16) > +#define RK3568_SYS_DSP_INFACE_EN_EDP_MUX GENMASK(15, 14) > +#define RK3568_SYS_DSP_INFACE_EN_HDMI_MUX GENMASK(11, 10) > +#define RK3568_SYS_DSP_INFACE_EN_RGB_MUX GENMASK(9, 8) > +#define RK3568_SYS_DSP_INFACE_EN_LVDS0 BIT(5) > +#define RK3568_SYS_DSP_INFACE_EN_MIPI0 BIT(4) > +#define RK3568_SYS_DSP_INFACE_EN_EDP BIT(3) > +#define RK3568_SYS_DSP_INFACE_EN_HDMI BIT(1) > +#define RK3568_SYS_DSP_INFACE_EN_RGB BIT(0) > + > +#define RK3568_DSP_IF_POL__MIPI_PIN_POL GENMASK(19, 16) > +#define RK3568_DSP_IF_POL__EDP_PIN_POL GENMASK(15, 12) > +#define RK3568_DSP_IF_POL__HDMI_PIN_POL GENMASK(7, 4) > +#define RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL GENMASK(3, 0) > + > +#define RK3568_VP0_MIPI_CTRL__DCLK_DIV2_PHASE_LOCK BIT(5) > +#define RK3568_VP0_MIPI_CTRL__DCLK_DIV2 BIT(4) > + > +#define RK3568_SYS_AUTO_GATING_CTRL__AUTO_GATING_EN BIT(31) > + > +#define RK3568_DSP_IF_POL__CFG_DONE_IMD BIT(28) > + > +#define VOP2_SYS_AXI_BUS_NUM 2 > + > +#define VOP2_CLUSTER_YUV444_10 0x12 > + > +#define VOP2_COLOR_KEY_MASK BIT(31) > + > +#define RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD BIT(28) > + > +#define RK3568_VP_BG_MIX_CTRL__BG_DLY GENMASK(31, 24) > + > +#define RK3568_OVL_PORT_SEL__SEL_PORT GENMASK(31, 16) > +#define RK3568_OVL_PORT_SEL__SMART1 GENMASK(31, 30) > +#define RK3568_OVL_PORT_SEL__SMART0 GENMASK(29, 28) > +#define RK3568_OVL_PORT_SEL__ESMART1 GENMASK(27, 26) > +#define RK3568_OVL_PORT_SEL__ESMART0 GENMASK(25, 24) > +#define RK3568_OVL_PORT_SEL__CLUSTER1 GENMASK(19, 18) > +#define RK3568_OVL_PORT_SEL__CLUSTER0 GENMASK(17, 16) > +#define RK3568_OVL_PORT_SET__PORT2_MUX GENMASK(11, 8) > +#define RK3568_OVL_PORT_SET__PORT1_MUX GENMASK(7, 4) > +#define RK3568_OVL_PORT_SET__PORT0_MUX GENMASK(3, 0) > +#define RK3568_OVL_LAYER_SEL__LAYER(layer, x) ((x) << ((layer) * 4)) > + > +#define RK3568_CLUSTER_DLY_NUM__CLUSTER1_1 GENMASK(31, 24) > +#define RK3568_CLUSTER_DLY_NUM__CLUSTER1_0 GENMASK(23, 16) > +#define RK3568_CLUSTER_DLY_NUM__CLUSTER0_1 GENMASK(15, 8) > +#define RK3568_CLUSTER_DLY_NUM__CLUSTER0_0 GENMASK(7, 0) > + > +#define RK3568_SMART_DLY_NUM__SMART1 GENMASK(31, 24) > +#define RK3568_SMART_DLY_NUM__SMART0 GENMASK(23, 16) > +#define RK3568_SMART_DLY_NUM__ESMART1 GENMASK(15, 8) > +#define RK3568_SMART_DLY_NUM__ESMART0 GENMASK(7, 0) > + > +#define VP_INT_DSP_HOLD_VALID BIT(6) > +#define VP_INT_FS_FIELD BIT(5) > +#define VP_INT_POST_BUF_EMPTY BIT(4) > +#define VP_INT_LINE_FLAG1 BIT(3) > +#define VP_INT_LINE_FLAG0 BIT(2) > +#define VOP2_INT_BUS_ERRPR BIT(1) > +#define VP_INT_FS BIT(0) > + > +#define POLFLAG_DCLK_INV BIT(3) > + > +enum vop2_layer_phy_id { > + ROCKCHIP_VOP2_CLUSTER0 = 0, > + ROCKCHIP_VOP2_CLUSTER1, > + ROCKCHIP_VOP2_ESMART0, > + ROCKCHIP_VOP2_ESMART1, > + ROCKCHIP_VOP2_SMART0, > + ROCKCHIP_VOP2_SMART1, > + ROCKCHIP_VOP2_CLUSTER2, > + ROCKCHIP_VOP2_CLUSTER3, > + ROCKCHIP_VOP2_ESMART2, > + ROCKCHIP_VOP2_ESMART3, > + ROCKCHIP_VOP2_PHY_ID_INVALID = -1, > +}; > + > +extern const struct component_ops vop2_component_ops; > + > +#endif /* _ROCKCHIP_DRM_VOP2_H */ > diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > new file mode 100644 > index 0000000000000..2376e63d9478f > --- /dev/null > +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > @@ -0,0 +1,285 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (C) Rockchip Electronics Co.Ltd > + * Author: Andy Yan > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "rockchip_drm_vop2.h" > + > +static const uint32_t formats_win_full_10bit[] = { > + DRM_FORMAT_XRGB8888, > + DRM_FORMAT_ARGB8888, > + DRM_FORMAT_XBGR8888, > + DRM_FORMAT_ABGR8888, > + DRM_FORMAT_RGB888, > + DRM_FORMAT_BGR888, > + DRM_FORMAT_RGB565, > + DRM_FORMAT_BGR565, > + DRM_FORMAT_NV12, > + DRM_FORMAT_NV16, > + DRM_FORMAT_NV24, > +}; > + > +static const uint32_t formats_win_full_10bit_yuyv[] = { > + DRM_FORMAT_XRGB8888, > + DRM_FORMAT_ARGB8888, > + DRM_FORMAT_XBGR8888, > + DRM_FORMAT_ABGR8888, > + DRM_FORMAT_RGB888, > + DRM_FORMAT_BGR888, > + DRM_FORMAT_RGB565, > + DRM_FORMAT_BGR565, > + DRM_FORMAT_NV12, > + DRM_FORMAT_NV16, > + DRM_FORMAT_NV24, > + DRM_FORMAT_YVYU, > + DRM_FORMAT_VYUY, > +}; > + > +static const uint32_t formats_win_lite[] = { > + DRM_FORMAT_XRGB8888, > + DRM_FORMAT_ARGB8888, > + DRM_FORMAT_XBGR8888, > + DRM_FORMAT_ABGR8888, > + DRM_FORMAT_RGB888, > + DRM_FORMAT_BGR888, > + DRM_FORMAT_RGB565, > + DRM_FORMAT_BGR565, > +}; > + > +static const uint64_t format_modifiers[] = { > + DRM_FORMAT_MOD_LINEAR, > + DRM_FORMAT_MOD_INVALID, > +}; > + > +static const uint64_t format_modifiers_afbc[] = { > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16), > + > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_SPARSE), > + > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_YTR), > + > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_CBR), > + > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_YTR | > + AFBC_FORMAT_MOD_SPARSE), > + > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_CBR | > + AFBC_FORMAT_MOD_SPARSE), > + > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_YTR | > + AFBC_FORMAT_MOD_CBR), > + > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_YTR | > + AFBC_FORMAT_MOD_CBR | > + AFBC_FORMAT_MOD_SPARSE), > + > + /* SPLIT mandates SPARSE, RGB modes mandates YTR */ > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_YTR | > + AFBC_FORMAT_MOD_SPARSE | > + AFBC_FORMAT_MOD_SPLIT), > + DRM_FORMAT_MOD_INVALID, > +}; > + > +static const struct vop2_video_port_data rk3568_vop_video_ports[] = { > + { > + .id = 0, > + .feature = VOP_FEATURE_OUTPUT_10BIT, > + .gamma_lut_len = 1024, > + .cubic_lut_len = 9 * 9 * 9, > + .max_output = { 4096, 2304 }, > + .pre_scan_max_dly = { 69, 53, 53, 42 }, > + .offset = 0xc00, > + }, { > + .id = 1, > + .gamma_lut_len = 1024, > + .max_output = { 2048, 1536 }, > + .pre_scan_max_dly = { 40, 40, 40, 40 }, > + .offset = 0xd00, > + }, { > + .id = 2, > + .gamma_lut_len = 1024, > + .max_output = { 1920, 1080 }, > + .pre_scan_max_dly = { 40, 40, 40, 40 }, > + .offset = 0xe00, > + }, > +}; > + > +/* > + * rk3568 vop with 2 cluster, 2 esmart win, 2 smart win. > + * Every cluster can work as 4K win or split into two win. > + * All win in cluster support AFBCD. > + * > + * Every esmart win and smart win support 4 Multi-region. > + * > + * Scale filter mode: > + * > + * * Cluster: bicubic for horizontal scale up, others use bilinear > + * * ESmart: > + * * nearest-neighbor/bilinear/bicubic for scale up > + * * nearest-neighbor/bilinear/average for scale down > + * > + * > + * @TODO describe the wind like cpu-map dt nodes; > + */ > +static const struct vop2_win_data rk3568_vop_win_data[] = { > + { > + .name = "Smart0-win0", > + .phys_id = ROCKCHIP_VOP2_SMART0, > + .base = 0x1c00, > + .formats = formats_win_lite, > + .nformats = ARRAY_SIZE(formats_win_lite), > + .format_modifiers = format_modifiers, > + .layer_sel_id = 3, > + .supported_rotations = DRM_MODE_REFLECT_Y, > + .type = DRM_PLANE_TYPE_PRIMARY, > + .max_upscale_factor = 8, > + .max_downscale_factor = 8, > + .dly = { 20, 47, 41 }, > + }, { > + .name = "Smart1-win0", > + .phys_id = ROCKCHIP_VOP2_SMART1, > + .formats = formats_win_lite, > + .nformats = ARRAY_SIZE(formats_win_lite), > + .format_modifiers = format_modifiers, > + .base = 0x1e00, > + .layer_sel_id = 7, > + .supported_rotations = DRM_MODE_REFLECT_Y, > + .type = DRM_PLANE_TYPE_PRIMARY, > + .max_upscale_factor = 8, > + .max_downscale_factor = 8, > + .dly = { 20, 47, 41 }, > + }, { > + .name = "Esmart1-win0", > + .phys_id = ROCKCHIP_VOP2_ESMART1, > + .formats = formats_win_full_10bit_yuyv, > + .nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv), > + .format_modifiers = format_modifiers, > + .base = 0x1a00, > + .layer_sel_id = 6, > + .supported_rotations = DRM_MODE_REFLECT_Y, > + .type = DRM_PLANE_TYPE_PRIMARY, > + .max_upscale_factor = 8, > + .max_downscale_factor = 8, > + .dly = { 20, 47, 41 }, > + }, { > + .name = "Esmart0-win0", > + .phys_id = ROCKCHIP_VOP2_ESMART0, > + .formats = formats_win_full_10bit_yuyv, > + .nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv), > + .format_modifiers = format_modifiers, > + .base = 0x1800, > + .layer_sel_id = 2, > + .supported_rotations = DRM_MODE_REFLECT_Y, > + .type = DRM_PLANE_TYPE_OVERLAY, > + .max_upscale_factor = 8, > + .max_downscale_factor = 8, > + .dly = { 20, 47, 41 }, > + }, { > + .name = "Cluster0-win0", > + .phys_id = ROCKCHIP_VOP2_CLUSTER0, > + .base = 0x1000, > + .formats = formats_win_full_10bit, > + .nformats = ARRAY_SIZE(formats_win_full_10bit), > + .format_modifiers = format_modifiers_afbc, > + .layer_sel_id = 0, > + .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | > + DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, > + .max_upscale_factor = 4, > + .max_downscale_factor = 4, > + .dly = { 0, 27, 21 }, > + .type = DRM_PLANE_TYPE_OVERLAY, > + .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER, > + }, { > + .name = "Cluster1-win0", > + .phys_id = ROCKCHIP_VOP2_CLUSTER1, > + .base = 0x1200, > + .formats = formats_win_full_10bit, > + .nformats = ARRAY_SIZE(formats_win_full_10bit), > + .format_modifiers = format_modifiers_afbc, > + .layer_sel_id = 1, > + .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | > + DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, > + .type = DRM_PLANE_TYPE_OVERLAY, > + .max_upscale_factor = 4, > + .max_downscale_factor = 4, > + .dly = { 0, 27, 21 }, > + .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER, > + }, > +}; > + > +static const struct vop2_data rk3566_vop = { > + .nr_vps = 3, > + .nr_mixers = 5, > + .nr_gammas = 1, > + .max_input = { 4096, 2304 }, > + .max_output = { 4096, 2304 }, > + .vp = rk3568_vop_video_ports, > + .win = rk3568_vop_win_data, > + .win_size = ARRAY_SIZE(rk3568_vop_win_data), > + .soc_id = 3566, > +}; > + > +static const struct vop2_data rk3568_vop = { > + .nr_vps = 3, > + .nr_mixers = 5, > + .nr_gammas = 1, > + .max_input = { 4096, 2304 }, > + .max_output = { 4096, 2304 }, > + .vp = rk3568_vop_video_ports, > + .win = rk3568_vop_win_data, > + .win_size = ARRAY_SIZE(rk3568_vop_win_data), > + .soc_id = 3568, > +}; > + > +static const struct of_device_id vop2_dt_match[] = { > + { > + .compatible = "rockchip,rk3566-vop", > + .data = &rk3566_vop, > + }, { > + .compatible = "rockchip,rk3568-vop", > + .data = &rk3568_vop, > + }, { > + }, > +}; > +MODULE_DEVICE_TABLE(of, vop2_dt_match); > + > +static int vop2_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + > + return component_add(dev, &vop2_component_ops); > +} > + > +static int vop2_remove(struct platform_device *pdev) > +{ > + component_del(&pdev->dev, &vop2_component_ops); > + > + return 0; > +} > + > +struct platform_driver vop2_platform_driver = { > + .probe = vop2_probe, > + .remove = vop2_remove, > + .driver = { > + .name = "rockchip-vop2", > + .of_match_table = of_match_ptr(vop2_dt_match), > + }, > +}; 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 8B665C433FE for ; Tue, 4 Jan 2022 11:14:10 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D21BE10E190; Tue, 4 Jan 2022 11:14:09 +0000 (UTC) X-Greylist: delayed 385 seconds by postgrey-1.36 at gabe; Tue, 04 Jan 2022 11:14:07 UTC Received: from smtphy.263.net (syd-smtp02.263.net [13.237.61.158]) by gabe.freedesktop.org (Postfix) with ESMTPS id 9083710E190 for ; Tue, 4 Jan 2022 11:14:07 +0000 (UTC) Received: from smtp.263.net (unknown [211.157.147.163]) by smtphy.263.net (Postfix) with ESMTPS id A03A0120026 for ; Tue, 4 Jan 2022 19:07:39 +0800 (CST) Received: from regular1.263xmail.com (unknown [192.168.165.185]) by smtp.263.net (Postfix) with ESMTP id B942319C6 for ; Tue, 4 Jan 2022 19:07:31 +0800 (CST) Received: from localhost (unknown [192.168.167.16]) by regular1.263xmail.com (Postfix) with ESMTP id 58C5A503; Tue, 4 Jan 2022 19:07:25 +0800 (CST) X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-ADDR-CHECKED4: 1 X-SKE-CHECKED: 1 X-ABS-CHECKED: 1 X-ANTISPAM-LEVEL: 2 Received: from [172.16.12.89] (unknown [58.22.7.114]) by smtp.263.net (postfix) whith ESMTP id P12624T140276825810688S1641294444616683_; Tue, 04 Jan 2022 19:07:25 +0800 (CST) X-IP-DOMAINF: 1 X-RL-SENDER: andy.yan@rock-chips.com X-SENDER: yxj@rock-chips.com X-LOGIN-NAME: andy.yan@rock-chips.com X-FST-TO: kever.yang@rock-chips.com X-RCPT-COUNT: 12 X-LOCAL-RCPT-COUNT: 2 X-MUTI-DOMAIN-COUNT: 0 X-SENDER-IP: 58.22.7.114 X-ATTACHMENT-NUM: 0 X-UNIQUE-TAG: X-System-Flag: 0 Subject: Re: [PATCH 22/22] drm: rockchip: Add VOP2 driver To: Sascha Hauer , dri-devel@lists.freedesktop.org References: <20211220110630.3521121-1-s.hauer@pengutronix.de> <20211220110630.3521121-23-s.hauer@pengutronix.de> From: Andy Yan Message-ID: Date: Tue, 4 Jan 2022 19:07:23 +0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.14.0 MIME-Version: 1.0 In-Reply-To: <20211220110630.3521121-23-s.hauer@pengutronix.de> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US 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: , Cc: devicetree@vger.kernel.org, Benjamin Gaignard , Sandy Huang , Kever Yang , linux-rockchip@lists.infradead.org, Michael Riesch , kernel@pengutronix.de, Peter Geis , linux-arm-kernel@lists.infradead.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Hi Sascha: Please add Series-version for all the patch series. add also Series-changes. I saw you have Series-changes in cover-letter, but we usually include them in patch. Here is a link you can take for reference[0] [0]https://source.denx.de/u-boot/u-boot/-/tree/master/tools/patman On 12/20/21 7:06 PM, Sascha Hauer wrote: > From: Andy Yan > > The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568. > It replaces the VOP unit found in the older Rockchip SoCs. > > This driver has been derived from the downstream Rockchip Kernel and > heavily modified: > > - All nonstandard DRM properties have been removed > - dropped struct vop2_plane_state and pass around less data between > functions > - Dropped all DRM_FORMAT_* not known on upstream > - rework register access to get rid of excessively used macros > - Drop all waiting for framesyncs > > The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB > board. Overlay support is tested with the modetest utility. AFBC support > on the cluster windows is tested with weston-simple-dmabuf-egl on > weston using the (yet to be upstreamed) panfrost driver support. > > Signed-off-by: Sascha Hauer > --- > drivers/gpu/drm/rockchip/Kconfig | 6 + > drivers/gpu/drm/rockchip/Makefile | 1 + > drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 1 + > drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 7 +- > drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 2 + > drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 15 + > drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 2768 ++++++++++++++++++ > drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 480 +++ > drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 285 ++ > 9 files changed, 3564 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > create mode 100644 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > > diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig > index b9b156308460a..4ff0043f0ee70 100644 > --- a/drivers/gpu/drm/rockchip/Kconfig > +++ b/drivers/gpu/drm/rockchip/Kconfig > @@ -28,6 +28,12 @@ config ROCKCHIP_VOP > This selects support for the VOP driver. You should enable it > on all older SoCs up to RK3399. > > +config ROCKCHIP_VOP2 > + bool "Rockchip VOP2 driver" > + help > + This selects support for the VOP2 driver. You should enable it > + on all newer SoCs beginning form RK3568. > + > config ROCKCHIP_ANALOGIX_DP > bool "Rockchip specific extensions for Analogix DP driver" > depends on ROCKCHIP_VOP > diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile > index cd6e7bb5ce9c5..29848caef5c21 100644 > --- a/drivers/gpu/drm/rockchip/Makefile > +++ b/drivers/gpu/drm/rockchip/Makefile > @@ -7,6 +7,7 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ > rockchip_drm_gem.o > rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o > > +rockchipdrm-$(CONFIG_ROCKCHIP_VOP2) += rockchip_drm_vop2.o rockchip_vop2_reg.o > rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o > rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o > rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c > index 64fa5fd62c01a..2bd9acb265e5a 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c > @@ -474,6 +474,7 @@ static int __init rockchip_drm_init(void) > > num_rockchip_sub_drivers = 0; > ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP); > + ADD_ROCKCHIP_SUB_DRIVER(vop2_platform_driver, CONFIG_ROCKCHIP_VOP2); > ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver, > CONFIG_ROCKCHIP_LVDS); > ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver, > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h > index aa0909e8edf93..fd6994f21817e 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h > @@ -18,7 +18,7 @@ > > #define ROCKCHIP_MAX_FB_BUFFER 3 > #define ROCKCHIP_MAX_CONNECTOR 2 > -#define ROCKCHIP_MAX_CRTC 2 > +#define ROCKCHIP_MAX_CRTC 4 > > struct drm_device; > struct drm_connector; > @@ -31,6 +31,9 @@ struct rockchip_crtc_state { > int output_bpc; > int output_flags; > bool enable_afbc; > + uint32_t bus_format; > + u32 bus_flags; > + int color_space; > }; > #define to_rockchip_crtc_state(s) \ > container_of(s, struct rockchip_crtc_state, base) > @@ -65,4 +68,6 @@ extern struct platform_driver rockchip_dp_driver; > extern struct platform_driver rockchip_lvds_driver; > extern struct platform_driver vop_platform_driver; > extern struct platform_driver rk3066_hdmi_driver; > +extern struct platform_driver vop2_platform_driver; > + > #endif /* _ROCKCHIP_DRM_DRV_H_ */ > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c > index 3aa37e177667e..0d2cb4f3922b8 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c > @@ -134,4 +134,6 @@ void rockchip_drm_mode_config_init(struct drm_device *dev) > > dev->mode_config.funcs = &rockchip_drm_mode_config_funcs; > dev->mode_config.helper_private = &rockchip_mode_config_helpers; > + > + dev->mode_config.normalize_zpos = true; > } > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h > index 857d97cdc67c6..1e364d7b50e69 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h > @@ -54,9 +54,23 @@ struct vop_afbc { > struct vop_reg enable; > struct vop_reg win_sel; > struct vop_reg format; > + struct vop_reg rb_swap; > + struct vop_reg uv_swap; > + struct vop_reg auto_gating_en; > + struct vop_reg block_split_en; > + struct vop_reg pic_vir_width; > + struct vop_reg tile_num; > struct vop_reg hreg_block_split; > + struct vop_reg pic_offset; > struct vop_reg pic_size; > + struct vop_reg dsp_offset; > + struct vop_reg transform_offset; > struct vop_reg hdr_ptr; > + struct vop_reg half_block_en; > + struct vop_reg xmirror; > + struct vop_reg ymirror; > + struct vop_reg rotate_270; > + struct vop_reg rotate_90; > struct vop_reg rstn; > }; > > @@ -410,4 +424,5 @@ static inline int scl_vop_cal_lb_mode(int width, bool is_yuv) > } > > extern const struct component_ops vop_component_ops; > + > #endif /* _ROCKCHIP_DRM_VOP_H */ > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > new file mode 100644 > index 0000000000000..7d39ba90061d1 > --- /dev/null > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > @@ -0,0 +1,2768 @@ > +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) > +/* > + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. > + * Author: Andy Yan > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include It seems that you removed the writeback code in the driver ? > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "rockchip_drm_drv.h" > +#include "rockchip_drm_gem.h" > +#include "rockchip_drm_fb.h" > +#include "rockchip_drm_vop2.h" > + > +/* > + * VOP2 architecture > + * > + +----------+ +-------------+ +-----------+ > + | Cluster | | Sel 1 from 6| | 1 from 3 | > + | window0 | | Layer0 | | RGB | > + +----------+ +-------------+ +---------------+ +-------------+ +-----------+ > + +----------+ +-------------+ |N from 6 layers| | | > + | Cluster | | Sel 1 from 6| | Overlay0 +--->| Video Port0 | +-----------+ > + | window1 | | Layer1 | | | | | | 1 from 3 | > + +----------+ +-------------+ +---------------+ +-------------+ | LVDS | > + +----------+ +-------------+ +-----------+ > + | Esmart | | Sel 1 from 6| > + | window0 | | Layer2 | +---------------+ +-------------+ +-----------+ > + +----------+ +-------------+ |N from 6 Layers| | | +--> | 1 from 3 | > + +----------+ +-------------+ --------> | Overlay1 +--->| Video Port1 | | MIPI | > + | Esmart | | Sel 1 from 6| --------> | | | | +-----------+ > + | Window1 | | Layer3 | +---------------+ +-------------+ > + +----------+ +-------------+ +-----------+ > + +----------+ +-------------+ | 1 from 3 | > + | Smart | | Sel 1 from 6| +---------------+ +-------------+ | HDMI | > + | Window0 | | Layer4 | |N from 6 Layers| | | +-----------+ > + +----------+ +-------------+ | Overlay2 +--->| Video Port2 | > + +----------+ +-------------+ | | | | +-----------+ > + | Smart | | Sel 1 from 6| +---------------+ +-------------+ | 1 from 3 | > + | Window1 | | Layer5 | | eDP | > + +----------+ +-------------+ +-----------+ > + * > + */ > + > +enum vop2_data_format { > + VOP2_FMT_ARGB8888 = 0, > + VOP2_FMT_RGB888, > + VOP2_FMT_RGB565, > + VOP2_FMT_XRGB101010, > + VOP2_FMT_YUV420SP, > + VOP2_FMT_YUV422SP, > + VOP2_FMT_YUV444SP, > + VOP2_FMT_YUYV422 = 8, > + VOP2_FMT_YUYV420, > + VOP2_FMT_VYUY422, > + VOP2_FMT_VYUY420, > + VOP2_FMT_YUV420SP_TILE_8x4 = 0x10, > + VOP2_FMT_YUV420SP_TILE_16x2, > + VOP2_FMT_YUV422SP_TILE_8x4, > + VOP2_FMT_YUV422SP_TILE_16x2, > + VOP2_FMT_YUV420SP_10, > + VOP2_FMT_YUV422SP_10, > + VOP2_FMT_YUV444SP_10, > +}; > + > +enum vop2_afbc_format { > + VOP2_AFBC_FMT_RGB565, > + VOP2_AFBC_FMT_ARGB2101010 = 2, > + VOP2_AFBC_FMT_YUV420_10BIT, > + VOP2_AFBC_FMT_RGB888, > + VOP2_AFBC_FMT_ARGB8888, > + VOP2_AFBC_FMT_YUV420 = 9, > + VOP2_AFBC_FMT_YUV422 = 0xb, > + VOP2_AFBC_FMT_YUV422_10BIT = 0xe, > + VOP2_AFBC_FMT_INVALID = -1, > +}; > + > +union vop2_alpha_ctrl { > + uint32_t val; > + struct { > + /* [0:1] */ > + uint32_t color_mode:1; > + uint32_t alpha_mode:1; > + /* [2:3] */ > + uint32_t blend_mode:2; > + uint32_t alpha_cal_mode:1; > + /* [5:7] */ > + uint32_t factor_mode:3; > + /* [8:9] */ > + uint32_t alpha_en:1; > + uint32_t src_dst_swap:1; > + uint32_t reserved:6; > + /* [16:23] */ > + uint32_t glb_alpha:8; > + } bits; > +}; > + > +struct vop2_alpha { > + union vop2_alpha_ctrl src_color_ctrl; > + union vop2_alpha_ctrl dst_color_ctrl; > + union vop2_alpha_ctrl src_alpha_ctrl; > + union vop2_alpha_ctrl dst_alpha_ctrl; > +}; > + > +struct vop2_alpha_config { > + bool src_premulti_en; > + bool dst_premulti_en; > + bool src_pixel_alpha_en; > + bool dst_pixel_alpha_en; > + uint16_t src_glb_alpha_value; > + uint16_t dst_glb_alpha_value; > +}; > + > +struct vop2_win { > + struct vop2 *vop2; > + struct drm_plane base; > + const struct vop2_win_data *data; > + struct regmap_field *reg[VOP2_WIN_MAX_REG]; > + > + /** > + * @win_id: graphic window id, a cluster maybe split into two > + * graphics windows. > + */ > + uint8_t win_id; > + > + uint32_t offset; > + > + uint8_t delay; > + enum drm_plane_type type; > +}; > + > +struct vop2_video_port { > + struct drm_crtc crtc; > + struct vop2 *vop2; > + struct clk *dclk; > + uint8_t id; > + const struct vop2_video_port_regs *regs; > + const struct vop2_video_port_data *data; > + > + struct completion dsp_hold_completion; > + > + /** > + * @win_mask: Bitmask of wins attached to the video port; > + */ > + uint32_t win_mask; > + > + struct vop2_win *primary_plane; > + struct drm_pending_vblank_event *event; > + > + int nlayers; > +}; > + > +struct vop2 { > + struct device *dev; > + struct drm_device *drm; > + struct vop2_video_port vps[ROCKCHIP_MAX_CRTC]; > + > + const struct vop2_data *data; > + /* Number of win that registered as plane, > + * maybe less than the total number of hardware > + * win. > + */ > + uint32_t registered_num_wins; > + > + void __iomem *regs; > + struct regmap *map; > + > + struct regmap *grf; > + > + /* physical map length of vop2 register */ > + uint32_t len; > + > + void __iomem *lut_regs; > + /* one time only one process allowed to config the register */ > + spinlock_t reg_lock; > + > + /* protects crtc enable/disable */ > + struct mutex vop2_lock; > + > + int irq; > + > + /* > + * Some globle resource are shared between all > + * the vidoe ports(crtcs), so we need a ref counter here. > + */ > + unsigned int enable_count; > + struct clk *hclk; > + struct clk *aclk; > + > + /* must put at the end of the struct */ > + struct vop2_win win[]; > +}; > + > +static struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc) > +{ > + return container_of(crtc, struct vop2_video_port, crtc); > +} > + > +static struct vop2_win *to_vop2_win(struct drm_plane *p) > +{ > + return container_of(p, struct vop2_win, base); > +} > + > +static void vop2_lock(struct vop2 *vop2) > +{ > + mutex_lock(&vop2->vop2_lock); > +} > + > +static void vop2_unlock(struct vop2 *vop2) > +{ > + mutex_unlock(&vop2->vop2_lock); > +} > + > +static void vop2_writel(struct vop2 *vop2, uint32_t offset, uint32_t v) > +{ > + regmap_write(vop2->map, offset, v); > +} > + > +static void vop2_vp_write(struct vop2_video_port *vp, uint32_t offset, > + uint32_t v) > +{ > + regmap_write(vp->vop2->map, vp->data->offset + offset, v); > +} > + > +static uint32_t vop2_readl(struct vop2 *vop2, uint32_t offset) > +{ > + uint32_t val; > + > + regmap_read(vop2->map, offset, &val); > + > + return val; > +} > + > +static void vop2_win_write(const struct vop2_win *win, unsigned int reg, > + uint32_t v) > +{ > + regmap_field_write(win->reg[reg], v); > +} > + > +static bool vop2_cluster_window(const struct vop2_win *win) > +{ > + return win->data->feature & WIN_FEATURE_CLUSTER; > +} > + > +static void vop2_cfg_done(struct vop2_video_port *vp) > +{ > + struct vop2 *vop2 = vp->vop2; > + uint32_t val; > + > + val = vop2_readl(vop2, RK3568_REG_CFG_DONE); > + > + val &= 0x7; > + > + vop2_writel(vop2, RK3568_REG_CFG_DONE, > + val | BIT(vp->id) | RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN); > +} > + > +static void vop2_win_disable(struct vop2_win *win) > +{ > + vop2_win_write(win, VOP2_WIN_ENABLE, 0); > + > + if (vop2_cluster_window(win)) > + vop2_win_write(win, VOP2_WIN_CLUSTER_ENABLE, 0); > +} > + > +static enum vop2_data_format vop2_convert_format(uint32_t format) > +{ > + switch (format) { > + case DRM_FORMAT_XRGB8888: > + case DRM_FORMAT_ARGB8888: > + case DRM_FORMAT_XBGR8888: > + case DRM_FORMAT_ABGR8888: > + return VOP2_FMT_ARGB8888; > + case DRM_FORMAT_RGB888: > + case DRM_FORMAT_BGR888: > + return VOP2_FMT_RGB888; > + case DRM_FORMAT_RGB565: > + case DRM_FORMAT_BGR565: > + return VOP2_FMT_RGB565; > + case DRM_FORMAT_NV12: > + return VOP2_FMT_YUV420SP; > + case DRM_FORMAT_NV16: > + return VOP2_FMT_YUV422SP; > + case DRM_FORMAT_NV24: > + return VOP2_FMT_YUV444SP; > + case DRM_FORMAT_YUYV: > + case DRM_FORMAT_YVYU: > + return VOP2_FMT_VYUY422; > + case DRM_FORMAT_VYUY: > + case DRM_FORMAT_UYVY: > + return VOP2_FMT_YUYV422; > + default: > + DRM_ERROR("unsupported format[%08x]\n", format); > + return -EINVAL; > + } > +} > + > +static enum vop2_afbc_format vop2_convert_afbc_format(uint32_t format) > +{ > + switch (format) { > + case DRM_FORMAT_XRGB8888: > + case DRM_FORMAT_ARGB8888: > + case DRM_FORMAT_XBGR8888: > + case DRM_FORMAT_ABGR8888: > + return VOP2_AFBC_FMT_ARGB8888; > + case DRM_FORMAT_RGB888: > + case DRM_FORMAT_BGR888: > + return VOP2_AFBC_FMT_RGB888; > + case DRM_FORMAT_RGB565: > + case DRM_FORMAT_BGR565: > + return VOP2_AFBC_FMT_RGB565; > + case DRM_FORMAT_NV12: > + return VOP2_AFBC_FMT_YUV420; > + case DRM_FORMAT_NV16: > + return VOP2_AFBC_FMT_YUV422; > + default: > + return VOP2_AFBC_FMT_INVALID; > + } > + > + return VOP2_AFBC_FMT_INVALID; > +} > + > +static bool vop2_win_rb_swap(uint32_t format) > +{ > + switch (format) { > + case DRM_FORMAT_XBGR8888: > + case DRM_FORMAT_ABGR8888: > + case DRM_FORMAT_BGR888: > + case DRM_FORMAT_BGR565: > + return true; > + default: > + return false; > + } > +} > + > +static bool vop2_afbc_rb_swap(uint32_t format) > +{ > + switch (format) { > + case DRM_FORMAT_NV24: > + return true; > + default: > + return false; > + } > +} > + > +static bool vop2_afbc_uv_swap(uint32_t format) > +{ > + switch (format) { > + case DRM_FORMAT_NV12: > + case DRM_FORMAT_NV16: > + return true; > + default: > + return false; > + } > +} > + > +static bool vop2_win_uv_swap(uint32_t format) > +{ > + switch (format) { > + case DRM_FORMAT_NV12: > + case DRM_FORMAT_NV16: > + case DRM_FORMAT_NV24: > + return true; > + default: > + return false; > + } > +} > + > +static bool vop2_win_dither_up(uint32_t format) > +{ > + switch (format) { > + case DRM_FORMAT_BGR565: > + case DRM_FORMAT_RGB565: > + return true; > + default: > + return false; > + } > +} > + > +static bool vop2_output_uv_swap(uint32_t bus_format, uint32_t output_mode) > +{ > + /* > + * FIXME: > + * > + * There is no media type for YUV444 output, > + * so when out_mode is AAAA or P888, assume output is YUV444 on > + * yuv format. > + * > + * From H/W testing, YUV444 mode need a rb swap. > + */ > + if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 || > + bus_format == MEDIA_BUS_FMT_VYUY8_1X16 || > + bus_format == MEDIA_BUS_FMT_YVYU8_2X8 || > + bus_format == MEDIA_BUS_FMT_VYUY8_2X8 || > + ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || > + bus_format == MEDIA_BUS_FMT_YUV10_1X30) && > + (output_mode == ROCKCHIP_OUT_MODE_AAAA || > + output_mode == ROCKCHIP_OUT_MODE_P888))) > + return true; > + else > + return false; > +} > + > +static bool is_yuv_output(uint32_t bus_format) > +{ > + switch (bus_format) { > + case MEDIA_BUS_FMT_YUV8_1X24: > + case MEDIA_BUS_FMT_YUV10_1X30: > + case MEDIA_BUS_FMT_UYYVYY8_0_5X24: > + case MEDIA_BUS_FMT_UYYVYY10_0_5X30: > + case MEDIA_BUS_FMT_YUYV8_2X8: > + case MEDIA_BUS_FMT_YVYU8_2X8: > + case MEDIA_BUS_FMT_UYVY8_2X8: > + case MEDIA_BUS_FMT_VYUY8_2X8: > + case MEDIA_BUS_FMT_YUYV8_1X16: > + case MEDIA_BUS_FMT_YVYU8_1X16: > + case MEDIA_BUS_FMT_UYVY8_1X16: > + case MEDIA_BUS_FMT_VYUY8_1X16: > + return true; > + default: > + return false; > + } > +} > + > +static bool rockchip_afbc(struct drm_plane *plane, u64 modifier) > +{ > + int i; > + > + if (modifier == DRM_FORMAT_MOD_LINEAR) > + return false; > + > + for (i = 0 ; i < plane->modifier_count; i++) > + if (plane->modifiers[i] == modifier) > + break; > + > + return (i < plane->modifier_count) ? true : false; > + > +} > + > +static bool rockchip_vop2_mod_supported(struct drm_plane *plane, uint32_t format, u64 modifier) > +{ > + struct vop2_win *win = to_vop2_win(plane); > + struct vop2 *vop2 = win->vop2; > + > + if (modifier == DRM_FORMAT_MOD_INVALID) > + return false; > + > + if (modifier == DRM_FORMAT_MOD_LINEAR) > + return true; > + > + if (!rockchip_afbc(plane, modifier)) { > + drm_err(vop2->drm, "Unsupported format modifier 0x%llx\n", modifier); > + > + return false; > + } > + > + return vop2_convert_afbc_format(format) >= 0; > +} > + > +static int vop2_afbc_half_block_enable(struct drm_plane_state *pstate) > +{ > + if ((pstate->rotation & DRM_MODE_ROTATE_270) || (pstate->rotation & DRM_MODE_ROTATE_90)) > + return 0; > + else > + return 1; > +} > + > +static uint32_t vop2_afbc_transform_offset(struct drm_plane_state *pstate, > + bool afbc_half_block_en) > +{ > + struct drm_rect *src = &pstate->src; > + struct drm_framebuffer *fb = pstate->fb; > + uint32_t bpp = fb->format->cpp[0] * 8; > + uint32_t vir_width = (fb->pitches[0] << 3) / bpp; > + uint32_t width = drm_rect_width(src) >> 16; > + uint32_t height = drm_rect_height(src) >> 16; > + uint32_t act_xoffset = src->x1 >> 16; > + uint32_t act_yoffset = src->y1 >> 16; > + uint32_t align16_crop = 0; > + uint32_t align64_crop = 0; > + uint32_t height_tmp = 0; > + uint32_t transform_tmp = 0; > + uint8_t transform_xoffset = 0; > + uint8_t transform_yoffset = 0; > + uint8_t top_crop = 0; > + uint8_t top_crop_line_num = 0; > + uint8_t bottom_crop_line_num = 0; > + > + /* 16 pixel align */ > + if (height & 0xf) > + align16_crop = 16 - (height & 0xf); > + > + height_tmp = height + align16_crop; > + > + /* 64 pixel align */ > + if (height_tmp & 0x3f) > + align64_crop = 64 - (height_tmp & 0x3f); > + > + top_crop_line_num = top_crop << 2; > + if (top_crop == 0) > + bottom_crop_line_num = align16_crop + align64_crop; > + else if (top_crop == 1) > + bottom_crop_line_num = align16_crop + align64_crop + 12; > + else if (top_crop == 2) > + bottom_crop_line_num = align16_crop + align64_crop + 8; > + > + switch (pstate->rotation & > + (DRM_MODE_REFLECT_X | > + DRM_MODE_REFLECT_Y | > + DRM_MODE_ROTATE_90 | > + DRM_MODE_ROTATE_270)) { > + case DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y: > + transform_tmp = act_xoffset + width; > + transform_xoffset = 16 - (transform_tmp & 0xf); > + transform_tmp = bottom_crop_line_num - act_yoffset; > + > + if (afbc_half_block_en) > + transform_yoffset = transform_tmp & 0x7; > + else > + transform_yoffset = (transform_tmp & 0xf); > + > + break; > + case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90: > + transform_tmp = bottom_crop_line_num - act_yoffset; > + transform_xoffset = transform_tmp & 0xf; > + transform_tmp = vir_width - width - act_xoffset; > + transform_yoffset = transform_tmp & 0xf; > + break; > + case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_270: > + transform_tmp = top_crop_line_num + act_yoffset; > + transform_xoffset = transform_tmp & 0xf; > + transform_tmp = act_xoffset; > + transform_yoffset = transform_tmp & 0xf; > + break; > + case DRM_MODE_REFLECT_X: > + transform_tmp = act_xoffset + width; > + transform_xoffset = 16 - (transform_tmp & 0xf); > + transform_tmp = top_crop_line_num + act_yoffset; > + > + if (afbc_half_block_en) > + transform_yoffset = transform_tmp & 0x7; > + else > + transform_yoffset = transform_tmp & 0xf; > + > + break; > + case DRM_MODE_REFLECT_Y: > + transform_tmp = act_xoffset; > + transform_xoffset = transform_tmp & 0xf; > + transform_tmp = bottom_crop_line_num - act_yoffset; > + > + if (afbc_half_block_en) > + transform_yoffset = transform_tmp & 0x7; > + else > + transform_yoffset = transform_tmp & 0xf; > + > + break; > + case DRM_MODE_ROTATE_90: > + transform_tmp = bottom_crop_line_num - act_yoffset; > + transform_xoffset = transform_tmp & 0xf; > + transform_tmp = act_xoffset; > + transform_yoffset = transform_tmp & 0xf; > + break; > + case DRM_MODE_ROTATE_270: > + transform_tmp = top_crop_line_num + act_yoffset; > + transform_xoffset = transform_tmp & 0xf; > + transform_tmp = vir_width - width - act_xoffset; > + transform_yoffset = transform_tmp & 0xf; > + break; > + case 0: > + transform_tmp = act_xoffset; > + transform_xoffset = transform_tmp & 0xf; > + transform_tmp = top_crop_line_num + act_yoffset; > + > + if (afbc_half_block_en) > + transform_yoffset = transform_tmp & 0x7; > + else > + transform_yoffset = transform_tmp & 0xf; > + > + break; > + } > + > + return (transform_xoffset & 0xf) | ((transform_yoffset & 0xf) << 16); > +} > + > +/* > + * A Cluster window has 2048 x 16 line buffer, which can > + * works at 2048 x 16(Full) or 4096 x 8 (Half) mode. > + * for Cluster_lb_mode register: > + * 0: half mode, for plane input width range 2048 ~ 4096 > + * 1: half mode, for cluster work at 2 * 2048 plane mode > + * 2: half mode, for rotate_90/270 mode > + * > + */ > +static int vop2_get_cluster_lb_mode(struct vop2_win *win, struct drm_plane_state *pstate) > +{ > + if ((pstate->rotation & DRM_MODE_ROTATE_270) || (pstate->rotation & DRM_MODE_ROTATE_90)) > + return 2; > + else > + return 0; > +} > + > +/* > + * bli_sd_factor = (src - 1) / (dst - 1) << 12; > + * avg_sd_factor: > + * bli_su_factor: > + * bic_su_factor: > + * = (src - 1) / (dst - 1) << 16; > + * > + * gt2 enable: dst get one line from two line of the src > + * gt4 enable: dst get one line from four line of the src. > + * > + */ > +static uint16_t vop2_scale_factor(enum scale_mode mode, > + int32_t filter_mode, > + uint32_t src, uint32_t dst) > +{ > + uint32_t fac; > + int i; > + > + if (mode == SCALE_NONE) > + return 0; > + > + /* > + * A workaround to avoid zero div. > + */ > + if (dst == 1 || src == 1) { > + dst++; > + src++; > + } > + > + if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) { > + fac = ((src - 1) << 12) / (dst - 1); > + for (i = 0; i < 100; i++) { > + if (fac * (dst - 1) >> 12 < (src - 1)) > + break; > + fac -= 1; > + DRM_DEBUG("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); > + } > + } else { > + fac = ((src - 1) << 16) / (dst - 1); > + for (i = 0; i < 100; i++) { > + if (fac * (dst - 1) >> 16 < (src - 1)) > + break; > + fac -= 1; > + DRM_DEBUG("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); > + } > + } > + > + return fac; > +} > + > +static void vop2_setup_scale(struct vop2 *vop2, const struct vop2_win *win, > + uint32_t src_w, uint32_t src_h, uint32_t dst_w, > + uint32_t dst_h, uint32_t pixel_format) > +{ > + const struct drm_format_info *info; > + uint16_t cbcr_src_w; > + uint16_t cbcr_src_h; > + uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode; > + uint16_t cbcr_hor_scl_mode, cbcr_ver_scl_mode; > + uint16_t hscl_filter_mode, vscl_filter_mode; > + uint8_t gt2 = 0; > + uint8_t gt4 = 0; > + uint32_t val; > + > + info = drm_format_info(pixel_format); > + > + cbcr_src_w = src_w / info->hsub; > + cbcr_src_h = src_h / info->vsub; > + > + if (src_h >= (4 * dst_h)) { > + gt4 = 1; > + src_h >>= 2; > + } else if (src_h >= (2 * dst_h)) { > + gt2 = 1; > + src_h >>= 1; > + } > + > + yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w); > + yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h); > + > + if (yrgb_hor_scl_mode == SCALE_UP) > + hscl_filter_mode = VOP2_SCALE_UP_BIC; > + else > + hscl_filter_mode = VOP2_SCALE_DOWN_BIL; > + > + if (yrgb_ver_scl_mode == SCALE_UP) > + vscl_filter_mode = VOP2_SCALE_UP_BIL; > + else > + vscl_filter_mode = VOP2_SCALE_DOWN_BIL; > + > + /* > + * RK3568 VOP Esmart/Smart dsp_w should be even pixel > + * at scale down mode > + */ > + if (!(win->data->feature & WIN_FEATURE_AFBDC)) { > + if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1)) { > + drm_dbg(vop2->drm, "%s dst_w[%d] should align as 2 pixel\n", > + win->data->name, dst_w); > + dst_w += 1; > + } > + } > + > + val = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, > + src_w, dst_w); > + vop2_win_write(win, VOP2_WIN_SCALE_YRGB_X, val); > + val = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, > + src_h, dst_h); > + vop2_win_write(win, VOP2_WIN_SCALE_YRGB_Y, val); > + > + vop2_win_write(win, VOP2_WIN_VSD_YRGB_GT4, gt4); > + vop2_win_write(win, VOP2_WIN_VSD_YRGB_GT2, gt2); > + > + vop2_win_write(win, VOP2_WIN_YRGB_HOR_SCL_MODE, yrgb_hor_scl_mode); > + vop2_win_write(win, VOP2_WIN_YRGB_VER_SCL_MODE, yrgb_ver_scl_mode); > + > + if (vop2_cluster_window(win)) > + return; > + > + vop2_win_write(win, VOP2_WIN_YRGB_HSCL_FILTER_MODE, hscl_filter_mode); > + vop2_win_write(win, VOP2_WIN_YRGB_VSCL_FILTER_MODE, vscl_filter_mode); > + > + if (info->is_yuv) { > + gt4 = gt2 = 0; > + > + if (cbcr_src_h >= (4 * dst_h)) > + gt4 = 1; > + else if (cbcr_src_h >= (2 * dst_h)) > + gt2 = 1; > + > + if (gt4) > + cbcr_src_h >>= 2; > + else if (gt2) > + cbcr_src_h >>= 1; > + > + cbcr_hor_scl_mode = scl_get_scl_mode(cbcr_src_w, dst_w); > + cbcr_ver_scl_mode = scl_get_scl_mode(cbcr_src_h, dst_h); > + > + val = vop2_scale_factor(cbcr_hor_scl_mode, hscl_filter_mode, > + cbcr_src_w, dst_w); > + vop2_win_write(win, VOP2_WIN_SCALE_CBCR_X, val); > + > + val = vop2_scale_factor(cbcr_ver_scl_mode, vscl_filter_mode, > + cbcr_src_h, dst_h); > + vop2_win_write(win, VOP2_WIN_SCALE_CBCR_Y, val); > + > + vop2_win_write(win, VOP2_WIN_VSD_CBCR_GT4, gt4); > + vop2_win_write(win, VOP2_WIN_VSD_CBCR_GT2, gt2); > + vop2_win_write(win, VOP2_WIN_CBCR_HOR_SCL_MODE, cbcr_hor_scl_mode); > + vop2_win_write(win, VOP2_WIN_CBCR_VER_SCL_MODE, cbcr_ver_scl_mode); > + vop2_win_write(win, VOP2_WIN_CBCR_HSCL_FILTER_MODE, hscl_filter_mode); > + vop2_win_write(win, VOP2_WIN_CBCR_VSCL_FILTER_MODE, vscl_filter_mode); > + } > +} > + > +static int vop2_convert_csc_mode(int csc_mode) > +{ > + switch (csc_mode) { > + case V4L2_COLORSPACE_SMPTE170M: > + case V4L2_COLORSPACE_470_SYSTEM_M: > + case V4L2_COLORSPACE_470_SYSTEM_BG: > + return CSC_BT601L; > + case V4L2_COLORSPACE_REC709: > + case V4L2_COLORSPACE_SMPTE240M: > + case V4L2_COLORSPACE_DEFAULT: > + return CSC_BT709L; > + case V4L2_COLORSPACE_JPEG: > + return CSC_BT601F; > + case V4L2_COLORSPACE_BT2020: > + return CSC_BT2020; > + default: > + return CSC_BT709L; > + } > +} > + > +/* > + * colorspace path: > + * Input Win csc Output > + * 1. YUV(2020) --> Y2R->2020To709->R2Y --> YUV_OUTPUT(601/709) > + * RGB --> R2Y __/ > + * > + * 2. YUV(2020) --> bypasss --> YUV_OUTPUT(2020) > + * RGB --> 709To2020->R2Y __/ > + * > + * 3. YUV(2020) --> Y2R->2020To709 --> RGB_OUTPUT(709) > + * RGB --> R2Y __/ > + * > + * 4. YUV(601/709)-> Y2R->709To2020->R2Y --> YUV_OUTPUT(2020) > + * RGB --> 709To2020->R2Y __/ > + * > + * 5. YUV(601/709)-> bypass --> YUV_OUTPUT(709) > + * RGB --> R2Y __/ > + * > + * 6. YUV(601/709)-> bypass --> YUV_OUTPUT(601) > + * RGB --> R2Y(601) __/ > + * > + * 7. YUV --> Y2R(709) --> RGB_OUTPUT(709) > + * RGB --> bypass __/ > + * > + * 8. RGB --> 709To2020->R2Y --> YUV_OUTPUT(2020) > + * > + * 9. RGB --> R2Y(709) --> YUV_OUTPUT(709) > + * > + * 10. RGB --> R2Y(601) --> YUV_OUTPUT(601) > + * > + * 11. RGB --> bypass --> RGB_OUTPUT(709) > + */ > + > +static void vop2_setup_csc_mode(struct vop2_video_port *vp, > + struct vop2_win *win, > + struct drm_plane_state *pstate) > +{ > + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); > + int is_input_yuv = pstate->fb->format->is_yuv; > + int is_output_yuv = is_yuv_output(vcstate->bus_format); > + int input_csc = V4L2_COLORSPACE_DEFAULT; > + int output_csc = vcstate->color_space; > + bool r2y_en, y2r_en; > + int csc_mode; > + > + if (is_input_yuv && !is_output_yuv) { > + y2r_en = 1; > + r2y_en = 0; > + csc_mode = vop2_convert_csc_mode(input_csc); > + } else if (!is_input_yuv && is_output_yuv) { > + y2r_en = 0; > + r2y_en = 1; > + csc_mode = vop2_convert_csc_mode(output_csc); > + } else { > + y2r_en = 0; > + r2y_en = 0; > + csc_mode = 0; > + } > + > + vop2_win_write(win, VOP2_WIN_Y2R_EN, y2r_en); > + vop2_win_write(win, VOP2_WIN_R2Y_EN, r2y_en); > + vop2_win_write(win, VOP2_WIN_CSC_MODE, csc_mode); > +} > + > +static void vop2_crtc_enable_irq(struct vop2_video_port *vp, uint32_t irq) > +{ > + struct vop2 *vop2 = vp->vop2; > + > + vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irq << 16 | irq); > + vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16 | irq); > +} > + > +static void vop2_crtc_disable_irq(struct vop2_video_port *vp, uint32_t irq) > +{ > + struct vop2 *vop2 = vp->vop2; > + > + vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16); > +} > + > +static int vop2_core_clks_prepare_enable(struct vop2 *vop2) > +{ > + int ret; > + > + ret = clk_prepare_enable(vop2->hclk); > + if (ret < 0) { > + drm_err(vop2->drm, "failed to enable hclk - %d\n", ret); > + return ret; > + } > + > + ret = clk_prepare_enable(vop2->aclk); > + if (ret < 0) { > + drm_err(vop2->drm, "failed to enable aclk - %d\n", ret); > + goto err; > + } > + > + return 0; > +err: > + clk_disable_unprepare(vop2->hclk); > + > + return ret; > +} > + > +static void vop2_enable(struct vop2 *vop2) > +{ > + int ret; > + uint32_t v; > + > + ret = pm_runtime_get_sync(vop2->dev); > + if (ret < 0) { > + drm_err(vop2->drm, "failed to get pm runtime: %d\n", ret); > + return; > + } > + > + ret = vop2_core_clks_prepare_enable(vop2); > + if (ret) { > + pm_runtime_put_sync(vop2->dev); > + return; > + } > + > + if (vop2->data->soc_id == 3566) > + vop2_writel(vop2, RK3568_OTP_WIN_EN, 1); > + > + vop2_writel(vop2, RK3568_REG_CFG_DONE, RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN); > + > + /* > + * Disable auto gating, this is a workaround to > + * avoid display image shift when a window enabled. > + */ > + v = vop2_readl(vop2, RK3568_SYS_AUTO_GATING_CTRL); > + v &= ~RK3568_SYS_AUTO_GATING_CTRL__AUTO_GATING_EN; > + vop2_writel(vop2, RK3568_SYS_AUTO_GATING_CTRL, v); > + > + vop2_writel(vop2, RK3568_SYS0_INT_CLR, > + VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR); > + vop2_writel(vop2, RK3568_SYS0_INT_EN, > + VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR); > + vop2_writel(vop2, RK3568_SYS1_INT_CLR, > + VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR); > + vop2_writel(vop2, RK3568_SYS1_INT_EN, > + VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR); > +} > + > +static void vop2_disable(struct vop2 *vop2) > +{ > + pm_runtime_put_sync(vop2->dev); > + > + clk_disable_unprepare(vop2->aclk); > + clk_disable_unprepare(vop2->hclk); > +} > + > +static void vop2_crtc_atomic_disable(struct drm_crtc *crtc, > + struct drm_atomic_state *state) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct vop2 *vop2 = vp->vop2; > + int ret; > + > + vop2_lock(vop2); > + > + drm_crtc_vblank_off(crtc); > + > + /* > + * Vop standby will take effect at end of current frame, > + * if dsp hold valid irq happen, it means standby complete. > + * > + * we must wait standby complete when we want to disable aclk, > + * if not, memory bus maybe dead. > + */ > + reinit_completion(&vp->dsp_hold_completion); > + > + vop2_crtc_enable_irq(vp, VP_INT_DSP_HOLD_VALID); > + spin_lock(&vop2->reg_lock); > + > + vop2_writel(vop2, RK3568_VP_DSP_CTRL, 1); > + > + spin_unlock(&vop2->reg_lock); > + > + ret = wait_for_completion_timeout(&vp->dsp_hold_completion, msecs_to_jiffies(50)); > + if (!ret) > + drm_info(vop2->drm, "wait for vp%d dsp_hold timeout\n", vp->id); > + > + vop2_crtc_disable_irq(vp, VP_INT_DSP_HOLD_VALID); > + > + clk_disable_unprepare(vp->dclk); > + > + vop2->enable_count--; > + > + if (!vop2->enable_count) > + vop2_disable(vop2); > + > + vop2_unlock(vop2); > + > + if (crtc->state->event && !crtc->state->active) { > + spin_lock_irq(&crtc->dev->event_lock); > + drm_crtc_send_vblank_event(crtc, crtc->state->event); > + spin_unlock_irq(&crtc->dev->event_lock); > + > + crtc->state->event = NULL; > + } > +} > + > +static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_state *astate) > +{ > + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(astate, plane); > + struct drm_framebuffer *fb = pstate->fb; > + struct drm_crtc *crtc = pstate->crtc; > + struct drm_crtc_state *cstate; > + struct vop2_video_port *vp; > + struct vop2 *vop2; > + const struct vop2_data *vop2_data; > + struct drm_rect *dest = &pstate->dst; > + struct drm_rect *src = &pstate->src; > + int min_scale = FRAC_16_16(1, 8); > + int max_scale = FRAC_16_16(8, 1); > + int format; > + int ret; > + > + if (!crtc) > + return 0; > + > + vp = to_vop2_video_port(crtc); > + vop2 = vp->vop2; > + vop2_data = vop2->data; > + > + cstate = drm_atomic_get_existing_crtc_state(pstate->state, crtc); > + if (WARN_ON(!cstate)) > + return -EINVAL; > + > + ret = drm_atomic_helper_check_plane_state(pstate, cstate, > + min_scale, max_scale, > + true, true); > + if (ret) > + return ret; > + > + if (!pstate->visible) > + return 0; > + > + format = vop2_convert_format(fb->format->format); > + if (format < 0) > + return format; > + > + if (drm_rect_width(src) >> 16 < 4 || drm_rect_height(src) >> 16 < 4 || > + drm_rect_width(dest) < 4 || drm_rect_width(dest) < 4) { > + drm_err(vop2->drm, "Invalid size: %dx%d->%dx%d, min size is 4x4\n", > + drm_rect_width(src) >> 16, drm_rect_height(src) >> 16, > + drm_rect_width(dest), drm_rect_height(dest)); > + pstate->visible = false; > + return 0; > + } > + > + if (drm_rect_width(src) >> 16 > vop2_data->max_input.width || > + drm_rect_height(src) >> 16 > vop2_data->max_input.height) { > + drm_err(vop2->drm, "Invalid source: %dx%d. max input: %dx%d\n", > + drm_rect_width(src) >> 16, > + drm_rect_height(src) >> 16, > + vop2_data->max_input.width, > + vop2_data->max_input.height); > + return -EINVAL; > + } > + > + /* > + * Src.x1 can be odd when do clip, but yuv plane start point > + * need align with 2 pixel. > + */ > + if (fb->format->is_yuv && ((pstate->src.x1 >> 16) % 2)) { > + drm_err(vop2->drm, "Invalid Source: Yuv format not support odd xpos\n"); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static void vop2_plane_atomic_disable(struct drm_plane *plane, struct drm_atomic_state *state) > +{ > + struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(state, plane); > + struct vop2_win *win = to_vop2_win(plane); > + struct vop2 *vop2 = win->vop2; > + > + drm_dbg(vop2->drm, "%s disable\n", win->data->name); > + > + if (!old_pstate->crtc) > + return; > + > + spin_lock(&vop2->reg_lock); > + > + vop2_win_disable(win); > + vop2_win_write(win, VOP2_WIN_YUV_CLIP, 0); > + > + spin_unlock(&vop2->reg_lock); > +} > + > +/* > + * The color key is 10 bit, so all format should > + * convert to 10 bit here. > + */ > +static void vop2_plane_setup_color_key(struct drm_plane *plane, uint32_t color_key) > +{ > + struct drm_plane_state *pstate = plane->state; > + struct drm_framebuffer *fb = pstate->fb; > + struct vop2_win *win = to_vop2_win(plane); > + uint32_t color_key_en = 0; > + uint32_t r = 0; > + uint32_t g = 0; > + uint32_t b = 0; > + > + if (!(color_key & VOP2_COLOR_KEY_MASK) || fb->format->is_yuv) { > + vop2_win_write(win, VOP2_WIN_COLOR_KEY_EN, 0); > + return; > + } > + > + switch (fb->format->format) { > + case DRM_FORMAT_RGB565: > + case DRM_FORMAT_BGR565: > + r = (color_key & 0xf800) >> 11; > + g = (color_key & 0x7e0) >> 5; > + b = (color_key & 0x1f); > + r <<= 5; > + g <<= 4; > + b <<= 5; > + color_key_en = 1; > + break; > + case DRM_FORMAT_XRGB8888: > + case DRM_FORMAT_ARGB8888: > + case DRM_FORMAT_XBGR8888: > + case DRM_FORMAT_ABGR8888: > + case DRM_FORMAT_RGB888: > + case DRM_FORMAT_BGR888: > + r = (color_key & 0xff0000) >> 16; > + g = (color_key & 0xff00) >> 8; > + b = (color_key & 0xff); > + r <<= 2; > + g <<= 2; > + b <<= 2; > + color_key_en = 1; > + break; > + } > + > + vop2_win_write(win, VOP2_WIN_COLOR_KEY_EN, color_key_en); > + vop2_win_write(win, VOP2_WIN_COLOR_KEY, (r << 20) | (g << 10) | b); > +} > + > +static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_atomic_state *state) > +{ > + struct drm_plane_state *pstate = plane->state; > + struct drm_crtc *crtc = pstate->crtc; > + struct vop2_win *win = to_vop2_win(plane); > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; > + struct vop2 *vop2 = win->vop2; > + struct drm_framebuffer *fb = pstate->fb; > + uint32_t bpp = fb->format->cpp[0] * 8; > + uint32_t actual_w, actual_h, dsp_w, dsp_h; > + uint32_t act_info, dsp_info; > + uint32_t format; > + uint32_t afbc_format; > + uint32_t rb_swap; > + uint32_t uv_swap; > + struct drm_rect *src = &pstate->src; > + struct drm_rect *dest = &pstate->dst; > + uint32_t afbc_tile_num; > + uint32_t afbc_half_block_en; > + uint32_t transform_offset; > + bool dither_up; > + bool xmirror = pstate->rotation & DRM_MODE_REFLECT_X; > + bool ymirror = pstate->rotation & DRM_MODE_REFLECT_Y; > + bool rotate_270 = pstate->rotation & DRM_MODE_ROTATE_270; > + bool rotate_90 = pstate->rotation & DRM_MODE_ROTATE_90; > + struct rockchip_gem_object *rk_obj; > + unsigned long offset; > + bool afbc_en; > + dma_addr_t yrgb_mst; > + dma_addr_t uv_mst; > + > + /* > + * can't update plane when vop2 is disabled. > + */ > + if (WARN_ON(!crtc)) > + return; > + > + if (!pstate->visible) { > + vop2_plane_atomic_disable(plane, state); > + return; > + } > + > + afbc_en = rockchip_afbc(plane, fb->modifier); > + > + offset = (src->x1 >> 16) * fb->format->cpp[0]; > + > + /* > + * AFBC HDR_PTR must set to the zero offset of the framebuffer. > + */ > + if (afbc_en) > + offset = 0; > + else if (pstate->rotation & DRM_MODE_REFLECT_Y) > + offset += ((src->y2 >> 16) - 1) * fb->pitches[0]; > + else > + offset += (src->y1 >> 16) * fb->pitches[0]; > + > + rk_obj = to_rockchip_obj(fb->obj[0]); > + > + yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0]; > + if (fb->format->is_yuv) { > + int hsub = fb->format->hsub; > + int vsub = fb->format->vsub; > + > + offset = (src->x1 >> 16) * fb->format->cpp[1] / hsub; > + offset += (src->y1 >> 16) * fb->pitches[1] / vsub; > + > + if ((pstate->rotation & DRM_MODE_REFLECT_Y) && !afbc_en) > + offset += fb->pitches[1] * ((pstate->src_h >> 16) - 2) / vsub; > + > + rk_obj = to_rockchip_obj(fb->obj[0]); > + uv_mst = rk_obj->dma_addr + offset + fb->offsets[1]; > + } > + > + actual_w = drm_rect_width(src) >> 16; > + actual_h = drm_rect_height(src) >> 16; > + dsp_w = drm_rect_width(dest); > + > + if (dest->x1 + dsp_w > adjusted_mode->hdisplay) { > + drm_err(vop2->drm, "vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n", > + vp->id, win->data->name, dest->x1, dsp_w, adjusted_mode->hdisplay); > + dsp_w = adjusted_mode->hdisplay - dest->x1; > + if (dsp_w < 4) > + dsp_w = 4; > + actual_w = dsp_w * actual_w / drm_rect_width(dest); > + } > + > + dsp_h = drm_rect_height(dest); > + > + if (dest->y1 + dsp_h > adjusted_mode->vdisplay) { > + drm_err(vop2->drm, "vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n", > + vp->id, win->data->name, dest->y1, dsp_h, adjusted_mode->vdisplay); > + dsp_h = adjusted_mode->vdisplay - dest->y1; > + if (dsp_h < 4) > + dsp_h = 4; > + actual_h = dsp_h * actual_h / drm_rect_height(dest); > + } > + > + /* > + * This is workaround solution for IC design: > + * esmart can't support scale down when actual_w % 16 == 1. > + */ > + if (!(win->data->feature & WIN_FEATURE_AFBDC)) { > + if (actual_w > dsp_w && (actual_w & 0xf) == 1) { > + drm_err(vop2->drm, "vp%d %s act_w[%d] MODE 16 == 1\n", vp->id, win->data->name, actual_w); > + actual_w -= 1; > + } > + } > + > + if (afbc_en && actual_w % 4) { > + drm_err(vop2->drm, "vp%d %s actual_w[%d] should align as 4 pixel when enable afbc\n", > + vp->id, win->data->name, actual_w); > + actual_w = ALIGN_DOWN(actual_w, 4); > + } > + > + act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); > + dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff); > + > + format = vop2_convert_format(fb->format->format); > + > + spin_lock(&vop2->reg_lock); > + drm_dbg(vop2->drm, "vp%d update %s[%dx%d->%dx%d@%dx%d] fmt[%p4cc_%s] addr[%pad]\n", > + vp->id, win->data->name, actual_w, actual_h, dsp_w, dsp_h, > + dest->x1, dest->y1, > + &fb->format->format, > + afbc_en ? "AFBC" : "", &yrgb_mst); > + > + if (afbc_en) { > + uint32_t stride; > + > + /* the afbc superblock is 16 x 16 */ > + afbc_format = vop2_convert_afbc_format(fb->format->format); > + > + /* Enable color transform for YTR */ > + if (fb->modifier & AFBC_FORMAT_MOD_YTR) > + afbc_format |= (1 << 4); > + > + afbc_tile_num = ALIGN(actual_w, 16) >> 4; > + > + /* > + * AFBC pic_vir_width is count by pixel, this is different > + * with WIN_VIR_STRIDE. > + */ > + stride = (fb->pitches[0] << 3) / bpp; > + if ((stride & 0x3f) && (xmirror || rotate_90 || rotate_270)) > + drm_err(vop2->drm, "vp%d %s stride[%d] must align as 64 pixel when enable xmirror/rotate_90/rotate_270[0x%x]\n", > + vp->id, win->data->name, stride, pstate->rotation); > + > + rb_swap = vop2_afbc_rb_swap(fb->format->format); > + uv_swap = vop2_afbc_uv_swap(fb->format->format); > + /* > + * This is a workaround for crazy IC design, Cluster > + * and Esmart/Smart use different format configuration map: > + * YUV420_10BIT: 0x10 for Cluster, 0x14 for Esmart/Smart. > + * > + * This is one thing we can make the convert simple: > + * AFBCD decode all the YUV data to YUV444. So we just > + * set all the yuv 10 bit to YUV444_10. > + */ > + if (fb->format->is_yuv && (bpp == 10)) > + format = VOP2_CLUSTER_YUV444_10; > + > + afbc_half_block_en = vop2_afbc_half_block_enable(pstate); > + transform_offset = vop2_afbc_transform_offset(pstate, afbc_half_block_en); > + if (vop2_cluster_window(win)) > + vop2_win_write(win, VOP2_WIN_AFBC_ENABLE, 1); > + vop2_win_write(win, VOP2_WIN_AFBC_FORMAT, afbc_format); > + vop2_win_write(win, VOP2_WIN_AFBC_RB_SWAP, rb_swap); > + vop2_win_write(win, VOP2_WIN_AFBC_UV_SWAP, uv_swap); > + vop2_win_write(win, VOP2_WIN_AFBC_AUTO_GATING_EN, 0); > + vop2_win_write(win, VOP2_WIN_AFBC_BLOCK_SPLIT_EN, 0); > + vop2_win_write(win, VOP2_WIN_AFBC_HALF_BLOCK_EN, afbc_half_block_en); > + vop2_win_write(win, VOP2_WIN_AFBC_HDR_PTR, yrgb_mst); > + vop2_win_write(win, VOP2_WIN_AFBC_PIC_SIZE, act_info); > + vop2_win_write(win, VOP2_WIN_AFBC_TRANSFORM_OFFSET, transform_offset); > + vop2_win_write(win, VOP2_WIN_AFBC_PIC_OFFSET, ((src->x1 >> 16) | src->y1)); > + vop2_win_write(win, VOP2_WIN_AFBC_DSP_OFFSET, (dest->x1 | (dest->y1 << 16))); > + vop2_win_write(win, VOP2_WIN_AFBC_PIC_VIR_WIDTH, stride); > + vop2_win_write(win, VOP2_WIN_AFBC_TILE_NUM, afbc_tile_num); > + vop2_win_write(win, VOP2_WIN_XMIRROR, xmirror); > + vop2_win_write(win, VOP2_WIN_AFBC_ROTATE_270, rotate_270); > + vop2_win_write(win, VOP2_WIN_AFBC_ROTATE_90, rotate_90); > + } else { > + vop2_win_write(win, VOP2_WIN_YRGB_VIR, DIV_ROUND_UP(fb->pitches[0], 4)); > + } > + > + vop2_win_write(win, VOP2_WIN_YMIRROR, ymirror); > + > + if (rotate_90 || rotate_270) { > + act_info = swahw32(act_info); > + actual_w = drm_rect_height(src) >> 16; > + actual_h = drm_rect_width(src) >> 16; > + } > + > + vop2_win_write(win, VOP2_WIN_FORMAT, format); > + vop2_win_write(win, VOP2_WIN_YRGB_MST, yrgb_mst); > + > + rb_swap = vop2_win_rb_swap(fb->format->format); > + vop2_win_write(win, VOP2_WIN_RB_SWAP, rb_swap); > + if (!vop2_cluster_window(win)) { > + uv_swap = vop2_win_uv_swap(fb->format->format); > + vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap); > + } > + > + if (fb->format->is_yuv) { > + vop2_win_write(win, VOP2_WIN_UV_VIR, DIV_ROUND_UP(fb->pitches[1], 4)); > + vop2_win_write(win, VOP2_WIN_UV_MST, uv_mst); > + } > + > + vop2_setup_scale(vop2, win, actual_w, actual_h, dsp_w, dsp_h, fb->format->format); > + if (!vop2_cluster_window(win)) > + vop2_plane_setup_color_key(plane, 0); > + vop2_win_write(win, VOP2_WIN_ACT_INFO, act_info); > + vop2_win_write(win, VOP2_WIN_DSP_INFO, dsp_info); > + vop2_win_write(win, VOP2_WIN_DSP_ST, dest->y1 << 16 | (dest->x1 & 0xffff)); > + > + vop2_setup_csc_mode(vp, win, pstate); > + > + dither_up = vop2_win_dither_up(fb->format->format); > + vop2_win_write(win, VOP2_WIN_DITHER_UP, dither_up); > + > + vop2_win_write(win, VOP2_WIN_ENABLE, 1); > + > + if (vop2_cluster_window(win)) { > + int lb_mode = vop2_get_cluster_lb_mode(win, pstate); > + > + vop2_win_write(win, VOP2_WIN_CLUSTER_LB_MODE, lb_mode); > + vop2_win_write(win, VOP2_WIN_CLUSTER_ENABLE, 1); > + } > + > + spin_unlock(&vop2->reg_lock); > +} > + > +static const struct drm_plane_helper_funcs vop2_plane_helper_funcs = { > + .atomic_check = vop2_plane_atomic_check, > + .atomic_update = vop2_plane_atomic_update, > + .atomic_disable = vop2_plane_atomic_disable, > +}; > + > +static const struct drm_plane_funcs vop2_plane_funcs = { > + .update_plane = drm_atomic_helper_update_plane, > + .disable_plane = drm_atomic_helper_disable_plane, > + .destroy = drm_plane_cleanup, > + .reset = drm_atomic_helper_plane_reset, > + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, > + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, > + .format_mod_supported = rockchip_vop2_mod_supported, > +}; > + > +static int vop2_crtc_enable_vblank(struct drm_crtc *crtc) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + > + vop2_crtc_enable_irq(vp, VP_INT_FS_FIELD); > + > + return 0; > +} > + > +static void vop2_crtc_disable_vblank(struct drm_crtc *crtc) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + > + vop2_crtc_disable_irq(vp, VP_INT_FS_FIELD); > +} > + > +static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc, > + const struct drm_display_mode *mode, > + struct drm_display_mode *adj_mode) > +{ > + drm_mode_set_crtcinfo(adj_mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE); > + > + return true; > +} > + > +static void vop2_dither_setup(struct drm_crtc *crtc, uint32_t *dsp_ctrl) > +{ > + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); > + > + switch (vcstate->bus_format) { > + case MEDIA_BUS_FMT_RGB565_1X16: > + *dsp_ctrl |= RK3568_VP_DSP_CTRL__DITHER_DOWN_EN; > + break; > + case MEDIA_BUS_FMT_RGB666_1X18: > + case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: > + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: > + *dsp_ctrl |= RK3568_VP_DSP_CTRL__DITHER_DOWN_EN; > + *dsp_ctrl |= RGB888_TO_RGB666; > + break; > + case MEDIA_BUS_FMT_YUV8_1X24: > + case MEDIA_BUS_FMT_UYYVYY8_0_5X24: > + *dsp_ctrl |= RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN; > + break; > + default: > + break; > + } > + > + if (vcstate->output_mode != ROCKCHIP_OUT_MODE_AAAA) > + *dsp_ctrl |= RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN; > + > + *dsp_ctrl |= FIELD_PREP(RK3568_VP_DSP_CTRL__DITHER_DOWN_SEL, > + DITHER_DOWN_ALLEGRO); > +} > + > +static void vop2_post_config(struct drm_crtc *crtc) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct vop2 *vop2 = vp->vop2; > + struct drm_display_mode *mode = &crtc->state->adjusted_mode; > + uint16_t vtotal = mode->crtc_vtotal; > + uint16_t hdisplay = mode->crtc_hdisplay; > + uint16_t hact_st = mode->crtc_htotal - mode->crtc_hsync_start; > + uint16_t vdisplay = mode->crtc_vdisplay; > + uint16_t vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; > + uint32_t left_margin = 100, right_margin = 100, top_margin = 100, bottom_margin = 100; > + uint16_t hsize = hdisplay * (left_margin + right_margin) / 200; > + uint16_t vsize = vdisplay * (top_margin + bottom_margin) / 200; > + uint16_t hact_end, vact_end; > + uint32_t val; > + > + vsize = rounddown(vsize, 2); > + hsize = rounddown(hsize, 2); > + hact_st += hdisplay * (100 - left_margin) / 200; > + hact_end = hact_st + hsize; > + val = hact_st << 16; > + val |= hact_end; > + vop2_vp_write(vp, RK3568_VP_POST_DSP_HACT_INFO, val); > + vact_st += vdisplay * (100 - top_margin) / 200; > + vact_end = vact_st + vsize; > + val = vact_st << 16; > + val |= vact_end; > + vop2_vp_write(vp, RK3568_VP_POST_DSP_VACT_INFO, val); > + val = scl_cal_scale2(vdisplay, vsize) << 16; > + val |= scl_cal_scale2(hdisplay, hsize); > + vop2_vp_write(vp, RK3568_VP_POST_SCL_FACTOR_YRGB, val); > + > + val = 0; > + if (hdisplay != hsize) > + val |= RK3568_VP_POST_SCL_CTRL__HSCALEDOWN; > + if (vdisplay != vsize) > + val |= RK3568_VP_POST_SCL_CTRL__VSCALEDOWN; > + vop2_writel(vop2, RK3568_VP_POST_SCL_CTRL, val); > + > + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { > + uint16_t vact_st_f1 = vtotal + vact_st + 1; > + uint16_t vact_end_f1 = vact_st_f1 + vsize; > + > + val = vact_st_f1 << 16 | vact_end_f1; > + vop2_vp_write(vp, RK3568_VP_POST_DSP_VACT_INFO_F1, val); > + } > + > + vop2_vp_write(vp, RK3568_VP_DSP_BG, 0); > +} > + > +static void rk3568_set_intf_mux(struct vop2_video_port *vp, int id, > + uint32_t polflags) > +{ > + struct vop2 *vop2 = vp->vop2; > + uint32_t die, dip; > + > + die = vop2_readl(vop2, RK3568_DSP_IF_EN); > + dip = vop2_readl(vop2, RK3568_DSP_IF_POL); > + > + switch (id) { > + case RK3568_VOP2_EP_RGB: > + die &= ~RK3568_SYS_DSP_INFACE_EN_RGB_MUX; > + die |= RK3568_SYS_DSP_INFACE_EN_RGB | > + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_RGB_MUX, vp->id); > + if (polflags & POLFLAG_DCLK_INV) > + regmap_write(vop2->grf, RK3568_GRF_VO_CON1, BIT(3 + 16) | BIT(3)); > + else > + regmap_write(vop2->grf, RK3568_GRF_VO_CON1, BIT(3 + 16)); > + break; > + case RK3568_VOP2_EP_HDMI: > + die &= ~RK3568_SYS_DSP_INFACE_EN_HDMI_MUX; > + die |= RK3568_SYS_DSP_INFACE_EN_HDMI | > + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_HDMI_MUX, vp->id); > + break; > + case RK3568_VOP2_EP_EDP: > + die &= ~RK3568_SYS_DSP_INFACE_EN_EDP_MUX; > + die |= RK3568_SYS_DSP_INFACE_EN_EDP | > + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_EDP_MUX, vp->id); > + break; > + case RK3568_VOP2_EP_MIPI0: > + die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX; > + die |= RK3568_SYS_DSP_INFACE_EN_MIPI0 | > + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX, vp->id); > + dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL; > + dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags); > + break; > + case RK3568_VOP2_EP_MIPI1: > + die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX; > + die |= RK3568_SYS_DSP_INFACE_EN_MIPI1 | > + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id); > + dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL; > + dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags); > + break; > + case RK3568_VOP2_EP_LVDS0: > + die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX; > + die |= RK3568_SYS_DSP_INFACE_EN_LVDS0 | > + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX, vp->id); > + dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; > + dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); > + break; > + case RK3568_VOP2_EP_LVDS1: > + die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX; > + die |= RK3568_SYS_DSP_INFACE_EN_LVDS1 | > + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX, vp->id); > + dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; > + dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); > + break; > + default: > + return; > + }; > + > + dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD; > + > + vop2_writel(vop2, RK3568_DSP_IF_EN, die); > + vop2_writel(vop2, RK3568_DSP_IF_POL, dip); > +} > + > +static int us_to_vertical_line(struct drm_display_mode *mode, int us) > +{ > + return us * mode->clock / mode->htotal / 1000; > +} > + > +static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct vop2 *vop2 = vp->vop2; > + const struct vop2_data *vop2_data = vop2->data; > + const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; > + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); > + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); > + struct drm_display_mode *mode = &crtc->state->adjusted_mode; > + unsigned long clock = mode->crtc_clock * 1000; > + uint16_t hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; > + uint16_t hdisplay = mode->crtc_hdisplay; > + uint16_t htotal = mode->crtc_htotal; > + uint16_t hact_st = mode->crtc_htotal - mode->crtc_hsync_start; > + uint16_t hact_end = hact_st + hdisplay; > + uint16_t vdisplay = mode->crtc_vdisplay; > + uint16_t vtotal = mode->crtc_vtotal; > + uint16_t vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; > + uint16_t vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; > + uint16_t vact_end = vact_st + vdisplay; > + uint8_t out_mode; > + uint32_t dsp_ctrl = 0; > + int act_end; > + uint32_t val, polflags; > + int ret; > + struct drm_encoder *encoder; > + > + drm_dbg(vop2->drm, "Update mode to %dx%d%s%d, type: %d for vp%d\n", > + hdisplay, vdisplay, mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", > + drm_mode_vrefresh(mode), vcstate->output_type, vp->id); > + > + vop2_lock(vop2); > + > + ret = clk_prepare_enable(vp->dclk); > + if (ret < 0) { > + drm_err(vop2->drm, "failed to enable dclk for video port%d - %d\n", > + vp->id, ret); > + return; > + } > + > + if (!vop2->enable_count) > + vop2_enable(vop2); > + > + vop2->enable_count++; > + > + vop2_crtc_enable_irq(vp, VP_INT_POST_BUF_EMPTY); > + > + polflags = 0; > + if (vcstate->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) > + polflags |= POLFLAG_DCLK_INV; > + if (mode->flags & DRM_MODE_FLAG_PHSYNC) > + polflags |= BIT(HSYNC_POSITIVE); > + if (mode->flags & DRM_MODE_FLAG_PVSYNC) > + polflags |= BIT(VSYNC_POSITIVE); > + > + drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) { > + struct device_node *node, *parent; > + > + parent = of_get_parent(encoder->port); > + > + for_each_endpoint_of_node(parent, node) { > + struct device_node *crtc_port = of_graph_get_remote_port(node); > + struct device_node *epn; > + struct of_endpoint endpoint; > + > + if (crtc->port != crtc_port) { > + of_node_put(crtc_port); > + continue; > + } > + > + of_node_put(crtc_port); > + > + epn = of_graph_get_remote_endpoint(node); > + of_graph_parse_endpoint(epn, &endpoint); > + of_node_put(epn); > + > + drm_dbg(vop2->drm, "vp%d is connected to %s, id %d\n", > + vp->id, encoder->name, endpoint.id); > + rk3568_set_intf_mux(vp, endpoint.id, polflags); > + } > + of_node_put(parent); > + } > + > + if (vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA && > + !(vp_data->feature & VOP_FEATURE_OUTPUT_10BIT)) > + out_mode = ROCKCHIP_OUT_MODE_P888; > + else > + out_mode = vcstate->output_mode; > + > + dsp_ctrl |= FIELD_PREP(RK3568_VP_DSP_CTRL__OUT_MODE, out_mode); > + > + if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode)) > + dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_RB_SWAP; > + > + if (is_yuv_output(vcstate->bus_format)) > + dsp_ctrl |= RK3568_VP_DSP_CTRL__POST_DSP_OUT_R2Y; > + > + vop2_dither_setup(crtc, &dsp_ctrl); > + > + vop2_vp_write(vp, RK3568_VP_DSP_HTOTAL_HS_END, (htotal << 16) | hsync_len); > + val = hact_st << 16; > + val |= hact_end; > + vop2_vp_write(vp, RK3568_VP_DSP_HACT_ST_END, val); > + > + val = vact_st << 16; > + val |= vact_end; > + vop2_vp_write(vp, RK3568_VP_DSP_VACT_ST_END, val); > + > + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { > + uint16_t vact_st_f1 = vtotal + vact_st + 1; > + uint16_t vact_end_f1 = vact_st_f1 + vdisplay; > + > + val = vact_st_f1 << 16 | vact_end_f1; > + vop2_vp_write(vp, RK3568_VP_DSP_VACT_ST_END_F1, val); > + > + val = vtotal << 16 | (vtotal + vsync_len); > + vop2_vp_write(vp, RK3568_VP_DSP_VS_ST_END_F1, val); > + dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_INTERLACE; > + dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_FILED_POL; > + dsp_ctrl |= RK3568_VP_DSP_CTRL__P2I_EN; > + vtotal += vtotal + 1; > + act_end = vact_end_f1; > + } else { > + act_end = vact_end; > + } > + > + vop2_writel(vop2, RK3568_VP_LINE_FLAG(vp->id), > + (act_end - us_to_vertical_line(mode, 0)) << 16 | act_end); > + > + vop2_vp_write(vp, RK3568_VP_DSP_VTOTAL_VS_END, vtotal << 16 | vsync_len); > + > + if (mode->flags & DRM_MODE_FLAG_DBLCLK) { > + dsp_ctrl |= RK3568_VP_DSP_CTRL__CORE_DCLK_DIV; > + clock *= 2; > + } > + > + vop2_vp_write(vp, RK3568_VP_MIPI_CTRL, 0); > + > + clk_set_rate(vp->dclk, clock); > + > + vop2_post_config(crtc); > + > + vop2_cfg_done(vp); > + > + vop2_vp_write(vp, RK3568_VP_DSP_CTRL, dsp_ctrl); > + > + drm_crtc_vblank_on(crtc); > + > + vop2_unlock(vop2); > +} > + > +static int vop2_crtc_atomic_check(struct drm_crtc *crtc, > + struct drm_atomic_state *state) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct drm_plane *plane; > + int nplanes = 0; > + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); > + > + drm_atomic_crtc_state_for_each_plane(plane, crtc_state) > + nplanes++; > + > + if (nplanes > vp->nlayers) > + return -EINVAL; > + > + return 0; > +} > + > +static bool is_opaque(uint16_t alpha) > +{ > + return (alpha >> 8) == 0xff; > +} > + > +static void vop2_parse_alpha(struct vop2_alpha_config *alpha_config, > + struct vop2_alpha *alpha) > +{ > + int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1; > + int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1; > + int src_color_mode = alpha_config->src_premulti_en ? ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL; > + int dst_color_mode = alpha_config->dst_premulti_en ? ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL; > + > + alpha->src_color_ctrl.val = 0; > + alpha->dst_color_ctrl.val = 0; > + alpha->src_alpha_ctrl.val = 0; > + alpha->dst_alpha_ctrl.val = 0; > + > + if (!alpha_config->src_pixel_alpha_en) > + alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; > + else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en) > + alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX; > + else > + alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; > + > + alpha->src_color_ctrl.bits.alpha_en = 1; > + > + if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) { > + alpha->src_color_ctrl.bits.color_mode = src_color_mode; > + alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; > + } else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) { > + alpha->src_color_ctrl.bits.color_mode = src_color_mode; > + alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE; > + } else { > + alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL; > + alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; > + } > + alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8; > + alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; > + alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; > + > + alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; > + alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; > + alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; > + alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8; > + alpha->dst_color_ctrl.bits.color_mode = dst_color_mode; > + alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; > + > + alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; > + alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode; > + alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; > + alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE; > + > + alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; > + if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en) > + alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX; > + else > + alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; > + alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION; > + alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; > +} > + > +static int vop2_find_start_mixer_id_for_vp(struct vop2 *vop2, uint8_t port_id) > +{ > + struct vop2_video_port *vp; > + int used_layer = 0; > + int i; > + > + for (i = 0; i < port_id; i++) { > + vp = &vop2->vps[i]; > + used_layer += hweight32(vp->win_mask); > + } > + > + return used_layer; > +} > + > +static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_win *main_win) > +{ > + uint32_t offset = (main_win->data->phys_id * 0x10); > + struct vop2_alpha_config alpha_config; > + struct vop2_alpha alpha; > + struct drm_plane_state *bottom_win_pstate; > + bool src_pixel_alpha_en = false; > + uint16_t src_glb_alpha_val, dst_glb_alpha_val; > + bool premulti_en = false; > + bool swap = false; > + > + /* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */ > + bottom_win_pstate = main_win->base.state; > + src_glb_alpha_val = 0; > + dst_glb_alpha_val = main_win->base.state->alpha; > + > + if (!bottom_win_pstate->fb) > + return; > + > + alpha_config.src_premulti_en = premulti_en; > + alpha_config.dst_premulti_en = false; > + alpha_config.src_pixel_alpha_en = src_pixel_alpha_en; > + alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ > + alpha_config.src_glb_alpha_value = src_glb_alpha_val; > + alpha_config.dst_glb_alpha_value = dst_glb_alpha_val; > + vop2_parse_alpha(&alpha_config, &alpha); > + > + alpha.src_color_ctrl.bits.src_dst_swap = swap; > + vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL + offset, > + alpha.src_color_ctrl.val); > + vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_COLOR_CTRL + offset, > + alpha.dst_color_ctrl.val); > + vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL + offset, > + alpha.src_alpha_ctrl.val); > + vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL + offset, > + alpha.dst_alpha_ctrl.val); > +} > + > +static void vop2_setup_alpha(struct vop2_video_port *vp) > +{ > + struct vop2 *vop2 = vp->vop2; > + struct drm_framebuffer *fb; > + struct vop2_alpha_config alpha_config; > + struct vop2_alpha alpha; > + struct drm_plane *plane; > + int pixel_alpha_en; > + int premulti_en, gpremulti_en = 0; > + int mixer_id; > + uint32_t offset; > + bool bottom_layer_alpha_en = false; > + uint32_t dst_global_alpha = DRM_BLEND_ALPHA_OPAQUE; > + > + mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id); > + alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ > + > + drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { > + struct vop2_win *win = to_vop2_win(plane); > + > + if (plane->state->normalized_zpos == 0 && > + !is_opaque(plane->state->alpha) && > + !vop2_cluster_window(win)) { > + /* > + * If bottom layer have global alpha effect [except cluster layer, > + * because cluster have deal with bottom layer global alpha value > + * at cluster mix], bottom layer mix need deal with global alpha. > + */ > + bottom_layer_alpha_en = true; > + dst_global_alpha = plane->state->alpha; > + } > + } > + > + drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { > + struct vop2_win *win = to_vop2_win(plane); > + int zpos = plane->state->normalized_zpos; > + > + if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) > + premulti_en = 1; > + else > + premulti_en = 0; > + > + plane = &win->base; > + fb = plane->state->fb; > + > + pixel_alpha_en = fb->format->has_alpha; > + > + alpha_config.src_premulti_en = premulti_en; > + > + if (bottom_layer_alpha_en && zpos == 1) { > + gpremulti_en = premulti_en; > + /* Cd = Cs + (1 - As) * Cd * Agd */ > + alpha_config.dst_premulti_en = false; > + alpha_config.src_pixel_alpha_en = pixel_alpha_en; > + alpha_config.src_glb_alpha_value = plane->state->alpha; > + alpha_config.dst_glb_alpha_value = dst_global_alpha; > + } else if (vop2_cluster_window(win)) { > + /* Mix output data only have pixel alpha */ > + alpha_config.dst_premulti_en = true; > + alpha_config.src_pixel_alpha_en = true; > + alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; > + alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; > + } else { > + /* Cd = Cs + (1 - As) * Cd */ > + alpha_config.dst_premulti_en = true; > + alpha_config.src_pixel_alpha_en = pixel_alpha_en; > + alpha_config.src_glb_alpha_value = plane->state->alpha; > + alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; > + } > + > + vop2_parse_alpha(&alpha_config, &alpha); > + > + offset = (mixer_id + zpos - 1) * 0x10; > + vop2_writel(vop2, RK3568_MIX0_SRC_COLOR_CTRL + offset, > + alpha.src_color_ctrl.val); > + vop2_writel(vop2, RK3568_MIX0_DST_COLOR_CTRL + offset, > + alpha.dst_color_ctrl.val); > + vop2_writel(vop2, RK3568_MIX0_SRC_ALPHA_CTRL + offset, > + alpha.src_alpha_ctrl.val); > + vop2_writel(vop2, RK3568_MIX0_DST_ALPHA_CTRL + offset, > + alpha.dst_alpha_ctrl.val); > + } > + > + if (vp->id == 0) { > + if (bottom_layer_alpha_en) { > + /* Transfer pixel alpha to hdr mix */ > + alpha_config.src_premulti_en = gpremulti_en; > + alpha_config.dst_premulti_en = true; > + alpha_config.src_pixel_alpha_en = true; > + alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; > + alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; > + vop2_parse_alpha(&alpha_config, &alpha); > + > + vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, > + alpha.src_color_ctrl.val); > + vop2_writel(vop2, RK3568_HDR0_DST_COLOR_CTRL, > + alpha.dst_color_ctrl.val); > + vop2_writel(vop2, RK3568_HDR0_SRC_ALPHA_CTRL, > + alpha.src_alpha_ctrl.val); > + vop2_writel(vop2, RK3568_HDR0_DST_ALPHA_CTRL, > + alpha.dst_alpha_ctrl.val); > + } else { > + vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, 0); > + } > + } > +} > + > +#define NR_VPS 3 > +#define NR_MIXERS 6 > + > +static void vop2_setup_layer_mixer(struct vop2_video_port *vp) > +{ > + struct vop2 *vop2 = vp->vop2; > + struct drm_plane *plane; > + uint32_t layer_sel = 0; > + uint32_t port_sel; > + int nlayer, ofs; > + struct drm_display_mode *adjusted_mode; > + uint16_t hsync_len; > + uint16_t hdisplay; > + uint32_t bg_dly; > + uint32_t pre_scan_dly; > + int i; > + struct vop2_video_port *vp0 = &vop2->vps[0]; > + struct vop2_video_port *vp1 = &vop2->vps[1]; > + struct vop2_video_port *vp2 = &vop2->vps[2]; > + > + adjusted_mode = &vp->crtc.state->adjusted_mode; > + hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; > + hdisplay = adjusted_mode->crtc_hdisplay; > + > + bg_dly = vp->data->pre_scan_max_dly[3]; > + vop2_writel(vop2, RK3568_VP_BG_MIX_CTRL(vp->id), > + FIELD_PREP(RK3568_VP_BG_MIX_CTRL__BG_DLY, bg_dly)); > + > + pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len; > + vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly); > + > + vop2_writel(vop2, RK3568_OVL_CTRL, 0); > + port_sel = vop2_readl(vop2, RK3568_OVL_PORT_SEL); > + port_sel &= RK3568_OVL_PORT_SEL__SEL_PORT; > + > + if (vp0->nlayers) > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, > + vp0->nlayers - 1); > + else > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, 8); > + > + if (vp1->nlayers) > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, > + (vp0->nlayers + vp1->nlayers - 1)); > + else > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8); > + > + if (vp2->nlayers) > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, > + (vp2->nlayers + vp1->nlayers + vp0->nlayers - 1)); > + else > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8); > + > + layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); > + > + ofs = 0; > + for (i = 0; i < vp->id; i++) > + ofs += vop2->vps[i].nlayers; > + > + nlayer = 0; > + drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { > + struct vop2_win *win = to_vop2_win(plane); > + > + switch (win->data->phys_id) { > + case ROCKCHIP_VOP2_CLUSTER0: > + port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER0; > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER0, vp->id); > + break; > + case ROCKCHIP_VOP2_CLUSTER1: > + port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER1; > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER1, vp->id); > + break; > + case ROCKCHIP_VOP2_ESMART0: > + port_sel &= ~RK3568_OVL_PORT_SEL__ESMART0; > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART0, vp->id); > + break; > + case ROCKCHIP_VOP2_ESMART1: > + port_sel &= ~RK3568_OVL_PORT_SEL__ESMART1; > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART1, vp->id); > + break; > + case ROCKCHIP_VOP2_SMART0: > + port_sel &= ~RK3568_OVL_PORT_SEL__SMART0; > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART0, vp->id); > + break; > + case ROCKCHIP_VOP2_SMART1: > + port_sel &= ~RK3568_OVL_PORT_SEL__SMART1; > + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART1, vp->id); > + break; > + } > + > + layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(nlayer + ofs, 0x7); > + layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(nlayer + ofs, win->data->layer_sel_id); > + nlayer++; > + } > + > + /* configure unused layers to 0x5 (reserved) */ > + for (; nlayer < 3; nlayer++) { > + layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(nlayer + ofs, 0x7); > + layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(nlayer + ofs, 5); > + } > + > + vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel); > + vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel); > + vop2_writel(vop2, RK3568_OVL_CTRL, RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD); > +} > + > +static void vop2_setup_dly_for_windows(struct vop2 *vop2) > +{ > + struct vop2_win *win; > + int i = 0; > + uint32_t cdly = 0, sdly = 0; > + > + for (i = 0; i < vop2->data->win_size; i++) { > + uint32_t dly; > + > + win = &vop2->win[i]; > + dly = win->delay; > + > + switch (win->data->phys_id) { > + case ROCKCHIP_VOP2_CLUSTER0: > + cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_0, dly); > + cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_1, dly); > + break; > + case ROCKCHIP_VOP2_CLUSTER1: > + cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_0, dly); > + cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_1, dly); > + break; > + case ROCKCHIP_VOP2_ESMART0: > + sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART0, dly); > + break; > + case ROCKCHIP_VOP2_ESMART1: > + sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART1, dly); > + break; > + case ROCKCHIP_VOP2_SMART0: > + sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART1, dly); > + break; > + case ROCKCHIP_VOP2_SMART1: > + sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART0, dly); > + break; > + } > + } > + > + vop2_writel(vop2, RK3568_CLUSTER_DLY_NUM, cdly); > + vop2_writel(vop2, RK3568_SMART_DLY_NUM, sdly); > +} > + > +static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct vop2 *vop2 = vp->vop2; > + struct drm_plane *plane; > + > + vp->win_mask = 0; > + > + drm_atomic_crtc_for_each_plane(plane, crtc) { > + struct vop2_win *win = to_vop2_win(plane); > + > + win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT]; > + > + vp->win_mask |= BIT(win->data->phys_id); > + > + if (vop2_cluster_window(win)) > + vop2_setup_cluster_alpha(vop2, win); > + } > + > + if (!vp->win_mask) > + return; > + > + vop2_setup_layer_mixer(vp); > + vop2_setup_alpha(vp); > + vop2_setup_dly_for_windows(vop2); > +} > + > +static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct vop2 *vop2 = vp->vop2; > + > + spin_lock(&vop2->reg_lock); > + > + vop2_post_config(crtc); > + > + spin_unlock(&vop2->reg_lock); > + > + vop2_cfg_done(vp); > + > + spin_lock_irq(&crtc->dev->event_lock); > + > + if (crtc->state->event) { > + WARN_ON(drm_crtc_vblank_get(crtc)); > + vp->event = crtc->state->event; > + crtc->state->event = NULL; > + } > + > + spin_unlock_irq(&crtc->dev->event_lock); > +} > + > +static const struct drm_crtc_helper_funcs vop2_crtc_helper_funcs = { > + .mode_fixup = vop2_crtc_mode_fixup, > + .atomic_check = vop2_crtc_atomic_check, > + .atomic_begin = vop2_crtc_atomic_begin, > + .atomic_flush = vop2_crtc_atomic_flush, > + .atomic_enable = vop2_crtc_atomic_enable, > + .atomic_disable = vop2_crtc_atomic_disable, > +}; > + > +static void vop2_crtc_reset(struct drm_crtc *crtc) > +{ > + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); > + > + if (crtc->state) { > + __drm_atomic_helper_crtc_destroy_state(crtc->state); > + kfree(vcstate); > + } > + > + vcstate = kzalloc(sizeof(*vcstate), GFP_KERNEL); > + if (!vcstate) > + return; > + > + crtc->state = &vcstate->base; > + crtc->state->crtc = crtc; > +} > + > +static struct drm_crtc_state *vop2_crtc_duplicate_state(struct drm_crtc *crtc) > +{ > + struct rockchip_crtc_state *vcstate, *old_vcstate; > + > + old_vcstate = to_rockchip_crtc_state(crtc->state); > + > + vcstate = kmemdup(old_vcstate, sizeof(*old_vcstate), GFP_KERNEL); > + if (!vcstate) > + return NULL; > + > + __drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base); > + > + return &vcstate->base; > +} > + > +static void vop2_crtc_destroy_state(struct drm_crtc *crtc, > + struct drm_crtc_state *state) > +{ > + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(state); > + > + __drm_atomic_helper_crtc_destroy_state(&vcstate->base); > + kfree(vcstate); > +} > + > +static const struct drm_crtc_funcs vop2_crtc_funcs = { > + .set_config = drm_atomic_helper_set_config, > + .page_flip = drm_atomic_helper_page_flip, > + .destroy = drm_crtc_cleanup, > + .reset = vop2_crtc_reset, > + .atomic_duplicate_state = vop2_crtc_duplicate_state, > + .atomic_destroy_state = vop2_crtc_destroy_state, > + .enable_vblank = vop2_crtc_enable_vblank, > + .disable_vblank = vop2_crtc_disable_vblank, > +}; > + > +static irqreturn_t vop2_isr(int irq, void *data) > +{ > + struct vop2 *vop2 = data; > + const struct vop2_data *vop2_data = vop2->data; > + uint32_t axi_irqs[VOP2_SYS_AXI_BUS_NUM]; > + int ret = IRQ_NONE; > + int i; > + > + /* > + * The irq is shared with the iommu. If the runtime-pm state of the > + * vop2-device is disabled the irq has to be targeted at the iommu. > + */ > + if (!pm_runtime_get_if_in_use(vop2->dev)) > + return IRQ_NONE; > + > + for (i = 0; i < vop2_data->nr_vps; i++) { > + struct vop2_video_port *vp = &vop2->vps[i]; > + struct drm_crtc *crtc = &vp->crtc; > + uint32_t irqs; > + > + irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id)); > + vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs); > + > + if (irqs & VP_INT_DSP_HOLD_VALID) { > + complete(&vp->dsp_hold_completion); > + ret = IRQ_HANDLED; > + } > + > + if (irqs & VP_INT_FS_FIELD) { > + unsigned long flags; > + > + drm_crtc_handle_vblank(crtc); > + spin_lock_irqsave(&crtc->dev->event_lock, flags); > + if (vp->event) { > + uint32_t val = vop2_readl(vop2, RK3568_REG_CFG_DONE); > + if (!(val & BIT(vp->id))) { > + drm_crtc_send_vblank_event(crtc, vp->event); > + vp->event = NULL; > + drm_crtc_vblank_put(crtc); > + } > + } > + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); > + > + ret = IRQ_HANDLED; > + } > + > + if (irqs & VP_INT_POST_BUF_EMPTY) { > + drm_err_ratelimited(vop2->drm, > + "POST_BUF_EMPTY irq err at vp%d\n", > + vp->id); > + ret = IRQ_HANDLED; > + } > + } > + > + axi_irqs[0] = vop2_readl(vop2, RK3568_SYS0_INT_STATUS); > + vop2_writel(vop2, RK3568_SYS0_INT_CLR, axi_irqs[0] << 16 | axi_irqs[0]); > + axi_irqs[1] = vop2_readl(vop2, RK3568_SYS1_INT_STATUS); > + vop2_writel(vop2, RK3568_SYS1_INT_CLR, axi_irqs[1] << 16 | axi_irqs[1]); > + > + for (i = 0; i < ARRAY_SIZE(axi_irqs); i++) { > + if (axi_irqs[i] & VOP2_INT_BUS_ERRPR) { > + drm_err_ratelimited(vop2->drm, "BUS_ERROR irq err\n"); > + ret = IRQ_HANDLED; > + } > + } > + > + pm_runtime_put(vop2->dev); > + > + return ret; > +} > + > +static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win, unsigned long possible_crtcs) > +{ > + const struct vop2_win_data *win_data = win->data; > + unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | BIT(DRM_MODE_BLEND_PREMULTI) | > + BIT(DRM_MODE_BLEND_COVERAGE); > + int ret; > + > + ret = drm_universal_plane_init(vop2->drm, &win->base, possible_crtcs, > + &vop2_plane_funcs, win_data->formats, win_data->nformats, > + win_data->format_modifiers, win->type, win_data->name); > + if (ret) { > + drm_err(vop2->drm, "failed to initialize plane %d\n", ret); > + return ret; > + } > + > + drm_plane_helper_add(&win->base, &vop2_plane_helper_funcs); > + > + if (win->data->supported_rotations) > + drm_plane_create_rotation_property(&win->base, DRM_MODE_ROTATE_0, > + DRM_MODE_ROTATE_0 | > + win->data->supported_rotations); > + drm_plane_create_alpha_property(&win->base); > + drm_plane_create_blend_mode_property(&win->base, blend_caps); > + drm_plane_create_zpos_property(&win->base, win->win_id, 0, > + vop2->registered_num_wins - 1); > + > + return 0; > +} > + > +static struct vop2_video_port *get_activated_vp(struct vop2 *vop2, int n) > +{ > + int i, id = 0; > + > + for (i = 0; i < vop2->data->nr_vps; i++) { > + struct vop2_video_port *vp = &vop2->vps[i]; > + > + if (!vp->crtc.port) > + continue; > + > + if (n == id) > + return vp; > + id++; > + } > + > + return NULL; > +} > + > +static int vop2_create_crtc(struct vop2 *vop2) > +{ > + const struct vop2_data *vop2_data = vop2->data; > + struct drm_device *drm = vop2->drm; > + struct device *dev = vop2->dev; > + struct drm_plane *plane; > + struct device_node *port; > + struct vop2_video_port *vp; > + uint32_t possible_crtcs; > + int i, nvp, nvps = 0; > + int ret; > + > + for (i = 0; i < vop2_data->nr_vps; i++) { > + const struct vop2_video_port_data *vp_data; > + struct device_node *np; > + char dclk_name[9]; > + > + vp_data = &vop2_data->vp[i]; > + vp = &vop2->vps[i]; > + vp->vop2 = vop2; > + vp->id = vp_data->id; > + vp->regs = vp_data->regs; > + vp->data = vp_data; > + > + snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", vp->id); > + vp->dclk = devm_clk_get(vop2->dev, dclk_name); > + if (IS_ERR(vp->dclk)) { > + drm_err(vop2->drm, "failed to get %s\n", dclk_name); > + return PTR_ERR(vp->dclk); > + } > + > + np = of_graph_get_remote_node(dev->of_node, i, -1); > + if (!np) { > + printk("%s: No remote for vp%d\n", __func__, i); > + continue; > + } > + of_node_put(np); > + > + port = of_graph_get_port_by_id(dev->of_node, i); > + if (!port) { > + drm_err(vop2->drm, "no port node found for video_port%d\n", i); > + return -ENOENT; > + } > + > + vp->crtc.port = port; > + nvps++; > + } > + > + nvp = 0; > + for (i = 0; i < vop2->registered_num_wins; i++) { > + struct vop2_win *win = &vop2->win[i]; > + > + if (win->type == DRM_PLANE_TYPE_PRIMARY) { > + vp = get_activated_vp(vop2, nvp); > + > + if (vp) { > + possible_crtcs = BIT(nvp); > + vp->primary_plane = win; > + > + nvp++; > + } else { > + /* change the unused primary window to overlay window */ > + win->type = DRM_PLANE_TYPE_OVERLAY; > + } > + } > + > + if (win->type == DRM_PLANE_TYPE_OVERLAY) > + possible_crtcs = (1 << vop2_data->nr_vps) - 1; > + > + ret = vop2_plane_init(vop2, win, possible_crtcs); > + > + if (ret) { > + drm_err(vop2->drm, "failed to init plane %s: %d\n", win->data->name, ret); > + return ret; > + } > + } > + > + for (i = 0; i < vop2_data->nr_vps; i++) { > + vp = &vop2->vps[i]; > + > + if (!vp->crtc.port) > + continue; > + > + plane = &vp->primary_plane->base; > + > + ret = drm_crtc_init_with_planes(drm, &vp->crtc, plane, NULL, &vop2_crtc_funcs, > + "video_port%d", vp->id); > + if (ret) { > + drm_err(vop2->drm, "crtc init for video_port%d failed\n", i); > + return ret; > + } > + > + drm_crtc_helper_add(&vp->crtc, &vop2_crtc_helper_funcs); > + > + init_completion(&vp->dsp_hold_completion); > + } > + > + for (i = 0; i < vop2->data->nr_vps; i++) { > + struct vop2_video_port *vp = &vop2->vps[i]; > + if (vp->crtc.port) > + vp->nlayers = NR_MIXERS / nvps; > + } > + > + return 0; > +} > + > +static void vop2_destroy_crtc(struct drm_crtc *crtc) > +{ > + of_node_put(crtc->port); > + > + /* > + * Destroy CRTC after vop2_plane_destroy() since vop2_disable_plane() > + * references the CRTC. > + */ > + drm_crtc_cleanup(crtc); > +} > + > +static int vop2_cluster_init(struct vop2_win *win) > +{ > + struct vop2 *vop2 = win->vop2; > + int i; > + struct reg_field vop2_cluster_regs[VOP2_WIN_MAX_REG] = { > + [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0), > + [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5), > + [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 14, 14), > + [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 18, 18), > + [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_ACT_INFO, 0, 31), > + [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_INFO, 0, 31), > + [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_ST, 0, 31), > + [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_CLUSTER_WIN_YRGB_MST, 0, 31), > + [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_CLUSTER_WIN_CBR_MST, 0, 31), > + [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 19, 19), > + [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 0, 15), > + [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 16, 31), > + [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 8, 8), > + [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 9, 9), > + [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 10, 11), > + > + /* Scale */ > + [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0, 15), > + [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 16, 31), > + [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 14, 15), > + [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 12, 13), > + [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 2, 3), > + [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 28, 28), > + [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 29, 29), > + > + /* cluster regs */ > + [VOP2_WIN_AFBC_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 1, 1), > + [VOP2_WIN_CLUSTER_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 0, 0), > + [VOP2_WIN_CLUSTER_LB_MODE] = REG_FIELD(RK3568_CLUSTER_CTRL, 4, 7), > + > + /* afbc regs */ > + [VOP2_WIN_AFBC_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 2, 6), > + [VOP2_WIN_AFBC_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 9, 9), > + [VOP2_WIN_AFBC_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 10, 10), > + [VOP2_WIN_AFBC_AUTO_GATING_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 4, 4), > + [VOP2_WIN_AFBC_HALF_BLOCK_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 7, 7), > + [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 8, 8), > + [VOP2_WIN_AFBC_HDR_PTR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0, 31), > + [VOP2_WIN_AFBC_PIC_SIZE] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0, 31), > + [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0, 15), > + [VOP2_WIN_AFBC_TILE_NUM] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 16, 31), > + [VOP2_WIN_AFBC_PIC_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0, 31), > + [VOP2_WIN_AFBC_DSP_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0, 31), > + [VOP2_WIN_AFBC_TRANSFORM_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET, 0, 31), > + [VOP2_WIN_AFBC_ROTATE_90] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0, 0), > + [VOP2_WIN_AFBC_ROTATE_270] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 1, 1), > + [VOP2_WIN_XMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 2, 2), > + [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 3, 3), > + [VOP2_WIN_UV_SWAP] = { .reg = 0xffffffff }, > + [VOP2_WIN_COLOR_KEY] = { .reg = 0xffffffff }, > + [VOP2_WIN_COLOR_KEY_EN] = { .reg = 0xffffffff }, > + [VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff }, > + [VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff }, > + [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = { .reg = 0xffffffff }, > + [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = { .reg = 0xffffffff }, > + [VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff }, > + [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff }, > + [VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff }, > + [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff }, > + [VOP2_WIN_VSD_CBCR_GT2] = { .reg = 0xffffffff }, > + [VOP2_WIN_VSD_CBCR_GT4] = { .reg = 0xffffffff }, > + }; > + > + for (i = 0; i < ARRAY_SIZE(vop2_cluster_regs); i++) > + vop2_cluster_regs[i].reg += win->offset; > + > + return devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg, > + vop2_cluster_regs, > + ARRAY_SIZE(vop2_cluster_regs)); > +}; > + > +static int vop2_esmart_init(struct vop2_win *win) > +{ > + struct vop2 *vop2 = win->vop2; > + int i; > + struct reg_field vop2_esmart_regs[VOP2_WIN_MAX_REG] = { > + [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 0, 0), > + [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 1, 5), > + [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 12, 12), > + [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 14, 14), > + [VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 16, 16), > + [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_SMART_REGION0_ACT_INFO, 0, 31), > + [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_SMART_REGION0_DSP_INFO, 0, 31), > + [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_SMART_REGION0_DSP_ST, 0, 28), > + [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_SMART_REGION0_YRGB_MST, 0, 31), > + [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_SMART_REGION0_CBR_MST, 0, 31), > + [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 17, 17), > + [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 0, 15), > + [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 16, 31), > + [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_SMART_CTRL0, 0, 0), > + [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_SMART_CTRL0, 1, 1), > + [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_SMART_CTRL0, 2, 3), > + [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_SMART_CTRL1, 31, 31), > + [VOP2_WIN_COLOR_KEY] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 0, 29), > + [VOP2_WIN_COLOR_KEY_EN] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 31, 31), > + > + /* Scale */ > + [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0, 15), > + [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 16, 31), > + [VOP2_WIN_SCALE_CBCR_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0, 15), > + [VOP2_WIN_SCALE_CBCR_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 16, 31), > + [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 0, 1), > + [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 2, 3), > + [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 4, 5), > + [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 6, 7), > + [VOP2_WIN_CBCR_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 8, 9), > + [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 10, 11), > + [VOP2_WIN_CBCR_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 12, 13), > + [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 14, 15), > + [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 16, 17), > + [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 8, 8), > + [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 9, 9), > + [VOP2_WIN_VSD_CBCR_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 10, 10), > + [VOP2_WIN_VSD_CBCR_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 11, 11), > + [VOP2_WIN_XMIRROR] = { .reg = 0xffffffff }, > + [VOP2_WIN_CLUSTER_ENABLE] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_ENABLE] = { .reg = 0xffffffff }, > + [VOP2_WIN_CLUSTER_LB_MODE] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_FORMAT] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_RB_SWAP] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_UV_SWAP] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_AUTO_GATING_EN] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_TILE_NUM] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_PIC_OFFSET] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_PIC_SIZE] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_DSP_OFFSET] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_TRANSFORM_OFFSET] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_HDR_PTR] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_HALF_BLOCK_EN] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_ROTATE_270] = { .reg = 0xffffffff }, > + [VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff }, > + }; > + > + for (i = 0; i < ARRAY_SIZE(vop2_esmart_regs); i++) > + vop2_esmart_regs[i].reg += win->offset; > + > + return devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg, > + vop2_esmart_regs, > + ARRAY_SIZE(vop2_esmart_regs)); > +}; > + > +static int vop2_win_init(struct vop2 *vop2) > +{ > + const struct vop2_data *vop2_data = vop2->data; > + struct vop2_win *win; > + int i, ret; > + > + for (i = 0; i < vop2_data->win_size; i++) { > + const struct vop2_win_data *win_data = &vop2_data->win[i]; > + > + win = &vop2->win[i]; > + win->data = win_data; > + win->type = win_data->type; > + win->offset = win_data->base; > + win->win_id = i; > + win->vop2 = vop2; > + if (vop2_cluster_window(win)) > + ret = vop2_cluster_init(win); > + else > + ret = vop2_esmart_init(win); > + if (ret) > + return ret; > + } > + > + vop2->registered_num_wins = vop2_data->win_size; > + > + return 0; > +} > + > +/* > + * The window registers are only updated when config done is written. > + * Until that they read back the old value. As we read-modify-write > + * these registers mark them as non-volatile. This makes sure we read > + * the new values from the regmap register cache. > + */ I thinks we should be very carefully about switch to regmap. Most of the registers are take effect by frame sync(that is you write the config done bit and when vsync interrupt come), Not only windows register, but also the SYS_CTRL, post processor(VP0/1/2),  OVERLAY, hdr and so on. > +static const struct regmap_range vop2_nonvolatile_range[] = { > + regmap_reg_range(0x1000, 0x23ff), > +}; > + > +static const struct regmap_access_table vop2_volatile_table = { > + .no_ranges = vop2_nonvolatile_range, > + .n_no_ranges = ARRAY_SIZE(vop2_nonvolatile_range), > +}; > + > +static const struct regmap_config vop2_regmap_config = { > + .reg_bits = 32, > + .val_bits = 32, > + .reg_stride = 4, > + .max_register = 0x3000, > + .name = "vop2", > + .volatile_table = &vop2_volatile_table, > + .cache_type = REGCACHE_RBTREE, > +}; > + > +static int vop2_bind(struct device *dev, struct device *master, void *data) > +{ > + struct platform_device *pdev = to_platform_device(dev); > + const struct vop2_data *vop2_data; > + struct drm_device *drm = data; > + struct vop2 *vop2; > + struct resource *res; > + size_t alloc_size; > + int ret; > + > + vop2_data = of_device_get_match_data(dev); > + if (!vop2_data) > + return -ENODEV; > + > + /* Allocate vop2 struct and its vop2_win array */ > + alloc_size = sizeof(*vop2) + sizeof(*vop2->win) * vop2_data->win_size; > + vop2 = devm_kzalloc(dev, alloc_size, GFP_KERNEL); > + if (!vop2) > + return -ENOMEM; > + > + vop2->dev = dev; > + vop2->data = vop2_data; > + vop2->drm = drm; > + > + dev_set_drvdata(dev, vop2); > + > + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); > + if (!res) { > + drm_err(vop2->drm, "failed to get vop2 register byname\n"); > + return -EINVAL; > + } > + > + vop2->regs = devm_ioremap_resource(dev, res); > + if (IS_ERR(vop2->regs)) > + return PTR_ERR(vop2->regs); > + vop2->len = resource_size(res); > + > + vop2->map = devm_regmap_init_mmio(dev, vop2->regs, &vop2_regmap_config); > + > + ret = vop2_win_init(vop2); > + if (ret) > + return ret; Do you have a count about how much time the function vop2_win_init cost ? > + > + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gamma_lut"); > + if (res) { > + vop2->lut_regs = devm_ioremap_resource(dev, res); > + if (IS_ERR(vop2->lut_regs)) > + return PTR_ERR(vop2->lut_regs); > + } > + > + vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf"); > + > + vop2->hclk = devm_clk_get(vop2->dev, "hclk_vop"); > + if (IS_ERR(vop2->hclk)) { > + drm_err(vop2->drm, "failed to get hclk source\n"); > + return PTR_ERR(vop2->hclk); > + } > + > + vop2->aclk = devm_clk_get(vop2->dev, "aclk_vop"); > + if (IS_ERR(vop2->aclk)) { > + drm_err(vop2->drm, "failed to get aclk source\n"); > + return PTR_ERR(vop2->aclk); > + } > + > + vop2->irq = platform_get_irq(pdev, 0); > + if (vop2->irq < 0) { > + drm_err(vop2->drm, "cannot find irq for vop2\n"); > + return vop2->irq; > + } > + > + spin_lock_init(&vop2->reg_lock); > + mutex_init(&vop2->vop2_lock); > + > + ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2); > + if (ret) > + return ret; > + > + ret = rockchip_drm_dma_attach_device(vop2->drm, vop2->dev); > + if (ret) { > + drm_err(vop2->drm, "failed to attach dma mapping, %d\n", ret); > + return ret; > + } > + > + ret = vop2_create_crtc(vop2); > + if (ret) > + return ret; > + > + pm_runtime_enable(&pdev->dev); > + > + return 0; > +} > + > +static void vop2_unbind(struct device *dev, struct device *master, void *data) > +{ > + struct vop2 *vop2 = dev_get_drvdata(dev); > + struct drm_device *drm = vop2->drm; > + struct list_head *plane_list = &drm->mode_config.plane_list; > + struct list_head *crtc_list = &drm->mode_config.crtc_list; > + struct drm_crtc *crtc, *tmpc; > + struct drm_plane *plane, *tmpp; > + > + rockchip_drm_dma_detach_device(vop2->drm, vop2->dev); > + > + pm_runtime_disable(dev); > + > + list_for_each_entry_safe(plane, tmpp, plane_list, head) > + drm_plane_cleanup(plane); > + > + list_for_each_entry_safe(crtc, tmpc, crtc_list, head) > + vop2_destroy_crtc(crtc); > +} > + > +const struct component_ops vop2_component_ops = { > + .bind = vop2_bind, > + .unbind = vop2_unbind, > +}; > +EXPORT_SYMBOL_GPL(vop2_component_ops); > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > new file mode 100644 > index 0000000000000..bb5677ff00e93 > --- /dev/null > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > @@ -0,0 +1,480 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd > + * Author:Mark Yao > + */ > + > +#ifndef _ROCKCHIP_DRM_VOP2_H > +#define _ROCKCHIP_DRM_VOP2_H > + > +#include "rockchip_drm_vop.h" > + > +#include > +#include > + > +#define VOP_FEATURE_OUTPUT_10BIT BIT(0) > + > +#define WIN_FEATURE_AFBDC BIT(0) > +#define WIN_FEATURE_CLUSTER BIT(1) > + > +/* > + * the delay number of a window in different mode. > + */ > +enum win_dly_mode { > + VOP2_DLY_MODE_DEFAULT, /**< default mode */ > + VOP2_DLY_MODE_HISO_S, /** HDR in SDR out mode, as a SDR window */ > + VOP2_DLY_MODE_HIHO_H, /** HDR in HDR out mode, as a HDR window */ > + VOP2_DLY_MODE_MAX, > +}; > + > +struct vop_rect { > + int width; > + int height; > +}; > + > +enum vop2_scale_up_mode { > + VOP2_SCALE_UP_NRST_NBOR, > + VOP2_SCALE_UP_BIL, > + VOP2_SCALE_UP_BIC, > +}; > + > +enum vop2_scale_down_mode { > + VOP2_SCALE_DOWN_NRST_NBOR, > + VOP2_SCALE_DOWN_BIL, > + VOP2_SCALE_DOWN_AVG, > +}; > + > +enum vop2_win_regs { > + VOP2_WIN_ENABLE, > + VOP2_WIN_FORMAT, > + VOP2_WIN_CSC_MODE, > + VOP2_WIN_XMIRROR, > + VOP2_WIN_YMIRROR, > + VOP2_WIN_RB_SWAP, > + VOP2_WIN_UV_SWAP, > + VOP2_WIN_ACT_INFO, > + VOP2_WIN_DSP_INFO, > + VOP2_WIN_DSP_ST, > + VOP2_WIN_YRGB_MST, > + VOP2_WIN_UV_MST, > + VOP2_WIN_YRGB_VIR, > + VOP2_WIN_UV_VIR, > + VOP2_WIN_YUV_CLIP, > + VOP2_WIN_Y2R_EN, > + VOP2_WIN_R2Y_EN, > + VOP2_WIN_COLOR_KEY, > + VOP2_WIN_COLOR_KEY_EN, > + VOP2_WIN_DITHER_UP, > + > + /* scale regs */ > + VOP2_WIN_SCALE_YRGB_X, > + VOP2_WIN_SCALE_YRGB_Y, > + VOP2_WIN_SCALE_CBCR_X, > + VOP2_WIN_SCALE_CBCR_Y, > + VOP2_WIN_YRGB_HOR_SCL_MODE, > + VOP2_WIN_YRGB_HSCL_FILTER_MODE, > + VOP2_WIN_YRGB_VER_SCL_MODE, > + VOP2_WIN_YRGB_VSCL_FILTER_MODE, > + VOP2_WIN_CBCR_VER_SCL_MODE, > + VOP2_WIN_CBCR_HSCL_FILTER_MODE, > + VOP2_WIN_CBCR_HOR_SCL_MODE, > + VOP2_WIN_CBCR_VSCL_FILTER_MODE, > + VOP2_WIN_VSD_CBCR_GT2, > + VOP2_WIN_VSD_CBCR_GT4, > + VOP2_WIN_VSD_YRGB_GT2, > + VOP2_WIN_VSD_YRGB_GT4, > + VOP2_WIN_BIC_COE_SEL, > + > + /* cluster regs */ > + VOP2_WIN_CLUSTER_ENABLE, > + VOP2_WIN_AFBC_ENABLE, > + VOP2_WIN_CLUSTER_LB_MODE, > + > + /* afbc regs */ > + VOP2_WIN_AFBC_FORMAT, > + VOP2_WIN_AFBC_RB_SWAP, > + VOP2_WIN_AFBC_UV_SWAP, > + VOP2_WIN_AFBC_AUTO_GATING_EN, > + VOP2_WIN_AFBC_BLOCK_SPLIT_EN, > + VOP2_WIN_AFBC_PIC_VIR_WIDTH, > + VOP2_WIN_AFBC_TILE_NUM, > + VOP2_WIN_AFBC_PIC_OFFSET, > + VOP2_WIN_AFBC_PIC_SIZE, > + VOP2_WIN_AFBC_DSP_OFFSET, > + VOP2_WIN_AFBC_TRANSFORM_OFFSET, > + VOP2_WIN_AFBC_HDR_PTR, > + VOP2_WIN_AFBC_HALF_BLOCK_EN, > + VOP2_WIN_AFBC_ROTATE_270, > + VOP2_WIN_AFBC_ROTATE_90, > + VOP2_WIN_MAX_REG, > +}; > + > +struct vop2_win_data { > + const char *name; > + uint8_t phys_id; > + > + uint32_t base; > + enum drm_plane_type type; > + > + uint32_t nformats; > + const uint32_t *formats; > + const uint64_t *format_modifiers; > + const unsigned int supported_rotations; > + > + /** > + * @layer_sel_id: defined by register OVERLAY_LAYER_SEL of VOP2 > + */ > + int layer_sel_id; > + uint64_t feature; > + > + unsigned int max_upscale_factor; > + unsigned int max_downscale_factor; > + const uint8_t dly[VOP2_DLY_MODE_MAX]; > +}; > + > +struct vop2_video_port_data { > + char id; > + uint32_t feature; > + uint16_t gamma_lut_len; > + uint16_t cubic_lut_len; > + struct vop_rect max_output; > + const u8 pre_scan_max_dly[4]; > + const struct vop2_video_port_regs *regs; > + int offset; > +}; > + > +struct vop2_data { > + uint8_t nr_vps; > + uint8_t nr_mixers; > + uint8_t nr_layers; > + uint8_t nr_gammas; > + const struct vop2_ctrl *ctrl; > + const struct vop2_win_data *win; > + const struct vop2_video_port_data *vp; > + const struct vop_csc_table *csc_table; > + struct vop_rect max_input; > + struct vop_rect max_output; > + > + unsigned int win_size; > + unsigned int soc_id; > +}; > + > +/* interrupt define */ > +#define FS_NEW_INTR BIT(4) > +#define ADDR_SAME_INTR BIT(5) > +#define LINE_FLAG1_INTR BIT(6) > +#define WIN0_EMPTY_INTR BIT(7) > +#define WIN1_EMPTY_INTR BIT(8) > +#define WIN2_EMPTY_INTR BIT(9) > +#define WIN3_EMPTY_INTR BIT(10) > +#define HWC_EMPTY_INTR BIT(11) > +#define POST_BUF_EMPTY_INTR BIT(12) > +#define PWM_GEN_INTR BIT(13) > +#define DMA_FINISH_INTR BIT(14) > +#define FS_FIELD_INTR BIT(15) > +#define FE_INTR BIT(16) > +#define WB_UV_FIFO_FULL_INTR BIT(17) > +#define WB_YRGB_FIFO_FULL_INTR BIT(18) > +#define WB_COMPLETE_INTR BIT(19) > + > +/* > + * display output interface supported by rockchip lcdc > + */ > +#define ROCKCHIP_OUT_MODE_P888 0 > +#define ROCKCHIP_OUT_MODE_BT1120 0 > +#define ROCKCHIP_OUT_MODE_P666 1 > +#define ROCKCHIP_OUT_MODE_P565 2 > +#define ROCKCHIP_OUT_MODE_BT656 5 > +#define ROCKCHIP_OUT_MODE_S888 8 > +#define ROCKCHIP_OUT_MODE_S888_DUMMY 12 > +#define ROCKCHIP_OUT_MODE_YUV420 14 > +/* for use special outface */ > +#define ROCKCHIP_OUT_MODE_AAAA 15 > + > +enum vop_csc_format { > + CSC_BT601L, > + CSC_BT709L, > + CSC_BT601F, > + CSC_BT2020, > +}; > + > +enum src_factor_mode { > + SRC_FAC_ALPHA_ZERO, > + SRC_FAC_ALPHA_ONE, > + SRC_FAC_ALPHA_DST, > + SRC_FAC_ALPHA_DST_INVERSE, > + SRC_FAC_ALPHA_SRC, > + SRC_FAC_ALPHA_SRC_GLOBAL, > +}; > + > +enum dst_factor_mode { > + DST_FAC_ALPHA_ZERO, > + DST_FAC_ALPHA_ONE, > + DST_FAC_ALPHA_SRC, > + DST_FAC_ALPHA_SRC_INVERSE, > + DST_FAC_ALPHA_DST, > + DST_FAC_ALPHA_DST_GLOBAL, > +}; > + > +#define RK3568_GRF_VO_CON1 0x0364 > +/* System registers definition */ > +#define RK3568_REG_CFG_DONE 0x000 > +#define RK3568_VERSION_INFO 0x004 > +#define RK3568_SYS_AUTO_GATING_CTRL 0x008 > +#define RK3568_SYS_AXI_LUT_CTRL 0x024 > +#define RK3568_DSP_IF_EN 0x028 > +#define RK3568_DSP_IF_CTRL 0x02c > +#define RK3568_DSP_IF_POL 0x030 > +#define RK3568_WB_CTRL 0x40 > +#define RK3568_WB_XSCAL_FACTOR 0x44 > +#define RK3568_WB_YRGB_MST 0x48 > +#define RK3568_WB_CBR_MST 0x4C > +#define RK3568_OTP_WIN_EN 0x050 > +#define RK3568_LUT_PORT_SEL 0x058 > +#define RK3568_SYS_STATUS0 0x060 > +#define RK3568_VP_LINE_FLAG(vp) (0x70 + (vp) * 0x4) > +#define RK3568_SYS0_INT_EN 0x80 > +#define RK3568_SYS0_INT_CLR 0x84 > +#define RK3568_SYS0_INT_STATUS 0x88 > +#define RK3568_SYS1_INT_EN 0x90 > +#define RK3568_SYS1_INT_CLR 0x94 > +#define RK3568_SYS1_INT_STATUS 0x98 > +#define RK3568_VP_INT_EN(vp) (0xA0 + (vp) * 0x10) > +#define RK3568_VP_INT_CLR(vp) (0xA4 + (vp) * 0x10) > +#define RK3568_VP_INT_STATUS(vp) (0xA8 + (vp) * 0x10) > +#define RK3568_VP_INT_RAW_STATUS(vp) (0xAC + (vp) * 0x10) > + > +/* Video Port registers definition */ > +#define RK3568_VP_DSP_CTRL 0x00 > +#define RK3568_VP_MIPI_CTRL 0x04 > +#define RK3568_VP_COLOR_BAR_CTRL 0x08 > +#define RK3568_VP_3D_LUT_CTRL 0x10 > +#define RK3568_VP_3D_LUT_MST 0x20 > +#define RK3568_VP_DSP_BG 0x2C > +#define RK3568_VP_PRE_SCAN_HTIMING 0x30 > +#define RK3568_VP_POST_DSP_HACT_INFO 0x34 > +#define RK3568_VP_POST_DSP_VACT_INFO 0x38 > +#define RK3568_VP_POST_SCL_FACTOR_YRGB 0x3C > +#define RK3568_VP_POST_SCL_CTRL 0x40 > +#define RK3568_VP_POST_DSP_VACT_INFO_F1 0x44 > +#define RK3568_VP_DSP_HTOTAL_HS_END 0x48 > +#define RK3568_VP_DSP_HACT_ST_END 0x4C > +#define RK3568_VP_DSP_VTOTAL_VS_END 0x50 > +#define RK3568_VP_DSP_VACT_ST_END 0x54 > +#define RK3568_VP_DSP_VS_ST_END_F1 0x58 > +#define RK3568_VP_DSP_VACT_ST_END_F1 0x5C > +#define RK3568_VP_BCSH_CTRL 0x60 > +#define RK3568_VP_BCSH_BCS 0x64 > +#define RK3568_VP_BCSH_H 0x68 > +#define RK3568_VP_BCSH_COLOR_BAR 0x6C > + > +/* Overlay registers definition */ > +#define RK3568_OVL_CTRL 0x600 > +#define RK3568_OVL_LAYER_SEL 0x604 > +#define RK3568_OVL_PORT_SEL 0x608 > +#define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610 > +#define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614 > +#define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618 > +#define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C > +#define RK3568_MIX0_SRC_COLOR_CTRL 0x650 > +#define RK3568_MIX0_DST_COLOR_CTRL 0x654 > +#define RK3568_MIX0_SRC_ALPHA_CTRL 0x658 > +#define RK3568_MIX0_DST_ALPHA_CTRL 0x65C > +#define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0 > +#define RK3568_HDR0_DST_COLOR_CTRL 0x6C4 > +#define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8 > +#define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC > +#define RK3568_VP_BG_MIX_CTRL(vp) (0x6E0 + (vp) * 4) > +#define RK3568_CLUSTER_DLY_NUM 0x6F0 > +#define RK3568_SMART_DLY_NUM 0x6F8 > + > +/* Cluster register definition, offset relative to window base */ > +#define RK3568_CLUSTER_WIN_CTRL0 0x00 > +#define RK3568_CLUSTER_WIN_CTRL1 0x04 > +#define RK3568_CLUSTER_WIN_YRGB_MST 0x10 > +#define RK3568_CLUSTER_WIN_CBR_MST 0x14 > +#define RK3568_CLUSTER_WIN_VIR 0x18 > +#define RK3568_CLUSTER_WIN_ACT_INFO 0x20 > +#define RK3568_CLUSTER_WIN_DSP_INFO 0x24 > +#define RK3568_CLUSTER_WIN_DSP_ST 0x28 > +#define RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB 0x30 > +#define RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET 0x3C > +#define RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL 0x50 > +#define RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE 0x54 > +#define RK3568_CLUSTER_WIN_AFBCD_HDR_PTR 0x58 > +#define RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH 0x5C > +#define RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE 0x60 > +#define RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET 0x64 > +#define RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET 0x68 > +#define RK3568_CLUSTER_WIN_AFBCD_CTRL 0x6C > + > +#define RK3568_CLUSTER_CTRL 0x100 > + > +/* (E)smart register definition, offset relative to window base */ > +#define RK3568_SMART_CTRL0 0x00 > +#define RK3568_SMART_CTRL1 0x04 > +#define RK3568_SMART_REGION0_CTRL 0x10 > +#define RK3568_SMART_REGION0_YRGB_MST 0x14 > +#define RK3568_SMART_REGION0_CBR_MST 0x18 > +#define RK3568_SMART_REGION0_VIR 0x1C > +#define RK3568_SMART_REGION0_ACT_INFO 0x20 > +#define RK3568_SMART_REGION0_DSP_INFO 0x24 > +#define RK3568_SMART_REGION0_DSP_ST 0x28 > +#define RK3568_SMART_REGION0_SCL_CTRL 0x30 > +#define RK3568_SMART_REGION0_SCL_FACTOR_YRGB 0x34 > +#define RK3568_SMART_REGION0_SCL_FACTOR_CBR 0x38 > +#define RK3568_SMART_REGION0_SCL_OFFSET 0x3C > +#define RK3568_SMART_REGION1_CTRL 0x40 > +#define RK3568_SMART_REGION1_YRGB_MST 0x44 > +#define RK3568_SMART_REGION1_CBR_MST 0x48 > +#define RK3568_SMART_REGION1_VIR 0x4C > +#define RK3568_SMART_REGION1_ACT_INFO 0x50 > +#define RK3568_SMART_REGION1_DSP_INFO 0x54 > +#define RK3568_SMART_REGION1_DSP_ST 0x58 > +#define RK3568_SMART_REGION1_SCL_CTRL 0x60 > +#define RK3568_SMART_REGION1_SCL_FACTOR_YRGB 0x64 > +#define RK3568_SMART_REGION1_SCL_FACTOR_CBR 0x68 > +#define RK3568_SMART_REGION1_SCL_OFFSET 0x6C > +#define RK3568_SMART_REGION2_CTRL 0x70 > +#define RK3568_SMART_REGION2_YRGB_MST 0x74 > +#define RK3568_SMART_REGION2_CBR_MST 0x78 > +#define RK3568_SMART_REGION2_VIR 0x7C > +#define RK3568_SMART_REGION2_ACT_INFO 0x80 > +#define RK3568_SMART_REGION2_DSP_INFO 0x84 > +#define RK3568_SMART_REGION2_DSP_ST 0x88 > +#define RK3568_SMART_REGION2_SCL_CTRL 0x90 > +#define RK3568_SMART_REGION2_SCL_FACTOR_YRGB 0x94 > +#define RK3568_SMART_REGION2_SCL_FACTOR_CBR 0x98 > +#define RK3568_SMART_REGION2_SCL_OFFSET 0x9C > +#define RK3568_SMART_REGION3_CTRL 0xA0 > +#define RK3568_SMART_REGION3_YRGB_MST 0xA4 > +#define RK3568_SMART_REGION3_CBR_MST 0xA8 > +#define RK3568_SMART_REGION3_VIR 0xAC > +#define RK3568_SMART_REGION3_ACT_INFO 0xB0 > +#define RK3568_SMART_REGION3_DSP_INFO 0xB4 > +#define RK3568_SMART_REGION3_DSP_ST 0xB8 > +#define RK3568_SMART_REGION3_SCL_CTRL 0xC0 > +#define RK3568_SMART_REGION3_SCL_FACTOR_YRGB 0xC4 > +#define RK3568_SMART_REGION3_SCL_FACTOR_CBR 0xC8 > +#define RK3568_SMART_REGION3_SCL_OFFSET 0xCC > +#define RK3568_SMART_COLOR_KEY_CTRL 0xD0 > + > +/* HDR register definition */ > +#define RK3568_HDR_LUT_CTRL 0x2000 > +#define RK3568_HDR_LUT_MST 0x2004 > +#define RK3568_SDR2HDR_CTRL 0x2010 > +#define RK3568_HDR2SDR_CTRL 0x2020 > +#define RK3568_HDR2SDR_SRC_RANGE 0x2024 > +#define RK3568_HDR2SDR_NORMFACEETF 0x2028 > +#define RK3568_HDR2SDR_DST_RANGE 0x202C > +#define RK3568_HDR2SDR_NORMFACCGAMMA 0x2030 > +#define RK3568_HDR_EETF_OETF_Y0 0x203C > +#define RK3568_HDR_SAT_Y0 0x20C0 > +#define RK3568_HDR_EOTF_OETF_Y0 0x20F0 > +#define RK3568_HDR_OETF_DX_POW1 0x2200 > +#define RK3568_HDR_OETF_XN1 0x2300 > + > +#define RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN BIT(15) > + > +#define RK3568_VP_DSP_CTRL__STANDBY BIT(31) > +#define RK3568_VP_DSP_CTRL__DITHER_DOWN_MODE BIT(20) > +#define RK3568_VP_DSP_CTRL__DITHER_DOWN_SEL GENMASK(19, 18) > +#define RK3568_VP_DSP_CTRL__DITHER_DOWN_EN BIT(17) > +#define RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN BIT(16) > +#define RK3568_VP_DSP_CTRL__POST_DSP_OUT_R2Y BIT(15) > +#define RK3568_VP_DSP_CTRL__DSP_RB_SWAP BIT(9) > +#define RK3568_VP_DSP_CTRL__DSP_INTERLACE BIT(7) > +#define RK3568_VP_DSP_CTRL__DSP_FILED_POL BIT(6) > +#define RK3568_VP_DSP_CTRL__P2I_EN BIT(5) > +#define RK3568_VP_DSP_CTRL__CORE_DCLK_DIV BIT(4) > +#define RK3568_VP_DSP_CTRL__OUT_MODE GENMASK(3, 0) > + > +#define RK3568_VP_POST_SCL_CTRL__VSCALEDOWN BIT(1) > +#define RK3568_VP_POST_SCL_CTRL__HSCALEDOWN BIT(0) > + > +#define RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX GENMASK(26, 25) > +#define RK3568_SYS_DSP_INFACE_EN_LVDS1 BIT(24) > +#define RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX GENMASK(22, 21) > +#define RK3568_SYS_DSP_INFACE_EN_MIPI1 BIT(20) > +#define RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX GENMASK(19, 18) > +#define RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX GENMASK(17, 16) > +#define RK3568_SYS_DSP_INFACE_EN_EDP_MUX GENMASK(15, 14) > +#define RK3568_SYS_DSP_INFACE_EN_HDMI_MUX GENMASK(11, 10) > +#define RK3568_SYS_DSP_INFACE_EN_RGB_MUX GENMASK(9, 8) > +#define RK3568_SYS_DSP_INFACE_EN_LVDS0 BIT(5) > +#define RK3568_SYS_DSP_INFACE_EN_MIPI0 BIT(4) > +#define RK3568_SYS_DSP_INFACE_EN_EDP BIT(3) > +#define RK3568_SYS_DSP_INFACE_EN_HDMI BIT(1) > +#define RK3568_SYS_DSP_INFACE_EN_RGB BIT(0) > + > +#define RK3568_DSP_IF_POL__MIPI_PIN_POL GENMASK(19, 16) > +#define RK3568_DSP_IF_POL__EDP_PIN_POL GENMASK(15, 12) > +#define RK3568_DSP_IF_POL__HDMI_PIN_POL GENMASK(7, 4) > +#define RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL GENMASK(3, 0) > + > +#define RK3568_VP0_MIPI_CTRL__DCLK_DIV2_PHASE_LOCK BIT(5) > +#define RK3568_VP0_MIPI_CTRL__DCLK_DIV2 BIT(4) > + > +#define RK3568_SYS_AUTO_GATING_CTRL__AUTO_GATING_EN BIT(31) > + > +#define RK3568_DSP_IF_POL__CFG_DONE_IMD BIT(28) > + > +#define VOP2_SYS_AXI_BUS_NUM 2 > + > +#define VOP2_CLUSTER_YUV444_10 0x12 > + > +#define VOP2_COLOR_KEY_MASK BIT(31) > + > +#define RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD BIT(28) > + > +#define RK3568_VP_BG_MIX_CTRL__BG_DLY GENMASK(31, 24) > + > +#define RK3568_OVL_PORT_SEL__SEL_PORT GENMASK(31, 16) > +#define RK3568_OVL_PORT_SEL__SMART1 GENMASK(31, 30) > +#define RK3568_OVL_PORT_SEL__SMART0 GENMASK(29, 28) > +#define RK3568_OVL_PORT_SEL__ESMART1 GENMASK(27, 26) > +#define RK3568_OVL_PORT_SEL__ESMART0 GENMASK(25, 24) > +#define RK3568_OVL_PORT_SEL__CLUSTER1 GENMASK(19, 18) > +#define RK3568_OVL_PORT_SEL__CLUSTER0 GENMASK(17, 16) > +#define RK3568_OVL_PORT_SET__PORT2_MUX GENMASK(11, 8) > +#define RK3568_OVL_PORT_SET__PORT1_MUX GENMASK(7, 4) > +#define RK3568_OVL_PORT_SET__PORT0_MUX GENMASK(3, 0) > +#define RK3568_OVL_LAYER_SEL__LAYER(layer, x) ((x) << ((layer) * 4)) > + > +#define RK3568_CLUSTER_DLY_NUM__CLUSTER1_1 GENMASK(31, 24) > +#define RK3568_CLUSTER_DLY_NUM__CLUSTER1_0 GENMASK(23, 16) > +#define RK3568_CLUSTER_DLY_NUM__CLUSTER0_1 GENMASK(15, 8) > +#define RK3568_CLUSTER_DLY_NUM__CLUSTER0_0 GENMASK(7, 0) > + > +#define RK3568_SMART_DLY_NUM__SMART1 GENMASK(31, 24) > +#define RK3568_SMART_DLY_NUM__SMART0 GENMASK(23, 16) > +#define RK3568_SMART_DLY_NUM__ESMART1 GENMASK(15, 8) > +#define RK3568_SMART_DLY_NUM__ESMART0 GENMASK(7, 0) > + > +#define VP_INT_DSP_HOLD_VALID BIT(6) > +#define VP_INT_FS_FIELD BIT(5) > +#define VP_INT_POST_BUF_EMPTY BIT(4) > +#define VP_INT_LINE_FLAG1 BIT(3) > +#define VP_INT_LINE_FLAG0 BIT(2) > +#define VOP2_INT_BUS_ERRPR BIT(1) > +#define VP_INT_FS BIT(0) > + > +#define POLFLAG_DCLK_INV BIT(3) > + > +enum vop2_layer_phy_id { > + ROCKCHIP_VOP2_CLUSTER0 = 0, > + ROCKCHIP_VOP2_CLUSTER1, > + ROCKCHIP_VOP2_ESMART0, > + ROCKCHIP_VOP2_ESMART1, > + ROCKCHIP_VOP2_SMART0, > + ROCKCHIP_VOP2_SMART1, > + ROCKCHIP_VOP2_CLUSTER2, > + ROCKCHIP_VOP2_CLUSTER3, > + ROCKCHIP_VOP2_ESMART2, > + ROCKCHIP_VOP2_ESMART3, > + ROCKCHIP_VOP2_PHY_ID_INVALID = -1, > +}; > + > +extern const struct component_ops vop2_component_ops; > + > +#endif /* _ROCKCHIP_DRM_VOP2_H */ > diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > new file mode 100644 > index 0000000000000..2376e63d9478f > --- /dev/null > +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > @@ -0,0 +1,285 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (C) Rockchip Electronics Co.Ltd > + * Author: Andy Yan > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "rockchip_drm_vop2.h" > + > +static const uint32_t formats_win_full_10bit[] = { > + DRM_FORMAT_XRGB8888, > + DRM_FORMAT_ARGB8888, > + DRM_FORMAT_XBGR8888, > + DRM_FORMAT_ABGR8888, > + DRM_FORMAT_RGB888, > + DRM_FORMAT_BGR888, > + DRM_FORMAT_RGB565, > + DRM_FORMAT_BGR565, > + DRM_FORMAT_NV12, > + DRM_FORMAT_NV16, > + DRM_FORMAT_NV24, > +}; > + > +static const uint32_t formats_win_full_10bit_yuyv[] = { > + DRM_FORMAT_XRGB8888, > + DRM_FORMAT_ARGB8888, > + DRM_FORMAT_XBGR8888, > + DRM_FORMAT_ABGR8888, > + DRM_FORMAT_RGB888, > + DRM_FORMAT_BGR888, > + DRM_FORMAT_RGB565, > + DRM_FORMAT_BGR565, > + DRM_FORMAT_NV12, > + DRM_FORMAT_NV16, > + DRM_FORMAT_NV24, > + DRM_FORMAT_YVYU, > + DRM_FORMAT_VYUY, > +}; > + > +static const uint32_t formats_win_lite[] = { > + DRM_FORMAT_XRGB8888, > + DRM_FORMAT_ARGB8888, > + DRM_FORMAT_XBGR8888, > + DRM_FORMAT_ABGR8888, > + DRM_FORMAT_RGB888, > + DRM_FORMAT_BGR888, > + DRM_FORMAT_RGB565, > + DRM_FORMAT_BGR565, > +}; > + > +static const uint64_t format_modifiers[] = { > + DRM_FORMAT_MOD_LINEAR, > + DRM_FORMAT_MOD_INVALID, > +}; > + > +static const uint64_t format_modifiers_afbc[] = { > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16), > + > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_SPARSE), > + > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_YTR), > + > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_CBR), > + > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_YTR | > + AFBC_FORMAT_MOD_SPARSE), > + > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_CBR | > + AFBC_FORMAT_MOD_SPARSE), > + > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_YTR | > + AFBC_FORMAT_MOD_CBR), > + > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_YTR | > + AFBC_FORMAT_MOD_CBR | > + AFBC_FORMAT_MOD_SPARSE), > + > + /* SPLIT mandates SPARSE, RGB modes mandates YTR */ > + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | > + AFBC_FORMAT_MOD_YTR | > + AFBC_FORMAT_MOD_SPARSE | > + AFBC_FORMAT_MOD_SPLIT), > + DRM_FORMAT_MOD_INVALID, > +}; > + > +static const struct vop2_video_port_data rk3568_vop_video_ports[] = { > + { > + .id = 0, > + .feature = VOP_FEATURE_OUTPUT_10BIT, > + .gamma_lut_len = 1024, > + .cubic_lut_len = 9 * 9 * 9, > + .max_output = { 4096, 2304 }, > + .pre_scan_max_dly = { 69, 53, 53, 42 }, > + .offset = 0xc00, > + }, { > + .id = 1, > + .gamma_lut_len = 1024, > + .max_output = { 2048, 1536 }, > + .pre_scan_max_dly = { 40, 40, 40, 40 }, > + .offset = 0xd00, > + }, { > + .id = 2, > + .gamma_lut_len = 1024, > + .max_output = { 1920, 1080 }, > + .pre_scan_max_dly = { 40, 40, 40, 40 }, > + .offset = 0xe00, > + }, > +}; > + > +/* > + * rk3568 vop with 2 cluster, 2 esmart win, 2 smart win. > + * Every cluster can work as 4K win or split into two win. > + * All win in cluster support AFBCD. > + * > + * Every esmart win and smart win support 4 Multi-region. > + * > + * Scale filter mode: > + * > + * * Cluster: bicubic for horizontal scale up, others use bilinear > + * * ESmart: > + * * nearest-neighbor/bilinear/bicubic for scale up > + * * nearest-neighbor/bilinear/average for scale down > + * > + * > + * @TODO describe the wind like cpu-map dt nodes; > + */ > +static const struct vop2_win_data rk3568_vop_win_data[] = { > + { > + .name = "Smart0-win0", > + .phys_id = ROCKCHIP_VOP2_SMART0, > + .base = 0x1c00, > + .formats = formats_win_lite, > + .nformats = ARRAY_SIZE(formats_win_lite), > + .format_modifiers = format_modifiers, > + .layer_sel_id = 3, > + .supported_rotations = DRM_MODE_REFLECT_Y, > + .type = DRM_PLANE_TYPE_PRIMARY, > + .max_upscale_factor = 8, > + .max_downscale_factor = 8, > + .dly = { 20, 47, 41 }, > + }, { > + .name = "Smart1-win0", > + .phys_id = ROCKCHIP_VOP2_SMART1, > + .formats = formats_win_lite, > + .nformats = ARRAY_SIZE(formats_win_lite), > + .format_modifiers = format_modifiers, > + .base = 0x1e00, > + .layer_sel_id = 7, > + .supported_rotations = DRM_MODE_REFLECT_Y, > + .type = DRM_PLANE_TYPE_PRIMARY, > + .max_upscale_factor = 8, > + .max_downscale_factor = 8, > + .dly = { 20, 47, 41 }, > + }, { > + .name = "Esmart1-win0", > + .phys_id = ROCKCHIP_VOP2_ESMART1, > + .formats = formats_win_full_10bit_yuyv, > + .nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv), > + .format_modifiers = format_modifiers, > + .base = 0x1a00, > + .layer_sel_id = 6, > + .supported_rotations = DRM_MODE_REFLECT_Y, > + .type = DRM_PLANE_TYPE_PRIMARY, > + .max_upscale_factor = 8, > + .max_downscale_factor = 8, > + .dly = { 20, 47, 41 }, > + }, { > + .name = "Esmart0-win0", > + .phys_id = ROCKCHIP_VOP2_ESMART0, > + .formats = formats_win_full_10bit_yuyv, > + .nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv), > + .format_modifiers = format_modifiers, > + .base = 0x1800, > + .layer_sel_id = 2, > + .supported_rotations = DRM_MODE_REFLECT_Y, > + .type = DRM_PLANE_TYPE_OVERLAY, > + .max_upscale_factor = 8, > + .max_downscale_factor = 8, > + .dly = { 20, 47, 41 }, > + }, { > + .name = "Cluster0-win0", > + .phys_id = ROCKCHIP_VOP2_CLUSTER0, > + .base = 0x1000, > + .formats = formats_win_full_10bit, > + .nformats = ARRAY_SIZE(formats_win_full_10bit), > + .format_modifiers = format_modifiers_afbc, > + .layer_sel_id = 0, > + .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | > + DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, > + .max_upscale_factor = 4, > + .max_downscale_factor = 4, > + .dly = { 0, 27, 21 }, > + .type = DRM_PLANE_TYPE_OVERLAY, > + .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER, > + }, { > + .name = "Cluster1-win0", > + .phys_id = ROCKCHIP_VOP2_CLUSTER1, > + .base = 0x1200, > + .formats = formats_win_full_10bit, > + .nformats = ARRAY_SIZE(formats_win_full_10bit), > + .format_modifiers = format_modifiers_afbc, > + .layer_sel_id = 1, > + .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | > + DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, > + .type = DRM_PLANE_TYPE_OVERLAY, > + .max_upscale_factor = 4, > + .max_downscale_factor = 4, > + .dly = { 0, 27, 21 }, > + .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER, > + }, > +}; > + > +static const struct vop2_data rk3566_vop = { > + .nr_vps = 3, > + .nr_mixers = 5, > + .nr_gammas = 1, > + .max_input = { 4096, 2304 }, > + .max_output = { 4096, 2304 }, > + .vp = rk3568_vop_video_ports, > + .win = rk3568_vop_win_data, > + .win_size = ARRAY_SIZE(rk3568_vop_win_data), > + .soc_id = 3566, > +}; > + > +static const struct vop2_data rk3568_vop = { > + .nr_vps = 3, > + .nr_mixers = 5, > + .nr_gammas = 1, > + .max_input = { 4096, 2304 }, > + .max_output = { 4096, 2304 }, > + .vp = rk3568_vop_video_ports, > + .win = rk3568_vop_win_data, > + .win_size = ARRAY_SIZE(rk3568_vop_win_data), > + .soc_id = 3568, > +}; > + > +static const struct of_device_id vop2_dt_match[] = { > + { > + .compatible = "rockchip,rk3566-vop", > + .data = &rk3566_vop, > + }, { > + .compatible = "rockchip,rk3568-vop", > + .data = &rk3568_vop, > + }, { > + }, > +}; > +MODULE_DEVICE_TABLE(of, vop2_dt_match); > + > +static int vop2_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + > + return component_add(dev, &vop2_component_ops); > +} > + > +static int vop2_remove(struct platform_device *pdev) > +{ > + component_del(&pdev->dev, &vop2_component_ops); > + > + return 0; > +} > + > +struct platform_driver vop2_platform_driver = { > + .probe = vop2_probe, > + .remove = vop2_remove, > + .driver = { > + .name = "rockchip-vop2", > + .of_match_table = of_match_ptr(vop2_dt_match), > + }, > +};