From mboxrd@z Thu Jan 1 00:00:00 1970 From: Yakir Yang Subject: Re: [RFC PATCH v1 1/2] drm: rockchip: hdmi: add RK3229 HDMI support Date: Thu, 7 Jan 2016 14:22:02 +0800 Message-ID: <568E040A.4020907@rock-chips.com> References: <1452141288-9292-1-git-send-email-ykk@rock-chips.com> <1452141447-9441-1-git-send-email-ykk@rock-chips.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8"; Format="flowed" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <1452141447-9441-1-git-send-email-ykk@rock-chips.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Mark Yao , Heiko Stuebner , Russell King , Philipp Zabel , Andy Yan Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-rockchip@lists.infradead.org, Rob Herring , Kumar Gala , linux-arm-kernel@lists.infradead.org, Zheng Yang List-Id: linux-rockchip.vger.kernel.org VGhhbmtzIGZvciAiS2J1aWxkIHRlc3Qgcm9ib3QiIHJlbWluZGluZywgSSBmb3JnZXQgdG8gdXBk YXRlIAoibW9kZV92YWxpZCIgZnVuY3Rpb24gZGVmaW5lIGluIGlteC1oZG1pIHNpZGUsIHdvdWxk IHNlbmQgbmV3IHZlcnNpb24gb3V0LAoKLS0KCj4+IGRyaXZlcnMvZ3B1L2RybS9pbXgvZHdfaGRt aS1pbXguYzoxODE6Mjogd2FybmluZzogaW5pdGlhbGl6YXRpb24gZnJvbSBpbmNvbXBhdGlibGUg cG9pbnRlciB0eXBlCgogICAgICAubW9kZV92YWxpZCA9IGlteDZxX2hkbWlfbW9kZV92YWxpZCwK ICAgICAgXgogICAgZHJpdmVycy9ncHUvZHJtL2lteC9kd19oZG1pLWlteC5jOjE4MToyOiB3YXJu aW5nOiAobmVhciBpbml0aWFsaXphdGlvbiBmb3IgJ2lteDZxX2hkbWlfZHJ2X2RhdGEubW9kZV92 YWxpZCcpCiAgICBkcml2ZXJzL2dwdS9kcm0vaW14L2R3X2hkbWktaW14LmM6MTg5OjI6IHdhcm5p bmc6IGluaXRpYWxpemF0aW9uIGZyb20gaW5jb21wYXRpYmxlIHBvaW50ZXIgdHlwZQogICAgICAu bW9kZV92YWxpZCA9IGlteDZkbF9oZG1pX21vZGVfdmFsaWQsCiAgICAgIF4KICAgIGRyaXZlcnMv Z3B1L2RybS9pbXgvZHdfaGRtaS1pbXguYzoxODk6Mjogd2FybmluZzogKG5lYXIgaW5pdGlhbGl6 YXRpb24gZm9yICdpbXg2ZGxfaGRtaV9kcnZfZGF0YS5tb2RlX3ZhbGlkJykKClNvcnJ5LAotIFlh a2lyCgoKT24gMDEvMDcvMjAxNiAxMjozNyBQTSwgWWFraXIgWWFuZyB3cm90ZToKPiBSSzMyMjkg aW50ZWdyYXRlIGFuIERlc2lnbmVkV2FyZSBIRE1JMi4wIGNvbnRyb2xsZXIgYW5kIGFuIElOTk8g SERNSTIuMCBwaHksCj4gdGhlIG1heCBvdXRwdXQgcmVzb2x1dGlvbiBpcyA0Sy4KPgo+IFNpZ25l ZC1vZmYtYnk6IFlha2lyIFlhbmcgPHlra0Byb2NrLWNoaXBzLmNvbT4KPiAtLS0KPiAgIGRyaXZl cnMvZ3B1L2RybS9icmlkZ2UvZHctaGRtaS5jICAgICAgICAgICAgfCAgMzMgKystCj4gICBkcml2 ZXJzL2dwdS9kcm0vcm9ja2NoaXAvZHdfaGRtaS1yb2NrY2hpcC5jIHwgMzgwICsrKysrKysrKysr KysrKysrKysrKysrKystLS0KPiAgIGRyaXZlcnMvZ3B1L2RybS9yb2NrY2hpcC9kd19oZG1pLXJv Y2tjaGlwLmggfCAxMzcgKysrKysrKysrKwo+ICAgaW5jbHVkZS9kcm0vYnJpZGdlL2R3X2hkbWku aCAgICAgICAgICAgICAgICB8ICAgNSArLQo+ICAgNCBmaWxlcyBjaGFuZ2VkLCA1MTYgaW5zZXJ0 aW9ucygrKSwgMzkgZGVsZXRpb25zKC0pCj4gICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9n cHUvZHJtL3JvY2tjaGlwL2R3X2hkbWktcm9ja2NoaXAuaAo+Cj4gZGlmZiAtLWdpdCBhL2RyaXZl cnMvZ3B1L2RybS9icmlkZ2UvZHctaGRtaS5jIGIvZHJpdmVycy9ncHUvZHJtL2JyaWRnZS9kdy1o ZG1pLmMKPiBpbmRleCA2ZmJlYzk5Li42MGIxZGNmIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvZ3B1 L2RybS9icmlkZ2UvZHctaGRtaS5jCj4gKysrIGIvZHJpdmVycy9ncHUvZHJtL2JyaWRnZS9kdy1o ZG1pLmMKPiBAQCAtNzM1LDEwICs3MzUsMTIgQEAgc3RhdGljIGludCBoZG1pX3BoeV9jb25maWd1 cmUoc3RydWN0IGR3X2hkbWkgKmhkbWksIHVuc2lnbmVkIGNoYXIgcHJlcCwKPiAgIHsKPiAgIAl1 bnNpZ25lZCByZXNfaWR4Owo+ICAgCXU4IHZhbCwgbXNlYzsKPiArCWludCByZXQ7Cj4gICAJY29u c3Qgc3RydWN0IGR3X2hkbWlfcGxhdF9kYXRhICpwZGF0YSA9IGhkbWktPnBsYXRfZGF0YTsKPiAg IAljb25zdCBzdHJ1Y3QgZHdfaGRtaV9tcGxsX2NvbmZpZyAqbXBsbF9jb25maWcgPSBwZGF0YS0+ bXBsbF9jZmc7Cj4gICAJY29uc3Qgc3RydWN0IGR3X2hkbWlfY3Vycl9jdHJsICpjdXJyX2N0cmwg PSBwZGF0YS0+Y3VyX2N0cjsKPiAgIAljb25zdCBzdHJ1Y3QgZHdfaGRtaV9waHlfY29uZmlnICpw aHlfY29uZmlnID0gcGRhdGEtPnBoeV9jb25maWc7Cj4gKwlpbnQgbXBpeGVsY2xvY2sgPSBoZG1p LT5oZG1pX2RhdGEudmlkZW9fbW9kZS5tcGl4ZWxjbG9jazsKPiAgIAo+ICAgCWlmIChwcmVwKQo+ ICAgCQlyZXR1cm4gLUVJTlZBTDsKPiBAQCAtNzU4LDI3ICs3NjAsMzggQEAgc3RhdGljIGludCBo ZG1pX3BoeV9jb25maWd1cmUoc3RydWN0IGR3X2hkbWkgKmhkbWksIHVuc2lnbmVkIGNoYXIgcHJl cCwKPiAgIAkJcmV0dXJuIC1FSU5WQUw7Cj4gICAJfQo+ICAgCj4gKwlpZiAoaGRtaS0+cGxhdF9k YXRhLT5leHRwaHlfY29uZmlnKSB7Cj4gKwkJLyogZ2VuMiB0eCBwb3dlciBvZmYgKi8KPiArCQlk d19oZG1pX3BoeV9nZW4yX3R4cHdyb24oaGRtaSwgMCk7Cj4gKwkJZHdfaGRtaV9waHlfZ2VuMl9w ZGRxKGhkbWksIDEpOwo+ICsKPiArCQlyZXQgPSBoZG1pLT5wbGF0X2RhdGEtPmV4dHBoeV9jb25m aWcoaGRtaS0+cGxhdF9kYXRhLCByZXNfaWR4LAo+ICsJCQkJCQkgICAgIG1waXhlbGNsb2NrKTsK PiArCQkvKiBnZW4yIHR4IHBvd2VyIG9uICovCj4gKwkJZHdfaGRtaV9waHlfZ2VuMl90eHB3cm9u KGhkbWksIDEpOwo+ICsJCWR3X2hkbWlfcGh5X2dlbjJfcGRkcShoZG1pLCAwKTsKPiArCj4gKwkJ cmV0dXJuIHJldDsKPiArCX0KPiArCj4gICAJLyogUExML01QTEwgQ2ZnIC0gYWx3YXlzIG1hdGNo IG9uIGZpbmFsIGVudHJ5ICovCj4gICAJZm9yICg7IG1wbGxfY29uZmlnLT5tcGl4ZWxjbG9jayAh PSB+MFVMOyBtcGxsX2NvbmZpZysrKQo+IC0JCWlmIChoZG1pLT5oZG1pX2RhdGEudmlkZW9fbW9k ZS5tcGl4ZWxjbG9jayA8PQo+IC0JCSAgICBtcGxsX2NvbmZpZy0+bXBpeGVsY2xvY2spCj4gKwkJ aWYgKG1waXhlbGNsb2NrIDw9IG1wbGxfY29uZmlnLT5tcGl4ZWxjbG9jaykKPiAgIAkJCWJyZWFr Owo+ICAgCj4gICAJZm9yICg7IGN1cnJfY3RybC0+bXBpeGVsY2xvY2sgIT0gfjBVTDsgY3Vycl9j dHJsKyspCj4gLQkJaWYgKGhkbWktPmhkbWlfZGF0YS52aWRlb19tb2RlLm1waXhlbGNsb2NrIDw9 Cj4gLQkJICAgIGN1cnJfY3RybC0+bXBpeGVsY2xvY2spCj4gKwkJaWYgKG1waXhlbGNsb2NrIDw9 IGN1cnJfY3RybC0+bXBpeGVsY2xvY2spCj4gICAJCQlicmVhazsKPiAgIAo+ICAgCWZvciAoOyBw aHlfY29uZmlnLT5tcGl4ZWxjbG9jayAhPSB+MFVMOyBwaHlfY29uZmlnKyspCj4gLQkJaWYgKGhk bWktPmhkbWlfZGF0YS52aWRlb19tb2RlLm1waXhlbGNsb2NrIDw9Cj4gLQkJICAgIHBoeV9jb25m aWctPm1waXhlbGNsb2NrKQo+ICsJCWlmIChtcGl4ZWxjbG9jayA8PSBwaHlfY29uZmlnLT5tcGl4 ZWxjbG9jaykKPiAgIAkJCWJyZWFrOwo+ICAgCj4gICAJaWYgKG1wbGxfY29uZmlnLT5tcGl4ZWxj bG9jayA9PSB+MFVMIHx8Cj4gICAJICAgIGN1cnJfY3RybC0+bXBpeGVsY2xvY2sgPT0gfjBVTCB8 fAo+ICAgCSAgICBwaHlfY29uZmlnLT5tcGl4ZWxjbG9jayA9PSB+MFVMKSB7Cj4gICAJCWRldl9l cnIoaGRtaS0+ZGV2LCAiUGl4ZWwgY2xvY2sgJWQgLSB1bnN1cHBvcnRlZCBieSBIRE1JXG4iLAo+ IC0JCQloZG1pLT5oZG1pX2RhdGEudmlkZW9fbW9kZS5tcGl4ZWxjbG9jayk7Cj4gKwkJCW1waXhl bGNsb2NrKTsKPiAgIAkJcmV0dXJuIC1FSU5WQUw7Cj4gICAJfQo+ICAgCj4gQEAgLTE0NzYsMTQg KzE0ODksMTYgQEAgZHdfaGRtaV9jb25uZWN0b3JfbW9kZV92YWxpZChzdHJ1Y3QgZHJtX2Nvbm5l Y3RvciAqY29ubmVjdG9yLAo+ICAgewo+ICAgCXN0cnVjdCBkd19oZG1pICpoZG1pID0gY29udGFp bmVyX29mKGNvbm5lY3RvciwKPiAgIAkJCQkJICAgc3RydWN0IGR3X2hkbWksIGNvbm5lY3Rvcik7 Cj4gKwlzdHJ1Y3QgZHdfaGRtaV9wbGF0X2RhdGEgKnBsYXRfZGF0YSA9IGhkbWktPnBsYXRfZGF0 YTsKPiAgIAllbnVtIGRybV9tb2RlX3N0YXR1cyBtb2RlX3N0YXR1cyA9IE1PREVfT0s7Cj4gICAK PiAgIAkvKiBXZSBkb24ndCBzdXBwb3J0IGRvdWJsZS1jbG9ja2VkIG1vZGVzICovCj4gICAJaWYg KG1vZGUtPmZsYWdzICYgRFJNX01PREVfRkxBR19EQkxDTEspCj4gICAJCXJldHVybiBNT0RFX0JB RDsKPiAgIAo+IC0JaWYgKGhkbWktPnBsYXRfZGF0YS0+bW9kZV92YWxpZCkKPiAtCQltb2RlX3N0 YXR1cyA9IGhkbWktPnBsYXRfZGF0YS0+bW9kZV92YWxpZChjb25uZWN0b3IsIG1vZGUpOwo+ICsJ aWYgKHBsYXRfZGF0YS0+bW9kZV92YWxpZCkKPiArCQltb2RlX3N0YXR1cyA9IHBsYXRfZGF0YS0+ bW9kZV92YWxpZChwbGF0X2RhdGEsIG1vZGUpOwo+ICsKPiAgIAo+ICAgCXJldHVybiBtb2RlX3N0 YXR1czsKPiAgIH0KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL3JvY2tjaGlwL2R3X2hk bWktcm9ja2NoaXAuYyBiL2RyaXZlcnMvZ3B1L2RybS9yb2NrY2hpcC9kd19oZG1pLXJvY2tjaGlw LmMKPiBpbmRleCBjNjVjZThjLi40MjRkNTQ4IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvZ3B1L2Ry bS9yb2NrY2hpcC9kd19oZG1pLXJvY2tjaGlwLmMKPiArKysgYi9kcml2ZXJzL2dwdS9kcm0vcm9j a2NoaXAvZHdfaGRtaS1yb2NrY2hpcC5jCj4gQEAgLTcsNiArNyw3IEBACj4gICAgKiAoYXQgeW91 ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgo+ICAgICovCj4gICAKPiArI2luY2x1ZGUgPGxp bnV4L2Nsay5oPgo+ICAgI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgo+ICAgI2luY2x1ZGUgPGxp bnV4L3BsYXRmb3JtX2RldmljZS5oPgo+ICAgI2luY2x1ZGUgPGxpbnV4L21mZC9zeXNjb24uaD4K PiBAQCAtMjEsMTggKzIyLDEzNSBAQAo+ICAgI2luY2x1ZGUgInJvY2tjaGlwX2RybV9kcnYuaCIK PiAgICNpbmNsdWRlICJyb2NrY2hpcF9kcm1fdm9wLmgiCj4gICAKPiAtI2RlZmluZSBHUkZfU09D X0NPTjYgICAgICAgICAgICAgICAgICAgIDB4MDI1Ywo+IC0jZGVmaW5lIEhETUlfU0VMX1ZPUF9M SVQgICAgICAgICAgICAgICAgKDEgPDwgNCkKPiArI2luY2x1ZGUgImR3X2hkbWktcm9ja2NoaXAu aCIKPiAgIAo+ICAgc3RydWN0IHJvY2tjaGlwX2hkbWkgewo+ICAgCXN0cnVjdCBkZXZpY2UgKmRl djsKPiAgIAlzdHJ1Y3QgcmVnbWFwICpyZWdtYXA7Cj4gICAJc3RydWN0IGRybV9lbmNvZGVyIGVu Y29kZXI7Cj4gKwlzdHJ1Y3QgZHdfaGRtaV9wbGF0X2RhdGEgcGxhdF9kYXRhOwo+ICsKPiArCXZv aWQgX19pb21lbSAqZXh0cGh5X3JlZ2Jhc2U7Cj4gKwlzdHJ1Y3QgY2xrICpleHRwaHlfcGNsazsK PiAgIH07Cj4gICAKPiAgICNkZWZpbmUgdG9fcm9ja2NoaXBfaGRtaSh4KQljb250YWluZXJfb2Yo eCwgc3RydWN0IHJvY2tjaGlwX2hkbWksIHgpCj4gICAKPiAtc3RhdGljIGNvbnN0IHN0cnVjdCBk d19oZG1pX21wbGxfY29uZmlnIHJvY2tjaGlwX21wbGxfY2ZnW10gPSB7Cj4gK3N0YXRpYyBjb25z dCBzdHJ1Y3QgZXh0cGh5X2NvbmZpZ190YWIgcmszMjI5X2V4dHBoeV9jZmdbXSA9IHsKPiArCXsg Lm1waXhlbGNsb2NrID0gMTY1MDAwMDAwLAo+ICsJICAucHJlX2VtcGhhc2lzID0gMCwgLnNsb3Bl Ym9vc3QgPSAwLCAuY2xrX2xldmVsID0gNCwKPiArCSAgLmRhdGEwX2xldmVsID0gNCwgNCwgNCwK PiArCX0sCj4gKwo+ICsJeyAubXBpeGVsY2xvY2sgPSAyMjUwMDAwMDAsCj4gKwkgIC5wcmVfZW1w aGFzaXMgPSAwLCAuc2xvcGVib29zdCA9IDAsIC5jbGtfbGV2ZWwgPSA2LAo+ICsJICAuZGF0YTBf bGV2ZWwgPSA2LCA2LCA2LAo+ICsJfSwKPiArCj4gKwl7IC5tcGl4ZWxjbG9jayA9IDM0MDAwMDAw MCwKPiArCSAgLnByZV9lbXBoYXNpcyA9IDEsIC5zbG9wZWJvb3N0ID0gMCwgLmNsa19sZXZlbCA9 IDYsCj4gKwkgIC5kYXRhMF9sZXZlbCA9IDEwLCAxMCwgMTAsCj4gKwl9LAo+ICsKPiArCXsgLm1w aXhlbGNsb2NrID0gNTk0MDAwMDAwLAo+ICsJICAucHJlX2VtcGhhc2lzID0gMSwgLnNsb3BlYm9v c3QgPSAwLCAuY2xrX2xldmVsID0gNywKPiArCSAgLmRhdGEwX2xldmVsID0gMTAsIDEwLCAxMCwK PiArCX0sCj4gKwo+ICsJeyAubXBpeGVsY2xvY2sgPSB+MFVMfSwKPiArfTsKPiArCj4gK3N0YXRp YyBjb25zdCBzdHJ1Y3QgZXh0cGh5X3BsbF9jb25maWdfdGFiIHJrMzIyOV9leHRwaHlfcGxsX2Nm Z1tdID0gewo+ICsJewo+ICsJCS5tcGl4ZWxjbG9jayA9IDI3MDAwMDAwLCAucGFyYW0gPSB7Cj4g KwkJCXsgLnBsbF9uZCA9IDEsIC5wbGxfbmYgPSA0NSwKPiArCQkJICAudG1zZF9kaXZpZGVyX2Eg PSAzLCAxLCAxLAo+ICsJCQkgIC5wY2xrX2RpdmlkZXJfYSA9IDEsIDMsIDMsIDQsCj4gKwkJCSAg LnZjb19kaXZfNSA9IDAsCj4gKwkJCSAgLnBwbGxfbmQgPSAxLCAucHBsbF9uZiA9IDQwLCAucHBs bF9ubyA9IDgsCj4gKwkJCX0sCj4gKwkJCXsgLnBsbF9uZCA9IDEsIC5wbGxfbmYgPSA0NSwKPiAr CQkJICAudG1zZF9kaXZpZGVyX2EgPSAwLCAzLCAzLAo+ICsJCQkgIC5wY2xrX2RpdmlkZXJfYSA9 IDEsIDMsIDMsIDQsCj4gKwkJCSAgLnZjb19kaXZfNSA9IDAsCj4gKwkJCSAgLnBwbGxfbmQgPSAx LCAucHBsbF9uZiA9IDQwLCAucHBsbF9ubyA9IDgsCj4gKwkJCX0sCj4gKwkJfSwKPiArCX0sIHsK PiArCQkubXBpeGVsY2xvY2sgPSA1OTQwMDAwMCwgLnBhcmFtID0gewo+ICsJCQl7IC5wbGxfbmQg PSAyLCAucGxsX25mID0gOTksCj4gKwkJCSAgLnRtc2RfZGl2aWRlcl9hID0gMywgMSwgMSwKPiAr CQkJICAucGNsa19kaXZpZGVyX2EgPSAxLCAzLCAyLCAyLAo+ICsJCQkgIC52Y29fZGl2XzUgPSAw LAo+ICsJCQkgIC5wcGxsX25kID0gMSwgLnBwbGxfbmYgPSA0MCwgLnBwbGxfbm8gPSA4LAo+ICsJ CQl9LAo+ICsJCQl7IC5wbGxfbmQgPSAyLCAucGxsX25mID0gOTksCj4gKwkJCSAgLnRtc2RfZGl2 aWRlcl9hID0gMSwgMSwgMSwKPiArCQkJICAucGNsa19kaXZpZGVyX2EgPSAxLCAzLCAyLCAyLAo+ ICsJCQkgIC52Y29fZGl2XzUgPSAwLAo+ICsJCQkgIC5wcGxsX25kID0gMSwgLnBwbGxfbmYgPSA0 MCwgLnBwbGxfbm8gPSA4LAo+ICsJCQl9LAo+ICsJCX0sCj4gKwl9LCB7Cj4gKwkJLm1waXhlbGNs b2NrID0gNzQyNTAwMDAsIC5wYXJhbSA9IHsKPiArCQkJeyAucGxsX25kID0gMiwgLnBsbF9uZiA9 IDk5LAo+ICsJCQkgIC50bXNkX2RpdmlkZXJfYSA9IDEsIDEsIDEsCj4gKwkJCSAgLnBjbGtfZGl2 aWRlcl9hID0gMSwgMiwgMiwgMiwKPiArCQkJICAudmNvX2Rpdl81ID0gMCwKPiArCQkJICAucHBs bF9uZCA9IDEsIC5wcGxsX25mID0gNDAsIC5wcGxsX25vID0gOCwKPiArCQkJfSwKPiArCQkJeyAu cGxsX25kID0gNCwgLnBsbF9uZiA9IDQ5NSwKPiArCQkJICAudG1zZF9kaXZpZGVyX2EgPSAxLCAy LCAyLAo+ICsJCQkgIC5wY2xrX2RpdmlkZXJfYSA9IDEsIDMsIDMsIDQsCj4gKwkJCSAgLnZjb19k aXZfNSA9IDAsCj4gKwkJCSAgLnBwbGxfbmQgPSAyLCAucHBsbF9uZiA9IDQwLCAucHBsbF9ubyA9 IDQsCj4gKwkJCX0sCj4gKwkJfSwKPiArCX0sIHsKPiArCQkubXBpeGVsY2xvY2sgPSAxNDg1MDAw MDAsIC5wYXJhbSA9IHsKPiArCQkJeyAucGxsX25kID0gMiwgLnBsbF9uZiA9IDk5LAo+ICsJCQkg IC50bXNkX2RpdmlkZXJfYSA9IDEsIDAsIDAsCj4gKwkJCSAgLnBjbGtfZGl2aWRlcl9hID0gMSwg MiwgMSwgMSwKPiArCQkJICAudmNvX2Rpdl81ID0gMCwKPiArCQkJICAucHBsbF9uZCA9IDIsIC5w cGxsX25mID0gNDAsIC5wcGxsX25vID0gNCwKPiArCQkJfSwKPiArCQkJeyAucGxsX25kID0gNCwg LnBsbF9uZiA9IDQ5NSwKPiArCQkJICAudG1zZF9kaXZpZGVyX2EgPSAwLCAyLCAyLAo+ICsJCQkg IC5wY2xrX2RpdmlkZXJfYSA9IDEsIDMsIDIsIDIsCj4gKwkJCSAgLnZjb19kaXZfNSA9IDAsCj4g KwkJCSAgLnBwbGxfbmQgPSA0LCAucHBsbF9uZiA9IDQwLCAucHBsbF9ubyA9IDIsCj4gKwkJCX0s Cj4gKwkJfSwKPiArCX0sIHsKPiArCQkubXBpeGVsY2xvY2sgPSAyOTcwMDAwMDAsIC5wYXJhbSA9 IHsKPiArCQkJeyAucGxsX25kID0gMiwgLnBsbF9uZiA9IDk5LAo+ICsJCQkgIC50bXNkX2Rpdmlk ZXJfYSA9IDAsIDAsIDAsCj4gKwkJCSAgLnBjbGtfZGl2aWRlcl9hID0gMSwgMCwgMSwgMSwKPiAr CQkJICAudmNvX2Rpdl81ID0gMCwKPiArCQkJICAucHBsbF9uZCA9IDQsIC5wcGxsX25mID0gNDAs IC5wcGxsX25vID0gMiwKPiArCQkJfSwKPiArCQkJeyAucGxsX25kID0gNCwgLnBsbF9uZiA9IDQ5 NSwKPiArCQkJICAudG1zZF9kaXZpZGVyX2EgPSAxLCAyLCAwLAo+ICsJCQkgIC5wY2xrX2Rpdmlk ZXJfYSA9IDEsIDMsIDEsIDEsCj4gKwkJCSAgLnZjb19kaXZfNSA9IDAsCj4gKwkJCSAgLnBwbGxf bmQgPSA4LCAucHBsbF9uZiA9IDQwLCAucHBsbF9ubyA9IDEsCj4gKwkJCX0sCj4gKwkJfSwKPiAr CX0sIHsKPiArCQkubXBpeGVsY2xvY2sgPSA1OTQwMDAwMDAsIC5wYXJhbSA9IHsKPiArCQkJeyAu cGxsX25kID0gMSwgLnBsbF9uZiA9IDk5LAo+ICsJCQkgIC50bXNkX2RpdmlkZXJfYSA9IDAsIDIs IDAsCj4gKwkJCSAgLnBjbGtfZGl2aWRlcl9hID0gMSwgMCwgMSwgMSwKPiArCQkJICAudmNvX2Rp dl81ID0gMCwKPiArCQkJICAucHBsbF9uZCA9IDgsIC5wcGxsX25mID0gNDAsIC5wcGxsX25vID0g MSwKPiArCQkJfSwKPiArCQl9Cj4gKwl9LCB7Cj4gKwkJLm1waXhlbGNsb2NrID0gfjBVTCwKPiAr CX0KPiArfTsKPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgZHdfaGRtaV9tcGxsX2NvbmZpZyBy azMyODhfbXBsbF9jZmdbXSA9IHsKPiAgIAl7Cj4gICAJCTI3MDAwMDAwLCB7Cj4gICAJCQl7IDB4 MDBiMywgMHgwMDAwfSwKPiBAQCAtMTEyLDcgKzIzMCw3IEBAIHN0YXRpYyBjb25zdCBzdHJ1Y3Qg ZHdfaGRtaV9tcGxsX2NvbmZpZyByb2NrY2hpcF9tcGxsX2NmZ1tdID0gewo+ICAgCX0KPiAgIH07 Cj4gICAKPiAtc3RhdGljIGNvbnN0IHN0cnVjdCBkd19oZG1pX2N1cnJfY3RybCByb2NrY2hpcF9j dXJfY3RyW10gPSB7Cj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgZHdfaGRtaV9jdXJyX2N0cmwgcmsz Mjg4X2N1cl9jdHJbXSA9IHsKPiAgIAkvKiAgICAgIHBpeGVsY2xrICAgIGJwcDggICAgYnBwMTAg ICBicHAxMiAqLwo+ICAgCXsKPiAgIAkJNDAwMDAwMDAsICB7IDB4MDAxOCwgMHgwMDE4LCAweDAw MTggfSwKPiBAQCAtMTMzLDcgKzI1MSw3IEBAIHN0YXRpYyBjb25zdCBzdHJ1Y3QgZHdfaGRtaV9j dXJyX2N0cmwgcm9ja2NoaXBfY3VyX2N0cltdID0gewo+ICAgCX0KPiAgIH07Cj4gICAKPiAtc3Rh dGljIGNvbnN0IHN0cnVjdCBkd19oZG1pX3BoeV9jb25maWcgcm9ja2NoaXBfcGh5X2NvbmZpZ1td ID0gewo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGR3X2hkbWlfcGh5X2NvbmZpZyByazMyODhfcGh5 X2NvbmZpZ1tdID0gewo+ICAgCS8qcGl4ZWxjbGsgICBzeW1ib2wgICB0ZXJtICAgdmxldiovCj4g ICAJeyA3NDI1MDAwMCwgIDB4ODAwOSwgMHgwMDA0LCAweDAyNzJ9LAo+ICAgCXsgMTQ4NTAwMDAw LCAweDgwMmIsIDB4MDAwNCwgMHgwMjhkfSwKPiBAQCAtMTQxLDkgKzI1OSwxNTggQEAgc3RhdGlj IGNvbnN0IHN0cnVjdCBkd19oZG1pX3BoeV9jb25maWcgcm9ja2NoaXBfcGh5X2NvbmZpZ1tdID0g ewo+ICAgCXsgfjBVTCwJICAgICAweDAwMDAsIDB4MDAwMCwgMHgwMDAwfQo+ICAgfTsKPiAgIAo+ ICtzdGF0aWMgaW50IGhkbWlfZXh0X3BoeV93cml0ZShzdHJ1Y3Qgcm9ja2NoaXBfaGRtaSAqaGRt aSwgdW5zaWduZWQgc2hvcnQgZGF0YSwKPiArCQkJICAgICAgdW5zaWduZWQgY2hhciBhZGRyKQo+ ICt7Cj4gKwl3cml0ZWxfcmVsYXhlZChkYXRhLCBoZG1pLT5leHRwaHlfcmVnYmFzZSArIChhZGRy KSAqIDB4MDQpOwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyB1bnNpZ25lZCBpbnQg aGRtaV9waHlfaTJjX3JlYWQoc3RydWN0IHJvY2tjaGlwX2hkbWkgKmhkbWksCj4gKwkJCQkgICAg ICB1bnNpZ25lZCBjaGFyIGFkZHIpCj4gK3sKPiArCXJldHVybiByZWFkbF9yZWxheGVkKGhkbWkt PmV4dHBoeV9yZWdiYXNlICsgKGFkZHIpICogMHgwNCk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQg cmszMjI5X2V4dHBoeV9jb25maWcoc3RydWN0IGR3X2hkbWlfcGxhdF9kYXRhICpwbGF0X2RhdGEs Cj4gKwkJCQkgIGludCByZXMsIGludCBwaXhlbGNsb2NrKQo+ICt7Cj4gKwlzdHJ1Y3Qgcm9ja2No aXBfaGRtaSAqaGRtaSA9IHRvX3JvY2tjaGlwX2hkbWkocGxhdF9kYXRhKTsKPiArCWNvbnN0IHN0 cnVjdCBleHRwaHlfcGxsX2NvbmZpZ190YWIgKm1wbGwgPSByazMyMjlfZXh0cGh5X3BsbF9jZmc7 Cj4gKwljb25zdCBzdHJ1Y3QgZXh0cGh5X2NvbmZpZ190YWIgKmN0cmwgPSByazMyMjlfZXh0cGh5 X2NmZzsKPiArCXVuc2lnbmVkIGxvbmcgdGltZW91dDsKPiArCWludCBpLCBzdGF0Owo+ICsKPiAr CS8qIEZpbmQgb3V0IHRoZSBleHRwaHkgTVBMTCBjb25maWd1cmUgcGFyYW1ldGVycyAqLwo+ICsJ Zm9yIChpID0gMDsgbXBsbFtpXS5tcGl4ZWxjbG9jayAhPSB+MFVMOyBpKyspCj4gKwkJaWYgKHBp eGVsY2xvY2sgPT0gbXBsbFtpXS5tcGl4ZWxjbG9jaykKPiArCQkJYnJlYWs7Cj4gKwlpZiAobXBs bFtpXS5tcGl4ZWxjbG9jayA9PSB+MFVMKSB7Cj4gKwkJZGV2X2VycihoZG1pLT5kZXYsICJFeHRw aHkgY291bGRuJ3Qgc3VwcG9ydCAlZEh6XG4iLCBwaXhlbGNsb2NrKTsKPiArCQlyZXR1cm4gLUVJ TlZBTDsKPiArCX0KPiArCj4gKwlyZWdtYXBfd3JpdGUoaGRtaS0+cmVnbWFwLCBSSzMyMjlfR1JG X1NPQ19DT04yLAo+ICsJCSAgICAgUkszMjI5X1BMTF9QT1dFUl9ET1dOIHwgUkszMjI5X1BMTF9Q REFUQV9ERU4pOwo+ICsKPiArCS8qCj4gKwkgKiBDb25maWd1cmUgZXh0ZXJuYWwgcGh5IFBMTCBy ZWdpc3RlcnMuCj4gKwkgKi8KPiArCXN0YXQgPSAoKG1wbGxbaV0ucGFyYW1bcmVzXS5wbGxfbmYg Pj4gMSkgJiBFWFRfUEhZX1BMTF9GQl9CSVQ4X01BU0spIHwKPiArCSAgICAgICAoKG1wbGxbaV0u cGFyYW1bcmVzXS52Y29fZGl2XzUgJiAxKSA8PCA1KSB8Cj4gKwkgICAgICAgKG1wbGxbaV0ucGFy YW1bcmVzXS5wbGxfbmQgJiBFWFRfUEhZX1BMTF9QUkVfRElWSURFUl9NQVNLKTsKPiArCWhkbWlf ZXh0X3BoeV93cml0ZShoZG1pLCBzdGF0LCBFWFRfUEhZX1BMTF9QUkVfRElWSURFUik7Cj4gKwo+ ICsJaGRtaV9leHRfcGh5X3dyaXRlKGhkbWksIG1wbGxbaV0ucGFyYW1bcmVzXS5wbGxfbmYsIEVY VF9QSFlfUExMX0ZCX0RJVklERVIpOwo+ICsKPiArCXN0YXQgPSAobXBsbFtpXS5wYXJhbVtyZXNd LnBjbGtfZGl2aWRlcl9hICYgRVhUX1BIWV9QQ0xLX0RJVklERVJBX01BU0spIHwKPiArCSAgICAg ICAoKG1wbGxbaV0ucGFyYW1bcmVzXS5wY2xrX2RpdmlkZXJfYiAmIDMpIDw8IDUpOwo+ICsJaGRt aV9leHRfcGh5X3dyaXRlKGhkbWksIHN0YXQsIEVYVF9QSFlfUENMS19ESVZJREVSMSk7Cj4gKwo+ ICsJc3RhdCA9IChtcGxsW2ldLnBhcmFtW3Jlc10ucGNsa19kaXZpZGVyX2QgJiBFWFRfUEhZX1BD TEtfRElWSURFUkRfTUFTSykgfAo+ICsJICAgICAgICgobXBsbFtpXS5wYXJhbVtyZXNdLnBjbGtf ZGl2aWRlcl9jICYgMykgPDwgNSk7Cj4gKwloZG1pX2V4dF9waHlfd3JpdGUoaGRtaSwgc3RhdCwg RVhUX1BIWV9QQ0xLX0RJVklERVIyKTsKPiArCj4gKwlzdGF0ID0gKChtcGxsW2ldLnBhcmFtW3Jl c10udG1zZF9kaXZpZGVyX2MgJiAzKSA8PCA0KSB8Cj4gKwkgICAgICAgKChtcGxsW2ldLnBhcmFt W3Jlc10udG1zZF9kaXZpZGVyX2EgJiAzKSA8PCAyKSB8Cj4gKwkgICAgICAgKG1wbGxbaV0ucGFy YW1bcmVzXS50bXNkX2RpdmlkZXJfYiAmIDMpOwo+ICsJaGRtaV9leHRfcGh5X3dyaXRlKGhkbWks IHN0YXQsIEVYVF9QSFlfVE1EU0NMS19ESVZJREVSKTsKPiArCj4gKwloZG1pX2V4dF9waHlfd3Jp dGUoaGRtaSwgbXBsbFtpXS5wYXJhbVtyZXNdLnBwbGxfbmYsIEVYVF9QSFlfUFBMTF9GQl9ESVZJ REVSKTsKPiArCj4gKwlpZiAobXBsbFtpXS5wYXJhbVtyZXNdLnBwbGxfbm8gPT0gMSkgewo+ICsJ CWhkbWlfZXh0X3BoeV93cml0ZShoZG1pLCAwLCBFWFRfUEhZX1BQTExfUE9TVF9ESVZJREVSKTsK PiArCj4gKwkJc3RhdCA9IDB4MjAgfCBtcGxsW2ldLnBhcmFtW3Jlc10ucHBsbF9uZDsKPiArCQlo ZG1pX2V4dF9waHlfd3JpdGUoaGRtaSwgc3RhdCwgRVhUX1BIWV9QUExMX1BSRV9ESVZJREVSKTsK PiArCX0gZWxzZSB7Cj4gKwkJc3RhdCA9ICgobXBsbFtpXS5wYXJhbVtyZXNdLnBwbGxfbm8gLyAy KSAtIDEpIDw8IDQ7Cj4gKwkJaGRtaV9leHRfcGh5X3dyaXRlKGhkbWksIHN0YXQsIEVYVF9QSFlf UFBMTF9QT1NUX0RJVklERVIpOwo+ICsKPiArCQlzdGF0ID0gMHhlMCB8IG1wbGxbaV0ucGFyYW1b cmVzXS5wcGxsX25kOwo+ICsJCWhkbWlfZXh0X3BoeV93cml0ZShoZG1pLCBzdGF0LCBFWFRfUEhZ X1BQTExfUFJFX0RJVklERVIpOwo+ICsJfQo+ICsKPiArCj4gKwkvKiBGaW5kIG91dCB0aGUgZXh0 cGh5IGRyaXZlciBjb25maWd1cmUgcGFyYW1ldGVycyAqLwo+ICsJZm9yIChpID0gMDsgY3RybFtp XS5tcGl4ZWxjbG9jayAhPSB+MFVMOyBpKyspCj4gKwkJaWYgKHBpeGVsY2xvY2sgPD0gY3RybFtp XS5tcGl4ZWxjbG9jaykKPiArCQkJYnJlYWs7Cj4gKwlpZiAoY3RybFtpXS5tcGl4ZWxjbG9jayA9 PSB+MFVMKSB7Cj4gKwkJZGV2X2VycihoZG1pLT5kZXYsICJFeHRwaHkgY291bGRuJ3Qgc3VwcG9y dCAlZEh6XG4iLCBwaXhlbGNsb2NrKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4g KwkvKgo+ICsJICogQ29uZmlndXJlIHRoZSBleHRwaHkgZHJpdmVyIHJlZ2lzdGVycy4KPiArCSAq Lwo+ICsJaWYgKGN0cmxbaV0uc2xvcGVib29zdCkgewo+ICsJCWhkbWlfZXh0X3BoeV93cml0ZSho ZG1pLCAweGZmLCBFWFRfUEhZX1NJR05BTF9DVFJMKTsKPiArCj4gKwkJc3RhdCA9IChjdHJsW2ld LnNsb3BlYm9vc3QgLSAxKSAmIDM7Cj4gKwkJc3RhdCA9IChzdGF0IDw8IDYpIHwgKHN0YXQgPDwg NCkgfCAoc3RhdCA8PCAyKSB8IHN0YXQ7Cj4gKwkJaGRtaV9leHRfcGh5X3dyaXRlKGhkbWksIHN0 YXQsIEVYVF9QSFlfU0xPUEVCT09TVCk7Cj4gKwl9IGVsc2UKPiArCQloZG1pX2V4dF9waHlfd3Jp dGUoaGRtaSwgMHgwZiwgRVhUX1BIWV9TSUdOQUxfQ1RSTCk7Cj4gKwo+ICsJc3RhdCA9IGN0cmxb aV0ucHJlX2VtcGhhc2lzICYgMzsKPiArCXN0YXQgPSAoc3RhdCA8PCA0KSB8IChzdGF0IDw8IDIp IHwgc3RhdDsKPiArCWhkbWlfZXh0X3BoeV93cml0ZShoZG1pLCBzdGF0LCBFWFRfUEhZX1BSRUVN UEhBU0lTKTsKPiArCj4gKwlzdGF0ID0gKChjdHJsW2ldLmNsa19sZXZlbCAmIDB4ZikgPDwgNCkg fCAoY3RybFtpXS5kYXRhMl9sZXZlbCAmIDB4Zik7Cj4gKwloZG1pX2V4dF9waHlfd3JpdGUoaGRt aSwgc3RhdCwgRVhUX1BIWV9MRVZFTDEpOwo+ICsKPiArCXN0YXQgPSAoKGN0cmxbaV0uZGF0YTFf bGV2ZWwgJiAweGYpIDw8IDQpIHwgKGN0cmxbaV0uZGF0YTBfbGV2ZWwgJiAweGYpOwo+ICsJaGRt aV9leHRfcGh5X3dyaXRlKGhkbWksIHN0YXQsIEVYVF9QSFlfTEVWRUwyKTsKPiArCj4gKwloZG1p X2V4dF9waHlfd3JpdGUoaGRtaSwgMHgyMiwgMHhmMyk7Cj4gKwo+ICsJc3RhdCA9IGNsa19nZXRf cmF0ZShoZG1pLT5leHRwaHlfcGNsaykgLyAxMDAwMDA7Cj4gKwloZG1pX2V4dF9waHlfd3JpdGUo aGRtaSwgKChzdGF0ID4+IDgpICYgMHhmZikgfCAweDgwLCBFWFRfUEhZX1RFUk1fQ0FMKTsKPiAr CWhkbWlfZXh0X3BoeV93cml0ZShoZG1pLCAgc3RhdCAmIDB4ZmYsIEVYVF9QSFlfVEVSTV9DQUxf RElWX0wpOwo+ICsKPiArCWlmIChwaXhlbGNsb2NrID4gMzQwMDAwMDAwKQo+ICsJCXN0YXQgPSBF WFRfUEhZX0FVVE9fUjEwMF9PSE1TOwo+ICsJZWxzZSBpZiAocGl4ZWxjbG9jayA+IDIwMDAwMDAw MCkKPiArCQlzdGF0ID0gRVhUX1BIWV9BVVRPX1I1MF9PSE1TOwo+ICsJZWxzZQo+ICsJCXN0YXQg PSBFWFRfUEhZX0FVVE9fUk9QRU5fQ0lSQ1VJVDsKPiArCWhkbWlfZXh0X3BoeV93cml0ZShoZG1p LCBzdGF0IHwgMHgyMCwgRVhUX1BIWV9URVJNX1JFU0lTX0FVVE8pOwo+ICsJaGRtaV9leHRfcGh5 X3dyaXRlKGhkbWksIChzdGF0ID4+IDgpICYgMHhmZiwgRVhUX1BIWV9URVJNX0NBTCk7Cj4gKwo+ ICsJc3RhdCA9IChwaXhlbGNsb2NrID4gMjAwMDAwMDAwKSA/IDAgOiAweDExOwo+ICsJaGRtaV9l eHRfcGh5X3dyaXRlKGhkbWksIHN0YXQsIEVYVF9QSFlfUExMX0JXKTsKPiArCWhkbWlfZXh0X3Bo eV93cml0ZShoZG1pLCAweDI3LCBFWFRfUEhZX1BQTExfQlcpOwo+ICsKPiArCXJlZ21hcF93cml0 ZShoZG1pLT5yZWdtYXAsIFJLMzIyOV9HUkZfU09DX0NPTjIsIFJLMzIyOV9QTExfUE9XRVJfVVAp Owo+ICsKPiArCS8qIERldGVjdCB3aGV0aGVyIFBMTCBpcyBsb2NrIG9yIG5vdCAqLwo+ICsJdGlt ZW91dCA9IGppZmZpZXMgKyBtc2Vjc190b19qaWZmaWVzKDEwMCk7Cj4gKwl3aGlsZSAoIXRpbWVf YWZ0ZXIoamlmZmllcywgdGltZW91dCkpIHsKPiArCQl1c2xlZXBfcmFuZ2UoMTAwMCwgMjAwMCk7 Cj4gKwkJc3RhdCA9IGhkbWlfcGh5X2kyY19yZWFkKGhkbWksIEVYVF9QSFlfUFBMTF9QT1NUX0RJ VklERVIpOwo+ICsJCWlmIChzdGF0ICYgRVhUX1BIWV9QUExMX0xPQ0tfU1RBVFVTX01BU0spCj4g KwkJCWJyZWFrOwo+ICsJfQo+ICsKPiArCXJlZ21hcF93cml0ZShoZG1pLT5yZWdtYXAsIFJLMzIy OV9HUkZfU09DX0NPTjIsIFJLMzIyOV9QTExfUERBVEFfRU4pOwo+ICsKPiArCWlmICgoc3RhdCAm IEVYVF9QSFlfUFBMTF9MT0NLX1NUQVRVU19NQVNLKSA9PSAwKSB7Cj4gKwkJZGV2X2VycihoZG1p LT5kZXYsICJFWFQgUEhZIFBMTCBub3QgbG9ja2VkXG4iKTsKPiArCQlyZXR1cm4gLUVCVVNZOwo+ ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICAgc3RhdGljIGludCByb2NrY2hpcF9o ZG1pX3BhcnNlX2R0KHN0cnVjdCByb2NrY2hpcF9oZG1pICpoZG1pKQo+ICAgewo+ICAgCXN0cnVj dCBkZXZpY2Vfbm9kZSAqbnAgPSBoZG1pLT5kZXYtPm9mX25vZGU7Cj4gKwlzdHJ1Y3QgcGxhdGZv cm1fZGV2aWNlICpwZGV2Owo+ICsJc3RydWN0IHJlc291cmNlICppb3JlczsKPiArCWludCByZXQ7 Cj4gKwo+ICsJcGRldiA9IGNvbnRhaW5lcl9vZihoZG1pLT5kZXYsIHN0cnVjdCBwbGF0Zm9ybV9k ZXZpY2UsIGRldik7Cj4gICAKPiAgIAloZG1pLT5yZWdtYXAgPSBzeXNjb25fcmVnbWFwX2xvb2t1 cF9ieV9waGFuZGxlKG5wLCAicm9ja2NoaXAsZ3JmIik7Cj4gICAJaWYgKElTX0VSUihoZG1pLT5y ZWdtYXApKSB7Cj4gQEAgLTE1MSwyNCArNDE4LDYyIEBAIHN0YXRpYyBpbnQgcm9ja2NoaXBfaGRt aV9wYXJzZV9kdChzdHJ1Y3Qgcm9ja2NoaXBfaGRtaSAqaGRtaSkKPiAgIAkJcmV0dXJuIFBUUl9F UlIoaGRtaS0+cmVnbWFwKTsKPiAgIAl9Cj4gICAKPiArCWlmIChoZG1pLT5wbGF0X2RhdGEuZGV2 X3R5cGUgPT0gUkszMjI5X0hETUkpIHsKPiArCQlpb3JlcyA9IHBsYXRmb3JtX2dldF9yZXNvdXJj ZShwZGV2LCBJT1JFU09VUkNFX01FTSwgMSk7Cj4gKwkJaWYgKCFpb3JlcykKPiArCQkJcmV0dXJu IC1FTlhJTzsKPiArCj4gKwkJaGRtaS0+ZXh0cGh5X3JlZ2Jhc2UgPSBkZXZtX2lvcmVtYXBfcmVz b3VyY2UoaGRtaS0+ZGV2LCBpb3Jlcyk7Cj4gKwkJaWYgKElTX0VSUihoZG1pLT5leHRwaHlfcmVn YmFzZSkpIHsKPiArCQkJZGV2X2VycihoZG1pLT5kZXYsICJmYWlsZWQgdG8gbWFwIGV4dHBoeSBy ZWdiYXNlXG4iKTsKPiArCQkJcmV0dXJuIFBUUl9FUlIoaGRtaS0+ZXh0cGh5X3JlZ2Jhc2UpOwo+ ICsJCX0KPiArCj4gKwkJaGRtaS0+ZXh0cGh5X3BjbGsgPSBkZXZtX2Nsa19nZXQoaGRtaS0+ZGV2 LCAiZXh0cGh5Iik7Cj4gKwkJaWYgKElTX0VSUihoZG1pLT5leHRwaHlfcGNsaykpIHsKPiArCQkJ ZGV2X2VycihoZG1pLT5kZXYsICJmYWlsZWQgdG8gZ2V0IGV4dHBoeSBjbG9ja1xuIik7Cj4gKwkJ CXJldHVybiBQVFJfRVJSKGhkbWktPmV4dHBoeV9wY2xrKTsKPiArCQl9Cj4gKwo+ICsJCXJldCA9 IGNsa19wcmVwYXJlX2VuYWJsZShoZG1pLT5leHRwaHlfcGNsayk7Cj4gKwkJaWYgKHJldCkgewo+ ICsJCQlkZXZfZXJyKGhkbWktPmRldiwgImZhaWxlZCB0byBlbmFibGUgZXh0cGh5IGNsazogJWRc biIsCj4gKwkJCQlyZXQpOwo+ICsJCQlyZXR1cm4gcmV0Owo+ICsJCX0KPiArCj4gKwkJcmVnbWFw X3dyaXRlKGhkbWktPnJlZ21hcCwgUkszMjI5X0dSRl9TT0NfQ09ONiwKPiArCQkJICAgICBSSzMy MjlfSU9fM1ZfRE9NQUlOKTsKPiArCj4gKwkJcmVnbWFwX3dyaXRlKGhkbWktPnJlZ21hcCwgUksz MjI5X0dSRl9TT0NfQ09OMiwKPiArCQkJICAgICBSSzMyMjlfRERDX01BU0tfRU4pOwo+ICsJfQo+ ICsKPiAgIAlyZXR1cm4gMDsKPiAgIH0KPiAgIAo+ICAgc3RhdGljIGVudW0gZHJtX21vZGVfc3Rh dHVzCj4gLWR3X2hkbWlfcm9ja2NoaXBfbW9kZV92YWxpZChzdHJ1Y3QgZHJtX2Nvbm5lY3RvciAq Y29ubmVjdG9yLAo+ICtkd19oZG1pX3JvY2tjaGlwX21vZGVfdmFsaWQoY29uc3Qgc3RydWN0IGR3 X2hkbWlfcGxhdF9kYXRhICpwbGF0X2RhdGEsCj4gICAJCQkgICAgc3RydWN0IGRybV9kaXNwbGF5 X21vZGUgKm1vZGUpCj4gICB7Cj4gLQljb25zdCBzdHJ1Y3QgZHdfaGRtaV9tcGxsX2NvbmZpZyAq bXBsbF9jZmcgPSByb2NrY2hpcF9tcGxsX2NmZzsKPiAgIAlpbnQgcGNsayA9IG1vZGUtPmNsb2Nr ICogMTAwMDsKPiAgIAlib29sIHZhbGlkID0gZmFsc2U7Cj4gICAJaW50IGk7Cj4gICAKPiAtCWZv ciAoaSA9IDA7IG1wbGxfY2ZnW2ldLm1waXhlbGNsb2NrICE9ICh+MFVMKTsgaSsrKSB7Cj4gLQkJ aWYgKHBjbGsgPT0gbXBsbF9jZmdbaV0ubXBpeGVsY2xvY2spIHsKPiAtCQkJdmFsaWQgPSB0cnVl Owo+IC0JCQlicmVhazsKPiArCWlmIChwbGF0X2RhdGEtPmRldl90eXBlID09IFJLMzI4OF9IRE1J KQo+ICsJCWZvciAoaSA9IDA7IHJrMzI4OF9tcGxsX2NmZ1tpXS5tcGl4ZWxjbG9jayAhPSAofjBV TCk7IGkrKykKPiArCQkJaWYgKHBjbGsgPT0gcmszMjg4X21wbGxfY2ZnW2ldLm1waXhlbGNsb2Nr KSB7Cj4gKwkJCQl2YWxpZCA9IHRydWU7Cj4gKwkJCQlicmVhazsKPiArCQkJfQo+ICsKPiArCWlm IChwbGF0X2RhdGEtPmRldl90eXBlID09IFJLMzIyOV9IRE1JKQo+ICsJCWZvciAoaSA9IDA7IHJr MzIyOV9leHRwaHlfcGxsX2NmZ1tpXS5tcGl4ZWxjbG9jayAhPSB+MFVMOyBpKyspIHsKPiArCQkJ aWYgKHBjbGsgPT0gcmszMjI5X2V4dHBoeV9wbGxfY2ZnW2ldLm1waXhlbGNsb2NrKSB7Cj4gKwkJ CQl2YWxpZCA9IHRydWU7Cj4gKwkJCQlicmVhazsKPiArCQkJfQo+ICAgCQl9Cj4gLQl9Cj4gICAK PiAgIAlyZXR1cm4gKHZhbGlkKSA/IE1PREVfT0sgOiBNT0RFX0JBRDsKPiAgIH0KPiBAQCAtMTk4 LDIxICs1MDMsMjkgQEAgc3RhdGljIHZvaWQgZHdfaGRtaV9yb2NrY2hpcF9lbmNvZGVyX21vZGVf c2V0KHN0cnVjdCBkcm1fZW5jb2RlciAqZW5jb2RlciwKPiAgIHN0YXRpYyB2b2lkIGR3X2hkbWlf cm9ja2NoaXBfZW5jb2Rlcl9lbmFibGUoc3RydWN0IGRybV9lbmNvZGVyICplbmNvZGVyKQo+ICAg ewo+ICAgCXN0cnVjdCByb2NrY2hpcF9oZG1pICpoZG1pID0gdG9fcm9ja2NoaXBfaGRtaShlbmNv ZGVyKTsKPiArCWludCBvdXRfbW9kZSA9IFJPQ0tDSElQX09VVF9NT0RFX0FBQUE7Cj4gICAJdTMy IHZhbDsKPiAgIAlpbnQgbXV4Owo+ICAgCj4gKwlpZiAoaGRtaS0+cGxhdF9kYXRhLmRldl90eXBl ID09IFJLMzIyOV9IRE1JKQo+ICsJCW91dF9tb2RlID0gUk9DS0NISVBfT1VUX01PREVfUDg4ODsK PiArCj4gICAJcm9ja2NoaXBfZHJtX2NydGNfbW9kZV9jb25maWcoZW5jb2Rlci0+Y3J0YywgRFJN X01PREVfQ09OTkVDVE9SX0hETUlBLAo+IC0JCQkJICAgICAgUk9DS0NISVBfT1VUX01PREVfQUFB QSk7Cj4gKwkJCQkgICAgICBvdXRfbW9kZSk7Cj4gICAKPiAtCW11eCA9IHJvY2tjaGlwX2RybV9l bmNvZGVyX2dldF9tdXhfaWQoaGRtaS0+ZGV2LT5vZl9ub2RlLCBlbmNvZGVyKTsKPiAtCWlmICht dXgpCj4gLQkJdmFsID0gSERNSV9TRUxfVk9QX0xJVCB8IChIRE1JX1NFTF9WT1BfTElUIDw8IDE2 KTsKPiAtCWVsc2UKPiAtCQl2YWwgPSBIRE1JX1NFTF9WT1BfTElUIDw8IDE2Owo+ICsJaWYgKGhk bWktPnBsYXRfZGF0YS5kZXZfdHlwZSA9PSBSSzMyODhfSERNSSkgewo+ICsJCW11eCA9IHJvY2tj aGlwX2RybV9lbmNvZGVyX2dldF9tdXhfaWQoaGRtaS0+ZGV2LT5vZl9ub2RlLAo+ICsJCQkJCQkg ICAgICBlbmNvZGVyKTsKPiArCQlpZiAobXV4KQo+ICsJCQl2YWwgPSBSSzMyODhfSERNSV9TRUxf Vk9QX0xJVCB8Cj4gKwkJCSAgICAgIChSSzMyODhfSERNSV9TRUxfVk9QX0xJVCA8PCAxNik7Cj4g KwkJZWxzZQo+ICsJCQl2YWwgPSBSSzMyODhfSERNSV9TRUxfVk9QX0xJVCA8PCAxNjsKPiAgIAo+ IC0JcmVnbWFwX3dyaXRlKGhkbWktPnJlZ21hcCwgR1JGX1NPQ19DT042LCB2YWwpOwo+IC0JZGV2 X2RiZyhoZG1pLT5kZXYsICJ2b3AgJXMgb3V0cHV0IHRvIGhkbWlcbiIsCj4gLQkJKG11eCkgPyAi TElUIiA6ICJCSUciKTsKPiArCQlyZWdtYXBfd3JpdGUoaGRtaS0+cmVnbWFwLCBSSzMyODhfR1JG X1NPQ19DT042LCB2YWwpOwo+ICsKPiArCQlkZXZfZGJnKGhkbWktPmRldiwgInZvcCAlcyBvdXRw dXQgdG8gaGRtaVxuIiwgKG11eCkgPyAiTElUIiA6ICJCSUciKTsKPiArCX0KPiAgIH0KPiAgIAo+ ICAgc3RhdGljIGNvbnN0IHN0cnVjdCBkcm1fZW5jb2Rlcl9oZWxwZXJfZnVuY3MgZHdfaGRtaV9y b2NrY2hpcF9lbmNvZGVyX2hlbHBlcl9mdW5jcyA9IHsKPiBAQCAtMjIyLDE3ICs1MzUsMjYgQEAg c3RhdGljIGNvbnN0IHN0cnVjdCBkcm1fZW5jb2Rlcl9oZWxwZXJfZnVuY3MgZHdfaGRtaV9yb2Nr Y2hpcF9lbmNvZGVyX2hlbHBlcl9mdW4KPiAgIAkuZGlzYWJsZSAgICA9IGR3X2hkbWlfcm9ja2No aXBfZW5jb2Rlcl9kaXNhYmxlLAo+ICAgfTsKPiAgIAo+IC1zdGF0aWMgY29uc3Qgc3RydWN0IGR3 X2hkbWlfcGxhdF9kYXRhIHJvY2tjaGlwX2hkbWlfZHJ2X2RhdGEgPSB7Cj4gK3N0YXRpYyBjb25z dCBzdHJ1Y3QgZHdfaGRtaV9wbGF0X2RhdGEgcmszMjg4X2hkbWlfZHJ2X2RhdGEgPSB7Cj4gICAJ Lm1vZGVfdmFsaWQgPSBkd19oZG1pX3JvY2tjaGlwX21vZGVfdmFsaWQsCj4gLQkubXBsbF9jZmcg ICA9IHJvY2tjaGlwX21wbGxfY2ZnLAo+IC0JLmN1cl9jdHIgICAgPSByb2NrY2hpcF9jdXJfY3Ry LAo+IC0JLnBoeV9jb25maWcgPSByb2NrY2hpcF9waHlfY29uZmlnLAo+ICsJLm1wbGxfY2ZnICAg PSByazMyODhfbXBsbF9jZmcsCj4gKwkuY3VyX2N0ciAgICA9IHJrMzI4OF9jdXJfY3RyLAo+ICsJ LnBoeV9jb25maWcgPSByazMyODhfcGh5X2NvbmZpZywKPiAgIAkuZGV2X3R5cGUgICA9IFJLMzI4 OF9IRE1JLAo+ICAgfTsKPiAgIAo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGR3X2hkbWlfcGxhdF9k YXRhIHJrMzIyOV9oZG1pX2Rydl9kYXRhID0gewo+ICsJLm1vZGVfdmFsaWQgPSBkd19oZG1pX3Jv Y2tjaGlwX21vZGVfdmFsaWQsCj4gKwkuZXh0cGh5X2NvbmZpZyA9IHJrMzIyOV9leHRwaHlfY29u ZmlnLAo+ICsJLmRldl90eXBlICAgPSBSSzMyMjlfSERNSSwKPiArfTsKPiArCj4gICBzdGF0aWMg Y29uc3Qgc3RydWN0IG9mX2RldmljZV9pZCBkd19oZG1pX3JvY2tjaGlwX2R0X2lkc1tdID0gewo+ ICAgCXsgLmNvbXBhdGlibGUgPSAicm9ja2NoaXAscmszMjg4LWR3LWhkbWkiLAo+IC0JICAuZGF0 YSA9ICZyb2NrY2hpcF9oZG1pX2Rydl9kYXRhCj4gKwkgIC5kYXRhID0gJnJrMzI4OF9oZG1pX2Ry dl9kYXRhCj4gKwl9LAo+ICsJeyAuY29tcGF0aWJsZSA9ICJyb2NrY2hpcCxyazMyMjktZHctaGRt aSIsCj4gKwkgIC5kYXRhID0gJnJrMzIyOV9oZG1pX2Rydl9kYXRhCj4gICAJfSwKPiAgIAl7fSwK PiAgIH07Cj4gQEAgLTI0Miw3ICs1NjQsNiBAQCBzdGF0aWMgaW50IGR3X2hkbWlfcm9ja2NoaXBf YmluZChzdHJ1Y3QgZGV2aWNlICpkZXYsIHN0cnVjdCBkZXZpY2UgKm1hc3RlciwKPiAgIAkJCQkg dm9pZCAqZGF0YSkKPiAgIHsKPiAgIAlzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2ID0gdG9f cGxhdGZvcm1fZGV2aWNlKGRldik7Cj4gLQljb25zdCBzdHJ1Y3QgZHdfaGRtaV9wbGF0X2RhdGEg KnBsYXRfZGF0YTsKPiAgIAljb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNlX2lkICptYXRjaDsKPiAgIAlz dHJ1Y3QgZHJtX2RldmljZSAqZHJtID0gZGF0YTsKPiAgIAlzdHJ1Y3QgZHJtX2VuY29kZXIgKmVu Y29kZXI7Cj4gQEAgLTI1OSw3ICs1ODAsNyBAQCBzdGF0aWMgaW50IGR3X2hkbWlfcm9ja2NoaXBf YmluZChzdHJ1Y3QgZGV2aWNlICpkZXYsIHN0cnVjdCBkZXZpY2UgKm1hc3RlciwKPiAgIAkJcmV0 dXJuIC1FTk9NRU07Cj4gICAKPiAgIAltYXRjaCA9IG9mX21hdGNoX25vZGUoZHdfaGRtaV9yb2Nr Y2hpcF9kdF9pZHMsIHBkZXYtPmRldi5vZl9ub2RlKTsKPiAtCXBsYXRfZGF0YSA9IG1hdGNoLT5k YXRhOwo+ICsJaGRtaS0+cGxhdF9kYXRhID0gKihzdHJ1Y3QgZHdfaGRtaV9wbGF0X2RhdGEgKiko bWF0Y2gtPmRhdGEpOwo+ICAgCWhkbWktPmRldiA9ICZwZGV2LT5kZXY7Cj4gICAJZW5jb2RlciA9 ICZoZG1pLT5lbmNvZGVyOwo+ICAgCj4gQEAgLTI5Myw3ICs2MTQsOCBAQCBzdGF0aWMgaW50IGR3 X2hkbWlfcm9ja2NoaXBfYmluZChzdHJ1Y3QgZGV2aWNlICpkZXYsIHN0cnVjdCBkZXZpY2UgKm1h c3RlciwKPiAgIAlkcm1fZW5jb2Rlcl9pbml0KGRybSwgZW5jb2RlciwgJmR3X2hkbWlfcm9ja2No aXBfZW5jb2Rlcl9mdW5jcywKPiAgIAkJCSBEUk1fTU9ERV9FTkNPREVSX1RNRFMsIE5VTEwpOwo+ ICAgCj4gLQlyZXR1cm4gZHdfaGRtaV9iaW5kKGRldiwgbWFzdGVyLCBkYXRhLCBlbmNvZGVyLCBp b3JlcywgaXJxLCBwbGF0X2RhdGEpOwo+ICsJcmV0dXJuIGR3X2hkbWlfYmluZChkZXYsIG1hc3Rl ciwgZGF0YSwgZW5jb2RlciwgaW9yZXMsIGlycSwKPiArCQkJICAgICZoZG1pLT5wbGF0X2RhdGEp Owo+ICAgfQo+ICAgCj4gICBzdGF0aWMgdm9pZCBkd19oZG1pX3JvY2tjaGlwX3VuYmluZChzdHJ1 Y3QgZGV2aWNlICpkZXYsIHN0cnVjdCBkZXZpY2UgKm1hc3RlciwKPiBkaWZmIC0tZ2l0IGEvZHJp dmVycy9ncHUvZHJtL3JvY2tjaGlwL2R3X2hkbWktcm9ja2NoaXAuaCBiL2RyaXZlcnMvZ3B1L2Ry bS9yb2NrY2hpcC9kd19oZG1pLXJvY2tjaGlwLmgKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGlu ZGV4IDAwMDAwMDAuLmFjYTI1NDMKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy9ncHUv ZHJtL3JvY2tjaGlwL2R3X2hkbWktcm9ja2NoaXAuaAo+IEBAIC0wLDAgKzEsMTM3IEBACj4gKyNp Zm5kZWYgX19EV19IRE1JX1JPQ0tDSElQX18KPiArI2RlZmluZSBfX0RXX0hETUlfUk9DS0NISVBf Xwo+ICsKPiArc3RydWN0IGV4dHBoeV9jb25maWdfdGFiIHsKPiArCXUzMiBtcGl4ZWxjbG9jazsK PiArCWludCBwcmVfZW1waGFzaXM7Cj4gKwlpbnQgc2xvcGVib29zdDsKPiArCWludCBjbGtfbGV2 ZWw7Cj4gKwlpbnQgZGF0YTBfbGV2ZWw7Cj4gKwlpbnQgZGF0YTFfbGV2ZWw7Cj4gKwlpbnQgZGF0 YTJfbGV2ZWw7Cj4gK307Cj4gKwo+ICtzdHJ1Y3QgZXh0cGh5X3BsbF9jb25maWdfdGFiIHsKPiAr CXVuc2lnbmVkIGxvbmcgbXBpeGVsY2xvY2s7Cj4gKwlzdHJ1Y3Qgewo+ICsJCXU4CXBsbF9uZDsK PiArCQl1MTYJcGxsX25mOwo+ICsJCXU4CXRtc2RfZGl2aWRlcl9hOwo+ICsJCXU4CXRtc2RfZGl2 aWRlcl9iOwo+ICsJCXU4CXRtc2RfZGl2aWRlcl9jOwo+ICsJCXU4CXBjbGtfZGl2aWRlcl9hOwo+ ICsJCXU4CXBjbGtfZGl2aWRlcl9iOwo+ICsJCXU4CXBjbGtfZGl2aWRlcl9jOwo+ICsJCXU4CXBj bGtfZGl2aWRlcl9kOwo+ICsJCXU4CXZjb19kaXZfNTsKPiArCQl1OAlwcGxsX25kOwo+ICsJCXU4 CXBwbGxfbmY7Cj4gKwkJdTgJcHBsbF9ubzsKPiArCX0gcGFyYW1bRFdfSERNSV9SRVNfTUFYXTsK PiArfTsKPiArCj4gKyNkZWZpbmUgUkszMjg4X0dSRl9TT0NfQ09ONgkJCTB4MDI1Ywo+ICsjZGVm aW5lIFJLMzI4OF9IRE1JX1NFTF9WT1BfTElUCQkJKDEgPDwgNCkKPiArCj4gKyNkZWZpbmUgUksz MjI5X0dSRl9TT0NfQ09ONgkJCTB4MDQxOAo+ICsjZGVmaW5lIFJLMzIyOV9JT18zVl9ET01BSU4J CQkoKDcgPDwgNCkgfCAoNyA8PCAoNCArIDE2KSkpCj4gKwo+ICsjZGVmaW5lIFJLMzIyOV9HUkZf U09DX0NPTjIJCQkweDA0MDgKPiArI2RlZmluZSBSSzMyMjlfRERDX01BU0tfRU4JCQkoKDMgPDwg MTMpIHwgKDMgPDwgKDEzICsgMTYpKSkKPiArCj4gKyNkZWZpbmUgUkszMjI5X1BMTF9QT1dFUl9E T1dOCQkJKEJJVCgxMikgfCBCSVQoMTIgKyAxNikpCj4gKyNkZWZpbmUgUkszMjI5X1BMTF9QT1dF Ul9VUAkJCUJJVCgxMiArIDE2KQo+ICsjZGVmaW5lIFJLMzIyOV9QTExfUERBVEFfREVOCQkJQklU KDExICsgMTYpCj4gKyNkZWZpbmUgUkszMjI5X1BMTF9QREFUQV9FTgkJCShCSVQoMTEpIHwgQklU KDExICsgMTYpKQo+ICsKPiArLyogUEhZIERlZmluZWQgZm9yIFJLMzIyWCAqLwo+ICsjZGVmaW5l IEVYVF9QSFlfQ09OVFJPTAkJCQkwCj4gKyNkZWZpbmUgRVhUX1BIWV9BTkFMT0dfUkVTRVRfTUFT SwkJMHg4MAo+ICsjZGVmaW5lIEVYVF9QSFlfRElHSVRBTF9SRVNFVF9NQVNLCQkweDQwCj4gKyNk ZWZpbmUgRVhUX1BIWV9QQ0xLX0lOVkVSVF9NQVNLCQkweDA4Cj4gKyNkZWZpbmUgRVhUX1BIWV9Q UkVQQ0xLX0lOVkVSVF9NQVNLCQkweDA0Cj4gKyNkZWZpbmUgRVhUX1BIWV9UTURTQ0xLX0lOVkVS VF9NQVNLCQkweDAyCj4gKyNkZWZpbmUgRVhUX1BIWV9TUkNfU0VMRUNUX01BU0sJCQkweDAxCj4g Kwo+ICsjZGVmaW5lIEVYVF9QSFlfVEVSTV9DQUwJCQkweDAzCj4gKyNkZWZpbmUgRVhUX1BIWV9U RVJNX0NBTF9FTl9NQVNLCQkweDgwCj4gKyNkZWZpbmUgRVhUX1BIWV9URVJNX0NBTF9ESVZfSF9N QVNLCQkweDdmCj4gKwo+ICsjZGVmaW5lIEVYVF9QSFlfVEVSTV9DQUxfRElWX0wJCQkweDA0Cj4g Kwo+ICsjZGVmaW5lIEVYVF9QSFlfUExMX1BSRV9ESVZJREVSCQkJMHhlMgo+ICsjZGVmaW5lIEVY VF9QSFlfUExMX0ZCX0JJVDhfTUFTSwkJMHg4MAo+ICsjZGVmaW5lIEVYVF9QSFlfUExMX1BDTEtf RElWNV9FTl9NQVNLCQkweDIwCj4gKyNkZWZpbmUgRVhUX1BIWV9QTExfUFJFX0RJVklERVJfTUFT SwkJMHgxZgo+ICsKPiArI2RlZmluZSBFWFRfUEhZX1BMTF9GQl9ESVZJREVSCQkJMHhlMwo+ICsK PiArI2RlZmluZSBFWFRfUEhZX1BDTEtfRElWSURFUjEJCQkweGU0Cj4gKyNkZWZpbmUgRVhUX1BI WV9QQ0xLX0RJVklERVJCX01BU0sJCTB4NjAKPiArI2RlZmluZSBFWFRfUEhZX1BDTEtfRElWSURF UkFfTUFTSwkJMHgxZgo+ICsKPiArI2RlZmluZSBFWFRfUEhZX1BDTEtfRElWSURFUjIJCQkweGU1 Cj4gKyNkZWZpbmUgRVhUX1BIWV9QQ0xLX0RJVklERVJDX01BU0sJCTB4NjAKPiArI2RlZmluZSBF WFRfUEhZX1BDTEtfRElWSURFUkRfTUFTSwkJMHgxZgo+ICsKPiArI2RlZmluZSBFWFRfUEhZX1RN RFNDTEtfRElWSURFUgkJCTB4ZTYKPiArI2RlZmluZSBFWFRfUEhZX1RNRFNDTEtfRElWSURFUkNf TUFTSwkJMHgzMAo+ICsjZGVmaW5lIEVYVF9QSFlfVE1EU0NMS19ESVZJREVSQV9NQVNLCQkweDBj Cj4gKyNkZWZpbmUgRVhUX1BIWV9UTURTQ0xLX0RJVklERVJCX01BU0sJCTB4MDMKPiArCj4gKyNk ZWZpbmUgRVhUX1BIWV9QTExfQlcJCQkJMHhlNwo+ICsKPiArI2RlZmluZSBFWFRfUEhZX1BQTExf UFJFX0RJVklERVIJCTB4ZTkKPiArI2RlZmluZSBFWFRfUEhZX1BQTExfRU5BQkxFX01BU0sJCTB4 YzAKPiArI2RlZmluZSBFWFRfUEhZX1BQTExfUFJFX0RJVklERVJfTUFTSwkJMHgxZgo+ICsKPiAr I2RlZmluZSBFWFRfUEhZX1BQTExfRkJfRElWSURFUgkJCTB4ZWEKPiArCj4gKyNkZWZpbmUgRVhU X1BIWV9QUExMX1BPU1RfRElWSURFUgkJMHhlYgo+ICsjZGVmaW5lIEVYVF9QSFlfUFBMTF9GQl9E SVZJREVSX0JJVDhfTUFTSwkweDgwCj4gKyNkZWZpbmUgRVhUX1BIWV9QUExMX1BPU1RfRElWSURF Ul9NQVNLCQkweDMwCj4gKyNkZWZpbmUgRVhUX1BIWV9QUExMX0xPQ0tfU1RBVFVTX01BU0sJCTB4 MDEKPiArCj4gKyNkZWZpbmUgRVhUX1BIWV9QUExMX0JXCQkJCTB4ZWMKPiArCj4gKyNkZWZpbmUg RVhUX1BIWV9TSUdOQUxfQ1RSTAkJCTB4ZWUKPiArI2RlZmluZSBFWFRfUEhZX1RSQU5TSVRJT05f Q0xLX0VOX01BU0sJCTB4ODAKPiArI2RlZmluZSBFWFRfUEhZX1RSQU5TSVRJT05fRDBfRU5fTUFT SwkJMHg0MAo+ICsjZGVmaW5lIEVYVF9QSFlfVFJBTlNJVElPTl9EMV9FTl9NQVNLCQkweDIwCj4g KyNkZWZpbmUgRVhUX1BIWV9UUkFOU0lUSU9OX0QyX0VOX01BU0sJCTB4MTAKPiArI2RlZmluZSBF WFRfUEhZX0xFVkVMX0NMS19FTl9NQVNLCQkweDA4Cj4gKyNkZWZpbmUgRVhUX1BIWV9MRVZFTF9E MF9FTl9NQVNLCQkweDA0Cj4gKyNkZWZpbmUgRVhUX1BIWV9MRVZFTF9EMV9FTl9NQVNLCQkweDAy Cj4gKyNkZWZpbmUgRVhUX1BIWV9MRVZFTF9EMl9FTl9NQVNLCQkweDAxCj4gKwo+ICsjZGVmaW5l IEVYVF9QSFlfU0xPUEVCT09TVAkJCTB4ZWYKPiArI2RlZmluZSBFWFRfUEhZX1NMT1BFQk9PU1Rf Q0xLX01BU0sJCTB4MDMKPiArI2RlZmluZSBFWFRfUEhZX1NMT1BFQk9PU1RfRDBfTUFTSwkJMHgw Ywo+ICsjZGVmaW5lIEVYVF9QSFlfU0xPUEVCT09TVF9EMV9NQVNLCQkweDMwCj4gKyNkZWZpbmUg RVhUX1BIWV9TTE9QRUJPT1NUX0QyX01BU0sJCTB4YzAKPiArCj4gKyNkZWZpbmUgRVhUX1BIWV9Q UkVFTVBIQVNJUwkJCTB4ZjAKPiArI2RlZmluZSBFWFRfUEhZX1BSRUVNUEhBU0lTX0QwX01BU0sJ CTB4MDMKPiArI2RlZmluZSBFWFRfUEhZX1BSRUVNUEhBU0lTX0QxX01BU0sJCTB4MGMKPiArI2Rl ZmluZSBFWFRfUEhZX1BSRUVNUEhBU0lTX0QyX01BU0sJCTB4MzAKPiArCj4gKyNkZWZpbmUgRVhU X1BIWV9MRVZFTDEJCQkJMHhmMQo+ICsjZGVmaW5lIEVYVF9QSFlfTEVWRUxfQ0xLX01BU0sJCQkw eGYwCj4gKyNkZWZpbmUgRVhUX1BIWV9MRVZFTF9EMl9NQVNLCQkJMHgwZgo+ICsKPiArI2RlZmlu ZSBFWFRfUEhZX0xFVkVMMgkJCQkweGYyCj4gKyNkZWZpbmUgRVhUX1BIWV9MRVZFTF9EMV9NQVNL CQkJMHhmMAo+ICsjZGVmaW5lIEVYVF9QSFlfTEVWRUxfRDBfTUFTSwkJCTB4MGYKPiArCj4gKyNk ZWZpbmUgRVhUX1BIWV9URVJNX1JFU0lTX0FVVE8JCQkweGY0Cj4gKyNkZWZpbmUgRVhUX1BIWV9B VVRPX1I1MF9PSE1TCQkJMAo+ICsjZGVmaW5lIEVYVF9QSFlfQVVUT19SNzVfT0hNUwkJCSgxIDw8 IDIpCj4gKyNkZWZpbmUgRVhUX1BIWV9BVVRPX1IxMDBfT0hNUwkJCSgyIDw8IDIpCj4gKyNkZWZp bmUgRVhUX1BIWV9BVVRPX1JPUEVOX0NJUkNVSVQJCSgzIDw8IDIpCj4gKwo+ICsjZGVmaW5lIEVY VF9QSFlfVEVSTV9SRVNJU19NQU5VQUxfQ0xLCQkweGZiCj4gKyNkZWZpbmUgRVhUX1BIWV9URVJN X1JFU0lTX01BTlVBTF9EMgkJMHhmYwo+ICsjZGVmaW5lIEVYVF9QSFlfVEVSTV9SRVNJU19NQU5V QUxfRDEJCTB4ZmQKPiArI2RlZmluZSBFWFRfUEhZX1RFUk1fUkVTSVNfTUFOVUFMX0QwCQkweGZl Cj4gKwo+ICsjZW5kaWYgLyogX19EV19IRE1JX1JPQ0tDSElQX18gKi8KPiBkaWZmIC0tZ2l0IGEv aW5jbHVkZS9kcm0vYnJpZGdlL2R3X2hkbWkuaCBiL2luY2x1ZGUvZHJtL2JyaWRnZS9kd19oZG1p LmgKPiBpbmRleCBiYWU3OWYzLi40NDA4NGU4IDEwMDY0NAo+IC0tLSBhL2luY2x1ZGUvZHJtL2Jy aWRnZS9kd19oZG1pLmgKPiArKysgYi9pbmNsdWRlL2RybS9icmlkZ2UvZHdfaGRtaS5oCj4gQEAg LTI0LDYgKzI0LDcgQEAgZW51bSB7Cj4gICBlbnVtIGR3X2hkbWlfZGV2dHlwZSB7Cj4gICAJSU1Y NlFfSERNSSwKPiAgIAlJTVg2RExfSERNSSwKPiArCVJLMzIyOV9IRE1JLAo+ICAgCVJLMzI4OF9I RE1JLAo+ICAgfTsKPiAgIAo+IEBAIC01Miw4ICs1MywxMCBAQCBzdHJ1Y3QgZHdfaGRtaV9wbGF0 X2RhdGEgewo+ICAgCWNvbnN0IHN0cnVjdCBkd19oZG1pX21wbGxfY29uZmlnICptcGxsX2NmZzsK PiAgIAljb25zdCBzdHJ1Y3QgZHdfaGRtaV9jdXJyX2N0cmwgKmN1cl9jdHI7Cj4gICAJY29uc3Qg c3RydWN0IGR3X2hkbWlfcGh5X2NvbmZpZyAqcGh5X2NvbmZpZzsKPiAtCWVudW0gZHJtX21vZGVf c3RhdHVzICgqbW9kZV92YWxpZCkoc3RydWN0IGRybV9jb25uZWN0b3IgKmNvbm5lY3RvciwKPiAr CWVudW0gZHJtX21vZGVfc3RhdHVzICgqbW9kZV92YWxpZCkoY29uc3Qgc3RydWN0IGR3X2hkbWlf cGxhdF9kYXRhICpwbGF0X2RhdGEsCj4gICAJCQkJCSAgIHN0cnVjdCBkcm1fZGlzcGxheV9tb2Rl ICptb2RlKTsKPiArCWludCAoKmV4dHBoeV9jb25maWcpKHN0cnVjdCBkd19oZG1pX3BsYXRfZGF0 YSAqcGxhdF9kYXRhLAo+ICsJCQkgICAgIGludCBicHAsIGludCBwaXhlbGNsb2NrKTsKPiAgIH07 Cj4gICAKPiAgIHZvaWQgZHdfaGRtaV91bmJpbmQoc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3Qg ZGV2aWNlICptYXN0ZXIsIHZvaWQgKmRhdGEpOwoKCl9fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fCmRyaS1kZXZlbCBtYWlsaW5nIGxpc3QKZHJpLWRldmVsQGxp c3RzLmZyZWVkZXNrdG9wLm9yZwpodHRwOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4v bGlzdGluZm8vZHJpLWRldmVsCg== From mboxrd@z Thu Jan 1 00:00:00 1970 From: ykk@rock-chips.com (Yakir Yang) Date: Thu, 7 Jan 2016 14:22:02 +0800 Subject: [RFC PATCH v1 1/2] drm: rockchip: hdmi: add RK3229 HDMI support In-Reply-To: <1452141447-9441-1-git-send-email-ykk@rock-chips.com> References: <1452141288-9292-1-git-send-email-ykk@rock-chips.com> <1452141447-9441-1-git-send-email-ykk@rock-chips.com> Message-ID: <568E040A.4020907@rock-chips.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Thanks for "Kbuild test robot" reminding, I forget to update "mode_valid" function define in imx-hdmi side, would send new version out, -- >> drivers/gpu/drm/imx/dw_hdmi-imx.c:181:2: warning: initialization from incompatible pointer type .mode_valid = imx6q_hdmi_mode_valid, ^ drivers/gpu/drm/imx/dw_hdmi-imx.c:181:2: warning: (near initialization for 'imx6q_hdmi_drv_data.mode_valid') drivers/gpu/drm/imx/dw_hdmi-imx.c:189:2: warning: initialization from incompatible pointer type .mode_valid = imx6dl_hdmi_mode_valid, ^ drivers/gpu/drm/imx/dw_hdmi-imx.c:189:2: warning: (near initialization for 'imx6dl_hdmi_drv_data.mode_valid') Sorry, - Yakir On 01/07/2016 12:37 PM, Yakir Yang wrote: > RK3229 integrate an DesignedWare HDMI2.0 controller and an INNO HDMI2.0 phy, > the max output resolution is 4K. > > Signed-off-by: Yakir Yang > --- > drivers/gpu/drm/bridge/dw-hdmi.c | 33 ++- > drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 380 +++++++++++++++++++++++++--- > drivers/gpu/drm/rockchip/dw_hdmi-rockchip.h | 137 ++++++++++ > include/drm/bridge/dw_hdmi.h | 5 +- > 4 files changed, 516 insertions(+), 39 deletions(-) > create mode 100644 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.h > > diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c > index 6fbec99..60b1dcf 100644 > --- a/drivers/gpu/drm/bridge/dw-hdmi.c > +++ b/drivers/gpu/drm/bridge/dw-hdmi.c > @@ -735,10 +735,12 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep, > { > unsigned res_idx; > u8 val, msec; > + int ret; > const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; > const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; > const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; > const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; > + int mpixelclock = hdmi->hdmi_data.video_mode.mpixelclock; > > if (prep) > return -EINVAL; > @@ -758,27 +760,38 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep, > return -EINVAL; > } > > + if (hdmi->plat_data->extphy_config) { > + /* gen2 tx power off */ > + dw_hdmi_phy_gen2_txpwron(hdmi, 0); > + dw_hdmi_phy_gen2_pddq(hdmi, 1); > + > + ret = hdmi->plat_data->extphy_config(hdmi->plat_data, res_idx, > + mpixelclock); > + /* gen2 tx power on */ > + dw_hdmi_phy_gen2_txpwron(hdmi, 1); > + dw_hdmi_phy_gen2_pddq(hdmi, 0); > + > + return ret; > + } > + > /* PLL/MPLL Cfg - always match on final entry */ > for (; mpll_config->mpixelclock != ~0UL; mpll_config++) > - if (hdmi->hdmi_data.video_mode.mpixelclock <= > - mpll_config->mpixelclock) > + if (mpixelclock <= mpll_config->mpixelclock) > break; > > for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++) > - if (hdmi->hdmi_data.video_mode.mpixelclock <= > - curr_ctrl->mpixelclock) > + if (mpixelclock <= curr_ctrl->mpixelclock) > break; > > for (; phy_config->mpixelclock != ~0UL; phy_config++) > - if (hdmi->hdmi_data.video_mode.mpixelclock <= > - phy_config->mpixelclock) > + if (mpixelclock <= phy_config->mpixelclock) > break; > > if (mpll_config->mpixelclock == ~0UL || > curr_ctrl->mpixelclock == ~0UL || > phy_config->mpixelclock == ~0UL) { > dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n", > - hdmi->hdmi_data.video_mode.mpixelclock); > + mpixelclock); > return -EINVAL; > } > > @@ -1476,14 +1489,16 @@ dw_hdmi_connector_mode_valid(struct drm_connector *connector, > { > struct dw_hdmi *hdmi = container_of(connector, > struct dw_hdmi, connector); > + struct dw_hdmi_plat_data *plat_data = hdmi->plat_data; > enum drm_mode_status mode_status = MODE_OK; > > /* We don't support double-clocked modes */ > if (mode->flags & DRM_MODE_FLAG_DBLCLK) > return MODE_BAD; > > - if (hdmi->plat_data->mode_valid) > - mode_status = hdmi->plat_data->mode_valid(connector, mode); > + if (plat_data->mode_valid) > + mode_status = plat_data->mode_valid(plat_data, mode); > + > > return mode_status; > } > diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c > index c65ce8c..424d548 100644 > --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c > +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c > @@ -7,6 +7,7 @@ > * (at your option) any later version. > */ > > +#include > #include > #include > #include > @@ -21,18 +22,135 @@ > #include "rockchip_drm_drv.h" > #include "rockchip_drm_vop.h" > > -#define GRF_SOC_CON6 0x025c > -#define HDMI_SEL_VOP_LIT (1 << 4) > +#include "dw_hdmi-rockchip.h" > > struct rockchip_hdmi { > struct device *dev; > struct regmap *regmap; > struct drm_encoder encoder; > + struct dw_hdmi_plat_data plat_data; > + > + void __iomem *extphy_regbase; > + struct clk *extphy_pclk; > }; > > #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) > > -static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { > +static const struct extphy_config_tab rk3229_extphy_cfg[] = { > + { .mpixelclock = 165000000, > + .pre_emphasis = 0, .slopeboost = 0, .clk_level = 4, > + .data0_level = 4, 4, 4, > + }, > + > + { .mpixelclock = 225000000, > + .pre_emphasis = 0, .slopeboost = 0, .clk_level = 6, > + .data0_level = 6, 6, 6, > + }, > + > + { .mpixelclock = 340000000, > + .pre_emphasis = 1, .slopeboost = 0, .clk_level = 6, > + .data0_level = 10, 10, 10, > + }, > + > + { .mpixelclock = 594000000, > + .pre_emphasis = 1, .slopeboost = 0, .clk_level = 7, > + .data0_level = 10, 10, 10, > + }, > + > + { .mpixelclock = ~0UL}, > +}; > + > +static const struct extphy_pll_config_tab rk3229_extphy_pll_cfg[] = { > + { > + .mpixelclock = 27000000, .param = { > + { .pll_nd = 1, .pll_nf = 45, > + .tmsd_divider_a = 3, 1, 1, > + .pclk_divider_a = 1, 3, 3, 4, > + .vco_div_5 = 0, > + .ppll_nd = 1, .ppll_nf = 40, .ppll_no = 8, > + }, > + { .pll_nd = 1, .pll_nf = 45, > + .tmsd_divider_a = 0, 3, 3, > + .pclk_divider_a = 1, 3, 3, 4, > + .vco_div_5 = 0, > + .ppll_nd = 1, .ppll_nf = 40, .ppll_no = 8, > + }, > + }, > + }, { > + .mpixelclock = 59400000, .param = { > + { .pll_nd = 2, .pll_nf = 99, > + .tmsd_divider_a = 3, 1, 1, > + .pclk_divider_a = 1, 3, 2, 2, > + .vco_div_5 = 0, > + .ppll_nd = 1, .ppll_nf = 40, .ppll_no = 8, > + }, > + { .pll_nd = 2, .pll_nf = 99, > + .tmsd_divider_a = 1, 1, 1, > + .pclk_divider_a = 1, 3, 2, 2, > + .vco_div_5 = 0, > + .ppll_nd = 1, .ppll_nf = 40, .ppll_no = 8, > + }, > + }, > + }, { > + .mpixelclock = 74250000, .param = { > + { .pll_nd = 2, .pll_nf = 99, > + .tmsd_divider_a = 1, 1, 1, > + .pclk_divider_a = 1, 2, 2, 2, > + .vco_div_5 = 0, > + .ppll_nd = 1, .ppll_nf = 40, .ppll_no = 8, > + }, > + { .pll_nd = 4, .pll_nf = 495, > + .tmsd_divider_a = 1, 2, 2, > + .pclk_divider_a = 1, 3, 3, 4, > + .vco_div_5 = 0, > + .ppll_nd = 2, .ppll_nf = 40, .ppll_no = 4, > + }, > + }, > + }, { > + .mpixelclock = 148500000, .param = { > + { .pll_nd = 2, .pll_nf = 99, > + .tmsd_divider_a = 1, 0, 0, > + .pclk_divider_a = 1, 2, 1, 1, > + .vco_div_5 = 0, > + .ppll_nd = 2, .ppll_nf = 40, .ppll_no = 4, > + }, > + { .pll_nd = 4, .pll_nf = 495, > + .tmsd_divider_a = 0, 2, 2, > + .pclk_divider_a = 1, 3, 2, 2, > + .vco_div_5 = 0, > + .ppll_nd = 4, .ppll_nf = 40, .ppll_no = 2, > + }, > + }, > + }, { > + .mpixelclock = 297000000, .param = { > + { .pll_nd = 2, .pll_nf = 99, > + .tmsd_divider_a = 0, 0, 0, > + .pclk_divider_a = 1, 0, 1, 1, > + .vco_div_5 = 0, > + .ppll_nd = 4, .ppll_nf = 40, .ppll_no = 2, > + }, > + { .pll_nd = 4, .pll_nf = 495, > + .tmsd_divider_a = 1, 2, 0, > + .pclk_divider_a = 1, 3, 1, 1, > + .vco_div_5 = 0, > + .ppll_nd = 8, .ppll_nf = 40, .ppll_no = 1, > + }, > + }, > + }, { > + .mpixelclock = 594000000, .param = { > + { .pll_nd = 1, .pll_nf = 99, > + .tmsd_divider_a = 0, 2, 0, > + .pclk_divider_a = 1, 0, 1, 1, > + .vco_div_5 = 0, > + .ppll_nd = 8, .ppll_nf = 40, .ppll_no = 1, > + }, > + } > + }, { > + .mpixelclock = ~0UL, > + } > +}; > + > +static const struct dw_hdmi_mpll_config rk3288_mpll_cfg[] = { > { > 27000000, { > { 0x00b3, 0x0000}, > @@ -112,7 +230,7 @@ static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { > } > }; > > -static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { > +static const struct dw_hdmi_curr_ctrl rk3288_cur_ctr[] = { > /* pixelclk bpp8 bpp10 bpp12 */ > { > 40000000, { 0x0018, 0x0018, 0x0018 }, > @@ -133,7 +251,7 @@ static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { > } > }; > > -static const struct dw_hdmi_phy_config rockchip_phy_config[] = { > +static const struct dw_hdmi_phy_config rk3288_phy_config[] = { > /*pixelclk symbol term vlev*/ > { 74250000, 0x8009, 0x0004, 0x0272}, > { 148500000, 0x802b, 0x0004, 0x028d}, > @@ -141,9 +259,158 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = { > { ~0UL, 0x0000, 0x0000, 0x0000} > }; > > +static int hdmi_ext_phy_write(struct rockchip_hdmi *hdmi, unsigned short data, > + unsigned char addr) > +{ > + writel_relaxed(data, hdmi->extphy_regbase + (addr) * 0x04); > + return 0; > +} > + > +static unsigned int hdmi_phy_i2c_read(struct rockchip_hdmi *hdmi, > + unsigned char addr) > +{ > + return readl_relaxed(hdmi->extphy_regbase + (addr) * 0x04); > +} > + > +static int rk3229_extphy_config(struct dw_hdmi_plat_data *plat_data, > + int res, int pixelclock) > +{ > + struct rockchip_hdmi *hdmi = to_rockchip_hdmi(plat_data); > + const struct extphy_pll_config_tab *mpll = rk3229_extphy_pll_cfg; > + const struct extphy_config_tab *ctrl = rk3229_extphy_cfg; > + unsigned long timeout; > + int i, stat; > + > + /* Find out the extphy MPLL configure parameters */ > + for (i = 0; mpll[i].mpixelclock != ~0UL; i++) > + if (pixelclock == mpll[i].mpixelclock) > + break; > + if (mpll[i].mpixelclock == ~0UL) { > + dev_err(hdmi->dev, "Extphy couldn't support %dHz\n", pixelclock); > + return -EINVAL; > + } > + > + regmap_write(hdmi->regmap, RK3229_GRF_SOC_CON2, > + RK3229_PLL_POWER_DOWN | RK3229_PLL_PDATA_DEN); > + > + /* > + * Configure external phy PLL registers. > + */ > + stat = ((mpll[i].param[res].pll_nf >> 1) & EXT_PHY_PLL_FB_BIT8_MASK) | > + ((mpll[i].param[res].vco_div_5 & 1) << 5) | > + (mpll[i].param[res].pll_nd & EXT_PHY_PLL_PRE_DIVIDER_MASK); > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PLL_PRE_DIVIDER); > + > + hdmi_ext_phy_write(hdmi, mpll[i].param[res].pll_nf, EXT_PHY_PLL_FB_DIVIDER); > + > + stat = (mpll[i].param[res].pclk_divider_a & EXT_PHY_PCLK_DIVIDERA_MASK) | > + ((mpll[i].param[res].pclk_divider_b & 3) << 5); > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PCLK_DIVIDER1); > + > + stat = (mpll[i].param[res].pclk_divider_d & EXT_PHY_PCLK_DIVIDERD_MASK) | > + ((mpll[i].param[res].pclk_divider_c & 3) << 5); > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PCLK_DIVIDER2); > + > + stat = ((mpll[i].param[res].tmsd_divider_c & 3) << 4) | > + ((mpll[i].param[res].tmsd_divider_a & 3) << 2) | > + (mpll[i].param[res].tmsd_divider_b & 3); > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_TMDSCLK_DIVIDER); > + > + hdmi_ext_phy_write(hdmi, mpll[i].param[res].ppll_nf, EXT_PHY_PPLL_FB_DIVIDER); > + > + if (mpll[i].param[res].ppll_no == 1) { > + hdmi_ext_phy_write(hdmi, 0, EXT_PHY_PPLL_POST_DIVIDER); > + > + stat = 0x20 | mpll[i].param[res].ppll_nd; > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PPLL_PRE_DIVIDER); > + } else { > + stat = ((mpll[i].param[res].ppll_no / 2) - 1) << 4; > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PPLL_POST_DIVIDER); > + > + stat = 0xe0 | mpll[i].param[res].ppll_nd; > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PPLL_PRE_DIVIDER); > + } > + > + > + /* Find out the extphy driver configure parameters */ > + for (i = 0; ctrl[i].mpixelclock != ~0UL; i++) > + if (pixelclock <= ctrl[i].mpixelclock) > + break; > + if (ctrl[i].mpixelclock == ~0UL) { > + dev_err(hdmi->dev, "Extphy couldn't support %dHz\n", pixelclock); > + return -EINVAL; > + } > + > + /* > + * Configure the extphy driver registers. > + */ > + if (ctrl[i].slopeboost) { > + hdmi_ext_phy_write(hdmi, 0xff, EXT_PHY_SIGNAL_CTRL); > + > + stat = (ctrl[i].slopeboost - 1) & 3; > + stat = (stat << 6) | (stat << 4) | (stat << 2) | stat; > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_SLOPEBOOST); > + } else > + hdmi_ext_phy_write(hdmi, 0x0f, EXT_PHY_SIGNAL_CTRL); > + > + stat = ctrl[i].pre_emphasis & 3; > + stat = (stat << 4) | (stat << 2) | stat; > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PREEMPHASIS); > + > + stat = ((ctrl[i].clk_level & 0xf) << 4) | (ctrl[i].data2_level & 0xf); > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_LEVEL1); > + > + stat = ((ctrl[i].data1_level & 0xf) << 4) | (ctrl[i].data0_level & 0xf); > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_LEVEL2); > + > + hdmi_ext_phy_write(hdmi, 0x22, 0xf3); > + > + stat = clk_get_rate(hdmi->extphy_pclk) / 100000; > + hdmi_ext_phy_write(hdmi, ((stat >> 8) & 0xff) | 0x80, EXT_PHY_TERM_CAL); > + hdmi_ext_phy_write(hdmi, stat & 0xff, EXT_PHY_TERM_CAL_DIV_L); > + > + if (pixelclock > 340000000) > + stat = EXT_PHY_AUTO_R100_OHMS; > + else if (pixelclock > 200000000) > + stat = EXT_PHY_AUTO_R50_OHMS; > + else > + stat = EXT_PHY_AUTO_ROPEN_CIRCUIT; > + hdmi_ext_phy_write(hdmi, stat | 0x20, EXT_PHY_TERM_RESIS_AUTO); > + hdmi_ext_phy_write(hdmi, (stat >> 8) & 0xff, EXT_PHY_TERM_CAL); > + > + stat = (pixelclock > 200000000) ? 0 : 0x11; > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PLL_BW); > + hdmi_ext_phy_write(hdmi, 0x27, EXT_PHY_PPLL_BW); > + > + regmap_write(hdmi->regmap, RK3229_GRF_SOC_CON2, RK3229_PLL_POWER_UP); > + > + /* Detect whether PLL is lock or not */ > + timeout = jiffies + msecs_to_jiffies(100); > + while (!time_after(jiffies, timeout)) { > + usleep_range(1000, 2000); > + stat = hdmi_phy_i2c_read(hdmi, EXT_PHY_PPLL_POST_DIVIDER); > + if (stat & EXT_PHY_PPLL_LOCK_STATUS_MASK) > + break; > + } > + > + regmap_write(hdmi->regmap, RK3229_GRF_SOC_CON2, RK3229_PLL_PDATA_EN); > + > + if ((stat & EXT_PHY_PPLL_LOCK_STATUS_MASK) == 0) { > + dev_err(hdmi->dev, "EXT PHY PLL not locked\n"); > + return -EBUSY; > + } > + > + return 0; > +} > + > static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) > { > struct device_node *np = hdmi->dev->of_node; > + struct platform_device *pdev; > + struct resource *iores; > + int ret; > + > + pdev = container_of(hdmi->dev, struct platform_device, dev); > > hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); > if (IS_ERR(hdmi->regmap)) { > @@ -151,24 +418,62 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) > return PTR_ERR(hdmi->regmap); > } > > + if (hdmi->plat_data.dev_type == RK3229_HDMI) { > + iores = platform_get_resource(pdev, IORESOURCE_MEM, 1); > + if (!iores) > + return -ENXIO; > + > + hdmi->extphy_regbase = devm_ioremap_resource(hdmi->dev, iores); > + if (IS_ERR(hdmi->extphy_regbase)) { > + dev_err(hdmi->dev, "failed to map extphy regbase\n"); > + return PTR_ERR(hdmi->extphy_regbase); > + } > + > + hdmi->extphy_pclk = devm_clk_get(hdmi->dev, "extphy"); > + if (IS_ERR(hdmi->extphy_pclk)) { > + dev_err(hdmi->dev, "failed to get extphy clock\n"); > + return PTR_ERR(hdmi->extphy_pclk); > + } > + > + ret = clk_prepare_enable(hdmi->extphy_pclk); > + if (ret) { > + dev_err(hdmi->dev, "failed to enable extphy clk: %d\n", > + ret); > + return ret; > + } > + > + regmap_write(hdmi->regmap, RK3229_GRF_SOC_CON6, > + RK3229_IO_3V_DOMAIN); > + > + regmap_write(hdmi->regmap, RK3229_GRF_SOC_CON2, > + RK3229_DDC_MASK_EN); > + } > + > return 0; > } > > static enum drm_mode_status > -dw_hdmi_rockchip_mode_valid(struct drm_connector *connector, > +dw_hdmi_rockchip_mode_valid(const struct dw_hdmi_plat_data *plat_data, > struct drm_display_mode *mode) > { > - const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; > int pclk = mode->clock * 1000; > bool valid = false; > int i; > > - for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) { > - if (pclk == mpll_cfg[i].mpixelclock) { > - valid = true; > - break; > + if (plat_data->dev_type == RK3288_HDMI) > + for (i = 0; rk3288_mpll_cfg[i].mpixelclock != (~0UL); i++) > + if (pclk == rk3288_mpll_cfg[i].mpixelclock) { > + valid = true; > + break; > + } > + > + if (plat_data->dev_type == RK3229_HDMI) > + for (i = 0; rk3229_extphy_pll_cfg[i].mpixelclock != ~0UL; i++) { > + if (pclk == rk3229_extphy_pll_cfg[i].mpixelclock) { > + valid = true; > + break; > + } > } > - } > > return (valid) ? MODE_OK : MODE_BAD; > } > @@ -198,21 +503,29 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, > static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) > { > struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); > + int out_mode = ROCKCHIP_OUT_MODE_AAAA; > u32 val; > int mux; > > + if (hdmi->plat_data.dev_type == RK3229_HDMI) > + out_mode = ROCKCHIP_OUT_MODE_P888; > + > rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA, > - ROCKCHIP_OUT_MODE_AAAA); > + out_mode); > > - mux = rockchip_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder); > - if (mux) > - val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16); > - else > - val = HDMI_SEL_VOP_LIT << 16; > + if (hdmi->plat_data.dev_type == RK3288_HDMI) { > + mux = rockchip_drm_encoder_get_mux_id(hdmi->dev->of_node, > + encoder); > + if (mux) > + val = RK3288_HDMI_SEL_VOP_LIT | > + (RK3288_HDMI_SEL_VOP_LIT << 16); > + else > + val = RK3288_HDMI_SEL_VOP_LIT << 16; > > - regmap_write(hdmi->regmap, GRF_SOC_CON6, val); > - dev_dbg(hdmi->dev, "vop %s output to hdmi\n", > - (mux) ? "LIT" : "BIG"); > + regmap_write(hdmi->regmap, RK3288_GRF_SOC_CON6, val); > + > + dev_dbg(hdmi->dev, "vop %s output to hdmi\n", (mux) ? "LIT" : "BIG"); > + } > } > > static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { > @@ -222,17 +535,26 @@ static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_fun > .disable = dw_hdmi_rockchip_encoder_disable, > }; > > -static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = { > +static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = { > .mode_valid = dw_hdmi_rockchip_mode_valid, > - .mpll_cfg = rockchip_mpll_cfg, > - .cur_ctr = rockchip_cur_ctr, > - .phy_config = rockchip_phy_config, > + .mpll_cfg = rk3288_mpll_cfg, > + .cur_ctr = rk3288_cur_ctr, > + .phy_config = rk3288_phy_config, > .dev_type = RK3288_HDMI, > }; > > +static const struct dw_hdmi_plat_data rk3229_hdmi_drv_data = { > + .mode_valid = dw_hdmi_rockchip_mode_valid, > + .extphy_config = rk3229_extphy_config, > + .dev_type = RK3229_HDMI, > +}; > + > static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { > { .compatible = "rockchip,rk3288-dw-hdmi", > - .data = &rockchip_hdmi_drv_data > + .data = &rk3288_hdmi_drv_data > + }, > + { .compatible = "rockchip,rk3229-dw-hdmi", > + .data = &rk3229_hdmi_drv_data > }, > {}, > }; > @@ -242,7 +564,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, > void *data) > { > struct platform_device *pdev = to_platform_device(dev); > - const struct dw_hdmi_plat_data *plat_data; > const struct of_device_id *match; > struct drm_device *drm = data; > struct drm_encoder *encoder; > @@ -259,7 +580,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, > return -ENOMEM; > > match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node); > - plat_data = match->data; > + hdmi->plat_data = *(struct dw_hdmi_plat_data *)(match->data); > hdmi->dev = &pdev->dev; > encoder = &hdmi->encoder; > > @@ -293,7 +614,8 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, > drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs, > DRM_MODE_ENCODER_TMDS, NULL); > > - return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data); > + return dw_hdmi_bind(dev, master, data, encoder, iores, irq, > + &hdmi->plat_data); > } > > static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, > diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.h b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.h > new file mode 100644 > index 0000000..aca2543 > --- /dev/null > +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.h > @@ -0,0 +1,137 @@ > +#ifndef __DW_HDMI_ROCKCHIP__ > +#define __DW_HDMI_ROCKCHIP__ > + > +struct extphy_config_tab { > + u32 mpixelclock; > + int pre_emphasis; > + int slopeboost; > + int clk_level; > + int data0_level; > + int data1_level; > + int data2_level; > +}; > + > +struct extphy_pll_config_tab { > + unsigned long mpixelclock; > + struct { > + u8 pll_nd; > + u16 pll_nf; > + u8 tmsd_divider_a; > + u8 tmsd_divider_b; > + u8 tmsd_divider_c; > + u8 pclk_divider_a; > + u8 pclk_divider_b; > + u8 pclk_divider_c; > + u8 pclk_divider_d; > + u8 vco_div_5; > + u8 ppll_nd; > + u8 ppll_nf; > + u8 ppll_no; > + } param[DW_HDMI_RES_MAX]; > +}; > + > +#define RK3288_GRF_SOC_CON6 0x025c > +#define RK3288_HDMI_SEL_VOP_LIT (1 << 4) > + > +#define RK3229_GRF_SOC_CON6 0x0418 > +#define RK3229_IO_3V_DOMAIN ((7 << 4) | (7 << (4 + 16))) > + > +#define RK3229_GRF_SOC_CON2 0x0408 > +#define RK3229_DDC_MASK_EN ((3 << 13) | (3 << (13 + 16))) > + > +#define RK3229_PLL_POWER_DOWN (BIT(12) | BIT(12 + 16)) > +#define RK3229_PLL_POWER_UP BIT(12 + 16) > +#define RK3229_PLL_PDATA_DEN BIT(11 + 16) > +#define RK3229_PLL_PDATA_EN (BIT(11) | BIT(11 + 16)) > + > +/* PHY Defined for RK322X */ > +#define EXT_PHY_CONTROL 0 > +#define EXT_PHY_ANALOG_RESET_MASK 0x80 > +#define EXT_PHY_DIGITAL_RESET_MASK 0x40 > +#define EXT_PHY_PCLK_INVERT_MASK 0x08 > +#define EXT_PHY_PREPCLK_INVERT_MASK 0x04 > +#define EXT_PHY_TMDSCLK_INVERT_MASK 0x02 > +#define EXT_PHY_SRC_SELECT_MASK 0x01 > + > +#define EXT_PHY_TERM_CAL 0x03 > +#define EXT_PHY_TERM_CAL_EN_MASK 0x80 > +#define EXT_PHY_TERM_CAL_DIV_H_MASK 0x7f > + > +#define EXT_PHY_TERM_CAL_DIV_L 0x04 > + > +#define EXT_PHY_PLL_PRE_DIVIDER 0xe2 > +#define EXT_PHY_PLL_FB_BIT8_MASK 0x80 > +#define EXT_PHY_PLL_PCLK_DIV5_EN_MASK 0x20 > +#define EXT_PHY_PLL_PRE_DIVIDER_MASK 0x1f > + > +#define EXT_PHY_PLL_FB_DIVIDER 0xe3 > + > +#define EXT_PHY_PCLK_DIVIDER1 0xe4 > +#define EXT_PHY_PCLK_DIVIDERB_MASK 0x60 > +#define EXT_PHY_PCLK_DIVIDERA_MASK 0x1f > + > +#define EXT_PHY_PCLK_DIVIDER2 0xe5 > +#define EXT_PHY_PCLK_DIVIDERC_MASK 0x60 > +#define EXT_PHY_PCLK_DIVIDERD_MASK 0x1f > + > +#define EXT_PHY_TMDSCLK_DIVIDER 0xe6 > +#define EXT_PHY_TMDSCLK_DIVIDERC_MASK 0x30 > +#define EXT_PHY_TMDSCLK_DIVIDERA_MASK 0x0c > +#define EXT_PHY_TMDSCLK_DIVIDERB_MASK 0x03 > + > +#define EXT_PHY_PLL_BW 0xe7 > + > +#define EXT_PHY_PPLL_PRE_DIVIDER 0xe9 > +#define EXT_PHY_PPLL_ENABLE_MASK 0xc0 > +#define EXT_PHY_PPLL_PRE_DIVIDER_MASK 0x1f > + > +#define EXT_PHY_PPLL_FB_DIVIDER 0xea > + > +#define EXT_PHY_PPLL_POST_DIVIDER 0xeb > +#define EXT_PHY_PPLL_FB_DIVIDER_BIT8_MASK 0x80 > +#define EXT_PHY_PPLL_POST_DIVIDER_MASK 0x30 > +#define EXT_PHY_PPLL_LOCK_STATUS_MASK 0x01 > + > +#define EXT_PHY_PPLL_BW 0xec > + > +#define EXT_PHY_SIGNAL_CTRL 0xee > +#define EXT_PHY_TRANSITION_CLK_EN_MASK 0x80 > +#define EXT_PHY_TRANSITION_D0_EN_MASK 0x40 > +#define EXT_PHY_TRANSITION_D1_EN_MASK 0x20 > +#define EXT_PHY_TRANSITION_D2_EN_MASK 0x10 > +#define EXT_PHY_LEVEL_CLK_EN_MASK 0x08 > +#define EXT_PHY_LEVEL_D0_EN_MASK 0x04 > +#define EXT_PHY_LEVEL_D1_EN_MASK 0x02 > +#define EXT_PHY_LEVEL_D2_EN_MASK 0x01 > + > +#define EXT_PHY_SLOPEBOOST 0xef > +#define EXT_PHY_SLOPEBOOST_CLK_MASK 0x03 > +#define EXT_PHY_SLOPEBOOST_D0_MASK 0x0c > +#define EXT_PHY_SLOPEBOOST_D1_MASK 0x30 > +#define EXT_PHY_SLOPEBOOST_D2_MASK 0xc0 > + > +#define EXT_PHY_PREEMPHASIS 0xf0 > +#define EXT_PHY_PREEMPHASIS_D0_MASK 0x03 > +#define EXT_PHY_PREEMPHASIS_D1_MASK 0x0c > +#define EXT_PHY_PREEMPHASIS_D2_MASK 0x30 > + > +#define EXT_PHY_LEVEL1 0xf1 > +#define EXT_PHY_LEVEL_CLK_MASK 0xf0 > +#define EXT_PHY_LEVEL_D2_MASK 0x0f > + > +#define EXT_PHY_LEVEL2 0xf2 > +#define EXT_PHY_LEVEL_D1_MASK 0xf0 > +#define EXT_PHY_LEVEL_D0_MASK 0x0f > + > +#define EXT_PHY_TERM_RESIS_AUTO 0xf4 > +#define EXT_PHY_AUTO_R50_OHMS 0 > +#define EXT_PHY_AUTO_R75_OHMS (1 << 2) > +#define EXT_PHY_AUTO_R100_OHMS (2 << 2) > +#define EXT_PHY_AUTO_ROPEN_CIRCUIT (3 << 2) > + > +#define EXT_PHY_TERM_RESIS_MANUAL_CLK 0xfb > +#define EXT_PHY_TERM_RESIS_MANUAL_D2 0xfc > +#define EXT_PHY_TERM_RESIS_MANUAL_D1 0xfd > +#define EXT_PHY_TERM_RESIS_MANUAL_D0 0xfe > + > +#endif /* __DW_HDMI_ROCKCHIP__ */ > diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h > index bae79f3..44084e8 100644 > --- a/include/drm/bridge/dw_hdmi.h > +++ b/include/drm/bridge/dw_hdmi.h > @@ -24,6 +24,7 @@ enum { > enum dw_hdmi_devtype { > IMX6Q_HDMI, > IMX6DL_HDMI, > + RK3229_HDMI, > RK3288_HDMI, > }; > > @@ -52,8 +53,10 @@ struct dw_hdmi_plat_data { > const struct dw_hdmi_mpll_config *mpll_cfg; > const struct dw_hdmi_curr_ctrl *cur_ctr; > const struct dw_hdmi_phy_config *phy_config; > - enum drm_mode_status (*mode_valid)(struct drm_connector *connector, > + enum drm_mode_status (*mode_valid)(const struct dw_hdmi_plat_data *plat_data, > struct drm_display_mode *mode); > + int (*extphy_config)(struct dw_hdmi_plat_data *plat_data, > + int bpp, int pixelclock); > }; > > void dw_hdmi_unbind(struct device *dev, struct device *master, void *data); From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752404AbcAGGWU (ORCPT ); Thu, 7 Jan 2016 01:22:20 -0500 Received: from lucky1.263xmail.com ([211.157.147.131]:36529 "EHLO lucky1.263xmail.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751545AbcAGGWP (ORCPT ); Thu, 7 Jan 2016 01:22:15 -0500 X-263anti-spam: KSV:0; X-MAIL-GRAY: 1 X-MAIL-DELIVERY: 0 X-KSVirus-check: 0 X-ABS-CHECKED: 4 X-ADDR-CHECKED: 0 X-RL-SENDER: ykk@rock-chips.com X-FST-TO: linux-arm-kernel@lists.infradead.org X-SENDER-IP: 58.22.7.114 X-LOGIN-NAME: ykk@rock-chips.com X-UNIQUE-TAG: <6fb9b83d8cc9f058e8d8200513c6be90> X-ATTACHMENT-NUM: 0 X-DNS-TYPE: 0 Subject: Re: [RFC PATCH v1 1/2] drm: rockchip: hdmi: add RK3229 HDMI support To: Mark Yao , Heiko Stuebner , Russell King , Philipp Zabel , Andy Yan References: <1452141288-9292-1-git-send-email-ykk@rock-chips.com> <1452141447-9441-1-git-send-email-ykk@rock-chips.com> Cc: David Airlie , Rob Herring , Kumar Gala , Zheng Yang , dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org From: Yakir Yang Message-ID: <568E040A.4020907@rock-chips.com> Date: Thu, 7 Jan 2016 14:22:02 +0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 In-Reply-To: <1452141447-9441-1-git-send-email-ykk@rock-chips.com> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Thanks for "Kbuild test robot" reminding, I forget to update "mode_valid" function define in imx-hdmi side, would send new version out, -- >> drivers/gpu/drm/imx/dw_hdmi-imx.c:181:2: warning: initialization from incompatible pointer type .mode_valid = imx6q_hdmi_mode_valid, ^ drivers/gpu/drm/imx/dw_hdmi-imx.c:181:2: warning: (near initialization for 'imx6q_hdmi_drv_data.mode_valid') drivers/gpu/drm/imx/dw_hdmi-imx.c:189:2: warning: initialization from incompatible pointer type .mode_valid = imx6dl_hdmi_mode_valid, ^ drivers/gpu/drm/imx/dw_hdmi-imx.c:189:2: warning: (near initialization for 'imx6dl_hdmi_drv_data.mode_valid') Sorry, - Yakir On 01/07/2016 12:37 PM, Yakir Yang wrote: > RK3229 integrate an DesignedWare HDMI2.0 controller and an INNO HDMI2.0 phy, > the max output resolution is 4K. > > Signed-off-by: Yakir Yang > --- > drivers/gpu/drm/bridge/dw-hdmi.c | 33 ++- > drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 380 +++++++++++++++++++++++++--- > drivers/gpu/drm/rockchip/dw_hdmi-rockchip.h | 137 ++++++++++ > include/drm/bridge/dw_hdmi.h | 5 +- > 4 files changed, 516 insertions(+), 39 deletions(-) > create mode 100644 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.h > > diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c > index 6fbec99..60b1dcf 100644 > --- a/drivers/gpu/drm/bridge/dw-hdmi.c > +++ b/drivers/gpu/drm/bridge/dw-hdmi.c > @@ -735,10 +735,12 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep, > { > unsigned res_idx; > u8 val, msec; > + int ret; > const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; > const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; > const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; > const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; > + int mpixelclock = hdmi->hdmi_data.video_mode.mpixelclock; > > if (prep) > return -EINVAL; > @@ -758,27 +760,38 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep, > return -EINVAL; > } > > + if (hdmi->plat_data->extphy_config) { > + /* gen2 tx power off */ > + dw_hdmi_phy_gen2_txpwron(hdmi, 0); > + dw_hdmi_phy_gen2_pddq(hdmi, 1); > + > + ret = hdmi->plat_data->extphy_config(hdmi->plat_data, res_idx, > + mpixelclock); > + /* gen2 tx power on */ > + dw_hdmi_phy_gen2_txpwron(hdmi, 1); > + dw_hdmi_phy_gen2_pddq(hdmi, 0); > + > + return ret; > + } > + > /* PLL/MPLL Cfg - always match on final entry */ > for (; mpll_config->mpixelclock != ~0UL; mpll_config++) > - if (hdmi->hdmi_data.video_mode.mpixelclock <= > - mpll_config->mpixelclock) > + if (mpixelclock <= mpll_config->mpixelclock) > break; > > for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++) > - if (hdmi->hdmi_data.video_mode.mpixelclock <= > - curr_ctrl->mpixelclock) > + if (mpixelclock <= curr_ctrl->mpixelclock) > break; > > for (; phy_config->mpixelclock != ~0UL; phy_config++) > - if (hdmi->hdmi_data.video_mode.mpixelclock <= > - phy_config->mpixelclock) > + if (mpixelclock <= phy_config->mpixelclock) > break; > > if (mpll_config->mpixelclock == ~0UL || > curr_ctrl->mpixelclock == ~0UL || > phy_config->mpixelclock == ~0UL) { > dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n", > - hdmi->hdmi_data.video_mode.mpixelclock); > + mpixelclock); > return -EINVAL; > } > > @@ -1476,14 +1489,16 @@ dw_hdmi_connector_mode_valid(struct drm_connector *connector, > { > struct dw_hdmi *hdmi = container_of(connector, > struct dw_hdmi, connector); > + struct dw_hdmi_plat_data *plat_data = hdmi->plat_data; > enum drm_mode_status mode_status = MODE_OK; > > /* We don't support double-clocked modes */ > if (mode->flags & DRM_MODE_FLAG_DBLCLK) > return MODE_BAD; > > - if (hdmi->plat_data->mode_valid) > - mode_status = hdmi->plat_data->mode_valid(connector, mode); > + if (plat_data->mode_valid) > + mode_status = plat_data->mode_valid(plat_data, mode); > + > > return mode_status; > } > diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c > index c65ce8c..424d548 100644 > --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c > +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c > @@ -7,6 +7,7 @@ > * (at your option) any later version. > */ > > +#include > #include > #include > #include > @@ -21,18 +22,135 @@ > #include "rockchip_drm_drv.h" > #include "rockchip_drm_vop.h" > > -#define GRF_SOC_CON6 0x025c > -#define HDMI_SEL_VOP_LIT (1 << 4) > +#include "dw_hdmi-rockchip.h" > > struct rockchip_hdmi { > struct device *dev; > struct regmap *regmap; > struct drm_encoder encoder; > + struct dw_hdmi_plat_data plat_data; > + > + void __iomem *extphy_regbase; > + struct clk *extphy_pclk; > }; > > #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) > > -static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { > +static const struct extphy_config_tab rk3229_extphy_cfg[] = { > + { .mpixelclock = 165000000, > + .pre_emphasis = 0, .slopeboost = 0, .clk_level = 4, > + .data0_level = 4, 4, 4, > + }, > + > + { .mpixelclock = 225000000, > + .pre_emphasis = 0, .slopeboost = 0, .clk_level = 6, > + .data0_level = 6, 6, 6, > + }, > + > + { .mpixelclock = 340000000, > + .pre_emphasis = 1, .slopeboost = 0, .clk_level = 6, > + .data0_level = 10, 10, 10, > + }, > + > + { .mpixelclock = 594000000, > + .pre_emphasis = 1, .slopeboost = 0, .clk_level = 7, > + .data0_level = 10, 10, 10, > + }, > + > + { .mpixelclock = ~0UL}, > +}; > + > +static const struct extphy_pll_config_tab rk3229_extphy_pll_cfg[] = { > + { > + .mpixelclock = 27000000, .param = { > + { .pll_nd = 1, .pll_nf = 45, > + .tmsd_divider_a = 3, 1, 1, > + .pclk_divider_a = 1, 3, 3, 4, > + .vco_div_5 = 0, > + .ppll_nd = 1, .ppll_nf = 40, .ppll_no = 8, > + }, > + { .pll_nd = 1, .pll_nf = 45, > + .tmsd_divider_a = 0, 3, 3, > + .pclk_divider_a = 1, 3, 3, 4, > + .vco_div_5 = 0, > + .ppll_nd = 1, .ppll_nf = 40, .ppll_no = 8, > + }, > + }, > + }, { > + .mpixelclock = 59400000, .param = { > + { .pll_nd = 2, .pll_nf = 99, > + .tmsd_divider_a = 3, 1, 1, > + .pclk_divider_a = 1, 3, 2, 2, > + .vco_div_5 = 0, > + .ppll_nd = 1, .ppll_nf = 40, .ppll_no = 8, > + }, > + { .pll_nd = 2, .pll_nf = 99, > + .tmsd_divider_a = 1, 1, 1, > + .pclk_divider_a = 1, 3, 2, 2, > + .vco_div_5 = 0, > + .ppll_nd = 1, .ppll_nf = 40, .ppll_no = 8, > + }, > + }, > + }, { > + .mpixelclock = 74250000, .param = { > + { .pll_nd = 2, .pll_nf = 99, > + .tmsd_divider_a = 1, 1, 1, > + .pclk_divider_a = 1, 2, 2, 2, > + .vco_div_5 = 0, > + .ppll_nd = 1, .ppll_nf = 40, .ppll_no = 8, > + }, > + { .pll_nd = 4, .pll_nf = 495, > + .tmsd_divider_a = 1, 2, 2, > + .pclk_divider_a = 1, 3, 3, 4, > + .vco_div_5 = 0, > + .ppll_nd = 2, .ppll_nf = 40, .ppll_no = 4, > + }, > + }, > + }, { > + .mpixelclock = 148500000, .param = { > + { .pll_nd = 2, .pll_nf = 99, > + .tmsd_divider_a = 1, 0, 0, > + .pclk_divider_a = 1, 2, 1, 1, > + .vco_div_5 = 0, > + .ppll_nd = 2, .ppll_nf = 40, .ppll_no = 4, > + }, > + { .pll_nd = 4, .pll_nf = 495, > + .tmsd_divider_a = 0, 2, 2, > + .pclk_divider_a = 1, 3, 2, 2, > + .vco_div_5 = 0, > + .ppll_nd = 4, .ppll_nf = 40, .ppll_no = 2, > + }, > + }, > + }, { > + .mpixelclock = 297000000, .param = { > + { .pll_nd = 2, .pll_nf = 99, > + .tmsd_divider_a = 0, 0, 0, > + .pclk_divider_a = 1, 0, 1, 1, > + .vco_div_5 = 0, > + .ppll_nd = 4, .ppll_nf = 40, .ppll_no = 2, > + }, > + { .pll_nd = 4, .pll_nf = 495, > + .tmsd_divider_a = 1, 2, 0, > + .pclk_divider_a = 1, 3, 1, 1, > + .vco_div_5 = 0, > + .ppll_nd = 8, .ppll_nf = 40, .ppll_no = 1, > + }, > + }, > + }, { > + .mpixelclock = 594000000, .param = { > + { .pll_nd = 1, .pll_nf = 99, > + .tmsd_divider_a = 0, 2, 0, > + .pclk_divider_a = 1, 0, 1, 1, > + .vco_div_5 = 0, > + .ppll_nd = 8, .ppll_nf = 40, .ppll_no = 1, > + }, > + } > + }, { > + .mpixelclock = ~0UL, > + } > +}; > + > +static const struct dw_hdmi_mpll_config rk3288_mpll_cfg[] = { > { > 27000000, { > { 0x00b3, 0x0000}, > @@ -112,7 +230,7 @@ static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { > } > }; > > -static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { > +static const struct dw_hdmi_curr_ctrl rk3288_cur_ctr[] = { > /* pixelclk bpp8 bpp10 bpp12 */ > { > 40000000, { 0x0018, 0x0018, 0x0018 }, > @@ -133,7 +251,7 @@ static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { > } > }; > > -static const struct dw_hdmi_phy_config rockchip_phy_config[] = { > +static const struct dw_hdmi_phy_config rk3288_phy_config[] = { > /*pixelclk symbol term vlev*/ > { 74250000, 0x8009, 0x0004, 0x0272}, > { 148500000, 0x802b, 0x0004, 0x028d}, > @@ -141,9 +259,158 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = { > { ~0UL, 0x0000, 0x0000, 0x0000} > }; > > +static int hdmi_ext_phy_write(struct rockchip_hdmi *hdmi, unsigned short data, > + unsigned char addr) > +{ > + writel_relaxed(data, hdmi->extphy_regbase + (addr) * 0x04); > + return 0; > +} > + > +static unsigned int hdmi_phy_i2c_read(struct rockchip_hdmi *hdmi, > + unsigned char addr) > +{ > + return readl_relaxed(hdmi->extphy_regbase + (addr) * 0x04); > +} > + > +static int rk3229_extphy_config(struct dw_hdmi_plat_data *plat_data, > + int res, int pixelclock) > +{ > + struct rockchip_hdmi *hdmi = to_rockchip_hdmi(plat_data); > + const struct extphy_pll_config_tab *mpll = rk3229_extphy_pll_cfg; > + const struct extphy_config_tab *ctrl = rk3229_extphy_cfg; > + unsigned long timeout; > + int i, stat; > + > + /* Find out the extphy MPLL configure parameters */ > + for (i = 0; mpll[i].mpixelclock != ~0UL; i++) > + if (pixelclock == mpll[i].mpixelclock) > + break; > + if (mpll[i].mpixelclock == ~0UL) { > + dev_err(hdmi->dev, "Extphy couldn't support %dHz\n", pixelclock); > + return -EINVAL; > + } > + > + regmap_write(hdmi->regmap, RK3229_GRF_SOC_CON2, > + RK3229_PLL_POWER_DOWN | RK3229_PLL_PDATA_DEN); > + > + /* > + * Configure external phy PLL registers. > + */ > + stat = ((mpll[i].param[res].pll_nf >> 1) & EXT_PHY_PLL_FB_BIT8_MASK) | > + ((mpll[i].param[res].vco_div_5 & 1) << 5) | > + (mpll[i].param[res].pll_nd & EXT_PHY_PLL_PRE_DIVIDER_MASK); > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PLL_PRE_DIVIDER); > + > + hdmi_ext_phy_write(hdmi, mpll[i].param[res].pll_nf, EXT_PHY_PLL_FB_DIVIDER); > + > + stat = (mpll[i].param[res].pclk_divider_a & EXT_PHY_PCLK_DIVIDERA_MASK) | > + ((mpll[i].param[res].pclk_divider_b & 3) << 5); > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PCLK_DIVIDER1); > + > + stat = (mpll[i].param[res].pclk_divider_d & EXT_PHY_PCLK_DIVIDERD_MASK) | > + ((mpll[i].param[res].pclk_divider_c & 3) << 5); > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PCLK_DIVIDER2); > + > + stat = ((mpll[i].param[res].tmsd_divider_c & 3) << 4) | > + ((mpll[i].param[res].tmsd_divider_a & 3) << 2) | > + (mpll[i].param[res].tmsd_divider_b & 3); > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_TMDSCLK_DIVIDER); > + > + hdmi_ext_phy_write(hdmi, mpll[i].param[res].ppll_nf, EXT_PHY_PPLL_FB_DIVIDER); > + > + if (mpll[i].param[res].ppll_no == 1) { > + hdmi_ext_phy_write(hdmi, 0, EXT_PHY_PPLL_POST_DIVIDER); > + > + stat = 0x20 | mpll[i].param[res].ppll_nd; > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PPLL_PRE_DIVIDER); > + } else { > + stat = ((mpll[i].param[res].ppll_no / 2) - 1) << 4; > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PPLL_POST_DIVIDER); > + > + stat = 0xe0 | mpll[i].param[res].ppll_nd; > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PPLL_PRE_DIVIDER); > + } > + > + > + /* Find out the extphy driver configure parameters */ > + for (i = 0; ctrl[i].mpixelclock != ~0UL; i++) > + if (pixelclock <= ctrl[i].mpixelclock) > + break; > + if (ctrl[i].mpixelclock == ~0UL) { > + dev_err(hdmi->dev, "Extphy couldn't support %dHz\n", pixelclock); > + return -EINVAL; > + } > + > + /* > + * Configure the extphy driver registers. > + */ > + if (ctrl[i].slopeboost) { > + hdmi_ext_phy_write(hdmi, 0xff, EXT_PHY_SIGNAL_CTRL); > + > + stat = (ctrl[i].slopeboost - 1) & 3; > + stat = (stat << 6) | (stat << 4) | (stat << 2) | stat; > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_SLOPEBOOST); > + } else > + hdmi_ext_phy_write(hdmi, 0x0f, EXT_PHY_SIGNAL_CTRL); > + > + stat = ctrl[i].pre_emphasis & 3; > + stat = (stat << 4) | (stat << 2) | stat; > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PREEMPHASIS); > + > + stat = ((ctrl[i].clk_level & 0xf) << 4) | (ctrl[i].data2_level & 0xf); > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_LEVEL1); > + > + stat = ((ctrl[i].data1_level & 0xf) << 4) | (ctrl[i].data0_level & 0xf); > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_LEVEL2); > + > + hdmi_ext_phy_write(hdmi, 0x22, 0xf3); > + > + stat = clk_get_rate(hdmi->extphy_pclk) / 100000; > + hdmi_ext_phy_write(hdmi, ((stat >> 8) & 0xff) | 0x80, EXT_PHY_TERM_CAL); > + hdmi_ext_phy_write(hdmi, stat & 0xff, EXT_PHY_TERM_CAL_DIV_L); > + > + if (pixelclock > 340000000) > + stat = EXT_PHY_AUTO_R100_OHMS; > + else if (pixelclock > 200000000) > + stat = EXT_PHY_AUTO_R50_OHMS; > + else > + stat = EXT_PHY_AUTO_ROPEN_CIRCUIT; > + hdmi_ext_phy_write(hdmi, stat | 0x20, EXT_PHY_TERM_RESIS_AUTO); > + hdmi_ext_phy_write(hdmi, (stat >> 8) & 0xff, EXT_PHY_TERM_CAL); > + > + stat = (pixelclock > 200000000) ? 0 : 0x11; > + hdmi_ext_phy_write(hdmi, stat, EXT_PHY_PLL_BW); > + hdmi_ext_phy_write(hdmi, 0x27, EXT_PHY_PPLL_BW); > + > + regmap_write(hdmi->regmap, RK3229_GRF_SOC_CON2, RK3229_PLL_POWER_UP); > + > + /* Detect whether PLL is lock or not */ > + timeout = jiffies + msecs_to_jiffies(100); > + while (!time_after(jiffies, timeout)) { > + usleep_range(1000, 2000); > + stat = hdmi_phy_i2c_read(hdmi, EXT_PHY_PPLL_POST_DIVIDER); > + if (stat & EXT_PHY_PPLL_LOCK_STATUS_MASK) > + break; > + } > + > + regmap_write(hdmi->regmap, RK3229_GRF_SOC_CON2, RK3229_PLL_PDATA_EN); > + > + if ((stat & EXT_PHY_PPLL_LOCK_STATUS_MASK) == 0) { > + dev_err(hdmi->dev, "EXT PHY PLL not locked\n"); > + return -EBUSY; > + } > + > + return 0; > +} > + > static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) > { > struct device_node *np = hdmi->dev->of_node; > + struct platform_device *pdev; > + struct resource *iores; > + int ret; > + > + pdev = container_of(hdmi->dev, struct platform_device, dev); > > hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); > if (IS_ERR(hdmi->regmap)) { > @@ -151,24 +418,62 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) > return PTR_ERR(hdmi->regmap); > } > > + if (hdmi->plat_data.dev_type == RK3229_HDMI) { > + iores = platform_get_resource(pdev, IORESOURCE_MEM, 1); > + if (!iores) > + return -ENXIO; > + > + hdmi->extphy_regbase = devm_ioremap_resource(hdmi->dev, iores); > + if (IS_ERR(hdmi->extphy_regbase)) { > + dev_err(hdmi->dev, "failed to map extphy regbase\n"); > + return PTR_ERR(hdmi->extphy_regbase); > + } > + > + hdmi->extphy_pclk = devm_clk_get(hdmi->dev, "extphy"); > + if (IS_ERR(hdmi->extphy_pclk)) { > + dev_err(hdmi->dev, "failed to get extphy clock\n"); > + return PTR_ERR(hdmi->extphy_pclk); > + } > + > + ret = clk_prepare_enable(hdmi->extphy_pclk); > + if (ret) { > + dev_err(hdmi->dev, "failed to enable extphy clk: %d\n", > + ret); > + return ret; > + } > + > + regmap_write(hdmi->regmap, RK3229_GRF_SOC_CON6, > + RK3229_IO_3V_DOMAIN); > + > + regmap_write(hdmi->regmap, RK3229_GRF_SOC_CON2, > + RK3229_DDC_MASK_EN); > + } > + > return 0; > } > > static enum drm_mode_status > -dw_hdmi_rockchip_mode_valid(struct drm_connector *connector, > +dw_hdmi_rockchip_mode_valid(const struct dw_hdmi_plat_data *plat_data, > struct drm_display_mode *mode) > { > - const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; > int pclk = mode->clock * 1000; > bool valid = false; > int i; > > - for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) { > - if (pclk == mpll_cfg[i].mpixelclock) { > - valid = true; > - break; > + if (plat_data->dev_type == RK3288_HDMI) > + for (i = 0; rk3288_mpll_cfg[i].mpixelclock != (~0UL); i++) > + if (pclk == rk3288_mpll_cfg[i].mpixelclock) { > + valid = true; > + break; > + } > + > + if (plat_data->dev_type == RK3229_HDMI) > + for (i = 0; rk3229_extphy_pll_cfg[i].mpixelclock != ~0UL; i++) { > + if (pclk == rk3229_extphy_pll_cfg[i].mpixelclock) { > + valid = true; > + break; > + } > } > - } > > return (valid) ? MODE_OK : MODE_BAD; > } > @@ -198,21 +503,29 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, > static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) > { > struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); > + int out_mode = ROCKCHIP_OUT_MODE_AAAA; > u32 val; > int mux; > > + if (hdmi->plat_data.dev_type == RK3229_HDMI) > + out_mode = ROCKCHIP_OUT_MODE_P888; > + > rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA, > - ROCKCHIP_OUT_MODE_AAAA); > + out_mode); > > - mux = rockchip_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder); > - if (mux) > - val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16); > - else > - val = HDMI_SEL_VOP_LIT << 16; > + if (hdmi->plat_data.dev_type == RK3288_HDMI) { > + mux = rockchip_drm_encoder_get_mux_id(hdmi->dev->of_node, > + encoder); > + if (mux) > + val = RK3288_HDMI_SEL_VOP_LIT | > + (RK3288_HDMI_SEL_VOP_LIT << 16); > + else > + val = RK3288_HDMI_SEL_VOP_LIT << 16; > > - regmap_write(hdmi->regmap, GRF_SOC_CON6, val); > - dev_dbg(hdmi->dev, "vop %s output to hdmi\n", > - (mux) ? "LIT" : "BIG"); > + regmap_write(hdmi->regmap, RK3288_GRF_SOC_CON6, val); > + > + dev_dbg(hdmi->dev, "vop %s output to hdmi\n", (mux) ? "LIT" : "BIG"); > + } > } > > static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { > @@ -222,17 +535,26 @@ static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_fun > .disable = dw_hdmi_rockchip_encoder_disable, > }; > > -static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = { > +static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = { > .mode_valid = dw_hdmi_rockchip_mode_valid, > - .mpll_cfg = rockchip_mpll_cfg, > - .cur_ctr = rockchip_cur_ctr, > - .phy_config = rockchip_phy_config, > + .mpll_cfg = rk3288_mpll_cfg, > + .cur_ctr = rk3288_cur_ctr, > + .phy_config = rk3288_phy_config, > .dev_type = RK3288_HDMI, > }; > > +static const struct dw_hdmi_plat_data rk3229_hdmi_drv_data = { > + .mode_valid = dw_hdmi_rockchip_mode_valid, > + .extphy_config = rk3229_extphy_config, > + .dev_type = RK3229_HDMI, > +}; > + > static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { > { .compatible = "rockchip,rk3288-dw-hdmi", > - .data = &rockchip_hdmi_drv_data > + .data = &rk3288_hdmi_drv_data > + }, > + { .compatible = "rockchip,rk3229-dw-hdmi", > + .data = &rk3229_hdmi_drv_data > }, > {}, > }; > @@ -242,7 +564,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, > void *data) > { > struct platform_device *pdev = to_platform_device(dev); > - const struct dw_hdmi_plat_data *plat_data; > const struct of_device_id *match; > struct drm_device *drm = data; > struct drm_encoder *encoder; > @@ -259,7 +580,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, > return -ENOMEM; > > match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node); > - plat_data = match->data; > + hdmi->plat_data = *(struct dw_hdmi_plat_data *)(match->data); > hdmi->dev = &pdev->dev; > encoder = &hdmi->encoder; > > @@ -293,7 +614,8 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, > drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs, > DRM_MODE_ENCODER_TMDS, NULL); > > - return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data); > + return dw_hdmi_bind(dev, master, data, encoder, iores, irq, > + &hdmi->plat_data); > } > > static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, > diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.h b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.h > new file mode 100644 > index 0000000..aca2543 > --- /dev/null > +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.h > @@ -0,0 +1,137 @@ > +#ifndef __DW_HDMI_ROCKCHIP__ > +#define __DW_HDMI_ROCKCHIP__ > + > +struct extphy_config_tab { > + u32 mpixelclock; > + int pre_emphasis; > + int slopeboost; > + int clk_level; > + int data0_level; > + int data1_level; > + int data2_level; > +}; > + > +struct extphy_pll_config_tab { > + unsigned long mpixelclock; > + struct { > + u8 pll_nd; > + u16 pll_nf; > + u8 tmsd_divider_a; > + u8 tmsd_divider_b; > + u8 tmsd_divider_c; > + u8 pclk_divider_a; > + u8 pclk_divider_b; > + u8 pclk_divider_c; > + u8 pclk_divider_d; > + u8 vco_div_5; > + u8 ppll_nd; > + u8 ppll_nf; > + u8 ppll_no; > + } param[DW_HDMI_RES_MAX]; > +}; > + > +#define RK3288_GRF_SOC_CON6 0x025c > +#define RK3288_HDMI_SEL_VOP_LIT (1 << 4) > + > +#define RK3229_GRF_SOC_CON6 0x0418 > +#define RK3229_IO_3V_DOMAIN ((7 << 4) | (7 << (4 + 16))) > + > +#define RK3229_GRF_SOC_CON2 0x0408 > +#define RK3229_DDC_MASK_EN ((3 << 13) | (3 << (13 + 16))) > + > +#define RK3229_PLL_POWER_DOWN (BIT(12) | BIT(12 + 16)) > +#define RK3229_PLL_POWER_UP BIT(12 + 16) > +#define RK3229_PLL_PDATA_DEN BIT(11 + 16) > +#define RK3229_PLL_PDATA_EN (BIT(11) | BIT(11 + 16)) > + > +/* PHY Defined for RK322X */ > +#define EXT_PHY_CONTROL 0 > +#define EXT_PHY_ANALOG_RESET_MASK 0x80 > +#define EXT_PHY_DIGITAL_RESET_MASK 0x40 > +#define EXT_PHY_PCLK_INVERT_MASK 0x08 > +#define EXT_PHY_PREPCLK_INVERT_MASK 0x04 > +#define EXT_PHY_TMDSCLK_INVERT_MASK 0x02 > +#define EXT_PHY_SRC_SELECT_MASK 0x01 > + > +#define EXT_PHY_TERM_CAL 0x03 > +#define EXT_PHY_TERM_CAL_EN_MASK 0x80 > +#define EXT_PHY_TERM_CAL_DIV_H_MASK 0x7f > + > +#define EXT_PHY_TERM_CAL_DIV_L 0x04 > + > +#define EXT_PHY_PLL_PRE_DIVIDER 0xe2 > +#define EXT_PHY_PLL_FB_BIT8_MASK 0x80 > +#define EXT_PHY_PLL_PCLK_DIV5_EN_MASK 0x20 > +#define EXT_PHY_PLL_PRE_DIVIDER_MASK 0x1f > + > +#define EXT_PHY_PLL_FB_DIVIDER 0xe3 > + > +#define EXT_PHY_PCLK_DIVIDER1 0xe4 > +#define EXT_PHY_PCLK_DIVIDERB_MASK 0x60 > +#define EXT_PHY_PCLK_DIVIDERA_MASK 0x1f > + > +#define EXT_PHY_PCLK_DIVIDER2 0xe5 > +#define EXT_PHY_PCLK_DIVIDERC_MASK 0x60 > +#define EXT_PHY_PCLK_DIVIDERD_MASK 0x1f > + > +#define EXT_PHY_TMDSCLK_DIVIDER 0xe6 > +#define EXT_PHY_TMDSCLK_DIVIDERC_MASK 0x30 > +#define EXT_PHY_TMDSCLK_DIVIDERA_MASK 0x0c > +#define EXT_PHY_TMDSCLK_DIVIDERB_MASK 0x03 > + > +#define EXT_PHY_PLL_BW 0xe7 > + > +#define EXT_PHY_PPLL_PRE_DIVIDER 0xe9 > +#define EXT_PHY_PPLL_ENABLE_MASK 0xc0 > +#define EXT_PHY_PPLL_PRE_DIVIDER_MASK 0x1f > + > +#define EXT_PHY_PPLL_FB_DIVIDER 0xea > + > +#define EXT_PHY_PPLL_POST_DIVIDER 0xeb > +#define EXT_PHY_PPLL_FB_DIVIDER_BIT8_MASK 0x80 > +#define EXT_PHY_PPLL_POST_DIVIDER_MASK 0x30 > +#define EXT_PHY_PPLL_LOCK_STATUS_MASK 0x01 > + > +#define EXT_PHY_PPLL_BW 0xec > + > +#define EXT_PHY_SIGNAL_CTRL 0xee > +#define EXT_PHY_TRANSITION_CLK_EN_MASK 0x80 > +#define EXT_PHY_TRANSITION_D0_EN_MASK 0x40 > +#define EXT_PHY_TRANSITION_D1_EN_MASK 0x20 > +#define EXT_PHY_TRANSITION_D2_EN_MASK 0x10 > +#define EXT_PHY_LEVEL_CLK_EN_MASK 0x08 > +#define EXT_PHY_LEVEL_D0_EN_MASK 0x04 > +#define EXT_PHY_LEVEL_D1_EN_MASK 0x02 > +#define EXT_PHY_LEVEL_D2_EN_MASK 0x01 > + > +#define EXT_PHY_SLOPEBOOST 0xef > +#define EXT_PHY_SLOPEBOOST_CLK_MASK 0x03 > +#define EXT_PHY_SLOPEBOOST_D0_MASK 0x0c > +#define EXT_PHY_SLOPEBOOST_D1_MASK 0x30 > +#define EXT_PHY_SLOPEBOOST_D2_MASK 0xc0 > + > +#define EXT_PHY_PREEMPHASIS 0xf0 > +#define EXT_PHY_PREEMPHASIS_D0_MASK 0x03 > +#define EXT_PHY_PREEMPHASIS_D1_MASK 0x0c > +#define EXT_PHY_PREEMPHASIS_D2_MASK 0x30 > + > +#define EXT_PHY_LEVEL1 0xf1 > +#define EXT_PHY_LEVEL_CLK_MASK 0xf0 > +#define EXT_PHY_LEVEL_D2_MASK 0x0f > + > +#define EXT_PHY_LEVEL2 0xf2 > +#define EXT_PHY_LEVEL_D1_MASK 0xf0 > +#define EXT_PHY_LEVEL_D0_MASK 0x0f > + > +#define EXT_PHY_TERM_RESIS_AUTO 0xf4 > +#define EXT_PHY_AUTO_R50_OHMS 0 > +#define EXT_PHY_AUTO_R75_OHMS (1 << 2) > +#define EXT_PHY_AUTO_R100_OHMS (2 << 2) > +#define EXT_PHY_AUTO_ROPEN_CIRCUIT (3 << 2) > + > +#define EXT_PHY_TERM_RESIS_MANUAL_CLK 0xfb > +#define EXT_PHY_TERM_RESIS_MANUAL_D2 0xfc > +#define EXT_PHY_TERM_RESIS_MANUAL_D1 0xfd > +#define EXT_PHY_TERM_RESIS_MANUAL_D0 0xfe > + > +#endif /* __DW_HDMI_ROCKCHIP__ */ > diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h > index bae79f3..44084e8 100644 > --- a/include/drm/bridge/dw_hdmi.h > +++ b/include/drm/bridge/dw_hdmi.h > @@ -24,6 +24,7 @@ enum { > enum dw_hdmi_devtype { > IMX6Q_HDMI, > IMX6DL_HDMI, > + RK3229_HDMI, > RK3288_HDMI, > }; > > @@ -52,8 +53,10 @@ struct dw_hdmi_plat_data { > const struct dw_hdmi_mpll_config *mpll_cfg; > const struct dw_hdmi_curr_ctrl *cur_ctr; > const struct dw_hdmi_phy_config *phy_config; > - enum drm_mode_status (*mode_valid)(struct drm_connector *connector, > + enum drm_mode_status (*mode_valid)(const struct dw_hdmi_plat_data *plat_data, > struct drm_display_mode *mode); > + int (*extphy_config)(struct dw_hdmi_plat_data *plat_data, > + int bpp, int pixelclock); > }; > > void dw_hdmi_unbind(struct device *dev, struct device *master, void *data);