From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jean-Francois Moine Subject: [PATCH] ASoC: tda998x: add a codec to the HDMI transmitter Date: Wed, 2 Jul 2014 18:38:41 +0200 Message-ID: <20140702183841.7c964832@armhf> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Mark Brown , Russell King - ARM Linux Cc: devicetree@vger.kernel.org, alsa-devel@alsa-project.org, lgirdwood@gmail.com, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org List-Id: alsa-devel@alsa-project.org VGhpcyBwYXRjaCBhZGRzIGEgQ09ERUMgZnVuY3Rpb24gdG8gdGhlIE5YUCBUREE5OTh4IEhETUkg dHJhbnNtaXR0ZXIuCgpUaGUgQ09ERUMgaGFuZGxlcyBib3RoIEkyUyBhbmQgUy9QRElGIGlucHV0 cyBhbmQgZG9lcyBkeW5hbWljIGlucHV0CnN3aXRjaCBpbiB0aGUgVERBOTk4eCBJMkMgZHJpdmVy IG9uIHN0YXJ0L3N0b3AgYXVkaW8gc3RyZWFtaW5nLgoKU2lnbmVkLW9mZi1ieTogSmVhbi1GcmFu Y29pcyBNb2luZSA8bW9pbmVqZkBmcmVlLmZyPgotLS0KVGhpcyBwYXRjaCBhcHBsaWVzIGFnYWlu c3QgbGludXgtbmV4dC4KLS0tCiAuLi4vZGV2aWNldHJlZS9iaW5kaW5ncy9kcm0vaTJjL3RkYTk5 OHgudHh0ICAgICAgICB8ICAxMyArKwogZHJpdmVycy9ncHUvZHJtL2kyYy9NYWtlZmlsZSAgICAg ICAgICAgICAgICAgICAgICAgfCAgIDIgKy0KIGRyaXZlcnMvZ3B1L2RybS9pMmMvdGRhOTk4eF9j b2RlYy5jICAgICAgICAgICAgICAgIHwgMjQxICsrKysrKysrKysrKysrKysrKysrKwogZHJpdmVy cy9ncHUvZHJtL2kyYy90ZGE5OTh4X2Rydi5jICAgICAgICAgICAgICAgICAgfCAgNzQgKysrKyst LQogZHJpdmVycy9ncHUvZHJtL2kyYy90ZGE5OTh4X2Rydi5oICAgICAgICAgICAgICAgICAgfCAg MzEgKysrCiBpbmNsdWRlL2RybS9pMmMvdGRhOTk4eC5oICAgICAgICAgICAgICAgICAgICAgICAg ICB8ICAgMSArCiA2IGZpbGVzIGNoYW5nZWQsIDM0MSBpbnNlcnRpb25zKCspLCAyMSBkZWxldGlv bnMoLSkKIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2dwdS9kcm0vaTJjL3RkYTk5OHhfY29k ZWMuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvZ3B1L2RybS9pMmMvdGRhOTk4eF9kcnYu aAoKZGlmZiAtLWdpdCBhL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9kcm0vaTJj L3RkYTk5OHgudHh0IGIvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2RybS9pMmMv dGRhOTk4eC50eHQKaW5kZXggZDdkZjAxYy4uN2NlNGVhYyAxMDA2NDQKLS0tIGEvRG9jdW1lbnRh dGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2RybS9pMmMvdGRhOTk4eC50eHQKKysrIGIvRG9jdW1l bnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2RybS9pMmMvdGRhOTk4eC50eHQKQEAgLTE1LDYg KzE1LDE1IEBAIE9wdGlvbmFsIHByb3BlcnRpZXM6CiAgIC0gdmlkZW8tcG9ydHM6IDI0IGJpdHMg dmFsdWUgd2hpY2ggZGVmaW5lcyBob3cgdGhlIHZpZGVvIGNvbnRyb2xsZXIKIAlvdXRwdXQgaXMg d2lyZWQgdG8gdGhlIFREQTk5OHggaW5wdXQgLSBkZWZhdWx0OiA8MHgyMzAxNDU+CiAKKyAgLSBh dWRpby1wb3J0czogb25lIG9yIHR3byB2YWx1ZXMgY29ycmVzcG9uZGluZyB0byBlbnRyaWVzIGlu CisJdGhlIGF1ZGlvLXBvcnQtbmFtZXMgcHJvcGVydHkuCisKKyAgLSBhdWRpby1wb3J0LW5hbWVz OiBtdXN0IGNvbnRhaW4gImkycyIsICJzcGRpZiIgZW50cmllcworCW1hdGNoaW5nIGVudHJpZXMg aW4gdGhlIGF1ZGlvLXBvcnRzIHByb3BlcnR5LgorCisgIC0gI3NvdW5kLWRhaS1jZWxsczogbXVz dCBiZSBzZXQgdG8gPDE+IGZvciB1c2Ugd2l0aCB0aGUgc2ltcGxlLWNhcmQuCisJVGhlIERBSSAw IGlzIHRoZSBJMlMgaW5wdXQgYW5kIHRoZSBEQUkgMSBpcyB0aGUgUy9QRElGIGlucHV0LgorCiBF eGFtcGxlOgogCiAJdGRhOTk4eDogaGRtaS1lbmNvZGVyIHsKQEAgLTI0LDQgKzMzLDggQEAgRXhh bXBsZToKIAkJaW50ZXJydXB0cyA9IDwyNyAyPjsJCS8qIGZhbGxpbmcgZWRnZSAqLwogCQlwaW5j dHJsLTAgPSA8JnBteF9jYW1lcmE+OwogCQlwaW5jdHJsLW5hbWVzID0gImRlZmF1bHQiOworCisJ CWF1ZGlvLXBvcnRzID0gPDB4MDM+LCA8MHgwND47CisJCWF1ZGlvLXBvcnQtbmFtZXMgPSAiaTJz IiwgInNwZGlmIjsKKwkJI3NvdW5kLWRhaS1jZWxscyA9IDwxPjsKIAl9OwpkaWZmIC0tZ2l0IGEv ZHJpdmVycy9ncHUvZHJtL2kyYy9NYWtlZmlsZSBiL2RyaXZlcnMvZ3B1L2RybS9pMmMvTWFrZWZp bGUKaW5kZXggNDNhYTMzYi4uZjJkNjI1YyAxMDA2NDQKLS0tIGEvZHJpdmVycy9ncHUvZHJtL2ky Yy9NYWtlZmlsZQorKysgYi9kcml2ZXJzL2dwdS9kcm0vaTJjL01ha2VmaWxlCkBAIC02LDUgKzYs NSBAQCBvYmotJChDT05GSUdfRFJNX0kyQ19DSDcwMDYpICs9IGNoNzAwNi5vCiBzaWwxNjQteSA6 PSBzaWwxNjRfZHJ2Lm8KIG9iai0kKENPTkZJR19EUk1fSTJDX1NJTDE2NCkgKz0gc2lsMTY0Lm8K IAotdGRhOTk4eC15IDo9IHRkYTk5OHhfZHJ2Lm8KK3RkYTk5OHgteSA6PSB0ZGE5OTh4X2Rydi5v IHRkYTk5OHhfY29kZWMubwogb2JqLSQoQ09ORklHX0RSTV9JMkNfTlhQX1REQTk5OFgpICs9IHRk YTk5OHgubwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL2kyYy90ZGE5OTh4X2NvZGVjLmMg Yi9kcml2ZXJzL2dwdS9kcm0vaTJjL3RkYTk5OHhfY29kZWMuYwpuZXcgZmlsZSBtb2RlIDEwMDY0 NAppbmRleCAwMDAwMDAwLi5kZmY2YWZiCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9ncHUv ZHJtL2kyYy90ZGE5OTh4X2NvZGVjLmMKQEAgLTAsMCArMSwyNDEgQEAKKy8qCisgKiBBTFNBIFNv QyBUREE5OThYIENPREVDCisgKgorICogQ29weXJpZ2h0IChDKSAyMDE0IEplYW4tRnJhbmNvaXMg TW9pbmUKKyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRp c3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeQorICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBH TlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSB2ZXJzaW9uIDIgYXMKKyAqIHB1Ymxpc2hlZCBieSB0 aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLgorICovCisKKyNpbmNsdWRlIDxsaW51eC9tb2R1 bGUuaD4KKyNpbmNsdWRlIDxzb3VuZC9zb2MuaD4KKyNpbmNsdWRlIDxzb3VuZC9wY20uaD4KKyNp bmNsdWRlIDxzb3VuZC9wY21fcGFyYW1zLmg+CisjaW5jbHVkZSA8bGludXgvb2YuaD4KKyNpbmNs dWRlIDxsaW51eC9pMmMuaD4KKyNpbmNsdWRlIDxkcm0vZHJtX2VuY29kZXJfc2xhdmUuaD4KKyNp bmNsdWRlIDxkcm0vaTJjL3RkYTk5OHguaD4KKworI2luY2x1ZGUgInRkYTk5OHhfZHJ2LmgiCisK KyNkZWZpbmUgVERBOTk4WF9GT1JNQVRTCShTTkRSVl9QQ01fRk1UQklUX1MxNl9MRSB8IFwKKwkJ CVNORFJWX1BDTV9GTVRCSVRfUzIwXzNMRSB8IFwKKwkJCVNORFJWX1BDTV9GTVRCSVRfUzI0X0xF IHwgXAorCQkJU05EUlZfUENNX0ZNVEJJVF9TMzJfTEUpCisKK3N0YXRpYyBpbnQgdGRhX3N0YXJ0 dXAoc3RydWN0IHNuZF9wY21fc3Vic3RyZWFtICpzdWJzdHJlYW0sCisJCQlzdHJ1Y3Qgc25kX3Nv Y19kYWkgKmRhaSkKK3sKKwlzdHJ1Y3QgdGRhOTk4eF9wcml2ICpwcml2ID0gc25kX3NvY19jb2Rl Y19nZXRfZHJ2ZGF0YShkYWktPmNvZGVjKTsKKwl1OCAqZWxkID0gcHJpdi0+ZWxkOworCXN0cnVj dCBzbmRfcGNtX3J1bnRpbWUgKnJ1bnRpbWUgPSBzdWJzdHJlYW0tPnJ1bnRpbWU7CisJdTggKnNh ZDsKKwlpbnQgc2FkX2NvdW50OworCXVuc2lnbmVkIGVsZF92ZXIsIG1ubCwgcmF0ZV9tYXNrOwor CXVuc2lnbmVkIG1heF9jaGFubmVscywgZm10OworCXU2NCBmb3JtYXRzOworCXN0cnVjdCBzbmRf cGNtX2h3X2NvbnN0cmFpbnRfbGlzdCAqcmF0ZV9jb25zdHJhaW50cyA9CisJCQkmcHJpdi0+cmF0 ZV9jb25zdHJhaW50czsKKwlzdGF0aWMgY29uc3QgdTMyIGhkbWlfcmF0ZXNbXSA9IHsKKwkJMzIw MDAsIDQ0MTAwLCA0ODAwMCwgODgyMDAsIDk2MDAsIDE3NjQwMCwgMTkyMDAwCisJfTsKKworCWlm ICghZWxkKQorCQlyZXR1cm4gMDsKKworCS8qIGFkanVzdCB0aGUgaHcgcGFyYW1zIGZyb20gdGhl IEVMRCAoRURJRCkgKi8KKwllbGRfdmVyID0gZWxkWzBdID4+IDM7CisJaWYgKGVsZF92ZXIgIT0g MiAmJiBlbGRfdmVyICE9IDMxKQorCQlyZXR1cm4gMDsKKworCW1ubCA9IGVsZFs0XSAmIDB4MWY7 CisJaWYgKG1ubCA+IDE2KQorCQlyZXR1cm4gMDsKKworCXNhZF9jb3VudCA9IGVsZFs1XSA+PiA0 OworCXNhZCA9IGVsZCArIDIwICsgbW5sOworCisJLyogU3RhcnQgZnJvbSB0aGUgYmFzaWMgYXVk aW8gc2V0dGluZ3MgKi8KKwltYXhfY2hhbm5lbHMgPSAyOworCXJhdGVfbWFzayA9IDA7CisJZm10 ID0gMDsKKwl3aGlsZSAoc2FkX2NvdW50LS0pIHsKKwkJc3dpdGNoIChzYWRbMF0gJiAweDc4KSB7 CisJCWNhc2UgMHgwODogLyogUENNICovCisJCQltYXhfY2hhbm5lbHMgPSBtYXgobWF4X2NoYW5u ZWxzLCAoc2FkWzBdICYgNykgKyAxdSk7CisJCQlyYXRlX21hc2sgfD0gc2FkWzFdOworCQkJZm10 IHw9IHNhZFsyXSAmIDB4MDc7CisJCQlicmVhazsKKwkJfQorCQlzYWQgKz0gMzsKKwl9CisKKwkv KiBzZXQgdGhlIGNvbnN0cmFpbnRzICovCisJcmF0ZV9jb25zdHJhaW50cy0+bGlzdCA9IGhkbWlf cmF0ZXM7CisJcmF0ZV9jb25zdHJhaW50cy0+Y291bnQgPSBBUlJBWV9TSVpFKGhkbWlfcmF0ZXMp OworCXJhdGVfY29uc3RyYWludHMtPm1hc2sgPSByYXRlX21hc2s7CisJc25kX3BjbV9od19jb25z dHJhaW50X2xpc3QocnVudGltZSwgMCwKKwkJCQkJU05EUlZfUENNX0hXX1BBUkFNX1JBVEUsCisJ CQkJCXJhdGVfY29uc3RyYWludHMpOworCisJZm9ybWF0cyA9IDA7CisJaWYgKGZtdCAmIDEpCisJ CWZvcm1hdHMgfD0gU05EUlZfUENNX0ZNVEJJVF9TMTZfTEU7CisJaWYgKGZtdCAmIDIpCisJCWZv cm1hdHMgfD0gU05EUlZfUENNX0ZNVEJJVF9TMjBfM0xFOworCWlmIChmbXQgJiA0KQorCQlmb3Jt YXRzIHw9IFNORFJWX1BDTV9GTVRCSVRfUzI0X0xFOworCXNuZF9wY21faHdfY29uc3RyYWludF9t YXNrNjQocnVudGltZSwKKwkJCQlTTkRSVl9QQ01fSFdfUEFSQU1fRk9STUFULAorCQkJCWZvcm1h dHMpOworCisJc25kX3BjbV9od19jb25zdHJhaW50X21pbm1heChydW50aW1lLAorCQkJCVNORFJW X1BDTV9IV19QQVJBTV9DSEFOTkVMUywKKwkJCQkxLCBtYXhfY2hhbm5lbHMpOworCXJldHVybiAw OworfQorCitzdGF0aWMgaW50IHRkYV9od19wYXJhbXMoc3RydWN0IHNuZF9wY21fc3Vic3RyZWFt ICpzdWJzdHJlYW0sCisJCQlzdHJ1Y3Qgc25kX3BjbV9od19wYXJhbXMgKnBhcmFtcywKKwkJCXN0 cnVjdCBzbmRfc29jX2RhaSAqZGFpKQoreworCXN0cnVjdCB0ZGE5OTh4X3ByaXYgKnByaXYgPSBz bmRfc29jX2NvZGVjX2dldF9kcnZkYXRhKGRhaS0+Y29kZWMpOworCisJLyogUmVxdWlyZXMgYW4g YXR0YWNoZWQgZGlzcGxheSAqLworCWlmICghcHJpdi0+ZW5jb2Rlci0+Y3J0YykKKwkJcmV0dXJu IC1FTk9ERVY7CisKKwkvKiBpZiBzYW1lIGlucHV0IGFuZCBzYW1lIHBhcmFtZXRlcnMsIGRvIG5v dCBkbyBhIGZ1bGwgc3dpdGNoICovCisJaWYgKGRhaS0+aWQgPT0gcHJpdi0+cGFyYW1zLmF1ZGlv X2Zvcm1hdCAmJgorCSAgICBwYXJhbXNfZm9ybWF0KHBhcmFtcykgPT0gcHJpdi0+YXVkaW9fc2Ft cGxlX2Zvcm1hdCkgeworCQl0ZGE5OTh4X2F1ZGlvX3N0YXJ0KHByaXYsIDApOworCQlyZXR1cm4g MDsKKwl9CisJcHJpdi0+cGFyYW1zLmF1ZGlvX2Zvcm1hdCA9IGRhaS0+aWQ7CisJcHJpdi0+YXVk aW9fc2FtcGxlX2Zvcm1hdCA9IHBhcmFtc19mb3JtYXQocGFyYW1zKTsKKwlwcml2LT5wYXJhbXMu YXVkaW9fY2ZnID0KKwkJcHJpdi0+YXVkaW9fcG9ydHNbZGFpLT5pZCA9PSBBRk1UX0kyUyA/IDAg OiAxXTsKKwl0ZGE5OTh4X2F1ZGlvX3N0YXJ0KHByaXYsIDEpOworCXJldHVybiAwOworfQorCitz dGF0aWMgdm9pZCB0ZGFfc2h1dGRvd24oc3RydWN0IHNuZF9wY21fc3Vic3RyZWFtICpzdWJzdHJl YW0sCisJCQlzdHJ1Y3Qgc25kX3NvY19kYWkgKmRhaSkKK3sKKwlzdHJ1Y3QgdGRhOTk4eF9wcml2 ICpwcml2ID0gc25kX3NvY19jb2RlY19nZXRfZHJ2ZGF0YShkYWktPmNvZGVjKTsKKworCXRkYTk5 OHhfYXVkaW9fc3RvcChwcml2KTsKK30KKworc3RhdGljIGNvbnN0IHN0cnVjdCBzbmRfc29jX2Rh aV9vcHMgdGRhX29wcyA9IHsKKwkuc3RhcnR1cCA9IHRkYV9zdGFydHVwLAorCS5od19wYXJhbXMg PSB0ZGFfaHdfcGFyYW1zLAorCS5zaHV0ZG93biA9IHRkYV9zaHV0ZG93biwKK307CisKK3N0YXRp YyBzdHJ1Y3Qgc25kX3NvY19kYWlfZHJpdmVyIHRkYTk5OHhfZGFpW10gPSB7CisJeworCQkubmFt ZSA9ICJpMnMtaGlmaSIsCisJCS5pZCA9IEFGTVRfSTJTLAorCQkucGxheWJhY2sgPSB7CisJCQku c3RyZWFtX25hbWUJPSAiSERNSSBJMlMgUGxheWJhY2siLAorCQkJLmNoYW5uZWxzX21pbgk9IDEs CisJCQkuY2hhbm5lbHNfbWF4CT0gOCwKKwkJCS5yYXRlcwkJPSBTTkRSVl9QQ01fUkFURV9DT05U SU5VT1VTLAorCQkJLnJhdGVfbWluCT0gNTUxMiwKKwkJCS5yYXRlX21heAk9IDE5MjAwMCwKKwkJ CS5mb3JtYXRzCT0gVERBOTk4WF9GT1JNQVRTLAorCQl9LAorCQkub3BzID0gJnRkYV9vcHMsCisJ fSwKKwl7CisJCS5uYW1lID0gInNwZGlmLWhpZmkiLAorCQkuaWQgPSBBRk1UX1NQRElGLAorCQku cGxheWJhY2sgPSB7CisJCQkuc3RyZWFtX25hbWUJPSAiSERNSSBTUERJRiBQbGF5YmFjayIsCisJ CQkuY2hhbm5lbHNfbWluCT0gMSwKKwkJCS5jaGFubmVsc19tYXgJPSAyLAorCQkJLnJhdGVzCQk9 IFNORFJWX1BDTV9SQVRFX0NPTlRJTlVPVVMsCisJCQkucmF0ZV9taW4JPSAyMjA1MCwKKwkJCS5y YXRlX21heAk9IDE5MjAwMCwKKwkJCS5mb3JtYXRzCT0gVERBOTk4WF9GT1JNQVRTLAorCQl9LAor CQkub3BzID0gJnRkYV9vcHMsCisJfSwKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc25kX3Nv Y19kYXBtX3dpZGdldCB0ZGFfd2lkZ2V0c1tdID0geworCVNORF9TT0NfREFQTV9PVVRQVVQoImhk bWktb3V0IiksCit9Oworc3RhdGljIGNvbnN0IHN0cnVjdCBzbmRfc29jX2RhcG1fcm91dGUgdGRh X3JvdXRlc1tdID0geworCXsgImhkbWktb3V0IiwgTlVMTCwgIkhETUkgSTJTIFBsYXliYWNrIiB9 LAorCXsgImhkbWktb3V0IiwgTlVMTCwgIkhETUkgU1BESUYgUGxheWJhY2siIH0sCit9OworCitz dGF0aWMgaW50IHRkYV9wcm9iZShzdHJ1Y3Qgc25kX3NvY19jb2RlYyAqY29kZWMpCit7CisJc3Ry dWN0IGkyY19jbGllbnQgKmkyY19jbGllbnQgPSB0b19pMmNfY2xpZW50KGNvZGVjLT5kZXYpOwor CXN0cnVjdCB0ZGE5OTh4X3ByaXYgKnByaXYgPSBpMmNfZ2V0X2NsaWVudGRhdGEoaTJjX2NsaWVu dCk7CisJc3RydWN0IGRldmljZV9ub2RlICpucCA9IGNvZGVjLT5kZXYtPm9mX25vZGU7CisJaW50 IGksIGosIHJldDsKKwljb25zdCBjaGFyICpwOworCisJaWYgKCFwcml2KQorCQlyZXR1cm4gLUVO T0RFVjsKKwlzbmRfc29jX2NvZGVjX3NldF9kcnZkYXRhKGNvZGVjLCBwcml2KTsKKworCWlmICgh bnApCisJCXJldHVybiAwOworCisJLyogZ2V0IHRoZSBhdWRpbyBpbnB1dCBwb3J0cyovCisJZm9y IChpID0gMDsgaSA8IDI7IGkrKykgeworCQl1MzIgcG9ydDsKKworCQlyZXQgPSBvZl9wcm9wZXJ0 eV9yZWFkX3UzMl9pbmRleChucCwgImF1ZGlvLXBvcnRzIiwgaSwgJnBvcnQpOworCQlpZiAocmV0 KSB7CisJCQlpZiAoaSA9PSAwKQorCQkJCWRldl9lcnIoY29kZWMtPmRldiwKKwkJCQkJImJhZCBv ciBtaXNzaW5nIGF1ZGlvLXBvcnRzXG4iKTsKKwkJCWJyZWFrOworCQl9CisJCXJldCA9IG9mX3By b3BlcnR5X3JlYWRfc3RyaW5nX2luZGV4KG5wLCAiYXVkaW8tcG9ydC1uYW1lcyIsCisJCQkJCQlp LCAmcCk7CisJCWlmIChyZXQpIHsKKwkJCWRldl9lcnIoY29kZWMtPmRldiwKKwkJCQkibWlzc2lu ZyBhdWRpby1wb3J0LW5hbWVzWyVkXVxuIiwgaSk7CisJCQlicmVhazsKKwkJfQorCQlpZiAoc3Ry Y21wKHAsICJpMnMiKSA9PSAwKSB7CisJCQlqID0gMDsKKwkJfSBlbHNlIGlmIChzdHJjbXAocCwg InNwZGlmIikgPT0gMCkgeworCQkJaiA9IDE7CisJCX0gZWxzZSB7CisJCQlkZXZfZXJyKGNvZGVj LT5kZXYsCisJCQkJImJhZCBhdWRpby1wb3J0LW5hbWVzICclcydcbiIsIHApOworCQkJYnJlYWs7 CisJCX0KKwkJcHJpdi0+YXVkaW9fcG9ydHNbal0gPSBwb3J0OworCX0KKwlyZXR1cm4gMDsKK30K Kworc3RhdGljIGNvbnN0IHN0cnVjdCBzbmRfc29jX2NvZGVjX2RyaXZlciBzb2NfY29kZWNfdGRh OTk4eCA9IHsKKwkucHJvYmUgPSB0ZGFfcHJvYmUsCisJLmRhcG1fd2lkZ2V0cyA9IHRkYV93aWRn ZXRzLAorCS5udW1fZGFwbV93aWRnZXRzID0gQVJSQVlfU0laRSh0ZGFfd2lkZ2V0cyksCisJLmRh cG1fcm91dGVzID0gdGRhX3JvdXRlcywKKwkubnVtX2RhcG1fcm91dGVzID0gQVJSQVlfU0laRSh0 ZGFfcm91dGVzKSwKK307CisKK2ludCB0ZGE5OTh4X2NvZGVjX3JlZ2lzdGVyKHN0cnVjdCBkZXZp Y2UgKmRldikKK3sKKwlyZXR1cm4gc25kX3NvY19yZWdpc3Rlcl9jb2RlYyhkZXYsCisJCQkJJnNv Y19jb2RlY190ZGE5OTh4LAorCQkJCXRkYTk5OHhfZGFpLCBBUlJBWV9TSVpFKHRkYTk5OHhfZGFp KSk7Cit9CisKK3ZvaWQgdGRhOTk4eF9jb2RlY191bnJlZ2lzdGVyKHN0cnVjdCBkZXZpY2UgKmRl dikKK3sKKwlzbmRfc29jX3VucmVnaXN0ZXJfY29kZWMoZGV2KTsKK30KZGlmZiAtLWdpdCBhL2Ry aXZlcnMvZ3B1L2RybS9pMmMvdGRhOTk4eF9kcnYuYyBiL2RyaXZlcnMvZ3B1L2RybS9pMmMvdGRh OTk4eF9kcnYuYwppbmRleCAyNDBjMzMxLi43ZTlmOWRjIDEwMDY0NAotLS0gYS9kcml2ZXJzL2dw dS9kcm0vaTJjL3RkYTk5OHhfZHJ2LmMKKysrIGIvZHJpdmVycy9ncHUvZHJtL2kyYy90ZGE5OTh4 X2Rydi5jCkBAIC0yMSw2ICsyMSw3IEBACiAjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CiAjaW5j bHVkZSA8bGludXgvaXJxLmg+CiAjaW5jbHVkZSA8c291bmQvYXNvdW5kZWYuaD4KKyNpbmNsdWRl IDxzb3VuZC9wY21fcGFyYW1zLmg+CiAKICNpbmNsdWRlIDxkcm0vZHJtUC5oPgogI2luY2x1ZGUg PGRybS9kcm1fY3J0Y19oZWxwZXIuaD4KQEAgLTI4LDI0ICsyOSw5IEBACiAjaW5jbHVkZSA8ZHJt L2RybV9lZGlkLmg+CiAjaW5jbHVkZSA8ZHJtL2kyYy90ZGE5OTh4Lmg+CiAKLSNkZWZpbmUgREJH KGZtdCwgLi4uKSBEUk1fREVCVUcoZm10IlxuIiwgIyNfX1ZBX0FSR1NfXykKKyNpbmNsdWRlICJ0 ZGE5OTh4X2Rydi5oIgogCi1zdHJ1Y3QgdGRhOTk4eF9wcml2IHsKLQlzdHJ1Y3QgaTJjX2NsaWVu dCAqY2VjOwotCXN0cnVjdCBpMmNfY2xpZW50ICpoZG1pOwotCXVpbnQxNl90IHJldjsKLQl1aW50 OF90IGN1cnJlbnRfcGFnZTsKLQlpbnQgZHBtczsKLQlib29sIGlzX2hkbWlfc2luazsKLQl1OCB2 aXBfY250cmxfMDsKLQl1OCB2aXBfY250cmxfMTsKLQl1OCB2aXBfY250cmxfMjsKLQlzdHJ1Y3Qg dGRhOTk4eF9lbmNvZGVyX3BhcmFtcyBwYXJhbXM7Ci0KLQl3YWl0X3F1ZXVlX2hlYWRfdCB3cV9l ZGlkOwotCXZvbGF0aWxlIGludCB3cV9lZGlkX3dhaXQ7Ci0Jc3RydWN0IGRybV9lbmNvZGVyICpl bmNvZGVyOwotfTsKKyNkZWZpbmUgREJHKGZtdCwgLi4uKSBEUk1fREVCVUcoZm10IlxuIiwgIyNf X1ZBX0FSR1NfXykKIAogI2RlZmluZSB0b190ZGE5OTh4X3ByaXYoeCkgICgoc3RydWN0IHRkYTk5 OHhfcHJpdiAqKXRvX2VuY29kZXJfc2xhdmUoeCktPnNsYXZlX3ByaXYpCiAKQEAgLTY0MCwxMiAr NjI2LDExIEBAIHN0YXRpYyB2b2lkCiB0ZGE5OTh4X2NvbmZpZ3VyZV9hdWRpbyhzdHJ1Y3QgdGRh OTk4eF9wcml2ICpwcml2LAogCQlzdHJ1Y3QgZHJtX2Rpc3BsYXlfbW9kZSAqbW9kZSwgc3RydWN0 IHRkYTk5OHhfZW5jb2Rlcl9wYXJhbXMgKnApCiB7Ci0JdWludDhfdCBidWZbNl0sIGNsa3NlbF9h aXAsIGNsa3NlbF9mcywgY3RzX24sIGFkaXY7CisJdWludDhfdCBidWZbNl0sIGNsa3NlbF9haXAs IGNsa3NlbF9mcywgY3RzX24sIGFkaXYsIGFjbGs7CiAJdWludDMyX3QgbjsKIAogCS8qIEVuYWJs ZSBhdWRpbyBwb3J0cyAqLwogCXJlZ193cml0ZShwcml2LCBSRUdfRU5BX0FQLCBwLT5hdWRpb19j ZmcpOwotCXJlZ193cml0ZShwcml2LCBSRUdfRU5BX0FDTEssIHAtPmF1ZGlvX2Nsa19jZmcpOwog CiAJLyogU2V0IGF1ZGlvIGlucHV0IHNvdXJjZSAqLwogCXN3aXRjaCAocC0+YXVkaW9fZm9ybWF0 KSB7CkBAIC02NTQsMTMgKzYzOSwyOCBAQCB0ZGE5OTh4X2NvbmZpZ3VyZV9hdWRpbyhzdHJ1Y3Qg dGRhOTk4eF9wcml2ICpwcml2LAogCQljbGtzZWxfYWlwID0gQUlQX0NMS1NFTF9BSVBfU1BESUY7 CiAJCWNsa3NlbF9mcyA9IEFJUF9DTEtTRUxfRlNfRlM2NFNQRElGOwogCQljdHNfbiA9IENUU19O X00oMykgfCBDVFNfTl9LKDMpOworCQlhY2xrID0gMDsJCQkJLyogbm8gY2xvY2sgKi8KIAkJYnJl YWs7CiAKIAljYXNlIEFGTVRfSTJTOgogCQlyZWdfd3JpdGUocHJpdiwgUkVHX01VWF9BUCwgTVVY X0FQX1NFTEVDVF9JMlMpOwogCQljbGtzZWxfYWlwID0gQUlQX0NMS1NFTF9BSVBfSTJTOwogCQlj bGtzZWxfZnMgPSBBSVBfQ0xLU0VMX0ZTX0FDTEs7Ci0JCWN0c19uID0gQ1RTX05fTSgzKSB8IENU U19OX0soMyk7CisJCS8qIHdpdGggSTJTIGlucHV0LCB0aGUgQ1RTX04gcHJlZGl2aWRlciBkZXBl bmRzIG9uCisJCSAqIHRoZSBzYW1wbGUgd2lkdGggKi8KKwkJc3dpdGNoIChwcml2LT5hdWRpb19z YW1wbGVfZm9ybWF0KSB7CisJCWNhc2UgU05EUlZfUENNX0ZPUk1BVF9TMTZfTEU6CisJCQljdHNf biA9IENUU19OX00oMykgfCBDVFNfTl9LKDEpOworCQkJYnJlYWs7CisJCWNhc2UgU05EUlZfUENN X0ZPUk1BVF9TMjRfTEU6CisJCQljdHNfbiA9IENUU19OX00oMykgfCBDVFNfTl9LKDIpOworCQkJ YnJlYWs7CisJCWRlZmF1bHQ6CisJCWNhc2UgU05EUlZfUENNX0ZPUk1BVF9TMzJfTEU6CisJCQlj dHNfbiA9IENUU19OX00oMykgfCBDVFNfTl9LKDMpOworCQkJYnJlYWs7CisJCX0KKwkJYWNsayA9 IDE7CQkJCS8qIGNsb2NrIGVuYWJsZSAqLwogCQlicmVhazsKIAogCWRlZmF1bHQ6CkBAIC02NzIs NiArNjcyLDcgQEAgdGRhOTk4eF9jb25maWd1cmVfYXVkaW8oc3RydWN0IHRkYTk5OHhfcHJpdiAq cHJpdiwKIAlyZWdfY2xlYXIocHJpdiwgUkVHX0FJUF9DTlRSTF8wLCBBSVBfQ05UUkxfMF9MQVlP VVQgfAogCQkJCQlBSVBfQ05UUkxfMF9BQ1JfTUFOKTsJLyogYXV0byBDVFMgKi8KIAlyZWdfd3Jp dGUocHJpdiwgUkVHX0NUU19OLCBjdHNfbik7CisJcmVnX3dyaXRlKHByaXYsIFJFR19FTkFfQUNM SywgYWNsayk7CiAKIAkvKgogCSAqIEF1ZGlvIGlucHV0IHNvbWVob3cgZGVwZW5kcyBvbiBIRE1J IGxpbmUgcmF0ZSB3aGljaCBpcwpAQCAtNzI4LDYgKzcyOSwyNCBAQCB0ZGE5OTh4X2NvbmZpZ3Vy ZV9hdWRpbyhzdHJ1Y3QgdGRhOTk4eF9wcml2ICpwcml2LAogCXRkYTk5OHhfd3JpdGVfYWlmKHBy aXYsIHApOwogfQogCisvKiB0ZGE5OTh4IGNvZGVjIGludGVyZmFjZSAqLwordm9pZCB0ZGE5OTh4 X2F1ZGlvX3N0YXJ0KHN0cnVjdCB0ZGE5OTh4X3ByaXYgKnByaXYsCisJCQkgaW50IGZ1bGwpCit7 CisJc3RydWN0IHRkYTk5OHhfZW5jb2Rlcl9wYXJhbXMgKnAgPSAmcHJpdi0+cGFyYW1zOworCisJ aWYgKCFmdWxsKSB7CisJCXJlZ193cml0ZShwcml2LCBSRUdfRU5BX0FQLCBwLT5hdWRpb19jZmcp OworCQlyZXR1cm47CisJfQorCXRkYTk5OHhfY29uZmlndXJlX2F1ZGlvKHByaXYsICZwcml2LT5l bmNvZGVyLT5jcnRjLT5od21vZGUsIHApOworfQorCit2b2lkIHRkYTk5OHhfYXVkaW9fc3RvcChz dHJ1Y3QgdGRhOTk4eF9wcml2ICpwcml2KQoreworCXJlZ193cml0ZShwcml2LCBSRUdfRU5BX0FQ LCAwKTsKK30KKwogLyogRFJNIGVuY29kZXIgZnVuY3Rpb25zICovCiAKIHN0YXRpYyB2b2lkCkBA IC0xMTQ5LDYgKzExNjgsMTEgQEAgdGRhOTk4eF9lbmNvZGVyX2dldF9tb2RlcyhzdHJ1Y3QgZHJt X2VuY29kZXIgKmVuY29kZXIsCiAJCWRybV9tb2RlX2Nvbm5lY3Rvcl91cGRhdGVfZWRpZF9wcm9w ZXJ0eShjb25uZWN0b3IsIGVkaWQpOwogCQluID0gZHJtX2FkZF9lZGlkX21vZGVzKGNvbm5lY3Rv ciwgZWRpZCk7CiAJCXByaXYtPmlzX2hkbWlfc2luayA9IGRybV9kZXRlY3RfaGRtaV9tb25pdG9y KGVkaWQpOworCisJCS8qIGtlZXAgdGhlIEVESUQgYXMgRUxEIGZvciB0aGUgYXVkaW8gc3Vic3lz dGVtICovCisJCWRybV9lZGlkX3RvX2VsZChjb25uZWN0b3IsIGVkaWQpOworCQlwcml2LT5lbGQg PSBjb25uZWN0b3ItPmVsZDsKKwogCQlrZnJlZShlZGlkKTsKIAl9CiAKQEAgLTExOTEsNiArMTIx NSw4IEBAIHRkYTk5OHhfZW5jb2Rlcl9kZXN0cm95KHN0cnVjdCBkcm1fZW5jb2RlciAqZW5jb2Rl cikKIAlpZiAocHJpdi0+aGRtaS0+aXJxKQogCQlmcmVlX2lycShwcml2LT5oZG1pLT5pcnEsIHBy aXYpOwogCisJdGRhOTk4eF9jb2RlY191bnJlZ2lzdGVyKCZwcml2LT5oZG1pLT5kZXYpOworCiAJ aWYgKHByaXYtPmNlYykKIAkJaTJjX3VucmVnaXN0ZXJfZGV2aWNlKHByaXYtPmNlYyk7CiAJa2Zy ZWUocHJpdik7CkBAIC0xMjM5LDEwICsxMjY1LDE1IEBAIHRkYTk5OHhfZW5jb2Rlcl9pbml0KHN0 cnVjdCBpMmNfY2xpZW50ICpjbGllbnQsCiAJaWYgKCFwcml2KQogCQlyZXR1cm4gLUVOT01FTTsK IAorCWkyY19zZXRfY2xpZW50ZGF0YShjbGllbnQsIHByaXYpOworCiAJcHJpdi0+dmlwX2NudHJs XzAgPSBWSVBfQ05UUkxfMF9TV0FQX0EoMikgfCBWSVBfQ05UUkxfMF9TV0FQX0IoMyk7CiAJcHJp di0+dmlwX2NudHJsXzEgPSBWSVBfQ05UUkxfMV9TV0FQX0MoMCkgfCBWSVBfQ05UUkxfMV9TV0FQ X0QoMSk7CiAJcHJpdi0+dmlwX2NudHJsXzIgPSBWSVBfQ05UUkxfMl9TV0FQX0UoNCkgfCBWSVBf Q05UUkxfMl9TV0FQX0YoNSk7CiAKKwlwcml2LT5wYXJhbXMuYXVkaW9fZnJhbWVbMV0gPSAxOwkJ LyogY2hhbm5lbHMgLSAxICovCisJcHJpdi0+cGFyYW1zLmF1ZGlvX3NhbXBsZV9yYXRlID0gNDgw MDA7CQkvKiA0OGtIeiAqLworCiAJcHJpdi0+Y3VycmVudF9wYWdlID0gMHhmZjsKIAlwcml2LT5o ZG1pID0gY2xpZW50OwogCXByaXYtPmNlYyA9IGkyY19uZXdfZHVtbXkoY2xpZW50LT5hZGFwdGVy LCAweDM0KTsKQEAgLTEzNDAsNiArMTM3MSw5IEBAIHRkYTk5OHhfZW5jb2Rlcl9pbml0KHN0cnVj dCBpMmNfY2xpZW50ICpjbGllbnQsCiAJLyogZW5hYmxlIEVESUQgcmVhZCBpcnE6ICovCiAJcmVn X3NldChwcml2LCBSRUdfSU5UX0ZMQUdTXzIsIElOVF9GTEFHU18yX0VESURfQkxLX1JEKTsKIAor CS8qIHJlZ2lzdGVyIHRoZSBhdWRpbyBDT0RFQyAqLworCXRkYTk5OHhfY29kZWNfcmVnaXN0ZXIo JmNsaWVudC0+ZGV2KTsKKwogCWlmICghbnApCiAJCXJldHVybiAwOwkJLyogbm9uLURUICovCiAK ZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9pMmMvdGRhOTk4eF9kcnYuaCBiL2RyaXZlcnMv Z3B1L2RybS9pMmMvdGRhOTk4eF9kcnYuaApuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAw MDAwLi42ZGI1MTYwCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9ncHUvZHJtL2kyYy90ZGE5 OTh4X2Rydi5oCkBAIC0wLDAgKzEsMzEgQEAKKy8qIHRkYTk5OHggcHJpdmF0ZSBkYXRhICovCisK K3N0cnVjdCB0ZGE5OTh4X3ByaXYgeworCXN0cnVjdCBpMmNfY2xpZW50ICpjZWM7CisJc3RydWN0 IGkyY19jbGllbnQgKmhkbWk7CisJdWludDE2X3QgcmV2OworCXVpbnQ4X3QgY3VycmVudF9wYWdl OworCWludCBkcG1zOworCWJvb2wgaXNfaGRtaV9zaW5rOworCXU4IHZpcF9jbnRybF8wOworCXU4 IHZpcF9jbnRybF8xOworCXU4IHZpcF9jbnRybF8yOworCXN0cnVjdCB0ZGE5OTh4X2VuY29kZXJf cGFyYW1zIHBhcmFtczsKKworCXdhaXRfcXVldWVfaGVhZF90IHdxX2VkaWQ7CisJdm9sYXRpbGUg aW50IHdxX2VkaWRfd2FpdDsKKwlzdHJ1Y3QgZHJtX2VuY29kZXIgKmVuY29kZXI7CisKKwl1OCBh dWRpb19wb3J0c1syXTsKKwlpbnQgYXVkaW9fc2FtcGxlX2Zvcm1hdDsKKworCXU4ICplbGQ7CisK KwlzdHJ1Y3Qgc25kX3BjbV9od19jb25zdHJhaW50X2xpc3QgcmF0ZV9jb25zdHJhaW50czsKK307 CisKK2ludCB0ZGE5OTh4X2NvZGVjX3JlZ2lzdGVyKHN0cnVjdCBkZXZpY2UgKmRldik7Cit2b2lk IHRkYTk5OHhfY29kZWNfdW5yZWdpc3RlcihzdHJ1Y3QgZGV2aWNlICpkZXYpOworCit2b2lkIHRk YTk5OHhfYXVkaW9fc3RhcnQoc3RydWN0IHRkYTk5OHhfcHJpdiAqcHJpdiwgaW50IGZ1bGwpOwor dm9pZCB0ZGE5OTh4X2F1ZGlvX3N0b3Aoc3RydWN0IHRkYTk5OHhfcHJpdiAqcHJpdik7CmRpZmYg LS1naXQgYS9pbmNsdWRlL2RybS9pMmMvdGRhOTk4eC5oIGIvaW5jbHVkZS9kcm0vaTJjL3RkYTk5 OHguaAppbmRleCAzZTQxOWQ5Li4zMTc1N2RmIDEwMDY0NAotLS0gYS9pbmNsdWRlL2RybS9pMmMv dGRhOTk4eC5oCisrKyBiL2luY2x1ZGUvZHJtL2kyYy90ZGE5OTh4LmgKQEAgLTIwLDYgKzIwLDcg QEAgc3RydWN0IHRkYTk5OHhfZW5jb2Rlcl9wYXJhbXMgewogCXU4IGF1ZGlvX2ZyYW1lWzZdOwog CiAJZW51bSB7CisJCUFGTVRfTk9fQVVESU8gPSAwLAogCQlBRk1UX1NQRElGLAogCQlBRk1UX0ky UwogCX0gYXVkaW9fZm9ybWF0OwotLSAKMi4wLjEKCgotLSAKS2VuIGFyIGMnaGVudGHDsQl8CSAg ICAgICoqIEJyZWl6aCBoYSBMaW51eCBhdGF2ISAqKgpKZWYJCXwJCWh0dHA6Ly9tb2luZWpmLmZy ZWUuZnIvCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmRy aS1kZXZlbCBtYWlsaW5nIGxpc3QKZHJpLWRldmVsQGxpc3RzLmZyZWVkZXNrdG9wLm9yZwpodHRw Oi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vZHJpLWRldmVsCg== From mboxrd@z Thu Jan 1 00:00:00 1970 From: moinejf@free.fr (Jean-Francois Moine) Date: Wed, 2 Jul 2014 18:38:41 +0200 Subject: [PATCH] ASoC: tda998x: add a codec to the HDMI transmitter Message-ID: <20140702183841.7c964832@armhf> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org This patch adds a CODEC function to the NXP TDA998x HDMI transmitter. The CODEC handles both I2S and S/PDIF inputs and does dynamic input switch in the TDA998x I2C driver on start/stop audio streaming. Signed-off-by: Jean-Francois Moine --- This patch applies against linux-next. --- .../devicetree/bindings/drm/i2c/tda998x.txt | 13 ++ drivers/gpu/drm/i2c/Makefile | 2 +- drivers/gpu/drm/i2c/tda998x_codec.c | 241 +++++++++++++++++++++ drivers/gpu/drm/i2c/tda998x_drv.c | 74 +++++-- drivers/gpu/drm/i2c/tda998x_drv.h | 31 +++ include/drm/i2c/tda998x.h | 1 + 6 files changed, 341 insertions(+), 21 deletions(-) create mode 100644 drivers/gpu/drm/i2c/tda998x_codec.c create mode 100644 drivers/gpu/drm/i2c/tda998x_drv.h diff --git a/Documentation/devicetree/bindings/drm/i2c/tda998x.txt b/Documentation/devicetree/bindings/drm/i2c/tda998x.txt index d7df01c..7ce4eac 100644 --- a/Documentation/devicetree/bindings/drm/i2c/tda998x.txt +++ b/Documentation/devicetree/bindings/drm/i2c/tda998x.txt @@ -15,6 +15,15 @@ Optional properties: - video-ports: 24 bits value which defines how the video controller output is wired to the TDA998x input - default: <0x230145> + - audio-ports: one or two values corresponding to entries in + the audio-port-names property. + + - audio-port-names: must contain "i2s", "spdif" entries + matching entries in the audio-ports property. + + - #sound-dai-cells: must be set to <1> for use with the simple-card. + The DAI 0 is the I2S input and the DAI 1 is the S/PDIF input. + Example: tda998x: hdmi-encoder { @@ -24,4 +33,8 @@ Example: interrupts = <27 2>; /* falling edge */ pinctrl-0 = <&pmx_camera>; pinctrl-names = "default"; + + audio-ports = <0x03>, <0x04>; + audio-port-names = "i2s", "spdif"; + #sound-dai-cells = <1>; }; diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile index 43aa33b..f2d625c 100644 --- a/drivers/gpu/drm/i2c/Makefile +++ b/drivers/gpu/drm/i2c/Makefile @@ -6,5 +6,5 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o sil164-y := sil164_drv.o obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o -tda998x-y := tda998x_drv.o +tda998x-y := tda998x_drv.o tda998x_codec.o obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o diff --git a/drivers/gpu/drm/i2c/tda998x_codec.c b/drivers/gpu/drm/i2c/tda998x_codec.c new file mode 100644 index 0000000..dff6afb --- /dev/null +++ b/drivers/gpu/drm/i2c/tda998x_codec.c @@ -0,0 +1,241 @@ +/* + * ALSA SoC TDA998X CODEC + * + * Copyright (C) 2014 Jean-Francois Moine + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tda998x_drv.h" + +#define TDA998X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +static int tda_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct tda998x_priv *priv = snd_soc_codec_get_drvdata(dai->codec); + u8 *eld = priv->eld; + struct snd_pcm_runtime *runtime = substream->runtime; + u8 *sad; + int sad_count; + unsigned eld_ver, mnl, rate_mask; + unsigned max_channels, fmt; + u64 formats; + struct snd_pcm_hw_constraint_list *rate_constraints = + &priv->rate_constraints; + static const u32 hdmi_rates[] = { + 32000, 44100, 48000, 88200, 9600, 176400, 192000 + }; + + if (!eld) + return 0; + + /* adjust the hw params from the ELD (EDID) */ + eld_ver = eld[0] >> 3; + if (eld_ver != 2 && eld_ver != 31) + return 0; + + mnl = eld[4] & 0x1f; + if (mnl > 16) + return 0; + + sad_count = eld[5] >> 4; + sad = eld + 20 + mnl; + + /* Start from the basic audio settings */ + max_channels = 2; + rate_mask = 0; + fmt = 0; + while (sad_count--) { + switch (sad[0] & 0x78) { + case 0x08: /* PCM */ + max_channels = max(max_channels, (sad[0] & 7) + 1u); + rate_mask |= sad[1]; + fmt |= sad[2] & 0x07; + break; + } + sad += 3; + } + + /* set the constraints */ + rate_constraints->list = hdmi_rates; + rate_constraints->count = ARRAY_SIZE(hdmi_rates); + rate_constraints->mask = rate_mask; + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + rate_constraints); + + formats = 0; + if (fmt & 1) + formats |= SNDRV_PCM_FMTBIT_S16_LE; + if (fmt & 2) + formats |= SNDRV_PCM_FMTBIT_S20_3LE; + if (fmt & 4) + formats |= SNDRV_PCM_FMTBIT_S24_LE; + snd_pcm_hw_constraint_mask64(runtime, + SNDRV_PCM_HW_PARAM_FORMAT, + formats); + + snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_CHANNELS, + 1, max_channels); + return 0; +} + +static int tda_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct tda998x_priv *priv = snd_soc_codec_get_drvdata(dai->codec); + + /* Requires an attached display */ + if (!priv->encoder->crtc) + return -ENODEV; + + /* if same input and same parameters, do not do a full switch */ + if (dai->id == priv->params.audio_format && + params_format(params) == priv->audio_sample_format) { + tda998x_audio_start(priv, 0); + return 0; + } + priv->params.audio_format = dai->id; + priv->audio_sample_format = params_format(params); + priv->params.audio_cfg = + priv->audio_ports[dai->id == AFMT_I2S ? 0 : 1]; + tda998x_audio_start(priv, 1); + return 0; +} + +static void tda_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct tda998x_priv *priv = snd_soc_codec_get_drvdata(dai->codec); + + tda998x_audio_stop(priv); +} + +static const struct snd_soc_dai_ops tda_ops = { + .startup = tda_startup, + .hw_params = tda_hw_params, + .shutdown = tda_shutdown, +}; + +static struct snd_soc_dai_driver tda998x_dai[] = { + { + .name = "i2s-hifi", + .id = AFMT_I2S, + .playback = { + .stream_name = "HDMI I2S Playback", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 5512, + .rate_max = 192000, + .formats = TDA998X_FORMATS, + }, + .ops = &tda_ops, + }, + { + .name = "spdif-hifi", + .id = AFMT_SPDIF, + .playback = { + .stream_name = "HDMI SPDIF Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 22050, + .rate_max = 192000, + .formats = TDA998X_FORMATS, + }, + .ops = &tda_ops, + }, +}; + +static const struct snd_soc_dapm_widget tda_widgets[] = { + SND_SOC_DAPM_OUTPUT("hdmi-out"), +}; +static const struct snd_soc_dapm_route tda_routes[] = { + { "hdmi-out", NULL, "HDMI I2S Playback" }, + { "hdmi-out", NULL, "HDMI SPDIF Playback" }, +}; + +static int tda_probe(struct snd_soc_codec *codec) +{ + struct i2c_client *i2c_client = to_i2c_client(codec->dev); + struct tda998x_priv *priv = i2c_get_clientdata(i2c_client); + struct device_node *np = codec->dev->of_node; + int i, j, ret; + const char *p; + + if (!priv) + return -ENODEV; + snd_soc_codec_set_drvdata(codec, priv); + + if (!np) + return 0; + + /* get the audio input ports*/ + for (i = 0; i < 2; i++) { + u32 port; + + ret = of_property_read_u32_index(np, "audio-ports", i, &port); + if (ret) { + if (i == 0) + dev_err(codec->dev, + "bad or missing audio-ports\n"); + break; + } + ret = of_property_read_string_index(np, "audio-port-names", + i, &p); + if (ret) { + dev_err(codec->dev, + "missing audio-port-names[%d]\n", i); + break; + } + if (strcmp(p, "i2s") == 0) { + j = 0; + } else if (strcmp(p, "spdif") == 0) { + j = 1; + } else { + dev_err(codec->dev, + "bad audio-port-names '%s'\n", p); + break; + } + priv->audio_ports[j] = port; + } + return 0; +} + +static const struct snd_soc_codec_driver soc_codec_tda998x = { + .probe = tda_probe, + .dapm_widgets = tda_widgets, + .num_dapm_widgets = ARRAY_SIZE(tda_widgets), + .dapm_routes = tda_routes, + .num_dapm_routes = ARRAY_SIZE(tda_routes), +}; + +int tda998x_codec_register(struct device *dev) +{ + return snd_soc_register_codec(dev, + &soc_codec_tda998x, + tda998x_dai, ARRAY_SIZE(tda998x_dai)); +} + +void tda998x_codec_unregister(struct device *dev) +{ + snd_soc_unregister_codec(dev); +} diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 240c331..7e9f9dc 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -28,24 +29,9 @@ #include #include -#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) +#include "tda998x_drv.h" -struct tda998x_priv { - struct i2c_client *cec; - struct i2c_client *hdmi; - uint16_t rev; - uint8_t current_page; - int dpms; - bool is_hdmi_sink; - u8 vip_cntrl_0; - u8 vip_cntrl_1; - u8 vip_cntrl_2; - struct tda998x_encoder_params params; - - wait_queue_head_t wq_edid; - volatile int wq_edid_wait; - struct drm_encoder *encoder; -}; +#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) #define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv) @@ -640,12 +626,11 @@ static void tda998x_configure_audio(struct tda998x_priv *priv, struct drm_display_mode *mode, struct tda998x_encoder_params *p) { - uint8_t buf[6], clksel_aip, clksel_fs, cts_n, adiv; + uint8_t buf[6], clksel_aip, clksel_fs, cts_n, adiv, aclk; uint32_t n; /* Enable audio ports */ reg_write(priv, REG_ENA_AP, p->audio_cfg); - reg_write(priv, REG_ENA_ACLK, p->audio_clk_cfg); /* Set audio input source */ switch (p->audio_format) { @@ -654,13 +639,28 @@ tda998x_configure_audio(struct tda998x_priv *priv, clksel_aip = AIP_CLKSEL_AIP_SPDIF; clksel_fs = AIP_CLKSEL_FS_FS64SPDIF; cts_n = CTS_N_M(3) | CTS_N_K(3); + aclk = 0; /* no clock */ break; case AFMT_I2S: reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_I2S); clksel_aip = AIP_CLKSEL_AIP_I2S; clksel_fs = AIP_CLKSEL_FS_ACLK; - cts_n = CTS_N_M(3) | CTS_N_K(3); + /* with I2S input, the CTS_N predivider depends on + * the sample width */ + switch (priv->audio_sample_format) { + case SNDRV_PCM_FORMAT_S16_LE: + cts_n = CTS_N_M(3) | CTS_N_K(1); + break; + case SNDRV_PCM_FORMAT_S24_LE: + cts_n = CTS_N_M(3) | CTS_N_K(2); + break; + default: + case SNDRV_PCM_FORMAT_S32_LE: + cts_n = CTS_N_M(3) | CTS_N_K(3); + break; + } + aclk = 1; /* clock enable */ break; default: @@ -672,6 +672,7 @@ tda998x_configure_audio(struct tda998x_priv *priv, reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_LAYOUT | AIP_CNTRL_0_ACR_MAN); /* auto CTS */ reg_write(priv, REG_CTS_N, cts_n); + reg_write(priv, REG_ENA_ACLK, aclk); /* * Audio input somehow depends on HDMI line rate which is @@ -728,6 +729,24 @@ tda998x_configure_audio(struct tda998x_priv *priv, tda998x_write_aif(priv, p); } +/* tda998x codec interface */ +void tda998x_audio_start(struct tda998x_priv *priv, + int full) +{ + struct tda998x_encoder_params *p = &priv->params; + + if (!full) { + reg_write(priv, REG_ENA_AP, p->audio_cfg); + return; + } + tda998x_configure_audio(priv, &priv->encoder->crtc->hwmode, p); +} + +void tda998x_audio_stop(struct tda998x_priv *priv) +{ + reg_write(priv, REG_ENA_AP, 0); +} + /* DRM encoder functions */ static void @@ -1149,6 +1168,11 @@ tda998x_encoder_get_modes(struct drm_encoder *encoder, drm_mode_connector_update_edid_property(connector, edid); n = drm_add_edid_modes(connector, edid); priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid); + + /* keep the EDID as ELD for the audio subsystem */ + drm_edid_to_eld(connector, edid); + priv->eld = connector->eld; + kfree(edid); } @@ -1191,6 +1215,8 @@ tda998x_encoder_destroy(struct drm_encoder *encoder) if (priv->hdmi->irq) free_irq(priv->hdmi->irq, priv); + tda998x_codec_unregister(&priv->hdmi->dev); + if (priv->cec) i2c_unregister_device(priv->cec); kfree(priv); @@ -1239,10 +1265,15 @@ tda998x_encoder_init(struct i2c_client *client, if (!priv) return -ENOMEM; + i2c_set_clientdata(client, priv); + priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3); priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1); priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5); + priv->params.audio_frame[1] = 1; /* channels - 1 */ + priv->params.audio_sample_rate = 48000; /* 48kHz */ + priv->current_page = 0xff; priv->hdmi = client; priv->cec = i2c_new_dummy(client->adapter, 0x34); @@ -1340,6 +1371,9 @@ tda998x_encoder_init(struct i2c_client *client, /* enable EDID read irq: */ reg_set(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); + /* register the audio CODEC */ + tda998x_codec_register(&client->dev); + if (!np) return 0; /* non-DT */ diff --git a/drivers/gpu/drm/i2c/tda998x_drv.h b/drivers/gpu/drm/i2c/tda998x_drv.h new file mode 100644 index 0000000..6db5160 --- /dev/null +++ b/drivers/gpu/drm/i2c/tda998x_drv.h @@ -0,0 +1,31 @@ +/* tda998x private data */ + +struct tda998x_priv { + struct i2c_client *cec; + struct i2c_client *hdmi; + uint16_t rev; + uint8_t current_page; + int dpms; + bool is_hdmi_sink; + u8 vip_cntrl_0; + u8 vip_cntrl_1; + u8 vip_cntrl_2; + struct tda998x_encoder_params params; + + wait_queue_head_t wq_edid; + volatile int wq_edid_wait; + struct drm_encoder *encoder; + + u8 audio_ports[2]; + int audio_sample_format; + + u8 *eld; + + struct snd_pcm_hw_constraint_list rate_constraints; +}; + +int tda998x_codec_register(struct device *dev); +void tda998x_codec_unregister(struct device *dev); + +void tda998x_audio_start(struct tda998x_priv *priv, int full); +void tda998x_audio_stop(struct tda998x_priv *priv); diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h index 3e419d9..31757df 100644 --- a/include/drm/i2c/tda998x.h +++ b/include/drm/i2c/tda998x.h @@ -20,6 +20,7 @@ struct tda998x_encoder_params { u8 audio_frame[6]; enum { + AFMT_NO_AUDIO = 0, AFMT_SPDIF, AFMT_I2S } audio_format; -- 2.0.1 -- Ken ar c'henta? | ** Breizh ha Linux atav! ** Jef | http://moinejf.free.fr/ From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756326AbaGBQgu (ORCPT ); Wed, 2 Jul 2014 12:36:50 -0400 Received: from smtp5-g21.free.fr ([212.27.42.5]:51345 "EHLO smtp5-g21.free.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751547AbaGBQgt convert rfc822-to-8bit (ORCPT ); Wed, 2 Jul 2014 12:36:49 -0400 X-Greylist: delayed 88452 seconds by postgrey-1.27 at vger.kernel.org; Wed, 02 Jul 2014 12:36:48 EDT Date: Wed, 2 Jul 2014 18:38:41 +0200 From: Jean-Francois Moine To: Mark Brown , Russell King - ARM Linux Cc: alsa-devel@alsa-project.org, lgirdwood@gmail.com, dri-devel@lists.freedesktop.org, Rob Clark , linux-arm-kernel@lists.infradead.org, Dave Airlie , linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH] ASoC: tda998x: add a codec to the HDMI transmitter Message-ID: <20140702183841.7c964832@armhf> X-Mailer: Claws Mail 3.10.1 (GTK+ 2.24.24; arm-unknown-linux-gnueabihf) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8BIT Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch adds a CODEC function to the NXP TDA998x HDMI transmitter. The CODEC handles both I2S and S/PDIF inputs and does dynamic input switch in the TDA998x I2C driver on start/stop audio streaming. Signed-off-by: Jean-Francois Moine --- This patch applies against linux-next. --- .../devicetree/bindings/drm/i2c/tda998x.txt | 13 ++ drivers/gpu/drm/i2c/Makefile | 2 +- drivers/gpu/drm/i2c/tda998x_codec.c | 241 +++++++++++++++++++++ drivers/gpu/drm/i2c/tda998x_drv.c | 74 +++++-- drivers/gpu/drm/i2c/tda998x_drv.h | 31 +++ include/drm/i2c/tda998x.h | 1 + 6 files changed, 341 insertions(+), 21 deletions(-) create mode 100644 drivers/gpu/drm/i2c/tda998x_codec.c create mode 100644 drivers/gpu/drm/i2c/tda998x_drv.h diff --git a/Documentation/devicetree/bindings/drm/i2c/tda998x.txt b/Documentation/devicetree/bindings/drm/i2c/tda998x.txt index d7df01c..7ce4eac 100644 --- a/Documentation/devicetree/bindings/drm/i2c/tda998x.txt +++ b/Documentation/devicetree/bindings/drm/i2c/tda998x.txt @@ -15,6 +15,15 @@ Optional properties: - video-ports: 24 bits value which defines how the video controller output is wired to the TDA998x input - default: <0x230145> + - audio-ports: one or two values corresponding to entries in + the audio-port-names property. + + - audio-port-names: must contain "i2s", "spdif" entries + matching entries in the audio-ports property. + + - #sound-dai-cells: must be set to <1> for use with the simple-card. + The DAI 0 is the I2S input and the DAI 1 is the S/PDIF input. + Example: tda998x: hdmi-encoder { @@ -24,4 +33,8 @@ Example: interrupts = <27 2>; /* falling edge */ pinctrl-0 = <&pmx_camera>; pinctrl-names = "default"; + + audio-ports = <0x03>, <0x04>; + audio-port-names = "i2s", "spdif"; + #sound-dai-cells = <1>; }; diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile index 43aa33b..f2d625c 100644 --- a/drivers/gpu/drm/i2c/Makefile +++ b/drivers/gpu/drm/i2c/Makefile @@ -6,5 +6,5 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o sil164-y := sil164_drv.o obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o -tda998x-y := tda998x_drv.o +tda998x-y := tda998x_drv.o tda998x_codec.o obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o diff --git a/drivers/gpu/drm/i2c/tda998x_codec.c b/drivers/gpu/drm/i2c/tda998x_codec.c new file mode 100644 index 0000000..dff6afb --- /dev/null +++ b/drivers/gpu/drm/i2c/tda998x_codec.c @@ -0,0 +1,241 @@ +/* + * ALSA SoC TDA998X CODEC + * + * Copyright (C) 2014 Jean-Francois Moine + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tda998x_drv.h" + +#define TDA998X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +static int tda_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct tda998x_priv *priv = snd_soc_codec_get_drvdata(dai->codec); + u8 *eld = priv->eld; + struct snd_pcm_runtime *runtime = substream->runtime; + u8 *sad; + int sad_count; + unsigned eld_ver, mnl, rate_mask; + unsigned max_channels, fmt; + u64 formats; + struct snd_pcm_hw_constraint_list *rate_constraints = + &priv->rate_constraints; + static const u32 hdmi_rates[] = { + 32000, 44100, 48000, 88200, 9600, 176400, 192000 + }; + + if (!eld) + return 0; + + /* adjust the hw params from the ELD (EDID) */ + eld_ver = eld[0] >> 3; + if (eld_ver != 2 && eld_ver != 31) + return 0; + + mnl = eld[4] & 0x1f; + if (mnl > 16) + return 0; + + sad_count = eld[5] >> 4; + sad = eld + 20 + mnl; + + /* Start from the basic audio settings */ + max_channels = 2; + rate_mask = 0; + fmt = 0; + while (sad_count--) { + switch (sad[0] & 0x78) { + case 0x08: /* PCM */ + max_channels = max(max_channels, (sad[0] & 7) + 1u); + rate_mask |= sad[1]; + fmt |= sad[2] & 0x07; + break; + } + sad += 3; + } + + /* set the constraints */ + rate_constraints->list = hdmi_rates; + rate_constraints->count = ARRAY_SIZE(hdmi_rates); + rate_constraints->mask = rate_mask; + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + rate_constraints); + + formats = 0; + if (fmt & 1) + formats |= SNDRV_PCM_FMTBIT_S16_LE; + if (fmt & 2) + formats |= SNDRV_PCM_FMTBIT_S20_3LE; + if (fmt & 4) + formats |= SNDRV_PCM_FMTBIT_S24_LE; + snd_pcm_hw_constraint_mask64(runtime, + SNDRV_PCM_HW_PARAM_FORMAT, + formats); + + snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_CHANNELS, + 1, max_channels); + return 0; +} + +static int tda_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct tda998x_priv *priv = snd_soc_codec_get_drvdata(dai->codec); + + /* Requires an attached display */ + if (!priv->encoder->crtc) + return -ENODEV; + + /* if same input and same parameters, do not do a full switch */ + if (dai->id == priv->params.audio_format && + params_format(params) == priv->audio_sample_format) { + tda998x_audio_start(priv, 0); + return 0; + } + priv->params.audio_format = dai->id; + priv->audio_sample_format = params_format(params); + priv->params.audio_cfg = + priv->audio_ports[dai->id == AFMT_I2S ? 0 : 1]; + tda998x_audio_start(priv, 1); + return 0; +} + +static void tda_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct tda998x_priv *priv = snd_soc_codec_get_drvdata(dai->codec); + + tda998x_audio_stop(priv); +} + +static const struct snd_soc_dai_ops tda_ops = { + .startup = tda_startup, + .hw_params = tda_hw_params, + .shutdown = tda_shutdown, +}; + +static struct snd_soc_dai_driver tda998x_dai[] = { + { + .name = "i2s-hifi", + .id = AFMT_I2S, + .playback = { + .stream_name = "HDMI I2S Playback", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 5512, + .rate_max = 192000, + .formats = TDA998X_FORMATS, + }, + .ops = &tda_ops, + }, + { + .name = "spdif-hifi", + .id = AFMT_SPDIF, + .playback = { + .stream_name = "HDMI SPDIF Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 22050, + .rate_max = 192000, + .formats = TDA998X_FORMATS, + }, + .ops = &tda_ops, + }, +}; + +static const struct snd_soc_dapm_widget tda_widgets[] = { + SND_SOC_DAPM_OUTPUT("hdmi-out"), +}; +static const struct snd_soc_dapm_route tda_routes[] = { + { "hdmi-out", NULL, "HDMI I2S Playback" }, + { "hdmi-out", NULL, "HDMI SPDIF Playback" }, +}; + +static int tda_probe(struct snd_soc_codec *codec) +{ + struct i2c_client *i2c_client = to_i2c_client(codec->dev); + struct tda998x_priv *priv = i2c_get_clientdata(i2c_client); + struct device_node *np = codec->dev->of_node; + int i, j, ret; + const char *p; + + if (!priv) + return -ENODEV; + snd_soc_codec_set_drvdata(codec, priv); + + if (!np) + return 0; + + /* get the audio input ports*/ + for (i = 0; i < 2; i++) { + u32 port; + + ret = of_property_read_u32_index(np, "audio-ports", i, &port); + if (ret) { + if (i == 0) + dev_err(codec->dev, + "bad or missing audio-ports\n"); + break; + } + ret = of_property_read_string_index(np, "audio-port-names", + i, &p); + if (ret) { + dev_err(codec->dev, + "missing audio-port-names[%d]\n", i); + break; + } + if (strcmp(p, "i2s") == 0) { + j = 0; + } else if (strcmp(p, "spdif") == 0) { + j = 1; + } else { + dev_err(codec->dev, + "bad audio-port-names '%s'\n", p); + break; + } + priv->audio_ports[j] = port; + } + return 0; +} + +static const struct snd_soc_codec_driver soc_codec_tda998x = { + .probe = tda_probe, + .dapm_widgets = tda_widgets, + .num_dapm_widgets = ARRAY_SIZE(tda_widgets), + .dapm_routes = tda_routes, + .num_dapm_routes = ARRAY_SIZE(tda_routes), +}; + +int tda998x_codec_register(struct device *dev) +{ + return snd_soc_register_codec(dev, + &soc_codec_tda998x, + tda998x_dai, ARRAY_SIZE(tda998x_dai)); +} + +void tda998x_codec_unregister(struct device *dev) +{ + snd_soc_unregister_codec(dev); +} diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 240c331..7e9f9dc 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -28,24 +29,9 @@ #include #include -#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) +#include "tda998x_drv.h" -struct tda998x_priv { - struct i2c_client *cec; - struct i2c_client *hdmi; - uint16_t rev; - uint8_t current_page; - int dpms; - bool is_hdmi_sink; - u8 vip_cntrl_0; - u8 vip_cntrl_1; - u8 vip_cntrl_2; - struct tda998x_encoder_params params; - - wait_queue_head_t wq_edid; - volatile int wq_edid_wait; - struct drm_encoder *encoder; -}; +#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) #define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv) @@ -640,12 +626,11 @@ static void tda998x_configure_audio(struct tda998x_priv *priv, struct drm_display_mode *mode, struct tda998x_encoder_params *p) { - uint8_t buf[6], clksel_aip, clksel_fs, cts_n, adiv; + uint8_t buf[6], clksel_aip, clksel_fs, cts_n, adiv, aclk; uint32_t n; /* Enable audio ports */ reg_write(priv, REG_ENA_AP, p->audio_cfg); - reg_write(priv, REG_ENA_ACLK, p->audio_clk_cfg); /* Set audio input source */ switch (p->audio_format) { @@ -654,13 +639,28 @@ tda998x_configure_audio(struct tda998x_priv *priv, clksel_aip = AIP_CLKSEL_AIP_SPDIF; clksel_fs = AIP_CLKSEL_FS_FS64SPDIF; cts_n = CTS_N_M(3) | CTS_N_K(3); + aclk = 0; /* no clock */ break; case AFMT_I2S: reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_I2S); clksel_aip = AIP_CLKSEL_AIP_I2S; clksel_fs = AIP_CLKSEL_FS_ACLK; - cts_n = CTS_N_M(3) | CTS_N_K(3); + /* with I2S input, the CTS_N predivider depends on + * the sample width */ + switch (priv->audio_sample_format) { + case SNDRV_PCM_FORMAT_S16_LE: + cts_n = CTS_N_M(3) | CTS_N_K(1); + break; + case SNDRV_PCM_FORMAT_S24_LE: + cts_n = CTS_N_M(3) | CTS_N_K(2); + break; + default: + case SNDRV_PCM_FORMAT_S32_LE: + cts_n = CTS_N_M(3) | CTS_N_K(3); + break; + } + aclk = 1; /* clock enable */ break; default: @@ -672,6 +672,7 @@ tda998x_configure_audio(struct tda998x_priv *priv, reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_LAYOUT | AIP_CNTRL_0_ACR_MAN); /* auto CTS */ reg_write(priv, REG_CTS_N, cts_n); + reg_write(priv, REG_ENA_ACLK, aclk); /* * Audio input somehow depends on HDMI line rate which is @@ -728,6 +729,24 @@ tda998x_configure_audio(struct tda998x_priv *priv, tda998x_write_aif(priv, p); } +/* tda998x codec interface */ +void tda998x_audio_start(struct tda998x_priv *priv, + int full) +{ + struct tda998x_encoder_params *p = &priv->params; + + if (!full) { + reg_write(priv, REG_ENA_AP, p->audio_cfg); + return; + } + tda998x_configure_audio(priv, &priv->encoder->crtc->hwmode, p); +} + +void tda998x_audio_stop(struct tda998x_priv *priv) +{ + reg_write(priv, REG_ENA_AP, 0); +} + /* DRM encoder functions */ static void @@ -1149,6 +1168,11 @@ tda998x_encoder_get_modes(struct drm_encoder *encoder, drm_mode_connector_update_edid_property(connector, edid); n = drm_add_edid_modes(connector, edid); priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid); + + /* keep the EDID as ELD for the audio subsystem */ + drm_edid_to_eld(connector, edid); + priv->eld = connector->eld; + kfree(edid); } @@ -1191,6 +1215,8 @@ tda998x_encoder_destroy(struct drm_encoder *encoder) if (priv->hdmi->irq) free_irq(priv->hdmi->irq, priv); + tda998x_codec_unregister(&priv->hdmi->dev); + if (priv->cec) i2c_unregister_device(priv->cec); kfree(priv); @@ -1239,10 +1265,15 @@ tda998x_encoder_init(struct i2c_client *client, if (!priv) return -ENOMEM; + i2c_set_clientdata(client, priv); + priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3); priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1); priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5); + priv->params.audio_frame[1] = 1; /* channels - 1 */ + priv->params.audio_sample_rate = 48000; /* 48kHz */ + priv->current_page = 0xff; priv->hdmi = client; priv->cec = i2c_new_dummy(client->adapter, 0x34); @@ -1340,6 +1371,9 @@ tda998x_encoder_init(struct i2c_client *client, /* enable EDID read irq: */ reg_set(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); + /* register the audio CODEC */ + tda998x_codec_register(&client->dev); + if (!np) return 0; /* non-DT */ diff --git a/drivers/gpu/drm/i2c/tda998x_drv.h b/drivers/gpu/drm/i2c/tda998x_drv.h new file mode 100644 index 0000000..6db5160 --- /dev/null +++ b/drivers/gpu/drm/i2c/tda998x_drv.h @@ -0,0 +1,31 @@ +/* tda998x private data */ + +struct tda998x_priv { + struct i2c_client *cec; + struct i2c_client *hdmi; + uint16_t rev; + uint8_t current_page; + int dpms; + bool is_hdmi_sink; + u8 vip_cntrl_0; + u8 vip_cntrl_1; + u8 vip_cntrl_2; + struct tda998x_encoder_params params; + + wait_queue_head_t wq_edid; + volatile int wq_edid_wait; + struct drm_encoder *encoder; + + u8 audio_ports[2]; + int audio_sample_format; + + u8 *eld; + + struct snd_pcm_hw_constraint_list rate_constraints; +}; + +int tda998x_codec_register(struct device *dev); +void tda998x_codec_unregister(struct device *dev); + +void tda998x_audio_start(struct tda998x_priv *priv, int full); +void tda998x_audio_stop(struct tda998x_priv *priv); diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h index 3e419d9..31757df 100644 --- a/include/drm/i2c/tda998x.h +++ b/include/drm/i2c/tda998x.h @@ -20,6 +20,7 @@ struct tda998x_encoder_params { u8 audio_frame[6]; enum { + AFMT_NO_AUDIO = 0, AFMT_SPDIF, AFMT_I2S } audio_format; -- 2.0.1 -- Ken ar c'hentaƱ | ** Breizh ha Linux atav! ** Jef | http://moinejf.free.fr/