From mboxrd@z Thu Jan 1 00:00:00 1970 From: yannick fertre Subject: [PATCH v2 03/10] video: add support of MIPI DSI interface Date: Fri, 2 Mar 2018 16:44:04 +0100 Message-ID: <1520005451-23217-4-git-send-email-yannick.fertre@st.com> References: <1520005451-23217-1-git-send-email-yannick.fertre@st.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from mx07-00178001.pphosted.com (mx08-00178001.pphosted.com [91.207.212.93]) by gabe.freedesktop.org (Postfix) with ESMTPS id 3D4B86E17E for ; Fri, 2 Mar 2018 15:44:34 +0000 (UTC) In-Reply-To: <1520005451-23217-1-git-send-email-yannick.fertre@st.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Vikas Manocha , Benjamin Gaignard , Yannick Fertre , Philippe Cornu , Patrice Chotard , Patrick DELAUNAY , Christophe KERELLO , Archit Taneja , Andrzej Hajda , Laurent Pinchart , David Airlie , Brian Norris , Bhumika Goyal , Gustavo Padovan , Maarten Lankhorst , Sean Paul , Albert Aribaud , Simon Glass , Anatolij Gustschin , Thierry Reding Cc: u-boot@lists.denx.de, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org List-Id: dri-devel@lists.freedesktop.org TWlwaV9kaXNwbGF5LmMgY29udGFpbnMgYSBzZXQgb2YgZHNpIGhlbHBlcnMuClRoaXMgZmlsZSBp cyBhIGNvcHkgb2YgZmlsZSBkcm1fbWlwaV9kc2kuYyAobGludXgga2VybmVsKS4KClNpZ25lZC1v ZmYtYnk6IHlhbm5pY2sgZmVydHJlIDx5YW5uaWNrLmZlcnRyZUBzdC5jb20+Ci0tLQogZHJpdmVy cy92aWRlby9LY29uZmlnICAgICAgICB8ICAgNyArCiBkcml2ZXJzL3ZpZGVvL01ha2VmaWxlICAg ICAgIHwgICAxICsKIGRyaXZlcnMvdmlkZW8vbWlwaV9kaXNwbGF5LmMgfCA4MDcgKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwogaW5jbHVkZS9taXBpX2Rpc3BsYXku aCAgICAgICB8IDI1NyArKysrKysrKysrKysrLQogNCBmaWxlcyBjaGFuZ2VkLCAxMDcxIGluc2Vy dGlvbnMoKyksIDEgZGVsZXRpb24oLSkKIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL3ZpZGVv L21pcGlfZGlzcGxheS5jCgpkaWZmIC0tZ2l0IGEvZHJpdmVycy92aWRlby9LY29uZmlnIGIvZHJp dmVycy92aWRlby9LY29uZmlnCmluZGV4IDJmYzBkZWYuLjE5ODEyOTggMTAwNjQ0Ci0tLSBhL2Ry aXZlcnMvdmlkZW8vS2NvbmZpZworKysgYi9kcml2ZXJzL3ZpZGVvL0tjb25maWcKQEAgLTc1LDYg Kzc1LDEzIEBAIGNvbmZpZyBWSURFT19BTlNJCiAJICBFbmFibGUgQU5TSSBlc2NhcGUgc2VxdWVu Y2UgZGVjb2RpbmcgZm9yIGEgbW9yZSBmdWxseSBmdW5jdGlvbmFsCiAJICBjb25zb2xlLgogCitj b25maWcgVklERU9fTUlQSV9EU0kKKwlib29sICJTdXBwb3J0IE1JUEkgRFNJIGludGVyZmFjZSIK KwlkZXBlbmRzIG9uIERNX1ZJREVPCisJZGVmYXVsdCB5IGlmIERNX1ZJREVPCisJaGVscAorCSAg U3VwcG9ydCBNSVBJIERTSSBpbnRlcmZhY2UgZm9yIGRyaXZpbmcgYSBNSVBJIGNvbXBhdGlibGUg TENEIHBhbmVsLgorCiBjb25maWcgQ09OU09MRV9OT1JNQUwKIAlib29sICJTdXBwb3J0IGEgc2lt cGxlIHRleHQgY29uc29sZSIKIAlkZXBlbmRzIG9uIERNX1ZJREVPCmRpZmYgLS1naXQgYS9kcml2 ZXJzL3ZpZGVvL01ha2VmaWxlIGIvZHJpdmVycy92aWRlby9NYWtlZmlsZQppbmRleCBkZmFmZTA4 Li42ZjQyY2NhIDEwMDY0NAotLS0gYS9kcml2ZXJzL3ZpZGVvL01ha2VmaWxlCisrKyBiL2RyaXZl cnMvdmlkZW8vTWFrZWZpbGUKQEAgLTUyLDYgKzUyLDcgQEAgb2JqLSQoQ09ORklHX0ZPUk1JS0Up ICs9IGZvcm1pa2Uubwogb2JqLSQoQ09ORklHX0xHNDU3MykgKz0gbGc0NTczLm8KIG9iai0kKENP TkZJR19BTTMzNVhfTENEKSArPSBhbTMzNXgtZmIubwogb2JqLSQoQ09ORklHX1ZJREVPX0RXX0hE TUkpICs9IGR3X2hkbWkubworb2JqLSR7Q09ORklHX1ZJREVPX01JUElfRFNJfSArPSBtaXBpX2Rp c3BsYXkubwogb2JqLSQoQ09ORklHX1ZJREVPX1NJTVBMRSkgKz0gc2ltcGxlZmIubwogb2JqLSR7 Q09ORklHX1ZJREVPX1RFR1JBMTI0fSArPSB0ZWdyYTEyNC8KIG9iai0ke0NPTkZJR19FWFlOT1Nf RkJ9ICs9IGV4eW5vcy8KZGlmZiAtLWdpdCBhL2RyaXZlcnMvdmlkZW8vbWlwaV9kaXNwbGF5LmMg Yi9kcml2ZXJzL3ZpZGVvL21pcGlfZGlzcGxheS5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4 IDAwMDAwMDAuLmQ5MGZmNWQKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL3ZpZGVvL21pcGlf ZGlzcGxheS5jCkBAIC0wLDAgKzEsODA3IEBACisvKgorICogTUlQSSBEU0kgQnVzCisgKgorICog Q29weXJpZ2h0IChDKSAyMDEyLTIwMTMsIFNhbXN1bmcgRWxlY3Ryb25pY3MsIENvLiwgTHRkLgor ICogQ29weXJpZ2h0IChDKSAyMDE4IFNUTWljcm9lbGVjdHJvbmljcyAtIEFsbCBSaWdodHMgUmVz ZXJ2ZWQKKyAqIEFuZHJ6ZWogSGFqZGEgPGEuaGFqZGFAc2Ftc3VuZy5jb20+CisgKgorICogUGVy bWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24g b2J0YWluaW5nIGEKKyAqIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1 bWVudGF0aW9uIGZpbGVzICh0aGUKKyAqICJTb2Z0d2FyZSIpLCB0byBkZWFsIGluIHRoZSBTb2Z0 d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcKKyAqIHdpdGhvdXQgbGltaXRhdGlv biB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwKKyAqIGRp c3RyaWJ1dGUsIHN1YiBsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJl LCBhbmQgdG8KKyAqIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5p c2hlZCB0byBkbyBzbywgc3ViamVjdCB0bworICogdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgor ICoKKyAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90 aWNlIChpbmNsdWRpbmcgdGhlCisgKiBuZXh0IHBhcmFncmFwaCkgc2hhbGwgYmUgaW5jbHVkZWQg aW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucworICogb2YgdGhlIFNvZnR3YXJl LgorICoKKyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdBUlJB TlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCisgKiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5P VCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKKyAqIEZJVE5F U1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT04tSU5GUklOR0VNRU5ULiBJTiBOTyBF VkVOVCBTSEFMTAorICogVEhFIENPUFlSSUdIVCBIT0xERVJTLCBBVVRIT1JTIEFORC9PUiBJVFMg U1VQUExJRVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLAorICogREFNQUdFUyBPUiBPVEhFUiBM SUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SCisgKiBP VEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUg U09GVFdBUkUgT1IgVEhFCisgKiBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJF LgorICovCisKKyNpbmNsdWRlIDxjb21tb24uaD4KKyNpbmNsdWRlIDxjbGsuaD4KKyNpbmNsdWRl IDxkaXNwbGF5Lmg+CisjaW5jbHVkZSA8ZG0uaD4KKyNpbmNsdWRlIDxtaXBpX2Rpc3BsYXkuaD4K KworLyoqCisgKiBET0M6IGRzaSBoZWxwZXJzCisgKgorICogVGhlc2UgZnVuY3Rpb25zIGNvbnRh aW4gc29tZSBjb21tb24gbG9naWMgYW5kIGhlbHBlcnMgdG8gZGVhbCB3aXRoIE1JUEkgRFNJCisg KiBwZXJpcGhlcmFscy4KKyAqCisgKiBIZWxwZXJzIGFyZSBwcm92aWRlZCBmb3IgYSBudW1iZXIg b2Ygc3RhbmRhcmQgTUlQSSBEU0kgY29tbWFuZCBhcyB3ZWxsIGFzIGEKKyAqIHN1YnNldCBvZiB0 aGUgTUlQSSBEQ1MgY29tbWFuZCBzZXQuCisgKi8KKworLyoqCisgKiBtaXBpX2RzaV9hdHRhY2gg LSBhdHRhY2ggYSBEU0kgZGV2aWNlIHRvIGl0cyBEU0kgaG9zdAorICogQGRzaTogRFNJIHBlcmlw aGVyYWwKKyAqLworaW50IG1pcGlfZHNpX2F0dGFjaChzdHJ1Y3QgbWlwaV9kc2lfZGV2aWNlICpk c2kpCit7CisJY29uc3Qgc3RydWN0IG1pcGlfZHNpX2hvc3Rfb3BzICpvcHMgPSBkc2ktPmhvc3Qt Pm9wczsKKworCWlmICghb3BzIHx8ICFvcHMtPmF0dGFjaCkKKwkJcmV0dXJuIC1FTk9TWVM7CisK KwlyZXR1cm4gb3BzLT5hdHRhY2goZHNpLT5ob3N0LCBkc2kpOworfQorRVhQT1JUX1NZTUJPTCht aXBpX2RzaV9hdHRhY2gpOworCisvKioKKyAqIG1pcGlfZHNpX2RldGFjaCAtIGRldGFjaCBhIERT SSBkZXZpY2UgZnJvbSBpdHMgRFNJIGhvc3QKKyAqIEBkc2k6IERTSSBwZXJpcGhlcmFsCisgKi8K K2ludCBtaXBpX2RzaV9kZXRhY2goc3RydWN0IG1pcGlfZHNpX2RldmljZSAqZHNpKQoreworCWNv bnN0IHN0cnVjdCBtaXBpX2RzaV9ob3N0X29wcyAqb3BzID0gZHNpLT5ob3N0LT5vcHM7CisKKwlp ZiAoIW9wcyB8fCAhb3BzLT5kZXRhY2gpCisJCXJldHVybiAtRU5PU1lTOworCisJcmV0dXJuIG9w cy0+ZGV0YWNoKGRzaS0+aG9zdCwgZHNpKTsKK30KK0VYUE9SVF9TWU1CT0wobWlwaV9kc2lfZGV0 YWNoKTsKKworc3RhdGljIHNzaXplX3QgbWlwaV9kc2lfZGV2aWNlX3RyYW5zZmVyKHN0cnVjdCBt aXBpX2RzaV9kZXZpY2UgKmRzaSwKKwkJCQkJc3RydWN0IG1pcGlfZHNpX21zZyAqbXNnKQorewor CWNvbnN0IHN0cnVjdCBtaXBpX2RzaV9ob3N0X29wcyAqb3BzID0gZHNpLT5ob3N0LT5vcHM7CisK KwlpZiAoIW9wcyB8fCAhb3BzLT50cmFuc2ZlcikKKwkJcmV0dXJuIC1FTk9TWVM7CisKKwlpZiAo ZHNpLT5tb2RlX2ZsYWdzICYgTUlQSV9EU0lfTU9ERV9MUE0pCisJCW1zZy0+ZmxhZ3MgfD0gTUlQ SV9EU0lfTVNHX1VTRV9MUE07CisKKwlyZXR1cm4gb3BzLT50cmFuc2Zlcihkc2ktPmhvc3QsIG1z Zyk7Cit9CisKKy8qKgorICogbWlwaV9kc2lfcGFja2V0X2Zvcm1hdF9pc19zaG9ydCAtIGNoZWNr IGlmIGEgcGFja2V0IGlzIG9mIHRoZSBzaG9ydCBmb3JtYXQKKyAqIEB0eXBlOiBNSVBJIERTSSBk YXRhIHR5cGUgb2YgdGhlIHBhY2tldAorICoKKyAqIFJldHVybjogdHJ1ZSBpZiB0aGUgcGFja2V0 IGZvciB0aGUgZ2l2ZW4gZGF0YSB0eXBlIGlzIGEgc2hvcnQgcGFja2V0LCBmYWxzZQorICogb3Ro ZXJ3aXNlLgorICovCitib29sIG1pcGlfZHNpX3BhY2tldF9mb3JtYXRfaXNfc2hvcnQodTggdHlw ZSkKK3sKKwlzd2l0Y2ggKHR5cGUpIHsKKwljYXNlIE1JUElfRFNJX1ZfU1lOQ19TVEFSVDoKKwlj YXNlIE1JUElfRFNJX1ZfU1lOQ19FTkQ6CisJY2FzZSBNSVBJX0RTSV9IX1NZTkNfU1RBUlQ6CisJ Y2FzZSBNSVBJX0RTSV9IX1NZTkNfRU5EOgorCWNhc2UgTUlQSV9EU0lfRU5EX09GX1RSQU5TTUlT U0lPTjoKKwljYXNlIE1JUElfRFNJX0NPTE9SX01PREVfT0ZGOgorCWNhc2UgTUlQSV9EU0lfQ09M T1JfTU9ERV9PTjoKKwljYXNlIE1JUElfRFNJX1NIVVRET1dOX1BFUklQSEVSQUw6CisJY2FzZSBN SVBJX0RTSV9UVVJOX09OX1BFUklQSEVSQUw6CisJY2FzZSBNSVBJX0RTSV9HRU5FUklDX1NIT1JU X1dSSVRFXzBfUEFSQU06CisJY2FzZSBNSVBJX0RTSV9HRU5FUklDX1NIT1JUX1dSSVRFXzFfUEFS QU06CisJY2FzZSBNSVBJX0RTSV9HRU5FUklDX1NIT1JUX1dSSVRFXzJfUEFSQU06CisJY2FzZSBN SVBJX0RTSV9HRU5FUklDX1JFQURfUkVRVUVTVF8wX1BBUkFNOgorCWNhc2UgTUlQSV9EU0lfR0VO RVJJQ19SRUFEX1JFUVVFU1RfMV9QQVJBTToKKwljYXNlIE1JUElfRFNJX0dFTkVSSUNfUkVBRF9S RVFVRVNUXzJfUEFSQU06CisJY2FzZSBNSVBJX0RTSV9EQ1NfU0hPUlRfV1JJVEU6CisJY2FzZSBN SVBJX0RTSV9EQ1NfU0hPUlRfV1JJVEVfUEFSQU06CisJY2FzZSBNSVBJX0RTSV9EQ1NfUkVBRDoK KwljYXNlIE1JUElfRFNJX1NFVF9NQVhJTVVNX1JFVFVSTl9QQUNLRVRfU0laRToKKwkJcmV0dXJu IHRydWU7CisJfQorCisJcmV0dXJuIGZhbHNlOworfQorRVhQT1JUX1NZTUJPTChtaXBpX2RzaV9w YWNrZXRfZm9ybWF0X2lzX3Nob3J0KTsKKworLyoqCisgKiBtaXBpX2RzaV9wYWNrZXRfZm9ybWF0 X2lzX2xvbmcgLSBjaGVjayBpZiBhIHBhY2tldCBpcyBvZiB0aGUgbG9uZyBmb3JtYXQKKyAqIEB0 eXBlOiBNSVBJIERTSSBkYXRhIHR5cGUgb2YgdGhlIHBhY2tldAorICoKKyAqIFJldHVybjogdHJ1 ZSBpZiB0aGUgcGFja2V0IGZvciB0aGUgZ2l2ZW4gZGF0YSB0eXBlIGlzIGEgbG9uZyBwYWNrZXQs IGZhbHNlCisgKiBvdGhlcndpc2UuCisgKi8KK2Jvb2wgbWlwaV9kc2lfcGFja2V0X2Zvcm1hdF9p c19sb25nKHU4IHR5cGUpCit7CisJc3dpdGNoICh0eXBlKSB7CisJY2FzZSBNSVBJX0RTSV9OVUxM X1BBQ0tFVDoKKwljYXNlIE1JUElfRFNJX0JMQU5LSU5HX1BBQ0tFVDoKKwljYXNlIE1JUElfRFNJ X0dFTkVSSUNfTE9OR19XUklURToKKwljYXNlIE1JUElfRFNJX0RDU19MT05HX1dSSVRFOgorCWNh c2UgTUlQSV9EU0lfTE9PU0VMWV9QQUNLRURfUElYRUxfU1RSRUFNX1lDQkNSMjA6CisJY2FzZSBN SVBJX0RTSV9QQUNLRURfUElYRUxfU1RSRUFNX1lDQkNSMjQ6CisJY2FzZSBNSVBJX0RTSV9QQUNL RURfUElYRUxfU1RSRUFNX1lDQkNSMTY6CisJY2FzZSBNSVBJX0RTSV9QQUNLRURfUElYRUxfU1RS RUFNXzMwOgorCWNhc2UgTUlQSV9EU0lfUEFDS0VEX1BJWEVMX1NUUkVBTV8zNjoKKwljYXNlIE1J UElfRFNJX1BBQ0tFRF9QSVhFTF9TVFJFQU1fWUNCQ1IxMjoKKwljYXNlIE1JUElfRFNJX1BBQ0tF RF9QSVhFTF9TVFJFQU1fMTY6CisJY2FzZSBNSVBJX0RTSV9QQUNLRURfUElYRUxfU1RSRUFNXzE4 OgorCWNhc2UgTUlQSV9EU0lfUElYRUxfU1RSRUFNXzNCWVRFXzE4OgorCWNhc2UgTUlQSV9EU0lf UEFDS0VEX1BJWEVMX1NUUkVBTV8yNDoKKwkJcmV0dXJuIHRydWU7CisJfQorCisJcmV0dXJuIGZh bHNlOworfQorRVhQT1JUX1NZTUJPTChtaXBpX2RzaV9wYWNrZXRfZm9ybWF0X2lzX2xvbmcpOwor CisvKioKKyAqIG1pcGlfZHNpX2NyZWF0ZV9wYWNrZXQgLSBjcmVhdGUgYSBwYWNrZXQgZnJvbSBh IG1lc3NhZ2UgYWNjb3JkaW5nIHRvIHRoZQorICogICAgIERTSSBwcm90b2NvbAorICogQHBhY2tl dDogcG9pbnRlciB0byBhIERTSSBwYWNrZXQgc3RydWN0dXJlCisgKiBAbXNnOiBtZXNzYWdlIHRv IHRyYW5zbGF0ZSBpbnRvIGEgcGFja2V0CisgKgorICogUmV0dXJuOiAwIG9uIHN1Y2Nlc3Mgb3Ig YSBuZWdhdGl2ZSBlcnJvciBjb2RlIG9uIGZhaWx1cmUuCisgKi8KK2ludCBtaXBpX2RzaV9jcmVh dGVfcGFja2V0KHN0cnVjdCBtaXBpX2RzaV9wYWNrZXQgKnBhY2tldCwKKwkJCSAgIGNvbnN0IHN0 cnVjdCBtaXBpX2RzaV9tc2cgKm1zZykKK3sKKwlpZiAoIXBhY2tldCB8fCAhbXNnKQorCQlyZXR1 cm4gLUVJTlZBTDsKKworCS8qIGRvIHNvbWUgbWluaW11bSBzYW5pdHkgY2hlY2tpbmcgKi8KKwlp ZiAoIW1pcGlfZHNpX3BhY2tldF9mb3JtYXRfaXNfc2hvcnQobXNnLT50eXBlKSAmJgorCSAgICAh bWlwaV9kc2lfcGFja2V0X2Zvcm1hdF9pc19sb25nKG1zZy0+dHlwZSkpCisJCXJldHVybiAtRUlO VkFMOworCisJaWYgKG1zZy0+Y2hhbm5lbCA+IDMpCisJCXJldHVybiAtRUlOVkFMOworCisJbWVt c2V0KHBhY2tldCwgMCwgc2l6ZW9mKCpwYWNrZXQpKTsKKwlwYWNrZXQtPmhlYWRlclswXSA9ICgo bXNnLT5jaGFubmVsICYgMHgzKSA8PCA2KSB8IChtc2ctPnR5cGUgJiAweDNmKTsKKworCS8qIFRP RE86IGNvbXB1dGUgRUNDIGlmIGhhcmR3YXJlIHN1cHBvcnQgaXMgbm90IGF2YWlsYWJsZSAqLwor CisJLyoKKwkgKiBMb25nIHdyaXRlIHBhY2tldHMgY29udGFpbiB0aGUgd29yZCBjb3VudCBpbiBo ZWFkZXIgYnl0ZXMgMSBhbmQgMi4KKwkgKiBUaGUgcGF5bG9hZCBmb2xsb3dzIHRoZSBoZWFkZXIg YW5kIGlzIHdvcmQgY291bnQgYnl0ZXMgbG9uZy4KKwkgKgorCSAqIFNob3J0IHdyaXRlIHBhY2tl dHMgZW5jb2RlIHVwIHRvIHR3byBwYXJhbWV0ZXJzIGluIGhlYWRlciBieXRlcyAxCisJICogYW5k IDIuCisJICovCisJaWYgKG1pcGlfZHNpX3BhY2tldF9mb3JtYXRfaXNfbG9uZyhtc2ctPnR5cGUp KSB7CisJCXBhY2tldC0+aGVhZGVyWzFdID0gKG1zZy0+dHhfbGVuID4+IDApICYgMHhmZjsKKwkJ cGFja2V0LT5oZWFkZXJbMl0gPSAobXNnLT50eF9sZW4gPj4gOCkgJiAweGZmOworCisJCXBhY2tl dC0+cGF5bG9hZF9sZW5ndGggPSBtc2ctPnR4X2xlbjsKKwkJcGFja2V0LT5wYXlsb2FkID0gbXNn LT50eF9idWY7CisJfSBlbHNlIHsKKwkJY29uc3QgdTggKnR4ID0gbXNnLT50eF9idWY7CisKKwkJ cGFja2V0LT5oZWFkZXJbMV0gPSAobXNnLT50eF9sZW4gPiAwKSA/IHR4WzBdIDogMDsKKwkJcGFj a2V0LT5oZWFkZXJbMl0gPSAobXNnLT50eF9sZW4gPiAxKSA/IHR4WzFdIDogMDsKKwl9CisKKwlw YWNrZXQtPnNpemUgPSBzaXplb2YocGFja2V0LT5oZWFkZXIpICsgcGFja2V0LT5wYXlsb2FkX2xl bmd0aDsKKworCXJldHVybiAwOworfQorRVhQT1JUX1NZTUJPTChtaXBpX2RzaV9jcmVhdGVfcGFj a2V0KTsKKworLyoKKyAqIG1pcGlfZHNpX3NldF9tYXhpbXVtX3JldHVybl9wYWNrZXRfc2l6ZSgp IC0gc3BlY2lmeSB0aGUgbWF4aW11bSBzaXplIG9mIHRoZQorICogICAgdGhlIHBheWxvYWQgaW4g YSBsb25nIHBhY2tldCB0cmFuc21pdHRlZCBmcm9tIHRoZSBwZXJpcGhlcmFsIGJhY2sgdG8gdGhl CisgKiAgICBob3N0IHByb2Nlc3NvcgorICogQGRzaTogRFNJIHBlcmlwaGVyYWwgZGV2aWNlCisg KiBAdmFsdWU6IHRoZSBtYXhpbXVtIHNpemUgb2YgdGhlIHBheWxvYWQKKyAqCisgKiBSZXR1cm46 IDAgb24gc3VjY2VzcyBvciBhIG5lZ2F0aXZlIGVycm9yIGNvZGUgb24gZmFpbHVyZS4KKyAqLwor aW50IG1pcGlfZHNpX3NldF9tYXhpbXVtX3JldHVybl9wYWNrZXRfc2l6ZShzdHJ1Y3QgbWlwaV9k c2lfZGV2aWNlICpkc2ksCisJCQkJCSAgICB1MTYgdmFsdWUpCit7CisJdTggdHhbMl0gPSB7IHZh bHVlICYgMHhmZiwgdmFsdWUgPj4gOCB9OworCXN0cnVjdCBtaXBpX2RzaV9tc2cgbXNnID0gewor CQkuY2hhbm5lbCA9IGRzaS0+Y2hhbm5lbCwKKwkJLnR5cGUgPSBNSVBJX0RTSV9TRVRfTUFYSU1V TV9SRVRVUk5fUEFDS0VUX1NJWkUsCisJCS50eF9sZW4gPSBzaXplb2YodHgpLAorCQkudHhfYnVm ID0gdHgsCisJfTsKKwlpbnQgcmV0ID0gbWlwaV9kc2lfZGV2aWNlX3RyYW5zZmVyKGRzaSwgJm1z Zyk7CisKKwlyZXR1cm4gKHJldCA8IDApID8gcmV0IDogMDsKK30KK0VYUE9SVF9TWU1CT0wobWlw aV9kc2lfc2V0X21heGltdW1fcmV0dXJuX3BhY2tldF9zaXplKTsKKworLyoqCisgKiBtaXBpX2Rz aV9nZW5lcmljX3dyaXRlKCkgLSB0cmFuc21pdCBkYXRhIHVzaW5nIGEgZ2VuZXJpYyB3cml0ZSBw YWNrZXQKKyAqIEBkc2k6IERTSSBwZXJpcGhlcmFsIGRldmljZQorICogQHBheWxvYWQ6IGJ1ZmZl ciBjb250YWluaW5nIHRoZSBwYXlsb2FkCisgKiBAc2l6ZTogc2l6ZSBvZiBwYXlsb2FkIGJ1ZmZl cgorICoKKyAqIFRoaXMgZnVuY3Rpb24gd2lsbCBhdXRvbWF0aWNhbGx5IGNob29zZSB0aGUgcmln aHQgZGF0YSB0eXBlIGRlcGVuZGluZyBvbgorICogdGhlIHBheWxvYWQgbGVuZ3RoLgorICoKKyAq IFJldHVybjogVGhlIG51bWJlciBvZiBieXRlcyB0cmFuc21pdHRlZCBvbiBzdWNjZXNzIG9yIGEg bmVnYXRpdmUgZXJyb3IgY29kZQorICogb24gZmFpbHVyZS4KKyAqLworc3NpemVfdCBtaXBpX2Rz aV9nZW5lcmljX3dyaXRlKHN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRzaSwgY29uc3Qgdm9pZCAq cGF5bG9hZCwKKwkJCSAgICAgICBzaXplX3Qgc2l6ZSkKK3sKKwlzdHJ1Y3QgbWlwaV9kc2lfbXNn IG1zZyA9IHsKKwkJLmNoYW5uZWwgPSBkc2ktPmNoYW5uZWwsCisJCS50eF9idWYgPSBwYXlsb2Fk LAorCQkudHhfbGVuID0gc2l6ZQorCX07CisKKwlzd2l0Y2ggKHNpemUpIHsKKwljYXNlIDA6CisJ CW1zZy50eXBlID0gTUlQSV9EU0lfR0VORVJJQ19TSE9SVF9XUklURV8wX1BBUkFNOworCQlicmVh azsKKworCWNhc2UgMToKKwkJbXNnLnR5cGUgPSBNSVBJX0RTSV9HRU5FUklDX1NIT1JUX1dSSVRF XzFfUEFSQU07CisJCWJyZWFrOworCisJY2FzZSAyOgorCQltc2cudHlwZSA9IE1JUElfRFNJX0dF TkVSSUNfU0hPUlRfV1JJVEVfMl9QQVJBTTsKKwkJYnJlYWs7CisKKwlkZWZhdWx0OgorCQltc2cu dHlwZSA9IE1JUElfRFNJX0dFTkVSSUNfTE9OR19XUklURTsKKwkJYnJlYWs7CisJfQorCisJcmV0 dXJuIG1pcGlfZHNpX2RldmljZV90cmFuc2Zlcihkc2ksICZtc2cpOworfQorRVhQT1JUX1NZTUJP TChtaXBpX2RzaV9nZW5lcmljX3dyaXRlKTsKKworLyoqCisgKiBtaXBpX2RzaV9nZW5lcmljX3Jl YWQoKSAtIHJlY2VpdmUgZGF0YSB1c2luZyBhIGdlbmVyaWMgcmVhZCBwYWNrZXQKKyAqIEBkc2k6 IERTSSBwZXJpcGhlcmFsIGRldmljZQorICogQHBhcmFtczogYnVmZmVyIGNvbnRhaW5pbmcgdGhl IHJlcXVlc3QgcGFyYW1ldGVycworICogQG51bV9wYXJhbXM6IG51bWJlciBvZiByZXF1ZXN0IHBh cmFtZXRlcnMKKyAqIEBkYXRhOiBidWZmZXIgaW4gd2hpY2ggdG8gcmV0dXJuIHRoZSByZWNlaXZl ZCBkYXRhCisgKiBAc2l6ZTogc2l6ZSBvZiByZWNlaXZlIGJ1ZmZlcgorICoKKyAqIFRoaXMgZnVu Y3Rpb24gd2lsbCBhdXRvbWF0aWNhbGx5IGNob29zZSB0aGUgcmlnaHQgZGF0YSB0eXBlIGRlcGVu ZGluZyBvbgorICogdGhlIG51bWJlciBvZiBwYXJhbWV0ZXJzIHBhc3NlZCBpbi4KKyAqCisgKiBS ZXR1cm46IFRoZSBudW1iZXIgb2YgYnl0ZXMgc3VjY2Vzc2Z1bGx5IHJlYWQgb3IgYSBuZWdhdGl2 ZSBlcnJvciBjb2RlIG9uCisgKiBmYWlsdXJlLgorICovCitzc2l6ZV90IG1pcGlfZHNpX2dlbmVy aWNfcmVhZChzdHJ1Y3QgbWlwaV9kc2lfZGV2aWNlICpkc2ksIGNvbnN0IHZvaWQgKnBhcmFtcywK KwkJCSAgICAgIHNpemVfdCBudW1fcGFyYW1zLCB2b2lkICpkYXRhLCBzaXplX3Qgc2l6ZSkKK3sK KwlzdHJ1Y3QgbWlwaV9kc2lfbXNnIG1zZyA9IHsKKwkJLmNoYW5uZWwgPSBkc2ktPmNoYW5uZWws CisJCS50eF9sZW4gPSBudW1fcGFyYW1zLAorCQkudHhfYnVmID0gcGFyYW1zLAorCQkucnhfbGVu ID0gc2l6ZSwKKwkJLnJ4X2J1ZiA9IGRhdGEKKwl9OworCisJc3dpdGNoIChudW1fcGFyYW1zKSB7 CisJY2FzZSAwOgorCQltc2cudHlwZSA9IE1JUElfRFNJX0dFTkVSSUNfUkVBRF9SRVFVRVNUXzBf UEFSQU07CisJCWJyZWFrOworCisJY2FzZSAxOgorCQltc2cudHlwZSA9IE1JUElfRFNJX0dFTkVS SUNfUkVBRF9SRVFVRVNUXzFfUEFSQU07CisJCWJyZWFrOworCisJY2FzZSAyOgorCQltc2cudHlw ZSA9IE1JUElfRFNJX0dFTkVSSUNfUkVBRF9SRVFVRVNUXzJfUEFSQU07CisJCWJyZWFrOworCisJ ZGVmYXVsdDoKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJcmV0dXJuIG1pcGlfZHNpX2Rldmlj ZV90cmFuc2Zlcihkc2ksICZtc2cpOworfQorRVhQT1JUX1NZTUJPTChtaXBpX2RzaV9nZW5lcmlj X3JlYWQpOworCisvKioKKyAqIG1pcGlfZHNpX2Rjc193cml0ZV9idWZmZXIoKSAtIHRyYW5zbWl0 IGEgRENTIGNvbW1hbmQgd2l0aCBwYXlsb2FkCisgKiBAZHNpOiBEU0kgcGVyaXBoZXJhbCBkZXZp Y2UKKyAqIEBkYXRhOiBidWZmZXIgY29udGFpbmluZyBkYXRhIHRvIGJlIHRyYW5zbWl0dGVkCisg KiBAbGVuOiBzaXplIG9mIHRyYW5zbWlzc2lvbiBidWZmZXIKKyAqCisgKiBUaGlzIGZ1bmN0aW9u IHdpbGwgYXV0b21hdGljYWxseSBjaG9vc2UgdGhlIHJpZ2h0IGRhdGEgdHlwZSBkZXBlbmRpbmcg b24KKyAqIHRoZSBjb21tYW5kIHBheWxvYWQgbGVuZ3RoLgorICoKKyAqIFJldHVybjogVGhlIG51 bWJlciBvZiBieXRlcyBzdWNjZXNzZnVsbHkgdHJhbnNtaXR0ZWQgb3IgYSBuZWdhdGl2ZSBlcnJv cgorICogY29kZSBvbiBmYWlsdXJlLgorICovCitzc2l6ZV90IG1pcGlfZHNpX2Rjc193cml0ZV9i dWZmZXIoc3RydWN0IG1pcGlfZHNpX2RldmljZSAqZHNpLAorCQkJCSAgY29uc3Qgdm9pZCAqZGF0 YSwgc2l6ZV90IGxlbikKK3sKKwlzdHJ1Y3QgbWlwaV9kc2lfbXNnIG1zZyA9IHsKKwkJLmNoYW5u ZWwgPSBkc2ktPmNoYW5uZWwsCisJCS50eF9idWYgPSBkYXRhLAorCQkudHhfbGVuID0gbGVuCisJ fTsKKworCXN3aXRjaCAobGVuKSB7CisJY2FzZSAwOgorCQlyZXR1cm4gLUVJTlZBTDsKKworCWNh c2UgMToKKwkJbXNnLnR5cGUgPSBNSVBJX0RTSV9EQ1NfU0hPUlRfV1JJVEU7CisJCWJyZWFrOwor CisJY2FzZSAyOgorCQltc2cudHlwZSA9IE1JUElfRFNJX0RDU19TSE9SVF9XUklURV9QQVJBTTsK KwkJYnJlYWs7CisKKwlkZWZhdWx0OgorCQltc2cudHlwZSA9IE1JUElfRFNJX0RDU19MT05HX1dS SVRFOworCQlicmVhazsKKwl9CisKKwlyZXR1cm4gbWlwaV9kc2lfZGV2aWNlX3RyYW5zZmVyKGRz aSwgJm1zZyk7Cit9CitFWFBPUlRfU1lNQk9MKG1pcGlfZHNpX2Rjc193cml0ZV9idWZmZXIpOwor CisvKioKKyAqIG1pcGlfZHNpX2Rjc193cml0ZSgpIC0gc2VuZCBEQ1Mgd3JpdGUgY29tbWFuZAor ICogQGRzaTogRFNJIHBlcmlwaGVyYWwgZGV2aWNlCisgKiBAY21kOiBEQ1MgY29tbWFuZAorICog QGRhdGE6IGJ1ZmZlciBjb250YWluaW5nIHRoZSBjb21tYW5kIHBheWxvYWQKKyAqIEBsZW46IGNv bW1hbmQgcGF5bG9hZCBsZW5ndGgKKyAqCisgKiBUaGlzIGZ1bmN0aW9uIHdpbGwgYXV0b21hdGlj YWxseSBjaG9vc2UgdGhlIHJpZ2h0IGRhdGEgdHlwZSBkZXBlbmRpbmcgb24KKyAqIHRoZSBjb21t YW5kIHBheWxvYWQgbGVuZ3RoLgorICoKKyAqIFJldHVybjogVGhlIG51bWJlciBvZiBieXRlcyBz dWNjZXNzZnVsbHkgdHJhbnNtaXR0ZWQgb3IgYSBuZWdhdGl2ZSBlcnJvcgorICogY29kZSBvbiBm YWlsdXJlLgorICovCitzc2l6ZV90IG1pcGlfZHNpX2Rjc193cml0ZShzdHJ1Y3QgbWlwaV9kc2lf ZGV2aWNlICpkc2ksIHU4IGNtZCwKKwkJCSAgIGNvbnN0IHZvaWQgKmRhdGEsIHNpemVfdCBsZW4p Cit7CisJc3NpemVfdCBlcnI7CisJc2l6ZV90IHNpemU7CisJdTggKnR4OworCisJaWYgKGxlbiA+ IDApIHsKKwkJc2l6ZSA9IDEgKyBsZW47CisKKwkJdHggPSBrbWFsbG9jKHNpemUsIEdGUF9LRVJO RUwpOworCQlpZiAoIXR4KQorCQkJcmV0dXJuIC1FTk9NRU07CisKKwkJLyogY29uY2F0ZW5hdGUg dGhlIERDUyBjb21tYW5kIGJ5dGUgYW5kIHRoZSBwYXlsb2FkICovCisJCXR4WzBdID0gY21kOwor CQltZW1jcHkoJnR4WzFdLCBkYXRhLCBsZW4pOworCX0gZWxzZSB7CisJCXR4ID0gJmNtZDsKKwkJ c2l6ZSA9IDE7CisJfQorCisJZXJyID0gbWlwaV9kc2lfZGNzX3dyaXRlX2J1ZmZlcihkc2ksIHR4 LCBzaXplKTsKKworCWlmIChsZW4gPiAwKQorCQlrZnJlZSh0eCk7CisKKwlyZXR1cm4gZXJyOwor fQorRVhQT1JUX1NZTUJPTChtaXBpX2RzaV9kY3Nfd3JpdGUpOworCisvKioKKyAqIG1pcGlfZHNp X2Rjc19yZWFkKCkgLSBzZW5kIERDUyByZWFkIHJlcXVlc3QgY29tbWFuZAorICogQGRzaTogRFNJ IHBlcmlwaGVyYWwgZGV2aWNlCisgKiBAY21kOiBEQ1MgY29tbWFuZAorICogQGRhdGE6IGJ1ZmZl ciBpbiB3aGljaCB0byByZWNlaXZlIGRhdGEKKyAqIEBsZW46IHNpemUgb2YgcmVjZWl2ZSBidWZm ZXIKKyAqCisgKiBSZXR1cm46IFRoZSBudW1iZXIgb2YgYnl0ZXMgcmVhZCBvciBhIG5lZ2F0aXZl IGVycm9yIGNvZGUgb24gZmFpbHVyZS4KKyAqLworc3NpemVfdCBtaXBpX2RzaV9kY3NfcmVhZChz dHJ1Y3QgbWlwaV9kc2lfZGV2aWNlICpkc2ksIHU4IGNtZCwgdm9pZCAqZGF0YSwKKwkJCSAgc2l6 ZV90IGxlbikKK3sKKwlzdHJ1Y3QgbWlwaV9kc2lfbXNnIG1zZyA9IHsKKwkJLmNoYW5uZWwgPSBk c2ktPmNoYW5uZWwsCisJCS50eXBlID0gTUlQSV9EU0lfRENTX1JFQUQsCisJCS50eF9idWYgPSAm Y21kLAorCQkudHhfbGVuID0gMSwKKwkJLnJ4X2J1ZiA9IGRhdGEsCisJCS5yeF9sZW4gPSBsZW4K Kwl9OworCisJcmV0dXJuIG1pcGlfZHNpX2RldmljZV90cmFuc2Zlcihkc2ksICZtc2cpOworfQor RVhQT1JUX1NZTUJPTChtaXBpX2RzaV9kY3NfcmVhZCk7CisKKy8qKgorICogbWlwaV9kc2lfcGl4 ZWxfZm9ybWF0X3RvX2JwcCAtIG9idGFpbiB0aGUgbnVtYmVyIG9mIGJpdHMgcGVyIHBpeGVsIGZv ciBhbnkKKyAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnaXZlbiBwaXhlbCBmb3Jt YXQgZGVmaW5lZCBieSB0aGUgTUlQSSBEU0kKKyAqICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICBzcGVjaWZpY2F0aW9uCisgKiBAZm10OiBNSVBJIERTSSBwaXhlbCBmb3JtYXQKKyAqCisg KiBSZXR1cm5zOiBUaGUgbnVtYmVyIG9mIGJpdHMgcGVyIHBpeGVsIG9mIHRoZSBnaXZlbiBwaXhl bCBmb3JtYXQuCisgKi8KK2ludCBtaXBpX2RzaV9waXhlbF9mb3JtYXRfdG9fYnBwKGVudW0gbWlw aV9kc2lfcGl4ZWxfZm9ybWF0IGZtdCkKK3sKKwlzd2l0Y2ggKGZtdCkgeworCWNhc2UgTUlQSV9E U0lfRk1UX1JHQjg4ODoKKwljYXNlIE1JUElfRFNJX0ZNVF9SR0I2NjY6CisJCXJldHVybiAyNDsK KworCWNhc2UgTUlQSV9EU0lfRk1UX1JHQjY2Nl9QQUNLRUQ6CisJCXJldHVybiAxODsKKworCWNh c2UgTUlQSV9EU0lfRk1UX1JHQjU2NToKKwkJcmV0dXJuIDE2OworCX0KKworCXJldHVybiAtRUlO VkFMOworfQorRVhQT1JUX1NZTUJPTChtaXBpX2RzaV9waXhlbF9mb3JtYXRfdG9fYnBwKTsKKwor LyoqCisgKiBtaXBpX2RzaV9kY3Nfbm9wKCkgLSBzZW5kIERDUyBub3AgcGFja2V0CisgKiBAZHNp OiBEU0kgcGVyaXBoZXJhbCBkZXZpY2UKKyAqCisgKiBSZXR1cm46IDAgb24gc3VjY2VzcyBvciBh IG5lZ2F0aXZlIGVycm9yIGNvZGUgb24gZmFpbHVyZS4KKyAqLworaW50IG1pcGlfZHNpX2Rjc19u b3Aoc3RydWN0IG1pcGlfZHNpX2RldmljZSAqZHNpKQoreworCXNzaXplX3QgZXJyOworCisJZXJy ID0gbWlwaV9kc2lfZGNzX3dyaXRlKGRzaSwgTUlQSV9EQ1NfTk9QLCBOVUxMLCAwKTsKKwlpZiAo ZXJyIDwgMCkKKwkJcmV0dXJuIGVycjsKKworCXJldHVybiAwOworfQorRVhQT1JUX1NZTUJPTCht aXBpX2RzaV9kY3Nfbm9wKTsKKworLyoqCisgKiBtaXBpX2RzaV9kY3Nfc29mdF9yZXNldCgpIC0g cGVyZm9ybSBhIHNvZnR3YXJlIHJlc2V0IG9mIHRoZSBkaXNwbGF5IG1vZHVsZQorICogQGRzaTog RFNJIHBlcmlwaGVyYWwgZGV2aWNlCisgKgorICogUmV0dXJuOiAwIG9uIHN1Y2Nlc3Mgb3IgYSBu ZWdhdGl2ZSBlcnJvciBjb2RlIG9uIGZhaWx1cmUuCisgKi8KK2ludCBtaXBpX2RzaV9kY3Nfc29m dF9yZXNldChzdHJ1Y3QgbWlwaV9kc2lfZGV2aWNlICpkc2kpCit7CisJc3NpemVfdCBlcnI7CisK KwllcnIgPSBtaXBpX2RzaV9kY3Nfd3JpdGUoZHNpLCBNSVBJX0RDU19TT0ZUX1JFU0VULCBOVUxM LCAwKTsKKwlpZiAoZXJyIDwgMCkKKwkJcmV0dXJuIGVycjsKKworCXJldHVybiAwOworfQorRVhQ T1JUX1NZTUJPTChtaXBpX2RzaV9kY3Nfc29mdF9yZXNldCk7CisKKy8qKgorICogbWlwaV9kc2lf ZGNzX2dldF9wb3dlcl9tb2RlKCkgLSBxdWVyeSB0aGUgZGlzcGxheSBtb2R1bGUncyBjdXJyZW50 IHBvd2VyCisgKiAgICBtb2RlCisgKiBAZHNpOiBEU0kgcGVyaXBoZXJhbCBkZXZpY2UKKyAqIEBt b2RlOiByZXR1cm4gbG9jYXRpb24gZm9yIHRoZSBjdXJyZW50IHBvd2VyIG1vZGUKKyAqCisgKiBS ZXR1cm46IDAgb24gc3VjY2VzcyBvciBhIG5lZ2F0aXZlIGVycm9yIGNvZGUgb24gZmFpbHVyZS4K KyAqLworaW50IG1pcGlfZHNpX2Rjc19nZXRfcG93ZXJfbW9kZShzdHJ1Y3QgbWlwaV9kc2lfZGV2 aWNlICpkc2ksIHU4ICptb2RlKQoreworCXNzaXplX3QgZXJyOworCisJZXJyID0gbWlwaV9kc2lf ZGNzX3JlYWQoZHNpLCBNSVBJX0RDU19HRVRfUE9XRVJfTU9ERSwgbW9kZSwKKwkJCQlzaXplb2Yo Km1vZGUpKTsKKwlpZiAoZXJyIDw9IDApIHsKKwkJaWYgKGVyciA9PSAwKQorCQkJZXJyID0gLUVO T0RBVEE7CisKKwkJcmV0dXJuIGVycjsKKwl9CisKKwlyZXR1cm4gMDsKK30KK0VYUE9SVF9TWU1C T0wobWlwaV9kc2lfZGNzX2dldF9wb3dlcl9tb2RlKTsKKworLyoqCisgKiBtaXBpX2RzaV9kY3Nf Z2V0X3BpeGVsX2Zvcm1hdCgpIC0gZ2V0cyB0aGUgcGl4ZWwgZm9ybWF0IGZvciB0aGUgUkdCIGlt YWdlCisgKiAgICBkYXRhIHVzZWQgYnkgdGhlIGludGVyZmFjZQorICogQGRzaTogRFNJIHBlcmlw aGVyYWwgZGV2aWNlCisgKiBAZm9ybWF0OiByZXR1cm4gbG9jYXRpb24gZm9yIHRoZSBwaXhlbCBm b3JtYXQKKyAqCisgKiBSZXR1cm46IDAgb24gc3VjY2VzcyBvciBhIG5lZ2F0aXZlIGVycm9yIGNv ZGUgb24gZmFpbHVyZS4KKyAqLworaW50IG1pcGlfZHNpX2Rjc19nZXRfcGl4ZWxfZm9ybWF0KHN0 cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRzaSwgdTggKmZvcm1hdCkKK3sKKwlzc2l6ZV90IGVycjsK KworCWVyciA9IG1pcGlfZHNpX2Rjc19yZWFkKGRzaSwgTUlQSV9EQ1NfR0VUX1BJWEVMX0ZPUk1B VCwgZm9ybWF0LAorCQkJCXNpemVvZigqZm9ybWF0KSk7CisJaWYgKGVyciA8PSAwKSB7CisJCWlm IChlcnIgPT0gMCkKKwkJCWVyciA9IC1FTk9EQVRBOworCisJCXJldHVybiBlcnI7CisJfQorCisJ cmV0dXJuIDA7Cit9CitFWFBPUlRfU1lNQk9MKG1pcGlfZHNpX2Rjc19nZXRfcGl4ZWxfZm9ybWF0 KTsKKworLyoqCisgKiBtaXBpX2RzaV9kY3NfZW50ZXJfc2xlZXBfbW9kZSgpIC0gZGlzYWJsZSBh bGwgdW5uZWNlc3NhcnkgYmxvY2tzIGluc2lkZSB0aGUKKyAqICAgIGRpc3BsYXkgbW9kdWxlIGV4 Y2VwdCBpbnRlcmZhY2UgY29tbXVuaWNhdGlvbgorICogQGRzaTogRFNJIHBlcmlwaGVyYWwgZGV2 aWNlCisgKgorICogUmV0dXJuOiAwIG9uIHN1Y2Nlc3Mgb3IgYSBuZWdhdGl2ZSBlcnJvciBjb2Rl IG9uIGZhaWx1cmUuCisgKi8KK2ludCBtaXBpX2RzaV9kY3NfZW50ZXJfc2xlZXBfbW9kZShzdHJ1 Y3QgbWlwaV9kc2lfZGV2aWNlICpkc2kpCit7CisJc3NpemVfdCBlcnI7CisKKwllcnIgPSBtaXBp X2RzaV9kY3Nfd3JpdGUoZHNpLCBNSVBJX0RDU19FTlRFUl9TTEVFUF9NT0RFLCBOVUxMLCAwKTsK KwlpZiAoZXJyIDwgMCkKKwkJcmV0dXJuIGVycjsKKworCXJldHVybiAwOworfQorRVhQT1JUX1NZ TUJPTChtaXBpX2RzaV9kY3NfZW50ZXJfc2xlZXBfbW9kZSk7CisKKy8qKgorICogbWlwaV9kc2lf ZGNzX2V4aXRfc2xlZXBfbW9kZSgpIC0gZW5hYmxlIGFsbCBibG9ja3MgaW5zaWRlIHRoZSBkaXNw bGF5CisgKiAgICBtb2R1bGUKKyAqIEBkc2k6IERTSSBwZXJpcGhlcmFsIGRldmljZQorICoKKyAq IFJldHVybjogMCBvbiBzdWNjZXNzIG9yIGEgbmVnYXRpdmUgZXJyb3IgY29kZSBvbiBmYWlsdXJl LgorICovCitpbnQgbWlwaV9kc2lfZGNzX2V4aXRfc2xlZXBfbW9kZShzdHJ1Y3QgbWlwaV9kc2lf ZGV2aWNlICpkc2kpCit7CisJc3NpemVfdCBlcnI7CisKKwllcnIgPSBtaXBpX2RzaV9kY3Nfd3Jp dGUoZHNpLCBNSVBJX0RDU19FWElUX1NMRUVQX01PREUsIE5VTEwsIDApOworCWlmIChlcnIgPCAw KQorCQlyZXR1cm4gZXJyOworCisJcmV0dXJuIDA7Cit9CitFWFBPUlRfU1lNQk9MKG1pcGlfZHNp X2Rjc19leGl0X3NsZWVwX21vZGUpOworCisvKioKKyAqIG1pcGlfZHNpX2Rjc19zZXRfZGlzcGxh eV9vZmYoKSAtIHN0b3AgZGlzcGxheWluZyB0aGUgaW1hZ2UgZGF0YSBvbiB0aGUKKyAqICAgIGRp c3BsYXkgZGV2aWNlCisgKiBAZHNpOiBEU0kgcGVyaXBoZXJhbCBkZXZpY2UKKyAqCisgKiBSZXR1 cm46IDAgb24gc3VjY2VzcyBvciBhIG5lZ2F0aXZlIGVycm9yIGNvZGUgb24gZmFpbHVyZS4KKyAq LworaW50IG1pcGlfZHNpX2Rjc19zZXRfZGlzcGxheV9vZmYoc3RydWN0IG1pcGlfZHNpX2Rldmlj ZSAqZHNpKQoreworCXNzaXplX3QgZXJyOworCisJZXJyID0gbWlwaV9kc2lfZGNzX3dyaXRlKGRz aSwgTUlQSV9EQ1NfU0VUX0RJU1BMQVlfT0ZGLCBOVUxMLCAwKTsKKwlpZiAoZXJyIDwgMCkKKwkJ cmV0dXJuIGVycjsKKworCXJldHVybiAwOworfQorRVhQT1JUX1NZTUJPTChtaXBpX2RzaV9kY3Nf c2V0X2Rpc3BsYXlfb2ZmKTsKKworLyoqCisgKiBtaXBpX2RzaV9kY3Nfc2V0X2Rpc3BsYXlfb24o KSAtIHN0YXJ0IGRpc3BsYXlpbmcgdGhlIGltYWdlIGRhdGEgb24gdGhlCisgKiAgICBkaXNwbGF5 IGRldmljZQorICogQGRzaTogRFNJIHBlcmlwaGVyYWwgZGV2aWNlCisgKgorICogUmV0dXJuOiAw IG9uIHN1Y2Nlc3Mgb3IgYSBuZWdhdGl2ZSBlcnJvciBjb2RlIG9uIGZhaWx1cmUKKyAqLworaW50 IG1pcGlfZHNpX2Rjc19zZXRfZGlzcGxheV9vbihzdHJ1Y3QgbWlwaV9kc2lfZGV2aWNlICpkc2kp Cit7CisJc3NpemVfdCBlcnI7CisKKwllcnIgPSBtaXBpX2RzaV9kY3Nfd3JpdGUoZHNpLCBNSVBJ X0RDU19TRVRfRElTUExBWV9PTiwgTlVMTCwgMCk7CisJaWYgKGVyciA8IDApCisJCXJldHVybiBl cnI7CisKKwlyZXR1cm4gMDsKK30KK0VYUE9SVF9TWU1CT0wobWlwaV9kc2lfZGNzX3NldF9kaXNw bGF5X29uKTsKKworLyoqCisgKiBtaXBpX2RzaV9kY3Nfc2V0X2NvbHVtbl9hZGRyZXNzKCkgLSBk ZWZpbmUgdGhlIGNvbHVtbiBleHRlbnQgb2YgdGhlIGZyYW1lCisgKiAgICBtZW1vcnkgYWNjZXNz ZWQgYnkgdGhlIGhvc3QgcHJvY2Vzc29yCisgKiBAZHNpOiBEU0kgcGVyaXBoZXJhbCBkZXZpY2UK KyAqIEBzdGFydDogZmlyc3QgY29sdW1uIG9mIGZyYW1lIG1lbW9yeQorICogQGVuZDogbGFzdCBj b2x1bW4gb2YgZnJhbWUgbWVtb3J5CisgKgorICogUmV0dXJuOiAwIG9uIHN1Y2Nlc3Mgb3IgYSBu ZWdhdGl2ZSBlcnJvciBjb2RlIG9uIGZhaWx1cmUuCisgKi8KK2ludCBtaXBpX2RzaV9kY3Nfc2V0 X2NvbHVtbl9hZGRyZXNzKHN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRzaSwgdTE2IHN0YXJ0LAor CQkJCSAgICB1MTYgZW5kKQoreworCXU4IHBheWxvYWRbNF0gPSB7IHN0YXJ0ID4+IDgsIHN0YXJ0 ICYgMHhmZiwgZW5kID4+IDgsIGVuZCAmIDB4ZmYgfTsKKwlzc2l6ZV90IGVycjsKKworCWVyciA9 IG1pcGlfZHNpX2Rjc193cml0ZShkc2ksIE1JUElfRENTX1NFVF9DT0xVTU5fQUREUkVTUywgcGF5 bG9hZCwKKwkJCQkgc2l6ZW9mKHBheWxvYWQpKTsKKwlpZiAoZXJyIDwgMCkKKwkJcmV0dXJuIGVy cjsKKworCXJldHVybiAwOworfQorRVhQT1JUX1NZTUJPTChtaXBpX2RzaV9kY3Nfc2V0X2NvbHVt bl9hZGRyZXNzKTsKKworLyoqCisgKiBtaXBpX2RzaV9kY3Nfc2V0X3BhZ2VfYWRkcmVzcygpIC0g ZGVmaW5lIHRoZSBwYWdlIGV4dGVudCBvZiB0aGUgZnJhbWUKKyAqICAgIG1lbW9yeSBhY2Nlc3Nl ZCBieSB0aGUgaG9zdCBwcm9jZXNzb3IKKyAqIEBkc2k6IERTSSBwZXJpcGhlcmFsIGRldmljZQor ICogQHN0YXJ0OiBmaXJzdCBwYWdlIG9mIGZyYW1lIG1lbW9yeQorICogQGVuZDogbGFzdCBwYWdl IG9mIGZyYW1lIG1lbW9yeQorICoKKyAqIFJldHVybjogMCBvbiBzdWNjZXNzIG9yIGEgbmVnYXRp dmUgZXJyb3IgY29kZSBvbiBmYWlsdXJlLgorICovCitpbnQgbWlwaV9kc2lfZGNzX3NldF9wYWdl X2FkZHJlc3Moc3RydWN0IG1pcGlfZHNpX2RldmljZSAqZHNpLCB1MTYgc3RhcnQsCisJCQkJICB1 MTYgZW5kKQoreworCXU4IHBheWxvYWRbNF0gPSB7IHN0YXJ0ID4+IDgsIHN0YXJ0ICYgMHhmZiwg ZW5kID4+IDgsIGVuZCAmIDB4ZmYgfTsKKwlzc2l6ZV90IGVycjsKKworCWVyciA9IG1pcGlfZHNp X2Rjc193cml0ZShkc2ksIE1JUElfRENTX1NFVF9QQUdFX0FERFJFU1MsIHBheWxvYWQsCisJCQkJ IHNpemVvZihwYXlsb2FkKSk7CisJaWYgKGVyciA8IDApCisJCXJldHVybiBlcnI7CisKKwlyZXR1 cm4gMDsKK30KK0VYUE9SVF9TWU1CT0wobWlwaV9kc2lfZGNzX3NldF9wYWdlX2FkZHJlc3MpOwor CisvKioKKyAqIG1pcGlfZHNpX2Rjc19zZXRfdGVhcl9vZmYoKSAtIHR1cm4gb2ZmIHRoZSBkaXNw bGF5IG1vZHVsZSdzIFRlYXJpbmcgRWZmZWN0CisgKiAgICBvdXRwdXQgc2lnbmFsIG9uIHRoZSBU RSBzaWduYWwgbGluZQorICogQGRzaTogRFNJIHBlcmlwaGVyYWwgZGV2aWNlCisgKgorICogUmV0 dXJuOiAwIG9uIHN1Y2Nlc3Mgb3IgYSBuZWdhdGl2ZSBlcnJvciBjb2RlIG9uIGZhaWx1cmUKKyAq LworaW50IG1pcGlfZHNpX2Rjc19zZXRfdGVhcl9vZmYoc3RydWN0IG1pcGlfZHNpX2RldmljZSAq ZHNpKQoreworCXNzaXplX3QgZXJyOworCisJZXJyID0gbWlwaV9kc2lfZGNzX3dyaXRlKGRzaSwg TUlQSV9EQ1NfU0VUX1RFQVJfT0ZGLCBOVUxMLCAwKTsKKwlpZiAoZXJyIDwgMCkKKwkJcmV0dXJu IGVycjsKKworCXJldHVybiAwOworfQorRVhQT1JUX1NZTUJPTChtaXBpX2RzaV9kY3Nfc2V0X3Rl YXJfb2ZmKTsKKworLyoqCisgKiBtaXBpX2RzaV9kY3Nfc2V0X3RlYXJfb24oKSAtIHR1cm4gb24g dGhlIGRpc3BsYXkgbW9kdWxlJ3MgVGVhcmluZyBFZmZlY3QKKyAqICAgIG91dHB1dCBzaWduYWwg b24gdGhlIFRFIHNpZ25hbCBsaW5lLgorICogQGRzaTogRFNJIHBlcmlwaGVyYWwgZGV2aWNlCisg KiBAbW9kZTogdGhlIFRlYXJpbmcgRWZmZWN0IE91dHB1dCBMaW5lIG1vZGUKKyAqCisgKiBSZXR1 cm46IDAgb24gc3VjY2VzcyBvciBhIG5lZ2F0aXZlIGVycm9yIGNvZGUgb24gZmFpbHVyZQorICov CitpbnQgbWlwaV9kc2lfZGNzX3NldF90ZWFyX29uKHN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRz aSwKKwkJCSAgICAgZW51bSBtaXBpX2RzaV9kY3NfdGVhcl9tb2RlIG1vZGUpCit7CisJdTggdmFs dWUgPSBtb2RlOworCXNzaXplX3QgZXJyOworCisJZXJyID0gbWlwaV9kc2lfZGNzX3dyaXRlKGRz aSwgTUlQSV9EQ1NfU0VUX1RFQVJfT04sICZ2YWx1ZSwKKwkJCQkgc2l6ZW9mKHZhbHVlKSk7CisJ aWYgKGVyciA8IDApCisJCXJldHVybiBlcnI7CisKKwlyZXR1cm4gMDsKK30KK0VYUE9SVF9TWU1C T0wobWlwaV9kc2lfZGNzX3NldF90ZWFyX29uKTsKKworLyoqCisgKiBtaXBpX2RzaV9kY3Nfc2V0 X3BpeGVsX2Zvcm1hdCgpIC0gc2V0cyB0aGUgcGl4ZWwgZm9ybWF0IGZvciB0aGUgUkdCIGltYWdl CisgKiAgICBkYXRhIHVzZWQgYnkgdGhlIGludGVyZmFjZQorICogQGRzaTogRFNJIHBlcmlwaGVy YWwgZGV2aWNlCisgKiBAZm9ybWF0OiBwaXhlbCBmb3JtYXQKKyAqCisgKiBSZXR1cm46IDAgb24g c3VjY2VzcyBvciBhIG5lZ2F0aXZlIGVycm9yIGNvZGUgb24gZmFpbHVyZS4KKyAqLworaW50IG1p cGlfZHNpX2Rjc19zZXRfcGl4ZWxfZm9ybWF0KHN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRzaSwg dTggZm9ybWF0KQoreworCXNzaXplX3QgZXJyOworCisJZXJyID0gbWlwaV9kc2lfZGNzX3dyaXRl KGRzaSwgTUlQSV9EQ1NfU0VUX1BJWEVMX0ZPUk1BVCwgJmZvcm1hdCwKKwkJCQkgc2l6ZW9mKGZv cm1hdCkpOworCWlmIChlcnIgPCAwKQorCQlyZXR1cm4gZXJyOworCisJcmV0dXJuIDA7Cit9CitF WFBPUlRfU1lNQk9MKG1pcGlfZHNpX2Rjc19zZXRfcGl4ZWxfZm9ybWF0KTsKKworLyoqCisgKiBt aXBpX2RzaV9kY3Nfc2V0X3RlYXJfc2NhbmxpbmUoKSAtIHNldCB0aGUgc2NhbmxpbmUgdG8gdXNl IGFzIHRyaWdnZXIgZm9yCisgKiAgICB0aGUgVGVhcmluZyBFZmZlY3Qgb3V0cHV0IHNpZ25hbCBv ZiB0aGUgZGlzcGxheSBtb2R1bGUKKyAqIEBkc2k6IERTSSBwZXJpcGhlcmFsIGRldmljZQorICog QHNjYW5saW5lOiBzY2FubGluZSB0byB1c2UgYXMgdHJpZ2dlcgorICoKKyAqIFJldHVybjogMCBv biBzdWNjZXNzIG9yIGEgbmVnYXRpdmUgZXJyb3IgY29kZSBvbiBmYWlsdXJlCisgKi8KK2ludCBt aXBpX2RzaV9kY3Nfc2V0X3RlYXJfc2NhbmxpbmUoc3RydWN0IG1pcGlfZHNpX2RldmljZSAqZHNp LCB1MTYgc2NhbmxpbmUpCit7CisJdTggcGF5bG9hZFszXSA9IHsgTUlQSV9EQ1NfU0VUX1RFQVJf U0NBTkxJTkUsIHNjYW5saW5lID4+IDgsCisJCQkgIHNjYW5saW5lICYgMHhmZiB9OworCXNzaXpl X3QgZXJyOworCisJZXJyID0gbWlwaV9kc2lfZ2VuZXJpY193cml0ZShkc2ksIHBheWxvYWQsIHNp emVvZihwYXlsb2FkKSk7CisJaWYgKGVyciA8IDApCisJCXJldHVybiBlcnI7CisKKwlyZXR1cm4g MDsKK30KK0VYUE9SVF9TWU1CT0wobWlwaV9kc2lfZGNzX3NldF90ZWFyX3NjYW5saW5lKTsKKwor LyoqCisgKiBtaXBpX2RzaV9kY3Nfc2V0X2Rpc3BsYXlfYnJpZ2h0bmVzcygpIC0gc2V0cyB0aGUg YnJpZ2h0bmVzcyB2YWx1ZSBvZiB0aGUKKyAqICAgIGRpc3BsYXkKKyAqIEBkc2k6IERTSSBwZXJp cGhlcmFsIGRldmljZQorICogQGJyaWdodG5lc3M6IGJyaWdodG5lc3MgdmFsdWUKKyAqCisgKiBS ZXR1cm46IDAgb24gc3VjY2VzcyBvciBhIG5lZ2F0aXZlIGVycm9yIGNvZGUgb24gZmFpbHVyZS4K KyAqLworaW50IG1pcGlfZHNpX2Rjc19zZXRfZGlzcGxheV9icmlnaHRuZXNzKHN0cnVjdCBtaXBp X2RzaV9kZXZpY2UgKmRzaSwKKwkJCQkJdTE2IGJyaWdodG5lc3MpCit7CisJdTggcGF5bG9hZFsy XSA9IHsgYnJpZ2h0bmVzcyAmIDB4ZmYsIGJyaWdodG5lc3MgPj4gOCB9OworCXNzaXplX3QgZXJy OworCisJZXJyID0gbWlwaV9kc2lfZGNzX3dyaXRlKGRzaSwgTUlQSV9EQ1NfU0VUX0RJU1BMQVlf QlJJR0hUTkVTUywKKwkJCQkgcGF5bG9hZCwgc2l6ZW9mKHBheWxvYWQpKTsKKwlpZiAoZXJyIDwg MCkKKwkJcmV0dXJuIGVycjsKKworCXJldHVybiAwOworfQorRVhQT1JUX1NZTUJPTChtaXBpX2Rz aV9kY3Nfc2V0X2Rpc3BsYXlfYnJpZ2h0bmVzcyk7CisKKy8qKgorICogbWlwaV9kc2lfZGNzX2dl dF9kaXNwbGF5X2JyaWdodG5lc3MoKSAtIGdldHMgdGhlIGN1cnJlbnQgYnJpZ2h0bmVzcyB2YWx1 ZQorICogICAgb2YgdGhlIGRpc3BsYXkKKyAqIEBkc2k6IERTSSBwZXJpcGhlcmFsIGRldmljZQor ICogQGJyaWdodG5lc3M6IGJyaWdodG5lc3MgdmFsdWUKKyAqCisgKiBSZXR1cm46IDAgb24gc3Vj Y2VzcyBvciBhIG5lZ2F0aXZlIGVycm9yIGNvZGUgb24gZmFpbHVyZS4KKyAqLworaW50IG1pcGlf ZHNpX2Rjc19nZXRfZGlzcGxheV9icmlnaHRuZXNzKHN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRz aSwKKwkJCQkJdTE2ICpicmlnaHRuZXNzKQoreworCXNzaXplX3QgZXJyOworCisJZXJyID0gbWlw aV9kc2lfZGNzX3JlYWQoZHNpLCBNSVBJX0RDU19HRVRfRElTUExBWV9CUklHSFRORVNTLAorCQkJ CWJyaWdodG5lc3MsIHNpemVvZigqYnJpZ2h0bmVzcykpOworCWlmIChlcnIgPD0gMCkgeworCQlp ZiAoZXJyID09IDApCisJCQllcnIgPSAtRU5PREFUQTsKKworCQlyZXR1cm4gZXJyOworCX0KKwor CXJldHVybiAwOworfQorRVhQT1JUX1NZTUJPTChtaXBpX2RzaV9kY3NfZ2V0X2Rpc3BsYXlfYnJp Z2h0bmVzcyk7CisKK01PRFVMRV9BVVRIT1IoIkFuZHJ6ZWogSGFqZGEgPGEuaGFqZGFAc2Ftc3Vu Zy5jb20+Iik7CitNT0RVTEVfQVVUSE9SKCJZYW5uaWNrIEZlcnRyZSA8eWFubmljay5mZXJ0cmVA c3QuY29tPiIpOworTU9EVUxFX0RFU0NSSVBUSU9OKCJNSVBJIERTSSBCdXMiKTsKK01PRFVMRV9M SUNFTlNFKCJHUEwgYW5kIGFkZGl0aW9uYWwgcmlnaHRzIik7CmRpZmYgLS1naXQgYS9pbmNsdWRl L21pcGlfZGlzcGxheS5oIGIvaW5jbHVkZS9taXBpX2Rpc3BsYXkuaAppbmRleCBkZGNjOGNhLi44 ZjlkNGE0IDEwMDY0NAotLS0gYS9pbmNsdWRlL21pcGlfZGlzcGxheS5oCisrKyBiL2luY2x1ZGUv bWlwaV9kaXNwbGF5LmgKQEAgLTQsMTIgKzQsMTYgQEAKICAqCiAgKiBDb3B5cmlnaHQgKEMpIDIw MTAgR3Vlbm5hZGkgTGlha2hvdmV0c2tpIDxnLmxpYWtob3ZldHNraUBnbXguZGU+CiAgKiBDb3B5 cmlnaHQgKEMpIDIwMDYgTm9raWEgQ29ycG9yYXRpb24KLSAqIEF1dGhvcjogSW1yZSBEZWFrIDxp bXJlLmRlYWtAbm9raWEuY29tPgorICogQ29weXJpZ2h0IChDKSAyMDE4IFNUTWljcm9lbGVjdHJv bmljcyAtIEFsbCBSaWdodHMgUmVzZXJ2ZWQKKyAqIEF1dGhvcihzKTogSW1yZSBEZWFrIDxpbXJl LmRlYWtAbm9raWEuY29tPgorICoJICAgWWFubmljayBGZXJ0cmUgPHlhbm5pY2suZmVydHJlQHN0 LmNvbT4KKyAqICAgICAgICAgUGhpbGlwcGUgQ29ybnUgPHBoaWxpcHBlLmNvcm51QHN0LmNvbT4K ICAqCiAgKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1 dGUgaXQgYW5kL29yIG1vZGlmeQogICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2Vu ZXJhbCBQdWJsaWMgTGljZW5zZSB2ZXJzaW9uIDIgYXMKICAqIHB1Ymxpc2hlZCBieSB0aGUgRnJl ZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLgogICovCisKICNpZm5kZWYgTUlQSV9ESVNQTEFZX0gKICNk ZWZpbmUgTUlQSV9ESVNQTEFZX0gKIApAQCAtMTE1LDYgKzExOSwxNCBAQCBlbnVtIHsKIAlNSVBJ X0RDU19SRUFEX01FTU9SWV9DT05USU5VRQk9IDB4M0UsCiAJTUlQSV9EQ1NfU0VUX1RFQVJfU0NB TkxJTkUJPSAweDQ0LAogCU1JUElfRENTX0dFVF9TQ0FOTElORQkJPSAweDQ1LAorCU1JUElfRENT X1NFVF9ESVNQTEFZX0JSSUdIVE5FU1MgPSAweDUxLAkJLyogTUlQSSBEQ1MgMS4zICovCisJTUlQ SV9EQ1NfR0VUX0RJU1BMQVlfQlJJR0hUTkVTUyA9IDB4NTIsCQkvKiBNSVBJIERDUyAxLjMgKi8K KwlNSVBJX0RDU19XUklURV9DT05UUk9MX0RJU1BMQVkgID0gMHg1MywJCS8qIE1JUEkgRENTIDEu MyAqLworCU1JUElfRENTX0dFVF9DT05UUk9MX0RJU1BMQVkJPSAweDU0LAkJLyogTUlQSSBEQ1Mg MS4zICovCisJTUlQSV9EQ1NfV1JJVEVfUE9XRVJfU0FWRQk9IDB4NTUsCQkvKiBNSVBJIERDUyAx LjMgKi8KKwlNSVBJX0RDU19HRVRfUE9XRVJfU0FWRQkJPSAweDU2LAkJLyogTUlQSSBEQ1MgMS4z ICovCisJTUlQSV9EQ1NfU0VUX0NBQkNfTUlOX0JSSUdIVE5FU1MgPSAweDVFLAkvKiBNSVBJIERD UyAxLjMgKi8KKwlNSVBJX0RDU19HRVRfQ0FCQ19NSU5fQlJJR0hUTkVTUyA9IDB4NUYsCS8qIE1J UEkgRENTIDEuMyAqLwogCU1JUElfRENTX1JFQURfRERCX1NUQVJUCQk9IDB4QTEsCiAJTUlQSV9E Q1NfUkVBRF9EREJfQ09OVElOVUUJPSAweEE4LAogfTsKQEAgLTEyNyw0ICsxMzksMjQ3IEBAIGVu dW0gewogI2RlZmluZSBNSVBJX0RDU19QSVhFTF9GTVRfOEJJVAkJMgogI2RlZmluZSBNSVBJX0RD U19QSVhFTF9GTVRfM0JJVAkJMQogCitzdHJ1Y3QgbWlwaV9kc2lfaG9zdDsKK3N0cnVjdCBtaXBp X2RzaV9kZXZpY2U7CisKKy8qIHJlcXVlc3QgQUNLIGZyb20gcGVyaXBoZXJhbCAqLworI2RlZmlu ZSBNSVBJX0RTSV9NU0dfUkVRX0FDSwlCSVQoMCkKKy8qIHVzZSBMb3cgUG93ZXIgTW9kZSB0byB0 cmFuc21pdCBtZXNzYWdlICovCisjZGVmaW5lIE1JUElfRFNJX01TR19VU0VfTFBNCUJJVCgxKQor CisvKioKKyAqIHN0cnVjdCBtaXBpX2RzaV9tc2cgLSByZWFkL3dyaXRlIERTSSBidWZmZXIKKyAq IEBjaGFubmVsOiB2aXJ0dWFsIGNoYW5uZWwgaWQKKyAqIEB0eXBlOiBwYXlsb2FkIGRhdGEgdHlw ZQorICogQGZsYWdzOiBmbGFncyBjb250cm9sbGluZyB0aGlzIG1lc3NhZ2UgdHJhbnNtaXNzaW9u CisgKiBAdHhfbGVuOiBsZW5ndGggb2YgQHR4X2J1ZgorICogQHR4X2J1ZjogZGF0YSB0byBiZSB3 cml0dGVuCisgKiBAcnhfbGVuOiBsZW5ndGggb2YgQHJ4X2J1ZgorICogQHJ4X2J1ZjogZGF0YSB0 byBiZSByZWFkLCBvciBOVUxMCisgKi8KK3N0cnVjdCBtaXBpX2RzaV9tc2cgeworCXU4IGNoYW5u ZWw7CisJdTggdHlwZTsKKwl1MTYgZmxhZ3M7CisKKwlzaXplX3QgdHhfbGVuOworCWNvbnN0IHZv aWQgKnR4X2J1ZjsKKworCXNpemVfdCByeF9sZW47CisJdm9pZCAqcnhfYnVmOworfTsKKworYm9v bCBtaXBpX2RzaV9wYWNrZXRfZm9ybWF0X2lzX3Nob3J0KHU4IHR5cGUpOworYm9vbCBtaXBpX2Rz aV9wYWNrZXRfZm9ybWF0X2lzX2xvbmcodTggdHlwZSk7CisKKy8qKgorICogc3RydWN0IG1pcGlf ZHNpX3BhY2tldCAtIHJlcHJlc2VudHMgYSBNSVBJIERTSSBwYWNrZXQgaW4gcHJvdG9jb2wgZm9y bWF0CisgKiBAc2l6ZTogc2l6ZSAoaW4gYnl0ZXMpIG9mIHRoZSBwYWNrZXQKKyAqIEBoZWFkZXI6 IHRoZSBmb3VyIGJ5dGVzIHRoYXQgbWFrZSB1cCB0aGUgaGVhZGVyIChEYXRhIElELCBXb3JkIENv dW50IG9yCisgKiAgICAgUGFja2V0IERhdGEsIGFuZCBFQ0MpCisgKiBAcGF5bG9hZF9sZW5ndGg6 IG51bWJlciBvZiBieXRlcyBpbiB0aGUgcGF5bG9hZAorICogQHBheWxvYWQ6IGEgcG9pbnRlciB0 byBhIGJ1ZmZlciBjb250YWluaW5nIHRoZSBwYXlsb2FkLCBpZiBhbnkKKyAqLworc3RydWN0IG1p cGlfZHNpX3BhY2tldCB7CisJc2l6ZV90IHNpemU7CisJdTggaGVhZGVyWzRdOworCXNpemVfdCBw YXlsb2FkX2xlbmd0aDsKKwljb25zdCB1OCAqcGF5bG9hZDsKK307CisKK2ludCBtaXBpX2RzaV9j cmVhdGVfcGFja2V0KHN0cnVjdCBtaXBpX2RzaV9wYWNrZXQgKnBhY2tldCwKKwkJCSAgIGNvbnN0 IHN0cnVjdCBtaXBpX2RzaV9tc2cgKm1zZyk7CisKKy8qKgorICogc3RydWN0IG1pcGlfZHNpX2hv c3Rfb3BzIC0gRFNJIGJ1cyBvcGVyYXRpb25zCisgKiBAYXR0YWNoOiBhdHRhY2ggRFNJIGRldmlj ZSB0byBEU0kgaG9zdAorICogQGRldGFjaDogZGV0YWNoIERTSSBkZXZpY2UgZnJvbSBEU0kgaG9z dAorICogQHRyYW5zZmVyOiB0cmFuc21pdCBhIERTSSBwYWNrZXQKKyAqCisgKiBEU0kgcGFja2V0 cyB0cmFuc21pdHRlZCBieSAudHJhbnNmZXIoKSBhcmUgcGFzc2VkIGluIGFzIG1pcGlfZHNpX21z ZworICogc3RydWN0dXJlcy4gVGhpcyBzdHJ1Y3R1cmUgY29udGFpbnMgaW5mb3JtYXRpb24gYWJv dXQgdGhlIHR5cGUgb2YgcGFja2V0CisgKiBiZWluZyB0cmFuc21pdHRlZCBhcyB3ZWxsIGFzIHRo ZSB0cmFuc21pdCBhbmQgcmVjZWl2ZSBidWZmZXJzLiBXaGVuIGFuCisgKiBlcnJvciBpcyBlbmNv dW50ZXJlZCBkdXJpbmcgdHJhbnNtaXNzaW9uLCB0aGlzIGZ1bmN0aW9uIHdpbGwgcmV0dXJuIGEK KyAqIG5lZ2F0aXZlIGVycm9yIGNvZGUuIE9uIHN1Y2Nlc3MgaXQgc2hhbGwgcmV0dXJuIHRoZSBu dW1iZXIgb2YgYnl0ZXMKKyAqIHRyYW5zbWl0dGVkIGZvciB3cml0ZSBwYWNrZXRzIG9yIHRoZSBu dW1iZXIgb2YgYnl0ZXMgcmVjZWl2ZWQgZm9yIHJlYWQKKyAqIHBhY2tldHMuCisgKgorICogTm90 ZSB0aGF0IHR5cGljYWxseSBEU0kgcGFja2V0IHRyYW5zbWlzc2lvbiBpcyBhdG9taWMsIHNvIHRo ZSAudHJhbnNmZXIoKQorICogZnVuY3Rpb24gd2lsbCBzZWxkb21seSByZXR1cm4gYW55dGhpbmcg b3RoZXIgdGhhbiB0aGUgbnVtYmVyIG9mIGJ5dGVzCisgKiBjb250YWluZWQgaW4gdGhlIHRyYW5z bWl0IGJ1ZmZlciBvbiBzdWNjZXNzLgorICovCitzdHJ1Y3QgbWlwaV9kc2lfaG9zdF9vcHMgewor CWludCAoKmF0dGFjaCkoc3RydWN0IG1pcGlfZHNpX2hvc3QgKmhvc3QsCisJCSAgICAgIHN0cnVj dCBtaXBpX2RzaV9kZXZpY2UgKmRzaSk7CisJaW50ICgqZGV0YWNoKShzdHJ1Y3QgbWlwaV9kc2lf aG9zdCAqaG9zdCwKKwkJICAgICAgc3RydWN0IG1pcGlfZHNpX2RldmljZSAqZHNpKTsKKwlzc2l6 ZV90ICgqdHJhbnNmZXIpKHN0cnVjdCBtaXBpX2RzaV9ob3N0ICpob3N0LAorCQkJICAgIGNvbnN0 IHN0cnVjdCBtaXBpX2RzaV9tc2cgKm1zZyk7Cit9OworCisvKioKKyAqIHN0cnVjdCBtaXBpX2Rz aV9ob3N0IC0gRFNJIGhvc3QgZGV2aWNlCisgKiBAZGV2OiBkcml2ZXIgbW9kZWwgZGV2aWNlIG5v ZGUgZm9yIHRoaXMgRFNJIGhvc3QKKyAqIEBvcHM6IERTSSBob3N0IG9wZXJhdGlvbnMKKyAqIEBs aXN0OiBsaXN0IG1hbmFnZW1lbnQKKyAqLworc3RydWN0IG1pcGlfZHNpX2hvc3QgeworCXN0cnVj dCBkZXZpY2UgKmRldjsKKwljb25zdCBzdHJ1Y3QgbWlwaV9kc2lfaG9zdF9vcHMgKm9wczsKKwlz dHJ1Y3QgbGlzdF9oZWFkIGxpc3Q7Cit9OworCisvKiBEU0kgbW9kZSBmbGFncyAqLworCisvKiB2 aWRlbyBtb2RlICovCisjZGVmaW5lIE1JUElfRFNJX01PREVfVklERU8JCUJJVCgwKQorLyogdmlk ZW8gYnVyc3QgbW9kZSAqLworI2RlZmluZSBNSVBJX0RTSV9NT0RFX1ZJREVPX0JVUlNUCUJJVCgx KQorLyogdmlkZW8gcHVsc2UgbW9kZSAqLworI2RlZmluZSBNSVBJX0RTSV9NT0RFX1ZJREVPX1NZ TkNfUFVMU0UJQklUKDIpCisvKiBlbmFibGUgYXV0byB2ZXJ0aWNhbCBjb3VudCBtb2RlICovCisj ZGVmaW5lIE1JUElfRFNJX01PREVfVklERU9fQVVUT19WRVJUCUJJVCgzKQorLyogZW5hYmxlIGhz eW5jLWVuZCBwYWNrZXRzIGluIHZzeW5jLXB1bHNlIGFuZCB2LXBvcmNoIGFyZWEgKi8KKyNkZWZp bmUgTUlQSV9EU0lfTU9ERV9WSURFT19IU0UJCUJJVCg0KQorLyogZGlzYWJsZSBoZnJvbnQtcG9y Y2ggYXJlYSAqLworI2RlZmluZSBNSVBJX0RTSV9NT0RFX1ZJREVPX0hGUAkJQklUKDUpCisvKiBk aXNhYmxlIGhiYWNrLXBvcmNoIGFyZWEgKi8KKyNkZWZpbmUgTUlQSV9EU0lfTU9ERV9WSURFT19I QlAJCUJJVCg2KQorLyogZGlzYWJsZSBoc3luYy1hY3RpdmUgYXJlYSAqLworI2RlZmluZSBNSVBJ X0RTSV9NT0RFX1ZJREVPX0hTQQkJQklUKDcpCisvKiBmbHVzaCBkaXNwbGF5IEZJRk8gb24gdnN5 bmMgcHVsc2UgKi8KKyNkZWZpbmUgTUlQSV9EU0lfTU9ERV9WU1lOQ19GTFVTSAlCSVQoOCkKKy8q IGRpc2FibGUgRW9UIHBhY2tldHMgaW4gSFMgbW9kZSAqLworI2RlZmluZSBNSVBJX0RTSV9NT0RF X0VPVF9QQUNLRVQJQklUKDkpCisvKiBkZXZpY2Ugc3VwcG9ydHMgbm9uLWNvbnRpbnVvdXMgY2xv Y2sgYmVoYXZpb3IgKERTSSBzcGVjIDUuNi4xKSAqLworI2RlZmluZSBNSVBJX0RTSV9DTE9DS19O T05fQ09OVElOVU9VUwlCSVQoMTApCisvKiB0cmFuc21pdCBkYXRhIGluIGxvdyBwb3dlciAqLwor I2RlZmluZSBNSVBJX0RTSV9NT0RFX0xQTQkJQklUKDExKQorCitlbnVtIG1pcGlfZHNpX3BpeGVs X2Zvcm1hdCB7CisJTUlQSV9EU0lfRk1UX1JHQjg4OCwKKwlNSVBJX0RTSV9GTVRfUkdCNjY2LAor CU1JUElfRFNJX0ZNVF9SR0I2NjZfUEFDS0VELAorCU1JUElfRFNJX0ZNVF9SR0I1NjUsCit9Owor CisjZGVmaW5lIERTSV9ERVZfTkFNRV9TSVpFCQkyMAorCisvKioKKyAqIHN0cnVjdCBtaXBpX2Rz aV9kZXZpY2VfaW5mbyAtIHRlbXBsYXRlIGZvciBjcmVhdGluZyBhIG1pcGlfZHNpX2RldmljZQor ICogQHR5cGU6IERTSSBwZXJpcGhlcmFsIGNoaXAgdHlwZQorICogQGNoYW5uZWw6IERTSSB2aXJ0 dWFsIGNoYW5uZWwgYXNzaWduZWQgdG8gcGVyaXBoZXJhbAorICogQG5vZGU6IHBvaW50ZXIgdG8g T0YgZGV2aWNlIG5vZGUgb3IgTlVMTAorICoKKyAqIFRoaXMgaXMgcG9wdWxhdGVkIGFuZCBwYXNz ZWQgdG8gbWlwaV9kc2lfZGV2aWNlX25ldyB0byBjcmVhdGUgYSBuZXcKKyAqIERTSSBkZXZpY2UK KyAqLworc3RydWN0IG1pcGlfZHNpX2RldmljZV9pbmZvIHsKKwljaGFyIHR5cGVbRFNJX0RFVl9O QU1FX1NJWkVdOworCXUzMiBjaGFubmVsOworCXN0cnVjdCBkZXZpY2Vfbm9kZSAqbm9kZTsKK307 CisKKy8qKgorICogc3RydWN0IG1pcGlfZHNpX2RldmljZSAtIERTSSBwZXJpcGhlcmFsIGRldmlj ZQorICogQGhvc3Q6IERTSSBob3N0IGZvciB0aGlzIHBlcmlwaGVyYWwKKyAqIEBkZXY6IGRyaXZl ciBtb2RlbCBkZXZpY2Ugbm9kZSBmb3IgdGhpcyBwZXJpcGhlcmFsCisgKiBAbmFtZTogRFNJIHBl cmlwaGVyYWwgY2hpcCB0eXBlCisgKiBAY2hhbm5lbDogdmlydHVhbCBjaGFubmVsIGFzc2lnbmVk IHRvIHRoZSBwZXJpcGhlcmFsCisgKiBAZm9ybWF0OiBwaXhlbCBmb3JtYXQgZm9yIHZpZGVvIG1v ZGUKKyAqIEBsYW5lczogbnVtYmVyIG9mIGFjdGl2ZSBkYXRhIGxhbmVzCisgKiBAbW9kZV9mbGFn czogRFNJIG9wZXJhdGlvbiBtb2RlIHJlbGF0ZWQgZmxhZ3MKKyAqLworc3RydWN0IG1pcGlfZHNp X2RldmljZSB7CisJc3RydWN0IG1pcGlfZHNpX2hvc3QgKmhvc3Q7CisJc3RydWN0IHVkZXZpY2Ug KmRldjsKKworCWNoYXIgbmFtZVtEU0lfREVWX05BTUVfU0laRV07CisJdW5zaWduZWQgaW50IGNo YW5uZWw7CisJdW5zaWduZWQgaW50IGxhbmVzOworCWVudW0gbWlwaV9kc2lfcGl4ZWxfZm9ybWF0 IGZvcm1hdDsKKwl1bnNpZ25lZCBsb25nIG1vZGVfZmxhZ3M7Cit9OworCisvKioKKyAqIGVudW0g bWlwaV9kc2lfZGNzX3RlYXJfbW9kZSAtIFRlYXJpbmcgRWZmZWN0IE91dHB1dCBMaW5lIG1vZGUK KyAqIEBNSVBJX0RTSV9EQ1NfVEVBUl9NT0RFX1ZCTEFOSzogdGhlIFRFIG91dHB1dCBsaW5lIGNv bnNpc3RzIG9mIFYtQmxhbmtpbmcKKyAqICAgIGluZm9ybWF0aW9uIG9ubHkKKyAqIEBNSVBJX0RT SV9EQ1NfVEVBUl9NT0RFX1ZIQkxBTksgOiB0aGUgVEUgb3V0cHV0IGxpbmUgY29uc2lzdHMgb2Yg Ym90aAorICogICAgVi1CbGFua2luZyBhbmQgSC1CbGFua2luZyBpbmZvcm1hdGlvbgorICovCitl bnVtIG1pcGlfZHNpX2Rjc190ZWFyX21vZGUgeworCU1JUElfRFNJX0RDU19URUFSX01PREVfVkJM QU5LLAorCU1JUElfRFNJX0RDU19URUFSX01PREVfVkhCTEFOSywKK307CisKKy8qKgorICogc3Ry dWN0IG1pcGlfZHNpX3BhbmVsX3BsYXQgLSBEU0kgcGFuZWwgcGxhdGZvcm0gZGF0YQorICogQGRl dmljZTogRFNJIHBlcmlwaGVyYWwgZGV2aWNlCisgKi8KK3N0cnVjdCBtaXBpX2RzaV9wYW5lbF9w bGF0IHsKKwlzdHJ1Y3QgbWlwaV9kc2lfZGV2aWNlICpkZXZpY2U7Cit9OworCitpbnQgbWlwaV9k c2lfYXR0YWNoKHN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRzaSk7CitpbnQgbWlwaV9kc2lfZGV0 YWNoKHN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRzaSk7CitpbnQgbWlwaV9kc2lfcGl4ZWxfZm9y bWF0X3RvX2JwcChlbnVtIG1pcGlfZHNpX3BpeGVsX2Zvcm1hdCBmbXQpOworCisvKiBiaXQgY29t cGF0aWJsZSB3aXRoIHRoZSB4cmFuZHIgUlJfIGRlZmluaXRpb25zIChiaXRzIDAtMTMpCisgKgor ICogQUJJIHdhcm5pbmc6IEV4aXN0aW5nIHVzZXJzcGFjZSByZWFsbHkgZXhwZWN0cworICogdGhl IG1vZGUgZmxhZ3MgdG8gbWF0Y2ggdGhlIHhyYW5kciBkZWZpbml0aW9ucy4gQW55CisgKiBjaGFu Z2VzIHRoYXQgZG9uJ3QgbWF0Y2ggdGhlIHhyYW5kciBkZWZpbml0aW9ucyB3aWxsCisgKiBsaWtl bHkgbmVlZCBhIG5ldyBjbGllbnQgY2FwIG9yIHNvbWUgb3RoZXIgbWVjaGFuaXNtCisgKiB0byBh dm9pZCBicmVha2luZyBleGlzdGluZyB1c2Vyc3BhY2UuIFRoaXMgaW5jbHVkZXMKKyAqIGFsbG9j YXRpbmcgbmV3IGZsYWdzIGluIHRoZSBwcmV2aW91c2x5IHVudXNlZCBiaXRzIQorICovCisjZGVm aW5lIE1JUElfRFNJX0ZMQUdfUEhTWU5DCQkJQklUKDApCisjZGVmaW5lIE1JUElfRFNJX0ZMQUdf TkhTWU5DCQkJQklUKDEpCisjZGVmaW5lIE1JUElfRFNJX0ZMQUdfUFZTWU5DCQkJQklUKDIpCisj ZGVmaW5lIE1JUElfRFNJX0ZMQUdfTlZTWU5DCQkJQklUKDMpCisjZGVmaW5lIE1JUElfRFNJX0ZM QUdfSU5URVJMQUNFCQkJQklUKDQpCisjZGVmaW5lIE1JUElfRFNJX0ZMQUdfREJMU0NBTgkJCUJJ VCg1KQorI2RlZmluZSBNSVBJX0RTSV9GTEFHX0NTWU5DCQkJQklUKDYpCisjZGVmaW5lIE1JUElf RFNJX0ZMQUdfUENTWU5DCQkJQklUKDcpCisjZGVmaW5lIE1JUElfRFNJX0ZMQUdfTkNTWU5DCQkJ QklUKDgpCisjZGVmaW5lIE1JUElfRFNJX0ZMQUdfSFNLRVcJCQlCSVQoOSkgLyogaHNrZXcgcHJv dmlkZWQgKi8KKyNkZWZpbmUgTUlQSV9EU0lfRkxBR19CQ0FTVAkJCUJJVCgxMCkKKyNkZWZpbmUg TUlQSV9EU0lfRkxBR19QSVhNVVgJCQlCSVQoMTEpCisjZGVmaW5lIE1JUElfRFNJX0ZMQUdfREJM Q0xLCQkJQklUKDEyKQorI2RlZmluZSBNSVBJX0RTSV9GTEFHX0NMS0RJVjIJCQlCSVQoMTMpCisK Ky8qIHJlcXVlc3QgQUNLIGZyb20gcGVyaXBoZXJhbCAqLworI2RlZmluZSBNSVBJX0RTSV9NU0df UkVRX0FDSwlCSVQoMCkKKy8qIHVzZSBMb3cgUG93ZXIgTW9kZSB0byB0cmFuc21pdCBtZXNzYWdl ICovCisjZGVmaW5lIE1JUElfRFNJX01TR19VU0VfTFBNCUJJVCgxKQorCitzc2l6ZV90IG1pcGlf ZHNpX2Rjc193cml0ZV9idWZmZXIoc3RydWN0IG1pcGlfZHNpX2RldmljZSAqZHNpLAorCQkJCSAg Y29uc3Qgdm9pZCAqZGF0YSwgc2l6ZV90IGxlbik7Citzc2l6ZV90IG1pcGlfZHNpX2Rjc193cml0 ZShzdHJ1Y3QgbWlwaV9kc2lfZGV2aWNlICpkc2ksIHU4IGNtZCwKKwkJCSAgIGNvbnN0IHZvaWQg KmRhdGEsIHNpemVfdCBsZW4pOworc3NpemVfdCBtaXBpX2RzaV9kY3NfcmVhZChzdHJ1Y3QgbWlw aV9kc2lfZGV2aWNlICpkc2ksIHU4IGNtZCwgdm9pZCAqZGF0YSwKKwkJCSAgc2l6ZV90IGxlbik7 CitpbnQgbWlwaV9kc2lfZGNzX25vcChzdHJ1Y3QgbWlwaV9kc2lfZGV2aWNlICpkc2kpOworaW50 IG1pcGlfZHNpX2Rjc19zb2Z0X3Jlc2V0KHN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRzaSk7Citp bnQgbWlwaV9kc2lfZGNzX2dldF9wb3dlcl9tb2RlKHN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRz aSwgdTggKm1vZGUpOworaW50IG1pcGlfZHNpX2Rjc19nZXRfcGl4ZWxfZm9ybWF0KHN0cnVjdCBt aXBpX2RzaV9kZXZpY2UgKmRzaSwgdTggKmZvcm1hdCk7CitpbnQgbWlwaV9kc2lfZGNzX2VudGVy X3NsZWVwX21vZGUoc3RydWN0IG1pcGlfZHNpX2RldmljZSAqZHNpKTsKK2ludCBtaXBpX2RzaV9k Y3NfZXhpdF9zbGVlcF9tb2RlKHN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRzaSk7CitpbnQgbWlw aV9kc2lfZGNzX3NldF9kaXNwbGF5X29mZihzdHJ1Y3QgbWlwaV9kc2lfZGV2aWNlICpkc2kpOwor aW50IG1pcGlfZHNpX2Rjc19zZXRfZGlzcGxheV9vbihzdHJ1Y3QgbWlwaV9kc2lfZGV2aWNlICpk c2kpOworaW50IG1pcGlfZHNpX2Rjc19zZXRfY29sdW1uX2FkZHJlc3Moc3RydWN0IG1pcGlfZHNp X2RldmljZSAqZHNpLCB1MTYgc3RhcnQsCisJCQkJICAgIHUxNiBlbmQpOworaW50IG1pcGlfZHNp X2Rjc19zZXRfcGFnZV9hZGRyZXNzKHN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRzaSwgdTE2IHN0 YXJ0LAorCQkJCSAgdTE2IGVuZCk7CitpbnQgbWlwaV9kc2lfZGNzX3NldF90ZWFyX29mZihzdHJ1 Y3QgbWlwaV9kc2lfZGV2aWNlICpkc2kpOworaW50IG1pcGlfZHNpX2Rjc19zZXRfdGVhcl9vbihz dHJ1Y3QgbWlwaV9kc2lfZGV2aWNlICpkc2ksCisJCQkgICAgIGVudW0gbWlwaV9kc2lfZGNzX3Rl YXJfbW9kZSBtb2RlKTsKK2ludCBtaXBpX2RzaV9kY3Nfc2V0X3BpeGVsX2Zvcm1hdChzdHJ1Y3Qg bWlwaV9kc2lfZGV2aWNlICpkc2ksIHU4IGZvcm1hdCk7CitpbnQgbWlwaV9kc2lfZGNzX3NldF90 ZWFyX3NjYW5saW5lKHN0cnVjdCBtaXBpX2RzaV9kZXZpY2UgKmRzaSwgdTE2IHNjYW5saW5lKTsK K2ludCBtaXBpX2RzaV9kY3Nfc2V0X2Rpc3BsYXlfYnJpZ2h0bmVzcyhzdHJ1Y3QgbWlwaV9kc2lf ZGV2aWNlICpkc2ksCisJCQkJCXUxNiBicmlnaHRuZXNzKTsKK2ludCBtaXBpX2RzaV9kY3NfZ2V0 X2Rpc3BsYXlfYnJpZ2h0bmVzcyhzdHJ1Y3QgbWlwaV9kc2lfZGV2aWNlICpkc2ksCisJCQkJCXUx NiAqYnJpZ2h0bmVzcyk7CisKICNlbmRpZgotLSAKMS45LjEKCl9fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fCmRyaS1kZXZlbCBtYWlsaW5nIGxpc3QKZHJpLWRl dmVsQGxpc3RzLmZyZWVkZXNrdG9wLm9yZwpodHRwczovL2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9t YWlsbWFuL2xpc3RpbmZvL2RyaS1kZXZlbAo= From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1427926AbeCBPto (ORCPT ); Fri, 2 Mar 2018 10:49:44 -0500 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:7366 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S936273AbeCBPol (ORCPT ); Fri, 2 Mar 2018 10:44:41 -0500 From: yannick fertre To: Vikas Manocha , Benjamin Gaignard , Yannick Fertre , Philippe Cornu , Patrice Chotard , Patrick DELAUNAY , Christophe KERELLO , Archit Taneja , Andrzej Hajda , "Laurent Pinchart" , David Airlie , Brian Norris , Bhumika Goyal , Gustavo Padovan , "Maarten Lankhorst" , Sean Paul , Albert Aribaud , "Simon Glass" , Anatolij Gustschin , Thierry Reding CC: , , Subject: [PATCH v2 03/10] video: add support of MIPI DSI interface Date: Fri, 2 Mar 2018 16:44:04 +0100 Message-ID: <1520005451-23217-4-git-send-email-yannick.fertre@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1520005451-23217-1-git-send-email-yannick.fertre@st.com> References: <1520005451-23217-1-git-send-email-yannick.fertre@st.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.201.23.68] X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2018-03-02_08:,, signatures=0 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Mipi_display.c contains a set of dsi helpers. This file is a copy of file drm_mipi_dsi.c (linux kernel). Signed-off-by: yannick fertre --- drivers/video/Kconfig | 7 + drivers/video/Makefile | 1 + drivers/video/mipi_display.c | 807 +++++++++++++++++++++++++++++++++++++++++++ include/mipi_display.h | 257 +++++++++++++- 4 files changed, 1071 insertions(+), 1 deletion(-) create mode 100644 drivers/video/mipi_display.c diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 2fc0def..1981298 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -75,6 +75,13 @@ config VIDEO_ANSI Enable ANSI escape sequence decoding for a more fully functional console. +config VIDEO_MIPI_DSI + bool "Support MIPI DSI interface" + depends on DM_VIDEO + default y if DM_VIDEO + help + Support MIPI DSI interface for driving a MIPI compatible LCD panel. + config CONSOLE_NORMAL bool "Support a simple text console" depends on DM_VIDEO diff --git a/drivers/video/Makefile b/drivers/video/Makefile index dfafe08..6f42cca 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_FORMIKE) += formike.o obj-$(CONFIG_LG4573) += lg4573.o obj-$(CONFIG_AM335X_LCD) += am335x-fb.o obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o +obj-${CONFIG_VIDEO_MIPI_DSI} += mipi_display.o obj-$(CONFIG_VIDEO_SIMPLE) += simplefb.o obj-${CONFIG_VIDEO_TEGRA124} += tegra124/ obj-${CONFIG_EXYNOS_FB} += exynos/ diff --git a/drivers/video/mipi_display.c b/drivers/video/mipi_display.c new file mode 100644 index 0000000..d90ff5d --- /dev/null +++ b/drivers/video/mipi_display.c @@ -0,0 +1,807 @@ +/* + * MIPI DSI Bus + * + * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd. + * Copyright (C) 2018 STMicroelectronics - All Rights Reserved + * Andrzej Hajda + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +/** + * DOC: dsi helpers + * + * These functions contain some common logic and helpers to deal with MIPI DSI + * peripherals. + * + * Helpers are provided for a number of standard MIPI DSI command as well as a + * subset of the MIPI DCS command set. + */ + +/** + * mipi_dsi_attach - attach a DSI device to its DSI host + * @dsi: DSI peripheral + */ +int mipi_dsi_attach(struct mipi_dsi_device *dsi) +{ + const struct mipi_dsi_host_ops *ops = dsi->host->ops; + + if (!ops || !ops->attach) + return -ENOSYS; + + return ops->attach(dsi->host, dsi); +} +EXPORT_SYMBOL(mipi_dsi_attach); + +/** + * mipi_dsi_detach - detach a DSI device from its DSI host + * @dsi: DSI peripheral + */ +int mipi_dsi_detach(struct mipi_dsi_device *dsi) +{ + const struct mipi_dsi_host_ops *ops = dsi->host->ops; + + if (!ops || !ops->detach) + return -ENOSYS; + + return ops->detach(dsi->host, dsi); +} +EXPORT_SYMBOL(mipi_dsi_detach); + +static ssize_t mipi_dsi_device_transfer(struct mipi_dsi_device *dsi, + struct mipi_dsi_msg *msg) +{ + const struct mipi_dsi_host_ops *ops = dsi->host->ops; + + if (!ops || !ops->transfer) + return -ENOSYS; + + if (dsi->mode_flags & MIPI_DSI_MODE_LPM) + msg->flags |= MIPI_DSI_MSG_USE_LPM; + + return ops->transfer(dsi->host, msg); +} + +/** + * mipi_dsi_packet_format_is_short - check if a packet is of the short format + * @type: MIPI DSI data type of the packet + * + * Return: true if the packet for the given data type is a short packet, false + * otherwise. + */ +bool mipi_dsi_packet_format_is_short(u8 type) +{ + switch (type) { + case MIPI_DSI_V_SYNC_START: + case MIPI_DSI_V_SYNC_END: + case MIPI_DSI_H_SYNC_START: + case MIPI_DSI_H_SYNC_END: + case MIPI_DSI_END_OF_TRANSMISSION: + case MIPI_DSI_COLOR_MODE_OFF: + case MIPI_DSI_COLOR_MODE_ON: + case MIPI_DSI_SHUTDOWN_PERIPHERAL: + case MIPI_DSI_TURN_ON_PERIPHERAL: + case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: + case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: + case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: + case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM: + case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM: + case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM: + case MIPI_DSI_DCS_SHORT_WRITE: + case MIPI_DSI_DCS_SHORT_WRITE_PARAM: + case MIPI_DSI_DCS_READ: + case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE: + return true; + } + + return false; +} +EXPORT_SYMBOL(mipi_dsi_packet_format_is_short); + +/** + * mipi_dsi_packet_format_is_long - check if a packet is of the long format + * @type: MIPI DSI data type of the packet + * + * Return: true if the packet for the given data type is a long packet, false + * otherwise. + */ +bool mipi_dsi_packet_format_is_long(u8 type) +{ + switch (type) { + case MIPI_DSI_NULL_PACKET: + case MIPI_DSI_BLANKING_PACKET: + case MIPI_DSI_GENERIC_LONG_WRITE: + case MIPI_DSI_DCS_LONG_WRITE: + case MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20: + case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24: + case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16: + case MIPI_DSI_PACKED_PIXEL_STREAM_30: + case MIPI_DSI_PACKED_PIXEL_STREAM_36: + case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12: + case MIPI_DSI_PACKED_PIXEL_STREAM_16: + case MIPI_DSI_PACKED_PIXEL_STREAM_18: + case MIPI_DSI_PIXEL_STREAM_3BYTE_18: + case MIPI_DSI_PACKED_PIXEL_STREAM_24: + return true; + } + + return false; +} +EXPORT_SYMBOL(mipi_dsi_packet_format_is_long); + +/** + * mipi_dsi_create_packet - create a packet from a message according to the + * DSI protocol + * @packet: pointer to a DSI packet structure + * @msg: message to translate into a packet + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, + const struct mipi_dsi_msg *msg) +{ + if (!packet || !msg) + return -EINVAL; + + /* do some minimum sanity checking */ + if (!mipi_dsi_packet_format_is_short(msg->type) && + !mipi_dsi_packet_format_is_long(msg->type)) + return -EINVAL; + + if (msg->channel > 3) + return -EINVAL; + + memset(packet, 0, sizeof(*packet)); + packet->header[0] = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f); + + /* TODO: compute ECC if hardware support is not available */ + + /* + * Long write packets contain the word count in header bytes 1 and 2. + * The payload follows the header and is word count bytes long. + * + * Short write packets encode up to two parameters in header bytes 1 + * and 2. + */ + if (mipi_dsi_packet_format_is_long(msg->type)) { + packet->header[1] = (msg->tx_len >> 0) & 0xff; + packet->header[2] = (msg->tx_len >> 8) & 0xff; + + packet->payload_length = msg->tx_len; + packet->payload = msg->tx_buf; + } else { + const u8 *tx = msg->tx_buf; + + packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0; + packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0; + } + + packet->size = sizeof(packet->header) + packet->payload_length; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_create_packet); + +/* + * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the + * the payload in a long packet transmitted from the peripheral back to the + * host processor + * @dsi: DSI peripheral device + * @value: the maximum size of the payload + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi, + u16 value) +{ + u8 tx[2] = { value & 0xff, value >> 8 }; + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, + .tx_len = sizeof(tx), + .tx_buf = tx, + }; + int ret = mipi_dsi_device_transfer(dsi, &msg); + + return (ret < 0) ? ret : 0; +} +EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size); + +/** + * mipi_dsi_generic_write() - transmit data using a generic write packet + * @dsi: DSI peripheral device + * @payload: buffer containing the payload + * @size: size of payload buffer + * + * This function will automatically choose the right data type depending on + * the payload length. + * + * Return: The number of bytes transmitted on success or a negative error code + * on failure. + */ +ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload, + size_t size) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .tx_buf = payload, + .tx_len = size + }; + + switch (size) { + case 0: + msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM; + break; + + case 1: + msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM; + break; + + case 2: + msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM; + break; + + default: + msg.type = MIPI_DSI_GENERIC_LONG_WRITE; + break; + } + + return mipi_dsi_device_transfer(dsi, &msg); +} +EXPORT_SYMBOL(mipi_dsi_generic_write); + +/** + * mipi_dsi_generic_read() - receive data using a generic read packet + * @dsi: DSI peripheral device + * @params: buffer containing the request parameters + * @num_params: number of request parameters + * @data: buffer in which to return the received data + * @size: size of receive buffer + * + * This function will automatically choose the right data type depending on + * the number of parameters passed in. + * + * Return: The number of bytes successfully read or a negative error code on + * failure. + */ +ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params, + size_t num_params, void *data, size_t size) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .tx_len = num_params, + .tx_buf = params, + .rx_len = size, + .rx_buf = data + }; + + switch (num_params) { + case 0: + msg.type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM; + break; + + case 1: + msg.type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM; + break; + + case 2: + msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM; + break; + + default: + return -EINVAL; + } + + return mipi_dsi_device_transfer(dsi, &msg); +} +EXPORT_SYMBOL(mipi_dsi_generic_read); + +/** + * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload + * @dsi: DSI peripheral device + * @data: buffer containing data to be transmitted + * @len: size of transmission buffer + * + * This function will automatically choose the right data type depending on + * the command payload length. + * + * Return: The number of bytes successfully transmitted or a negative error + * code on failure. + */ +ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi, + const void *data, size_t len) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .tx_buf = data, + .tx_len = len + }; + + switch (len) { + case 0: + return -EINVAL; + + case 1: + msg.type = MIPI_DSI_DCS_SHORT_WRITE; + break; + + case 2: + msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM; + break; + + default: + msg.type = MIPI_DSI_DCS_LONG_WRITE; + break; + } + + return mipi_dsi_device_transfer(dsi, &msg); +} +EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer); + +/** + * mipi_dsi_dcs_write() - send DCS write command + * @dsi: DSI peripheral device + * @cmd: DCS command + * @data: buffer containing the command payload + * @len: command payload length + * + * This function will automatically choose the right data type depending on + * the command payload length. + * + * Return: The number of bytes successfully transmitted or a negative error + * code on failure. + */ +ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd, + const void *data, size_t len) +{ + ssize_t err; + size_t size; + u8 *tx; + + if (len > 0) { + size = 1 + len; + + tx = kmalloc(size, GFP_KERNEL); + if (!tx) + return -ENOMEM; + + /* concatenate the DCS command byte and the payload */ + tx[0] = cmd; + memcpy(&tx[1], data, len); + } else { + tx = &cmd; + size = 1; + } + + err = mipi_dsi_dcs_write_buffer(dsi, tx, size); + + if (len > 0) + kfree(tx); + + return err; +} +EXPORT_SYMBOL(mipi_dsi_dcs_write); + +/** + * mipi_dsi_dcs_read() - send DCS read request command + * @dsi: DSI peripheral device + * @cmd: DCS command + * @data: buffer in which to receive data + * @len: size of receive buffer + * + * Return: The number of bytes read or a negative error code on failure. + */ +ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data, + size_t len) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .type = MIPI_DSI_DCS_READ, + .tx_buf = &cmd, + .tx_len = 1, + .rx_buf = data, + .rx_len = len + }; + + return mipi_dsi_device_transfer(dsi, &msg); +} +EXPORT_SYMBOL(mipi_dsi_dcs_read); + +/** + * mipi_dsi_pixel_format_to_bpp - obtain the number of bits per pixel for any + * given pixel format defined by the MIPI DSI + * specification + * @fmt: MIPI DSI pixel format + * + * Returns: The number of bits per pixel of the given pixel format. + */ +int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt) +{ + switch (fmt) { + case MIPI_DSI_FMT_RGB888: + case MIPI_DSI_FMT_RGB666: + return 24; + + case MIPI_DSI_FMT_RGB666_PACKED: + return 18; + + case MIPI_DSI_FMT_RGB565: + return 16; + } + + return -EINVAL; +} +EXPORT_SYMBOL(mipi_dsi_pixel_format_to_bpp); + +/** + * mipi_dsi_dcs_nop() - send DCS nop packet + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_NOP, NULL, 0); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_nop); + +/** + * mipi_dsi_dcs_soft_reset() - perform a software reset of the display module + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SOFT_RESET, NULL, 0); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_soft_reset); + +/** + * mipi_dsi_dcs_get_power_mode() - query the display module's current power + * mode + * @dsi: DSI peripheral device + * @mode: return location for the current power mode + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode) +{ + ssize_t err; + + err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_POWER_MODE, mode, + sizeof(*mode)); + if (err <= 0) { + if (err == 0) + err = -ENODATA; + + return err; + } + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_get_power_mode); + +/** + * mipi_dsi_dcs_get_pixel_format() - gets the pixel format for the RGB image + * data used by the interface + * @dsi: DSI peripheral device + * @format: return location for the pixel format + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format) +{ + ssize_t err; + + err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_PIXEL_FORMAT, format, + sizeof(*format)); + if (err <= 0) { + if (err == 0) + err = -ENODATA; + + return err; + } + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_get_pixel_format); + +/** + * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the + * display module except interface communication + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode); + +/** + * mipi_dsi_dcs_exit_sleep_mode() - enable all blocks inside the display + * module + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode); + +/** + * mipi_dsi_dcs_set_display_off() - stop displaying the image data on the + * display device + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off); + +/** + * mipi_dsi_dcs_set_display_on() - start displaying the image data on the + * display device + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure + */ +int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on); + +/** + * mipi_dsi_dcs_set_column_address() - define the column extent of the frame + * memory accessed by the host processor + * @dsi: DSI peripheral device + * @start: first column of frame memory + * @end: last column of frame memory + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start, + u16 end) +{ + u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff }; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_COLUMN_ADDRESS, payload, + sizeof(payload)); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_column_address); + +/** + * mipi_dsi_dcs_set_page_address() - define the page extent of the frame + * memory accessed by the host processor + * @dsi: DSI peripheral device + * @start: first page of frame memory + * @end: last page of frame memory + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start, + u16 end) +{ + u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff }; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PAGE_ADDRESS, payload, + sizeof(payload)); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_page_address); + +/** + * mipi_dsi_dcs_set_tear_off() - turn off the display module's Tearing Effect + * output signal on the TE signal line + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure + */ +int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_off); + +/** + * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect + * output signal on the TE signal line. + * @dsi: DSI peripheral device + * @mode: the Tearing Effect Output Line mode + * + * Return: 0 on success or a negative error code on failure + */ +int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi, + enum mipi_dsi_dcs_tear_mode mode) +{ + u8 value = mode; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, &value, + sizeof(value)); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on); + +/** + * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image + * data used by the interface + * @dsi: DSI peripheral device + * @format: pixel format + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, &format, + sizeof(format)); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format); + +/** + * mipi_dsi_dcs_set_tear_scanline() - set the scanline to use as trigger for + * the Tearing Effect output signal of the display module + * @dsi: DSI peripheral device + * @scanline: scanline to use as trigger + * + * Return: 0 on success or a negative error code on failure + */ +int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline) +{ + u8 payload[3] = { MIPI_DCS_SET_TEAR_SCANLINE, scanline >> 8, + scanline & 0xff }; + ssize_t err; + + err = mipi_dsi_generic_write(dsi, payload, sizeof(payload)); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_scanline); + +/** + * mipi_dsi_dcs_set_display_brightness() - sets the brightness value of the + * display + * @dsi: DSI peripheral device + * @brightness: brightness value + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi, + u16 brightness) +{ + u8 payload[2] = { brightness & 0xff, brightness >> 8 }; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, + payload, sizeof(payload)); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_display_brightness); + +/** + * mipi_dsi_dcs_get_display_brightness() - gets the current brightness value + * of the display + * @dsi: DSI peripheral device + * @brightness: brightness value + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi, + u16 *brightness) +{ + ssize_t err; + + err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_DISPLAY_BRIGHTNESS, + brightness, sizeof(*brightness)); + if (err <= 0) { + if (err == 0) + err = -ENODATA; + + return err; + } + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_get_display_brightness); + +MODULE_AUTHOR("Andrzej Hajda "); +MODULE_AUTHOR("Yannick Fertre "); +MODULE_DESCRIPTION("MIPI DSI Bus"); +MODULE_LICENSE("GPL and additional rights"); diff --git a/include/mipi_display.h b/include/mipi_display.h index ddcc8ca..8f9d4a4 100644 --- a/include/mipi_display.h +++ b/include/mipi_display.h @@ -4,12 +4,16 @@ * * Copyright (C) 2010 Guennadi Liakhovetski * Copyright (C) 2006 Nokia Corporation - * Author: Imre Deak + * Copyright (C) 2018 STMicroelectronics - All Rights Reserved + * Author(s): Imre Deak + * Yannick Fertre + * Philippe Cornu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ + #ifndef MIPI_DISPLAY_H #define MIPI_DISPLAY_H @@ -115,6 +119,14 @@ enum { MIPI_DCS_READ_MEMORY_CONTINUE = 0x3E, MIPI_DCS_SET_TEAR_SCANLINE = 0x44, MIPI_DCS_GET_SCANLINE = 0x45, + MIPI_DCS_SET_DISPLAY_BRIGHTNESS = 0x51, /* MIPI DCS 1.3 */ + MIPI_DCS_GET_DISPLAY_BRIGHTNESS = 0x52, /* MIPI DCS 1.3 */ + MIPI_DCS_WRITE_CONTROL_DISPLAY = 0x53, /* MIPI DCS 1.3 */ + MIPI_DCS_GET_CONTROL_DISPLAY = 0x54, /* MIPI DCS 1.3 */ + MIPI_DCS_WRITE_POWER_SAVE = 0x55, /* MIPI DCS 1.3 */ + MIPI_DCS_GET_POWER_SAVE = 0x56, /* MIPI DCS 1.3 */ + MIPI_DCS_SET_CABC_MIN_BRIGHTNESS = 0x5E, /* MIPI DCS 1.3 */ + MIPI_DCS_GET_CABC_MIN_BRIGHTNESS = 0x5F, /* MIPI DCS 1.3 */ MIPI_DCS_READ_DDB_START = 0xA1, MIPI_DCS_READ_DDB_CONTINUE = 0xA8, }; @@ -127,4 +139,247 @@ enum { #define MIPI_DCS_PIXEL_FMT_8BIT 2 #define MIPI_DCS_PIXEL_FMT_3BIT 1 +struct mipi_dsi_host; +struct mipi_dsi_device; + +/* request ACK from peripheral */ +#define MIPI_DSI_MSG_REQ_ACK BIT(0) +/* use Low Power Mode to transmit message */ +#define MIPI_DSI_MSG_USE_LPM BIT(1) + +/** + * struct mipi_dsi_msg - read/write DSI buffer + * @channel: virtual channel id + * @type: payload data type + * @flags: flags controlling this message transmission + * @tx_len: length of @tx_buf + * @tx_buf: data to be written + * @rx_len: length of @rx_buf + * @rx_buf: data to be read, or NULL + */ +struct mipi_dsi_msg { + u8 channel; + u8 type; + u16 flags; + + size_t tx_len; + const void *tx_buf; + + size_t rx_len; + void *rx_buf; +}; + +bool mipi_dsi_packet_format_is_short(u8 type); +bool mipi_dsi_packet_format_is_long(u8 type); + +/** + * struct mipi_dsi_packet - represents a MIPI DSI packet in protocol format + * @size: size (in bytes) of the packet + * @header: the four bytes that make up the header (Data ID, Word Count or + * Packet Data, and ECC) + * @payload_length: number of bytes in the payload + * @payload: a pointer to a buffer containing the payload, if any + */ +struct mipi_dsi_packet { + size_t size; + u8 header[4]; + size_t payload_length; + const u8 *payload; +}; + +int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, + const struct mipi_dsi_msg *msg); + +/** + * struct mipi_dsi_host_ops - DSI bus operations + * @attach: attach DSI device to DSI host + * @detach: detach DSI device from DSI host + * @transfer: transmit a DSI packet + * + * DSI packets transmitted by .transfer() are passed in as mipi_dsi_msg + * structures. This structure contains information about the type of packet + * being transmitted as well as the transmit and receive buffers. When an + * error is encountered during transmission, this function will return a + * negative error code. On success it shall return the number of bytes + * transmitted for write packets or the number of bytes received for read + * packets. + * + * Note that typically DSI packet transmission is atomic, so the .transfer() + * function will seldomly return anything other than the number of bytes + * contained in the transmit buffer on success. + */ +struct mipi_dsi_host_ops { + int (*attach)(struct mipi_dsi_host *host, + struct mipi_dsi_device *dsi); + int (*detach)(struct mipi_dsi_host *host, + struct mipi_dsi_device *dsi); + ssize_t (*transfer)(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg); +}; + +/** + * struct mipi_dsi_host - DSI host device + * @dev: driver model device node for this DSI host + * @ops: DSI host operations + * @list: list management + */ +struct mipi_dsi_host { + struct device *dev; + const struct mipi_dsi_host_ops *ops; + struct list_head list; +}; + +/* DSI mode flags */ + +/* video mode */ +#define MIPI_DSI_MODE_VIDEO BIT(0) +/* video burst mode */ +#define MIPI_DSI_MODE_VIDEO_BURST BIT(1) +/* video pulse mode */ +#define MIPI_DSI_MODE_VIDEO_SYNC_PULSE BIT(2) +/* enable auto vertical count mode */ +#define MIPI_DSI_MODE_VIDEO_AUTO_VERT BIT(3) +/* enable hsync-end packets in vsync-pulse and v-porch area */ +#define MIPI_DSI_MODE_VIDEO_HSE BIT(4) +/* disable hfront-porch area */ +#define MIPI_DSI_MODE_VIDEO_HFP BIT(5) +/* disable hback-porch area */ +#define MIPI_DSI_MODE_VIDEO_HBP BIT(6) +/* disable hsync-active area */ +#define MIPI_DSI_MODE_VIDEO_HSA BIT(7) +/* flush display FIFO on vsync pulse */ +#define MIPI_DSI_MODE_VSYNC_FLUSH BIT(8) +/* disable EoT packets in HS mode */ +#define MIPI_DSI_MODE_EOT_PACKET BIT(9) +/* device supports non-continuous clock behavior (DSI spec 5.6.1) */ +#define MIPI_DSI_CLOCK_NON_CONTINUOUS BIT(10) +/* transmit data in low power */ +#define MIPI_DSI_MODE_LPM BIT(11) + +enum mipi_dsi_pixel_format { + MIPI_DSI_FMT_RGB888, + MIPI_DSI_FMT_RGB666, + MIPI_DSI_FMT_RGB666_PACKED, + MIPI_DSI_FMT_RGB565, +}; + +#define DSI_DEV_NAME_SIZE 20 + +/** + * struct mipi_dsi_device_info - template for creating a mipi_dsi_device + * @type: DSI peripheral chip type + * @channel: DSI virtual channel assigned to peripheral + * @node: pointer to OF device node or NULL + * + * This is populated and passed to mipi_dsi_device_new to create a new + * DSI device + */ +struct mipi_dsi_device_info { + char type[DSI_DEV_NAME_SIZE]; + u32 channel; + struct device_node *node; +}; + +/** + * struct mipi_dsi_device - DSI peripheral device + * @host: DSI host for this peripheral + * @dev: driver model device node for this peripheral + * @name: DSI peripheral chip type + * @channel: virtual channel assigned to the peripheral + * @format: pixel format for video mode + * @lanes: number of active data lanes + * @mode_flags: DSI operation mode related flags + */ +struct mipi_dsi_device { + struct mipi_dsi_host *host; + struct udevice *dev; + + char name[DSI_DEV_NAME_SIZE]; + unsigned int channel; + unsigned int lanes; + enum mipi_dsi_pixel_format format; + unsigned long mode_flags; +}; + +/** + * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode + * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking + * information only + * @MIPI_DSI_DCS_TEAR_MODE_VHBLANK : the TE output line consists of both + * V-Blanking and H-Blanking information + */ +enum mipi_dsi_dcs_tear_mode { + MIPI_DSI_DCS_TEAR_MODE_VBLANK, + MIPI_DSI_DCS_TEAR_MODE_VHBLANK, +}; + +/** + * struct mipi_dsi_panel_plat - DSI panel platform data + * @device: DSI peripheral device + */ +struct mipi_dsi_panel_plat { + struct mipi_dsi_device *device; +}; + +int mipi_dsi_attach(struct mipi_dsi_device *dsi); +int mipi_dsi_detach(struct mipi_dsi_device *dsi); +int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt); + +/* bit compatible with the xrandr RR_ definitions (bits 0-13) + * + * ABI warning: Existing userspace really expects + * the mode flags to match the xrandr definitions. Any + * changes that don't match the xrandr definitions will + * likely need a new client cap or some other mechanism + * to avoid breaking existing userspace. This includes + * allocating new flags in the previously unused bits! + */ +#define MIPI_DSI_FLAG_PHSYNC BIT(0) +#define MIPI_DSI_FLAG_NHSYNC BIT(1) +#define MIPI_DSI_FLAG_PVSYNC BIT(2) +#define MIPI_DSI_FLAG_NVSYNC BIT(3) +#define MIPI_DSI_FLAG_INTERLACE BIT(4) +#define MIPI_DSI_FLAG_DBLSCAN BIT(5) +#define MIPI_DSI_FLAG_CSYNC BIT(6) +#define MIPI_DSI_FLAG_PCSYNC BIT(7) +#define MIPI_DSI_FLAG_NCSYNC BIT(8) +#define MIPI_DSI_FLAG_HSKEW BIT(9) /* hskew provided */ +#define MIPI_DSI_FLAG_BCAST BIT(10) +#define MIPI_DSI_FLAG_PIXMUX BIT(11) +#define MIPI_DSI_FLAG_DBLCLK BIT(12) +#define MIPI_DSI_FLAG_CLKDIV2 BIT(13) + +/* request ACK from peripheral */ +#define MIPI_DSI_MSG_REQ_ACK BIT(0) +/* use Low Power Mode to transmit message */ +#define MIPI_DSI_MSG_USE_LPM BIT(1) + +ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi, + const void *data, size_t len); +ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd, + const void *data, size_t len); +ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data, + size_t len); +int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode); +int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format); +int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start, + u16 end); +int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start, + u16 end); +int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi, + enum mipi_dsi_dcs_tear_mode mode); +int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format); +int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline); +int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi, + u16 brightness); +int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi, + u16 *brightness); + #endif -- 1.9.1 From mboxrd@z Thu Jan 1 00:00:00 1970 From: yannick fertre Date: Fri, 2 Mar 2018 16:44:04 +0100 Subject: [U-Boot] [PATCH v2 03/10] video: add support of MIPI DSI interface In-Reply-To: <1520005451-23217-1-git-send-email-yannick.fertre@st.com> References: <1520005451-23217-1-git-send-email-yannick.fertre@st.com> Message-ID: <1520005451-23217-4-git-send-email-yannick.fertre@st.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Mipi_display.c contains a set of dsi helpers. This file is a copy of file drm_mipi_dsi.c (linux kernel). Signed-off-by: yannick fertre --- drivers/video/Kconfig | 7 + drivers/video/Makefile | 1 + drivers/video/mipi_display.c | 807 +++++++++++++++++++++++++++++++++++++++++++ include/mipi_display.h | 257 +++++++++++++- 4 files changed, 1071 insertions(+), 1 deletion(-) create mode 100644 drivers/video/mipi_display.c diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 2fc0def..1981298 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -75,6 +75,13 @@ config VIDEO_ANSI Enable ANSI escape sequence decoding for a more fully functional console. +config VIDEO_MIPI_DSI + bool "Support MIPI DSI interface" + depends on DM_VIDEO + default y if DM_VIDEO + help + Support MIPI DSI interface for driving a MIPI compatible LCD panel. + config CONSOLE_NORMAL bool "Support a simple text console" depends on DM_VIDEO diff --git a/drivers/video/Makefile b/drivers/video/Makefile index dfafe08..6f42cca 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_FORMIKE) += formike.o obj-$(CONFIG_LG4573) += lg4573.o obj-$(CONFIG_AM335X_LCD) += am335x-fb.o obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o +obj-${CONFIG_VIDEO_MIPI_DSI} += mipi_display.o obj-$(CONFIG_VIDEO_SIMPLE) += simplefb.o obj-${CONFIG_VIDEO_TEGRA124} += tegra124/ obj-${CONFIG_EXYNOS_FB} += exynos/ diff --git a/drivers/video/mipi_display.c b/drivers/video/mipi_display.c new file mode 100644 index 0000000..d90ff5d --- /dev/null +++ b/drivers/video/mipi_display.c @@ -0,0 +1,807 @@ +/* + * MIPI DSI Bus + * + * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd. + * Copyright (C) 2018 STMicroelectronics - All Rights Reserved + * Andrzej Hajda + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +/** + * DOC: dsi helpers + * + * These functions contain some common logic and helpers to deal with MIPI DSI + * peripherals. + * + * Helpers are provided for a number of standard MIPI DSI command as well as a + * subset of the MIPI DCS command set. + */ + +/** + * mipi_dsi_attach - attach a DSI device to its DSI host + * @dsi: DSI peripheral + */ +int mipi_dsi_attach(struct mipi_dsi_device *dsi) +{ + const struct mipi_dsi_host_ops *ops = dsi->host->ops; + + if (!ops || !ops->attach) + return -ENOSYS; + + return ops->attach(dsi->host, dsi); +} +EXPORT_SYMBOL(mipi_dsi_attach); + +/** + * mipi_dsi_detach - detach a DSI device from its DSI host + * @dsi: DSI peripheral + */ +int mipi_dsi_detach(struct mipi_dsi_device *dsi) +{ + const struct mipi_dsi_host_ops *ops = dsi->host->ops; + + if (!ops || !ops->detach) + return -ENOSYS; + + return ops->detach(dsi->host, dsi); +} +EXPORT_SYMBOL(mipi_dsi_detach); + +static ssize_t mipi_dsi_device_transfer(struct mipi_dsi_device *dsi, + struct mipi_dsi_msg *msg) +{ + const struct mipi_dsi_host_ops *ops = dsi->host->ops; + + if (!ops || !ops->transfer) + return -ENOSYS; + + if (dsi->mode_flags & MIPI_DSI_MODE_LPM) + msg->flags |= MIPI_DSI_MSG_USE_LPM; + + return ops->transfer(dsi->host, msg); +} + +/** + * mipi_dsi_packet_format_is_short - check if a packet is of the short format + * @type: MIPI DSI data type of the packet + * + * Return: true if the packet for the given data type is a short packet, false + * otherwise. + */ +bool mipi_dsi_packet_format_is_short(u8 type) +{ + switch (type) { + case MIPI_DSI_V_SYNC_START: + case MIPI_DSI_V_SYNC_END: + case MIPI_DSI_H_SYNC_START: + case MIPI_DSI_H_SYNC_END: + case MIPI_DSI_END_OF_TRANSMISSION: + case MIPI_DSI_COLOR_MODE_OFF: + case MIPI_DSI_COLOR_MODE_ON: + case MIPI_DSI_SHUTDOWN_PERIPHERAL: + case MIPI_DSI_TURN_ON_PERIPHERAL: + case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: + case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: + case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: + case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM: + case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM: + case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM: + case MIPI_DSI_DCS_SHORT_WRITE: + case MIPI_DSI_DCS_SHORT_WRITE_PARAM: + case MIPI_DSI_DCS_READ: + case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE: + return true; + } + + return false; +} +EXPORT_SYMBOL(mipi_dsi_packet_format_is_short); + +/** + * mipi_dsi_packet_format_is_long - check if a packet is of the long format + * @type: MIPI DSI data type of the packet + * + * Return: true if the packet for the given data type is a long packet, false + * otherwise. + */ +bool mipi_dsi_packet_format_is_long(u8 type) +{ + switch (type) { + case MIPI_DSI_NULL_PACKET: + case MIPI_DSI_BLANKING_PACKET: + case MIPI_DSI_GENERIC_LONG_WRITE: + case MIPI_DSI_DCS_LONG_WRITE: + case MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20: + case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24: + case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16: + case MIPI_DSI_PACKED_PIXEL_STREAM_30: + case MIPI_DSI_PACKED_PIXEL_STREAM_36: + case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12: + case MIPI_DSI_PACKED_PIXEL_STREAM_16: + case MIPI_DSI_PACKED_PIXEL_STREAM_18: + case MIPI_DSI_PIXEL_STREAM_3BYTE_18: + case MIPI_DSI_PACKED_PIXEL_STREAM_24: + return true; + } + + return false; +} +EXPORT_SYMBOL(mipi_dsi_packet_format_is_long); + +/** + * mipi_dsi_create_packet - create a packet from a message according to the + * DSI protocol + * @packet: pointer to a DSI packet structure + * @msg: message to translate into a packet + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, + const struct mipi_dsi_msg *msg) +{ + if (!packet || !msg) + return -EINVAL; + + /* do some minimum sanity checking */ + if (!mipi_dsi_packet_format_is_short(msg->type) && + !mipi_dsi_packet_format_is_long(msg->type)) + return -EINVAL; + + if (msg->channel > 3) + return -EINVAL; + + memset(packet, 0, sizeof(*packet)); + packet->header[0] = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f); + + /* TODO: compute ECC if hardware support is not available */ + + /* + * Long write packets contain the word count in header bytes 1 and 2. + * The payload follows the header and is word count bytes long. + * + * Short write packets encode up to two parameters in header bytes 1 + * and 2. + */ + if (mipi_dsi_packet_format_is_long(msg->type)) { + packet->header[1] = (msg->tx_len >> 0) & 0xff; + packet->header[2] = (msg->tx_len >> 8) & 0xff; + + packet->payload_length = msg->tx_len; + packet->payload = msg->tx_buf; + } else { + const u8 *tx = msg->tx_buf; + + packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0; + packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0; + } + + packet->size = sizeof(packet->header) + packet->payload_length; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_create_packet); + +/* + * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the + * the payload in a long packet transmitted from the peripheral back to the + * host processor + * @dsi: DSI peripheral device + * @value: the maximum size of the payload + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi, + u16 value) +{ + u8 tx[2] = { value & 0xff, value >> 8 }; + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, + .tx_len = sizeof(tx), + .tx_buf = tx, + }; + int ret = mipi_dsi_device_transfer(dsi, &msg); + + return (ret < 0) ? ret : 0; +} +EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size); + +/** + * mipi_dsi_generic_write() - transmit data using a generic write packet + * @dsi: DSI peripheral device + * @payload: buffer containing the payload + * @size: size of payload buffer + * + * This function will automatically choose the right data type depending on + * the payload length. + * + * Return: The number of bytes transmitted on success or a negative error code + * on failure. + */ +ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload, + size_t size) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .tx_buf = payload, + .tx_len = size + }; + + switch (size) { + case 0: + msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM; + break; + + case 1: + msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM; + break; + + case 2: + msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM; + break; + + default: + msg.type = MIPI_DSI_GENERIC_LONG_WRITE; + break; + } + + return mipi_dsi_device_transfer(dsi, &msg); +} +EXPORT_SYMBOL(mipi_dsi_generic_write); + +/** + * mipi_dsi_generic_read() - receive data using a generic read packet + * @dsi: DSI peripheral device + * @params: buffer containing the request parameters + * @num_params: number of request parameters + * @data: buffer in which to return the received data + * @size: size of receive buffer + * + * This function will automatically choose the right data type depending on + * the number of parameters passed in. + * + * Return: The number of bytes successfully read or a negative error code on + * failure. + */ +ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params, + size_t num_params, void *data, size_t size) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .tx_len = num_params, + .tx_buf = params, + .rx_len = size, + .rx_buf = data + }; + + switch (num_params) { + case 0: + msg.type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM; + break; + + case 1: + msg.type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM; + break; + + case 2: + msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM; + break; + + default: + return -EINVAL; + } + + return mipi_dsi_device_transfer(dsi, &msg); +} +EXPORT_SYMBOL(mipi_dsi_generic_read); + +/** + * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload + * @dsi: DSI peripheral device + * @data: buffer containing data to be transmitted + * @len: size of transmission buffer + * + * This function will automatically choose the right data type depending on + * the command payload length. + * + * Return: The number of bytes successfully transmitted or a negative error + * code on failure. + */ +ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi, + const void *data, size_t len) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .tx_buf = data, + .tx_len = len + }; + + switch (len) { + case 0: + return -EINVAL; + + case 1: + msg.type = MIPI_DSI_DCS_SHORT_WRITE; + break; + + case 2: + msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM; + break; + + default: + msg.type = MIPI_DSI_DCS_LONG_WRITE; + break; + } + + return mipi_dsi_device_transfer(dsi, &msg); +} +EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer); + +/** + * mipi_dsi_dcs_write() - send DCS write command + * @dsi: DSI peripheral device + * @cmd: DCS command + * @data: buffer containing the command payload + * @len: command payload length + * + * This function will automatically choose the right data type depending on + * the command payload length. + * + * Return: The number of bytes successfully transmitted or a negative error + * code on failure. + */ +ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd, + const void *data, size_t len) +{ + ssize_t err; + size_t size; + u8 *tx; + + if (len > 0) { + size = 1 + len; + + tx = kmalloc(size, GFP_KERNEL); + if (!tx) + return -ENOMEM; + + /* concatenate the DCS command byte and the payload */ + tx[0] = cmd; + memcpy(&tx[1], data, len); + } else { + tx = &cmd; + size = 1; + } + + err = mipi_dsi_dcs_write_buffer(dsi, tx, size); + + if (len > 0) + kfree(tx); + + return err; +} +EXPORT_SYMBOL(mipi_dsi_dcs_write); + +/** + * mipi_dsi_dcs_read() - send DCS read request command + * @dsi: DSI peripheral device + * @cmd: DCS command + * @data: buffer in which to receive data + * @len: size of receive buffer + * + * Return: The number of bytes read or a negative error code on failure. + */ +ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data, + size_t len) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .type = MIPI_DSI_DCS_READ, + .tx_buf = &cmd, + .tx_len = 1, + .rx_buf = data, + .rx_len = len + }; + + return mipi_dsi_device_transfer(dsi, &msg); +} +EXPORT_SYMBOL(mipi_dsi_dcs_read); + +/** + * mipi_dsi_pixel_format_to_bpp - obtain the number of bits per pixel for any + * given pixel format defined by the MIPI DSI + * specification + * @fmt: MIPI DSI pixel format + * + * Returns: The number of bits per pixel of the given pixel format. + */ +int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt) +{ + switch (fmt) { + case MIPI_DSI_FMT_RGB888: + case MIPI_DSI_FMT_RGB666: + return 24; + + case MIPI_DSI_FMT_RGB666_PACKED: + return 18; + + case MIPI_DSI_FMT_RGB565: + return 16; + } + + return -EINVAL; +} +EXPORT_SYMBOL(mipi_dsi_pixel_format_to_bpp); + +/** + * mipi_dsi_dcs_nop() - send DCS nop packet + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_NOP, NULL, 0); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_nop); + +/** + * mipi_dsi_dcs_soft_reset() - perform a software reset of the display module + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SOFT_RESET, NULL, 0); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_soft_reset); + +/** + * mipi_dsi_dcs_get_power_mode() - query the display module's current power + * mode + * @dsi: DSI peripheral device + * @mode: return location for the current power mode + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode) +{ + ssize_t err; + + err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_POWER_MODE, mode, + sizeof(*mode)); + if (err <= 0) { + if (err == 0) + err = -ENODATA; + + return err; + } + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_get_power_mode); + +/** + * mipi_dsi_dcs_get_pixel_format() - gets the pixel format for the RGB image + * data used by the interface + * @dsi: DSI peripheral device + * @format: return location for the pixel format + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format) +{ + ssize_t err; + + err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_PIXEL_FORMAT, format, + sizeof(*format)); + if (err <= 0) { + if (err == 0) + err = -ENODATA; + + return err; + } + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_get_pixel_format); + +/** + * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the + * display module except interface communication + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode); + +/** + * mipi_dsi_dcs_exit_sleep_mode() - enable all blocks inside the display + * module + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode); + +/** + * mipi_dsi_dcs_set_display_off() - stop displaying the image data on the + * display device + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off); + +/** + * mipi_dsi_dcs_set_display_on() - start displaying the image data on the + * display device + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure + */ +int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on); + +/** + * mipi_dsi_dcs_set_column_address() - define the column extent of the frame + * memory accessed by the host processor + * @dsi: DSI peripheral device + * @start: first column of frame memory + * @end: last column of frame memory + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start, + u16 end) +{ + u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff }; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_COLUMN_ADDRESS, payload, + sizeof(payload)); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_column_address); + +/** + * mipi_dsi_dcs_set_page_address() - define the page extent of the frame + * memory accessed by the host processor + * @dsi: DSI peripheral device + * @start: first page of frame memory + * @end: last page of frame memory + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start, + u16 end) +{ + u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff }; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PAGE_ADDRESS, payload, + sizeof(payload)); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_page_address); + +/** + * mipi_dsi_dcs_set_tear_off() - turn off the display module's Tearing Effect + * output signal on the TE signal line + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure + */ +int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_off); + +/** + * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect + * output signal on the TE signal line. + * @dsi: DSI peripheral device + * @mode: the Tearing Effect Output Line mode + * + * Return: 0 on success or a negative error code on failure + */ +int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi, + enum mipi_dsi_dcs_tear_mode mode) +{ + u8 value = mode; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, &value, + sizeof(value)); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on); + +/** + * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image + * data used by the interface + * @dsi: DSI peripheral device + * @format: pixel format + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, &format, + sizeof(format)); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format); + +/** + * mipi_dsi_dcs_set_tear_scanline() - set the scanline to use as trigger for + * the Tearing Effect output signal of the display module + * @dsi: DSI peripheral device + * @scanline: scanline to use as trigger + * + * Return: 0 on success or a negative error code on failure + */ +int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline) +{ + u8 payload[3] = { MIPI_DCS_SET_TEAR_SCANLINE, scanline >> 8, + scanline & 0xff }; + ssize_t err; + + err = mipi_dsi_generic_write(dsi, payload, sizeof(payload)); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_scanline); + +/** + * mipi_dsi_dcs_set_display_brightness() - sets the brightness value of the + * display + * @dsi: DSI peripheral device + * @brightness: brightness value + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi, + u16 brightness) +{ + u8 payload[2] = { brightness & 0xff, brightness >> 8 }; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, + payload, sizeof(payload)); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_display_brightness); + +/** + * mipi_dsi_dcs_get_display_brightness() - gets the current brightness value + * of the display + * @dsi: DSI peripheral device + * @brightness: brightness value + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi, + u16 *brightness) +{ + ssize_t err; + + err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_DISPLAY_BRIGHTNESS, + brightness, sizeof(*brightness)); + if (err <= 0) { + if (err == 0) + err = -ENODATA; + + return err; + } + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_get_display_brightness); + +MODULE_AUTHOR("Andrzej Hajda "); +MODULE_AUTHOR("Yannick Fertre "); +MODULE_DESCRIPTION("MIPI DSI Bus"); +MODULE_LICENSE("GPL and additional rights"); diff --git a/include/mipi_display.h b/include/mipi_display.h index ddcc8ca..8f9d4a4 100644 --- a/include/mipi_display.h +++ b/include/mipi_display.h @@ -4,12 +4,16 @@ * * Copyright (C) 2010 Guennadi Liakhovetski * Copyright (C) 2006 Nokia Corporation - * Author: Imre Deak + * Copyright (C) 2018 STMicroelectronics - All Rights Reserved + * Author(s): Imre Deak + * Yannick Fertre + * Philippe Cornu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ + #ifndef MIPI_DISPLAY_H #define MIPI_DISPLAY_H @@ -115,6 +119,14 @@ enum { MIPI_DCS_READ_MEMORY_CONTINUE = 0x3E, MIPI_DCS_SET_TEAR_SCANLINE = 0x44, MIPI_DCS_GET_SCANLINE = 0x45, + MIPI_DCS_SET_DISPLAY_BRIGHTNESS = 0x51, /* MIPI DCS 1.3 */ + MIPI_DCS_GET_DISPLAY_BRIGHTNESS = 0x52, /* MIPI DCS 1.3 */ + MIPI_DCS_WRITE_CONTROL_DISPLAY = 0x53, /* MIPI DCS 1.3 */ + MIPI_DCS_GET_CONTROL_DISPLAY = 0x54, /* MIPI DCS 1.3 */ + MIPI_DCS_WRITE_POWER_SAVE = 0x55, /* MIPI DCS 1.3 */ + MIPI_DCS_GET_POWER_SAVE = 0x56, /* MIPI DCS 1.3 */ + MIPI_DCS_SET_CABC_MIN_BRIGHTNESS = 0x5E, /* MIPI DCS 1.3 */ + MIPI_DCS_GET_CABC_MIN_BRIGHTNESS = 0x5F, /* MIPI DCS 1.3 */ MIPI_DCS_READ_DDB_START = 0xA1, MIPI_DCS_READ_DDB_CONTINUE = 0xA8, }; @@ -127,4 +139,247 @@ enum { #define MIPI_DCS_PIXEL_FMT_8BIT 2 #define MIPI_DCS_PIXEL_FMT_3BIT 1 +struct mipi_dsi_host; +struct mipi_dsi_device; + +/* request ACK from peripheral */ +#define MIPI_DSI_MSG_REQ_ACK BIT(0) +/* use Low Power Mode to transmit message */ +#define MIPI_DSI_MSG_USE_LPM BIT(1) + +/** + * struct mipi_dsi_msg - read/write DSI buffer + * @channel: virtual channel id + * @type: payload data type + * @flags: flags controlling this message transmission + * @tx_len: length of @tx_buf + * @tx_buf: data to be written + * @rx_len: length of @rx_buf + * @rx_buf: data to be read, or NULL + */ +struct mipi_dsi_msg { + u8 channel; + u8 type; + u16 flags; + + size_t tx_len; + const void *tx_buf; + + size_t rx_len; + void *rx_buf; +}; + +bool mipi_dsi_packet_format_is_short(u8 type); +bool mipi_dsi_packet_format_is_long(u8 type); + +/** + * struct mipi_dsi_packet - represents a MIPI DSI packet in protocol format + * @size: size (in bytes) of the packet + * @header: the four bytes that make up the header (Data ID, Word Count or + * Packet Data, and ECC) + * @payload_length: number of bytes in the payload + * @payload: a pointer to a buffer containing the payload, if any + */ +struct mipi_dsi_packet { + size_t size; + u8 header[4]; + size_t payload_length; + const u8 *payload; +}; + +int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, + const struct mipi_dsi_msg *msg); + +/** + * struct mipi_dsi_host_ops - DSI bus operations + * @attach: attach DSI device to DSI host + * @detach: detach DSI device from DSI host + * @transfer: transmit a DSI packet + * + * DSI packets transmitted by .transfer() are passed in as mipi_dsi_msg + * structures. This structure contains information about the type of packet + * being transmitted as well as the transmit and receive buffers. When an + * error is encountered during transmission, this function will return a + * negative error code. On success it shall return the number of bytes + * transmitted for write packets or the number of bytes received for read + * packets. + * + * Note that typically DSI packet transmission is atomic, so the .transfer() + * function will seldomly return anything other than the number of bytes + * contained in the transmit buffer on success. + */ +struct mipi_dsi_host_ops { + int (*attach)(struct mipi_dsi_host *host, + struct mipi_dsi_device *dsi); + int (*detach)(struct mipi_dsi_host *host, + struct mipi_dsi_device *dsi); + ssize_t (*transfer)(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg); +}; + +/** + * struct mipi_dsi_host - DSI host device + * @dev: driver model device node for this DSI host + * @ops: DSI host operations + * @list: list management + */ +struct mipi_dsi_host { + struct device *dev; + const struct mipi_dsi_host_ops *ops; + struct list_head list; +}; + +/* DSI mode flags */ + +/* video mode */ +#define MIPI_DSI_MODE_VIDEO BIT(0) +/* video burst mode */ +#define MIPI_DSI_MODE_VIDEO_BURST BIT(1) +/* video pulse mode */ +#define MIPI_DSI_MODE_VIDEO_SYNC_PULSE BIT(2) +/* enable auto vertical count mode */ +#define MIPI_DSI_MODE_VIDEO_AUTO_VERT BIT(3) +/* enable hsync-end packets in vsync-pulse and v-porch area */ +#define MIPI_DSI_MODE_VIDEO_HSE BIT(4) +/* disable hfront-porch area */ +#define MIPI_DSI_MODE_VIDEO_HFP BIT(5) +/* disable hback-porch area */ +#define MIPI_DSI_MODE_VIDEO_HBP BIT(6) +/* disable hsync-active area */ +#define MIPI_DSI_MODE_VIDEO_HSA BIT(7) +/* flush display FIFO on vsync pulse */ +#define MIPI_DSI_MODE_VSYNC_FLUSH BIT(8) +/* disable EoT packets in HS mode */ +#define MIPI_DSI_MODE_EOT_PACKET BIT(9) +/* device supports non-continuous clock behavior (DSI spec 5.6.1) */ +#define MIPI_DSI_CLOCK_NON_CONTINUOUS BIT(10) +/* transmit data in low power */ +#define MIPI_DSI_MODE_LPM BIT(11) + +enum mipi_dsi_pixel_format { + MIPI_DSI_FMT_RGB888, + MIPI_DSI_FMT_RGB666, + MIPI_DSI_FMT_RGB666_PACKED, + MIPI_DSI_FMT_RGB565, +}; + +#define DSI_DEV_NAME_SIZE 20 + +/** + * struct mipi_dsi_device_info - template for creating a mipi_dsi_device + * @type: DSI peripheral chip type + * @channel: DSI virtual channel assigned to peripheral + * @node: pointer to OF device node or NULL + * + * This is populated and passed to mipi_dsi_device_new to create a new + * DSI device + */ +struct mipi_dsi_device_info { + char type[DSI_DEV_NAME_SIZE]; + u32 channel; + struct device_node *node; +}; + +/** + * struct mipi_dsi_device - DSI peripheral device + * @host: DSI host for this peripheral + * @dev: driver model device node for this peripheral + * @name: DSI peripheral chip type + * @channel: virtual channel assigned to the peripheral + * @format: pixel format for video mode + * @lanes: number of active data lanes + * @mode_flags: DSI operation mode related flags + */ +struct mipi_dsi_device { + struct mipi_dsi_host *host; + struct udevice *dev; + + char name[DSI_DEV_NAME_SIZE]; + unsigned int channel; + unsigned int lanes; + enum mipi_dsi_pixel_format format; + unsigned long mode_flags; +}; + +/** + * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode + * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking + * information only + * @MIPI_DSI_DCS_TEAR_MODE_VHBLANK : the TE output line consists of both + * V-Blanking and H-Blanking information + */ +enum mipi_dsi_dcs_tear_mode { + MIPI_DSI_DCS_TEAR_MODE_VBLANK, + MIPI_DSI_DCS_TEAR_MODE_VHBLANK, +}; + +/** + * struct mipi_dsi_panel_plat - DSI panel platform data + * @device: DSI peripheral device + */ +struct mipi_dsi_panel_plat { + struct mipi_dsi_device *device; +}; + +int mipi_dsi_attach(struct mipi_dsi_device *dsi); +int mipi_dsi_detach(struct mipi_dsi_device *dsi); +int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt); + +/* bit compatible with the xrandr RR_ definitions (bits 0-13) + * + * ABI warning: Existing userspace really expects + * the mode flags to match the xrandr definitions. Any + * changes that don't match the xrandr definitions will + * likely need a new client cap or some other mechanism + * to avoid breaking existing userspace. This includes + * allocating new flags in the previously unused bits! + */ +#define MIPI_DSI_FLAG_PHSYNC BIT(0) +#define MIPI_DSI_FLAG_NHSYNC BIT(1) +#define MIPI_DSI_FLAG_PVSYNC BIT(2) +#define MIPI_DSI_FLAG_NVSYNC BIT(3) +#define MIPI_DSI_FLAG_INTERLACE BIT(4) +#define MIPI_DSI_FLAG_DBLSCAN BIT(5) +#define MIPI_DSI_FLAG_CSYNC BIT(6) +#define MIPI_DSI_FLAG_PCSYNC BIT(7) +#define MIPI_DSI_FLAG_NCSYNC BIT(8) +#define MIPI_DSI_FLAG_HSKEW BIT(9) /* hskew provided */ +#define MIPI_DSI_FLAG_BCAST BIT(10) +#define MIPI_DSI_FLAG_PIXMUX BIT(11) +#define MIPI_DSI_FLAG_DBLCLK BIT(12) +#define MIPI_DSI_FLAG_CLKDIV2 BIT(13) + +/* request ACK from peripheral */ +#define MIPI_DSI_MSG_REQ_ACK BIT(0) +/* use Low Power Mode to transmit message */ +#define MIPI_DSI_MSG_USE_LPM BIT(1) + +ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi, + const void *data, size_t len); +ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd, + const void *data, size_t len); +ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data, + size_t len); +int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode); +int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format); +int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start, + u16 end); +int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start, + u16 end); +int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi, + enum mipi_dsi_dcs_tear_mode mode); +int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format); +int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline); +int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi, + u16 brightness); +int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi, + u16 *brightness); + #endif -- 1.9.1