From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.3 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY, URIBL_BLOCKED,USER_AGENT_SANE_2 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3E131C38A24 for ; Thu, 7 May 2020 12:46:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 091A8207DD for ; Thu, 7 May 2020 12:46:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="seEm0ytv" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725953AbgEGMqq (ORCPT ); Thu, 7 May 2020 08:46:46 -0400 Received: from mailgw02.mediatek.com ([1.203.163.81]:36747 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1725857AbgEGMqq (ORCPT ); Thu, 7 May 2020 08:46:46 -0400 X-UUID: f281595b85724906b1b2ac3234039cca-20200507 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:MIME-Version:Content-Type:References:In-Reply-To:Date:CC:To:From:Subject:Message-ID; bh=Cnyq0ap0od9ETjikpOiyNssrJ6H77vhRUTGnWmVzp7A=; b=seEm0ytv0D8UIHGeeOoS923kMDaWmUNcbSH9qqaeMjW0Qkn/cLupSrllSiFyksHap1XZ7Q1c7vQbVdiXhc4L3aaxXEz0H8y78yYukG0DZkNtm0CrvOYGOkwuTvh9zAURRUhdga5YYJzUesxjS/V640jThTmH9KVMEd84Jek1JaM=; X-UUID: f281595b85724906b1b2ac3234039cca-20200507 Received: from mtkcas35.mediatek.inc [(172.27.4.253)] by mailgw02.mediatek.com (envelope-from ) (mailgw01.mediatek.com ESMTP with TLS) with ESMTP id 761235958; Thu, 07 May 2020 20:46:30 +0800 Received: from MTKCAS36.mediatek.inc (172.27.4.186) by MTKMBS31N1.mediatek.inc (172.27.4.69) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 7 May 2020 20:46:28 +0800 Received: from [10.17.3.153] (10.17.3.153) by MTKCAS36.mediatek.inc (172.27.4.170) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Thu, 7 May 2020 20:46:29 +0800 Message-ID: <1588855524.8804.168.camel@mhfsdcap03> Subject: Re: [V5, 2/2] media: i2c: dw9768: Add DW9768 VCM driver From: Dongchun Zhu To: Sakari Ailus CC: , , , , , , , , , , , , , , , , , Date: Thu, 7 May 2020 20:45:24 +0800 In-Reply-To: <20200506151352.GZ9190@paasikivi.fi.intel.com> References: <20200502161727.30463-1-dongchun.zhu@mediatek.com> <20200502161727.30463-3-dongchun.zhu@mediatek.com> <20200506151352.GZ9190@paasikivi.fi.intel.com> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.10.4-0ubuntu2 MIME-Version: 1.0 X-TM-SNTS-SMTP: D1FAE596B3EA16B283DDB710A97CBE78338F679B1D408994C1DC7D551E3354D82000:8 X-MTK: N Content-Transfer-Encoding: base64 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org SGkgU2FrYXJpLA0KDQpUaGFua3MgZm9yIHRoZSByZXZpZXcuDQoNCk9uIFdlZCwgMjAyMC0wNS0w NiBhdCAxODoxMyArMDMwMCwgU2FrYXJpIEFpbHVzIHdyb3RlOg0KPiBIaSBEb25nY2h1biwNCj4g DQo+IE9uIFN1biwgTWF5IDAzLCAyMDIwIGF0IDEyOjE3OjI3QU0gKzA4MDAsIERvbmdjaHVuIFpo dSB3cm90ZToNCj4gPiBBZGQgYSBWNEwyIHN1Yi1kZXZpY2UgZHJpdmVyIGZvciBEVzk3Njggdm9p Y2UgY29pbCBtb3RvciwgcHJvdmlkaW5nDQo+ID4gY29udHJvbCB0byBzZXQgdGhlIGRlc2lyZWQg Zm9jdXMgdmlhIElJQyBzZXJpYWwgaW50ZXJmYWNlLg0KPiA+IA0KPiA+IFNpZ25lZC1vZmYtYnk6 IERvbmdjaHVuIFpodSA8ZG9uZ2NodW4uemh1QG1lZGlhdGVrLmNvbT4NCj4gPiAtLS0NCj4gPiAg TUFJTlRBSU5FUlMgICAgICAgICAgICAgICAgfCAgIDEgKw0KPiA+ICBkcml2ZXJzL21lZGlhL2ky Yy9LY29uZmlnICB8ICAxMSArKw0KPiA+ICBkcml2ZXJzL21lZGlhL2kyYy9NYWtlZmlsZSB8ICAg MSArDQo+ID4gIGRyaXZlcnMvbWVkaWEvaTJjL2R3OTc2OC5jIHwgNDQwICsrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKw0KPiA+ICA0IGZpbGVzIGNoYW5nZWQsIDQ1 MyBpbnNlcnRpb25zKCspDQo+ID4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21lZGlhL2ky Yy9kdzk3NjguYw0KPiA+IA0KPiA+IGRpZmYgLS1naXQgYS9NQUlOVEFJTkVSUyBiL01BSU5UQUlO RVJTDQo+ID4gaW5kZXggOGQ3MmM0MS4uYzkyZGM5OSAxMDA2NDQNCj4gPiAtLS0gYS9NQUlOVEFJ TkVSUw0KPiA+ICsrKyBiL01BSU5UQUlORVJTDQo+ID4gQEAgLTUxNTcsNiArNTE1Nyw3IEBAIEw6 CWxpbnV4LW1lZGlhQHZnZXIua2VybmVsLm9yZw0KPiA+ICBTOglNYWludGFpbmVkDQo+ID4gIFQ6 CWdpdCBnaXQ6Ly9saW51eHR2Lm9yZy9tZWRpYV90cmVlLmdpdA0KPiA+ICBGOglEb2N1bWVudGF0 aW9uL2RldmljZXRyZWUvYmluZGluZ3MvbWVkaWEvaTJjL2Rvbmd3b29uLGR3OTc2OC55YW1sDQo+ ID4gK0Y6CWRyaXZlcnMvbWVkaWEvaTJjL2R3OTc2OC5jDQo+ID4gIA0KPiA+ICBET05HV09PTiBE Vzk4MDcgTEVOUyBWT0lDRSBDT0lMIERSSVZFUg0KPiA+ICBNOglTYWthcmkgQWlsdXMgPHNha2Fy aS5haWx1c0BsaW51eC5pbnRlbC5jb20+DQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWVkaWEv aTJjL0tjb25maWcgYi9kcml2ZXJzL21lZGlhL2kyYy9LY29uZmlnDQo+ID4gaW5kZXggMTI1ZDU5 Ni4uNmEzZjlkYSAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL21lZGlhL2kyYy9LY29uZmlnDQo+ ID4gKysrIGIvZHJpdmVycy9tZWRpYS9pMmMvS2NvbmZpZw0KPiA+IEBAIC0xMDQwLDYgKzEwNDAs MTcgQEAgY29uZmlnIFZJREVPX0RXOTcxNA0KPiA+ICAJICBjYXBhYmlsaXR5LiBUaGlzIGlzIGRl c2lnbmVkIGZvciBsaW5lYXIgY29udHJvbCBvZg0KPiA+ICAJICB2b2ljZSBjb2lsIG1vdG9ycywg Y29udHJvbGxlZCB2aWEgSTJDIHNlcmlhbCBpbnRlcmZhY2UuDQo+ID4gIA0KPiA+ICtjb25maWcg VklERU9fRFc5NzY4DQo+ID4gKwl0cmlzdGF0ZSAiRFc5NzY4IGxlbnMgdm9pY2UgY29pbCBzdXBw b3J0Ig0KPiA+ICsJZGVwZW5kcyBvbiBJMkMgJiYgVklERU9fVjRMMiAmJiBNRURJQV9DT05UUk9M TEVSDQo+ID4gKwlkZXBlbmRzIG9uIFZJREVPX1Y0TDJfU1VCREVWX0FQSQ0KPiANCj4gUGxlYXNl IGNoZWNrIGhvdyB0aGlzIHdvcmtzIGluIHRoZSBtZWRpYSB0cmVlIG1hc3RlciBicmFuY2ggbm93 IC0tLSBpdCdzDQo+IGxhcmdlbHkgc2VsZWN0IGJhc2VkLg0KPiANCg0KVGhlIGFjdHVhdG9yIGRy aXZlciB1c2VzIHNvbWUgc3RydWN0dXJlcyB0aGF0IHJlcXVpcmUgdGhlDQpWSURFT19WNEwyX1NV QkRFVl9BUEkgY29kZSwgc28gaGVyZSB3ZSBhZGQgVklERU9fVjRMMl9TVUJERVZfQVBJDQpkZXBl bmRlbmN5IHRvIGF2b2lkIHBvc3NpYmxlIGJ1aWxkIGVycm9yIHdoZW4gaXQncyBub3QgZW5hYmxl ZC4NCg0KPiBJbiBnZW5lcmFsIHRoZSBwYXRjaCBzZWVtcyBmaW5lIHRvIG1lLCBidXQgcGxlYXNl IHNlZSB0aGUgb3RoZXIgY29tbWVudHMNCj4gYmVsb3csIHRvby4NCj4gDQo+ID4gKwlkZXBlbmRz IG9uIFBNDQo+ID4gKwloZWxwDQo+ID4gKwkgIFRoaXMgaXMgYSBkcml2ZXIgZm9yIHRoZSBEVzk3 NjggY2FtZXJhIGxlbnMgdm9pY2UgY29pbC4NCj4gPiArCSAgRFc5NzY4IGlzIGEgMTAgYml0IERB QyB3aXRoIDEwMG1BIG91dHB1dCBjdXJyZW50IHNpbmsNCj4gPiArCSAgY2FwYWJpbGl0eS4gVGhp cyBpcyBkZXNpZ25lZCBmb3IgbGluZWFyIGNvbnRyb2wgb2YNCj4gPiArCSAgdm9pY2UgY29pbCBt b3RvcnMsIGNvbnRyb2xsZWQgdmlhIEkyQyBzZXJpYWwgaW50ZXJmYWNlLg0KPiA+ICsNCj4gPiAg Y29uZmlnIFZJREVPX0RXOTgwN19WQ00NCj4gPiAgCXRyaXN0YXRlICJEVzk4MDcgbGVucyB2b2lj ZSBjb2lsIHN1cHBvcnQiDQo+ID4gIAlkZXBlbmRzIG9uIEkyQyAmJiBWSURFT19WNEwyICYmIE1F RElBX0NPTlRST0xMRVINCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9tZWRpYS9pMmMvTWFrZWZp bGUgYi9kcml2ZXJzL21lZGlhL2kyYy9NYWtlZmlsZQ0KPiA+IGluZGV4IDc3YmY3ZDAuLjQwNTc0 NzYgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9tZWRpYS9pMmMvTWFrZWZpbGUNCj4gPiArKysg Yi9kcml2ZXJzL21lZGlhL2kyYy9NYWtlZmlsZQ0KPiA+IEBAIC0yNCw2ICsyNCw3IEBAIG9iai0k KENPTkZJR19WSURFT19TQUE2NzUySFMpICs9IHNhYTY3NTJocy5vDQo+ID4gIG9iai0kKENPTkZJ R19WSURFT19BRDU4MjApICArPSBhZDU4MjAubw0KPiA+ICBvYmotJChDT05GSUdfVklERU9fQUs3 Mzc1KSAgKz0gYWs3Mzc1Lm8NCj4gPiAgb2JqLSQoQ09ORklHX1ZJREVPX0RXOTcxNCkgICs9IGR3 OTcxNC5vDQo+ID4gK29iai0kKENPTkZJR19WSURFT19EVzk3NjgpICArPSBkdzk3Njgubw0KPiA+ ICBvYmotJChDT05GSUdfVklERU9fRFc5ODA3X1ZDTSkgICs9IGR3OTgwNy12Y20ubw0KPiA+ICBv YmotJChDT05GSUdfVklERU9fQURWNzE3MCkgKz0gYWR2NzE3MC5vDQo+ID4gIG9iai0kKENPTkZJ R19WSURFT19BRFY3MTc1KSArPSBhZHY3MTc1Lm8NCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9t ZWRpYS9pMmMvZHc5NzY4LmMgYi9kcml2ZXJzL21lZGlhL2kyYy9kdzk3NjguYw0KPiA+IG5ldyBm aWxlIG1vZGUgMTAwNjQ0DQo+ID4gaW5kZXggMDAwMDAwMC4uZGQ2ODUzNA0KPiA+IC0tLSAvZGV2 L251bGwNCj4gPiArKysgYi9kcml2ZXJzL21lZGlhL2kyYy9kdzk3NjguYw0KPiA+IEBAIC0wLDAg KzEsNDQwIEBADQo+ID4gKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wDQo+ID4g Ky8vIENvcHlyaWdodCAoYykgMjAyMCBNZWRpYVRlayBJbmMuDQo+ID4gKw0KPiA+ICsjaW5jbHVk ZSA8bGludXgvZGVsYXkuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L2kyYy5oPg0KPiA+ICsjaW5j bHVkZSA8bGludXgvbW9kdWxlLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9wbV9ydW50aW1lLmg+ DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9yZWd1bGF0b3IvY29uc3VtZXIuaD4NCj4gPiArI2luY2x1 ZGUgPG1lZGlhL3Y0bDItYXN5bmMuaD4NCj4gPiArI2luY2x1ZGUgPG1lZGlhL3Y0bDItY3RybHMu aD4NCj4gPiArI2luY2x1ZGUgPG1lZGlhL3Y0bDItZGV2aWNlLmg+DQo+ID4gKyNpbmNsdWRlIDxt ZWRpYS92NGwyLXN1YmRldi5oPg0KPiA+ICsNCj4gPiArI2RlZmluZSBEVzk3NjhfTkFNRQkJCQki ZHc5NzY4Ig0KPiA+ICsjZGVmaW5lIERXOTc2OF9NQVhfRk9DVVNfUE9TCQkJKDEwMjQgLSAxKQ0K PiA+ICsvKg0KPiA+ICsgKiBUaGlzIHNldHMgdGhlIG1pbmltdW0gZ3JhbnVsYXJpdHkgZm9yIHRo ZSBmb2N1cyBwb3NpdGlvbnMuDQo+ID4gKyAqIEEgdmFsdWUgb2YgMSBnaXZlcyBtYXhpbXVtIGFj Y3VyYWN5IGZvciBhIGRlc2lyZWQgZm9jdXMgcG9zaXRpb24NCj4gPiArICovDQo+ID4gKyNkZWZp bmUgRFc5NzY4X0ZPQ1VTX1NURVBTCQkJMQ0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogUmluZyBj b250cm9sIGFuZCBQb3dlciBjb250cm9sIHJlZ2lzdGVyDQo+ID4gKyAqIEJpdFsxXSBSSU5HX0VO DQo+ID4gKyAqIDA6IERpcmVjdCBtb2RlDQo+ID4gKyAqIDE6IEFBQyBtb2RlIChyaW5naW5nIGNv bnRyb2wgbW9kZSkNCj4gPiArICogQml0WzBdIFBEDQo+ID4gKyAqIDA6IE5vcm1hbCBvcGVyYXRp b24gbW9kZQ0KPiA+ICsgKiAxOiBQb3dlciBkb3duIG1vZGUNCj4gPiArICogRFc5NzY4IHJlcXVp cmVzIHdhaXRpbmcgdGltZSBvZiBUb3ByIGFmdGVyIFBEIHJlc2V0IHRha2VzIHBsYWNlLg0KPiA+ ICsgKi8NCj4gPiArI2RlZmluZSBEVzk3NjhfUklOR19QRF9DT05UUk9MX1JFRwkJMHgwMg0KPiA+ ICsjZGVmaW5lIERXOTc2OF9QRF9NT0RFX09GRgkJCTB4MDANCj4gPiArI2RlZmluZSBEVzk3Njhf UERfTU9ERV9FTgkJCUJJVCgwKQ0KPiA+ICsjZGVmaW5lIERXOTc2OF9BQUNfTU9ERV9FTgkJCUJJ VCgxKQ0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogRFc5NzY4IHNlcGFyYXRlcyB0d28gcmVnaXN0 ZXJzIHRvIGNvbnRyb2wgdGhlIFZDTSBwb3NpdGlvbi4NCj4gPiArICogT25lIGZvciBNU0IgdmFs dWUsIGFub3RoZXIgaXMgTFNCIHZhbHVlLg0KPiA+ICsgKiBEQUNfTVNCOiBEWzk6OF0gKEFERDog MHgwMykNCj4gPiArICogREFDX0xTQjogRFs3OjBdIChBREQ6IDB4MDQpDQo+ID4gKyAqIERbOTow XSBEQUMgZGF0YSBpbnB1dDogcG9zaXRpdmUgb3V0cHV0IGN1cnJlbnQgPSBEWzk6MF0gLyAxMDIz ICogMTAwW21BXQ0KPiA+ICsgKi8NCj4gPiArI2RlZmluZSBEVzk3NjhfTVNCX0FERFIJCQkJMHgw Mw0KPiA+ICsjZGVmaW5lIERXOTc2OF9MU0JfQUREUgkJCQkweDA0DQo+ID4gKyNkZWZpbmUgRFc5 NzY4X1NUQVRVU19BRERSCQkJMHgwNQ0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogQUFDIG1vZGUg Y29udHJvbCAmIHByZXNjYWxlIHJlZ2lzdGVyDQo+ID4gKyAqIEJpdFs3OjVdIE5hbWVseSBBQ1sy OjBdLCBkZWNpZGUgdGhlIFZDTSBtb2RlIGFuZCBvcGVyYXRpb24gdGltZS4NCj4gPiArICogMDAw IERpcmVjdChkZWZhdWx0KQ0KPiA+ICsgKiAwMDEgQUFDMiAwLjQ4eFR2aWINCj4gPiArICogMDEw IEFBQzMgMC43MHhUdmliDQo+ID4gKyAqIDAxMSBBQUM0IDAuNzV4VHZpYg0KPiA+ICsgKiAxMDAg UmVzZXJ2ZWQNCj4gPiArICogMTAxIEFBQzggMS4xM3hUdmliDQo+ID4gKyAqIDExMCBSZXNlcnZl ZA0KPiA+ICsgKiAxMTEgUmVzZXJ2ZWQNCj4gPiArICogQml0WzI6MF0gTmFtZWx5IFBSRVNDWzI6 MF0sIHNldCB0aGUgaW50ZXJuYWwgY2xvY2sgZGl2aWRpbmcgcmF0ZSBhcyBmb2xsb3cuDQo+ID4g KyAqIDAwMCAyDQo+ID4gKyAqIDAwMSAxKGRlZmF1bHQpDQo+ID4gKyAqIDAxMCAxLzINCj4gPiAr ICogMDExIDEvNA0KPiA+ICsgKiAxMDAgOA0KPiA+ICsgKiAxMDEgNA0KPiA+ICsgKiAxMTAgUmVz ZXJ2ZWQNCj4gPiArICogMTExIFJlc2VydmVkDQo+ID4gKyAqLw0KPiA+ICsjZGVmaW5lIERXOTc2 OF9BQUNfUFJFU0NfUkVHCQkJMHgwNg0KPiA+ICsjZGVmaW5lIERXOTc2OF9BQUMzX1NFTEVDVF9E SVZJRElOR19SQVRFXzEJMHg0MQ0KPiANCj4gSSBndWVzcyB3ZSBjYW4gc3RhcnQgd2l0aCB0aGVz ZSB2YWx1ZXMuIEJ1dCBJIGNhbid0IHRoaW5rIG9mIGFub3RoZXIgb3B0aW9uDQo+IHRoYW4gcHV0 dGluZyB0aGVtIGludG8gRFQgaWYgdGhlcmUgYXJlIGRpZmZlcmVuY2VzIGJldHdlZW4gd2hhdCBo YXJkd2FyZQ0KPiBwbGF0Zm9ybXMgcmVxdWlyZS4NCj4gDQoNCkxldCdzIGhhdmUgYSBkaXNjdXNz aW9uIGFib3V0IHRoaXMuDQpOb3cgdGhlc2Ugbm9uLWRlZmF1bHQgcmVnaXN0ZXIgc2V0dGluZ3Mg cmVwcmVzZW50IG9uZSBBQUMgb3BlcmF0aW9uDQptb2RlLCB0aGlzIGlzIG9uZSBvcHRpb24gYW5k IHdvcmtzIGZvciBhIGdpdmVuIGxlbnMgb3IgYSBtb2R1bGUuDQpJZiBzb21ldGltZSBpbiB0aGUg ZnV0dXJlIGhhcmR3YXJlIHBsYXRmb3JtcyByZXF1aXJlIGFub3RoZXIgZGlmZmVyZW50DQpzZXR0 aW5ncywgdGhlbiBEVCBwcm9wZXJ0aWVzIG1heSBuZWVkIHRvIGJlIGNyZWF0ZWQuDQoNCj4gPiAr DQo+ID4gKy8qDQo+ID4gKyAqIFZDTSBwZXJpb2Qgb2YgdmlicmF0aW9uIHJlZ2lzdGVyDQo+ID4g KyAqIEJpdFs1OjBdIERlZmluZWQgYXMgVkNNIHJpc2luZyBwZXJpb2RpYyB0aW1lIChUdmliKSB0 b2dldGhlciB3aXRoIFBSRVNDWzI6MF0NCj4gPiArICogVHZpYiA9ICg2LjNtcyArIEFBQ1RbNTow XSAqIDAuMW1zKSAqIERpdmlkaW5nIFJhdGUNCj4gPiArICogRGl2aWRpbmcgUmF0ZSBpcyB0aGUg aW50ZXJuYWwgY2xvY2sgZGl2aWRpbmcgcmF0ZSB0aGF0IGlzIGRlZmluZWQgYXQNCj4gPiArICog UFJFU0NBTEUgcmVnaXN0ZXIgKEFERDogMHgwNikNCj4gPiArICovDQo+ID4gKyNkZWZpbmUgRFc5 NzY4X0FBQ19USU1FX1JFRwkJCTB4MDcNCj4gPiArI2RlZmluZSBEVzk3NjhfQUFDVF9DTlQJCQkJ MHgzOQ0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogRFc5NzY4IHJlcXVpcmVzIHdhaXRpbmcgdGlt ZSAoZGVsYXkgdGltZSkgb2YgdF9PUFIgYWZ0ZXIgcG93ZXItdXAsDQo+ID4gKyAqIG9yIGluIHRo ZSBjYXNlIG9mIFBEIHJlc2V0IHRha2luZyBwbGFjZS4NCj4gPiArICovDQo+ID4gKyNkZWZpbmUg RFc5NzY4X1RfT1BSX1VTCQkJCTEwMDANCj4gPiArDQo+ID4gKy8qDQo+ID4gKyAqIFRoaXMgYWN0 cyBhcyB0aGUgbWluaW11bSBncmFudWxhcml0eSBvZiBsZW5zIG1vdmVtZW50Lg0KPiA+ICsgKiBL ZWVwIHRoaXMgdmFsdWUgcG93ZXIgb2YgMiwgc28gdGhlIGNvbnRyb2wgc3RlcHMgY2FuIGJlDQo+ ID4gKyAqIHVuaWZvcm1seSBhZGp1c3RlZCBmb3IgZ3JhZHVhbCBsZW5zIG1vdmVtZW50LCB3aXRo IGRlc2lyZWQNCj4gPiArICogbnVtYmVyIG9mIGNvbnRyb2wgc3RlcHMuDQo+ID4gKyAqLw0KPiA+ ICsjZGVmaW5lIERXOTc2OF9NT1ZFX1NURVBTCQkJMTYNCj4gPiArDQo+ID4gKy8qDQo+ID4gKyAq IERXOTc2OF9BQUNfUFJFU0NfUkVHICYgRFc5NzY4X0FBQ19USU1FX1JFRyBkZXRlcm1pbmUgVkNN IG9wZXJhdGlvbiB0aW1lLg0KPiA+ICsgKiBJZiBEVzk3NjhfQUFDX1BSRVNDX1JFRyBpcyAweDQx LCBhbmQgRFc5NzY4X0FBQ19USU1FX1JFRyBpcyAweDM5LCBWQ00gbW9kZQ0KPiA+ICsgKiB3b3Vs ZCBiZSBBQUMzLCBPcGVyYXRpb24gVGltZSB3b3VsZCBiZSAwLjcweFR2aWIsIHRoYXQgaXMgOC40 MG1zLg0KPiA+ICsgKi8NCj4gPiArI2RlZmluZSBEVzk3NjhfTU9WRV9ERUxBWV9VUwkJCTg0MDAN Cj4gPiArI2RlZmluZSBEVzk3NjhfU1RBQkxFX1RJTUVfVVMJCQkyMDAwMA0KPiA+ICsNCj4gPiAr c3RhdGljIGNvbnN0IGNoYXIgKiBjb25zdCBkdzk3Njhfc3VwcGx5X25hbWVzW10gPSB7DQo+ID4g KwkidmluIiwJLyogSTJDIEkvTyBpbnRlcmZhY2UgcG93ZXIgKi8NCj4gPiArCSJ2ZGQiLAkvKiBW Q00gcG93ZXIgKi8NCj4gPiArfTsNCj4gPiArDQo+ID4gKy8qIGR3OTc2OCBkZXZpY2Ugc3RydWN0 dXJlICovDQo+ID4gK3N0cnVjdCBkdzk3Njggew0KPiA+ICsJc3RydWN0IHJlZ3VsYXRvcl9idWxr X2RhdGEgc3VwcGxpZXNbQVJSQVlfU0laRShkdzk3Njhfc3VwcGx5X25hbWVzKV07DQo+ID4gKwlz dHJ1Y3QgdjRsMl9jdHJsX2hhbmRsZXIgY3RybHM7DQo+ID4gKwlzdHJ1Y3QgdjRsMl9jdHJsICpm b2N1czsNCj4gPiArCXN0cnVjdCB2NGwyX3N1YmRldiBzZDsNCj4gPiArfTsNCj4gPiArDQo+ID4g K3N0YXRpYyBpbmxpbmUgc3RydWN0IGR3OTc2OCAqdG9fZHc5NzY4KHN0cnVjdCB2NGwyX2N0cmwg KmN0cmwpDQo+ID4gK3sNCj4gPiArCXJldHVybiBjb250YWluZXJfb2YoY3RybC0+aGFuZGxlciwg c3RydWN0IGR3OTc2OCwgY3RybHMpOw0KPiA+ICt9DQo+IA0KPiBUaGlzIGlzIHVzZWQgaW4gYSBz aW5nbGUgcGxhY2UuIEknZCBqdXN0IHVzZSBjb250YWluZXJfb2YoKSBkaXJlY3RseSB0aGVyZS4N Cj4gDQoNClRoYW5rcyBmb3IgdGhlIHJlbWluZGVyLg0KRml4ZWQgaW4gbmV4dCByZWxlYXNlLg0K DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW5saW5lIHN0cnVjdCBkdzk3NjggKnNkX3RvX2R3OTc2OChz dHJ1Y3QgdjRsMl9zdWJkZXYgKnN1YmRldikNCj4gPiArew0KPiA+ICsJcmV0dXJuIGNvbnRhaW5l cl9vZihzdWJkZXYsIHN0cnVjdCBkdzk3NjgsIHNkKTsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3Ry dWN0IHJlZ3ZhbF9saXN0IHsNCj4gPiArCXU4IHJlZ19udW07DQo+ID4gKwl1OCB2YWx1ZTsNCj4g PiArfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgcmVndmFsX2xpc3QgZHc5NzY4 X2luaXRfcmVnc1tdID0gew0KPiA+ICsJe0RXOTc2OF9SSU5HX1BEX0NPTlRST0xfUkVHLCBEVzk3 NjhfQUFDX01PREVfRU59LA0KPiA+ICsJe0RXOTc2OF9BQUNfUFJFU0NfUkVHLCBEVzk3NjhfQUFD M19TRUxFQ1RfRElWSURJTkdfUkFURV8xfSwNCj4gPiArCXtEVzk3NjhfQUFDX1RJTUVfUkVHLCBE Vzk3NjhfQUFDVF9DTlR9LA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGludCBkdzk3Njhf d3JpdGVfYXJyYXkoc3RydWN0IGR3OTc2OCAqZHc5NzY4LA0KPiA+ICsJCQkgICAgICBjb25zdCBz dHJ1Y3QgcmVndmFsX2xpc3QgKnZhbHMsIHNpemVfdCBsZW4pDQo+ID4gK3sNCj4gPiArCXN0cnVj dCBpMmNfY2xpZW50ICpjbGllbnQgPSB2NGwyX2dldF9zdWJkZXZkYXRhKCZkdzk3NjgtPnNkKTsN Cj4gPiArCXVuc2lnbmVkIGludCBpOw0KPiA+ICsJaW50IHJldDsNCj4gPiArDQo+ID4gKwlmb3Ig KGkgPSAwOyBpIDwgbGVuOyBpKyspIHsNCj4gPiArCQlyZXQgPSBpMmNfc21idXNfd3JpdGVfYnl0 ZV9kYXRhKGNsaWVudCwgdmFsc1tpXS5yZWdfbnVtLA0KPiA+ICsJCQkJCQl2YWxzW2ldLnZhbHVl KTsNCj4gPiArCQlpZiAocmV0IDwgMCkNCj4gPiArCQkJcmV0dXJuIHJldDsNCj4gPiArCX0NCj4g PiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGR3OTc2OF9zZXRf ZGFjKHN0cnVjdCBkdzk3NjggKmR3OTc2OCwgdTE2IHZhbCkNCj4gPiArew0KPiA+ICsJc3RydWN0 IGkyY19jbGllbnQgKmNsaWVudCA9IHY0bDJfZ2V0X3N1YmRldmRhdGEoJmR3OTc2OC0+c2QpOw0K PiA+ICsNCj4gPiArCS8qIFdyaXRlIFZDTSBwb3NpdGlvbiB0byByZWdpc3RlcnMgKi8NCj4gPiAr CXJldHVybiBpMmNfc21idXNfd3JpdGVfd29yZF9zd2FwcGVkKGNsaWVudCwgRFc5NzY4X01TQl9B RERSLCB2YWwpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGR3OTc2OF9pbml0KHN0 cnVjdCBkdzk3NjggKmR3OTc2OCkNCj4gPiArew0KPiA+ICsJc3RydWN0IGkyY19jbGllbnQgKmNs aWVudCA9IHY0bDJfZ2V0X3N1YmRldmRhdGEoJmR3OTc2OC0+c2QpOw0KPiA+ICsJaW50IHJldCwg dmFsOw0KPiA+ICsNCj4gPiArCS8qIFJlc2V0IERXOTc2OF9SSU5HX1BEX0NPTlRST0xfUkVHIHRv IGRlZmF1bHQgc3RhdHVzIDB4MDAgKi8NCj4gPiArCXJldCA9IGkyY19zbWJ1c193cml0ZV9ieXRl X2RhdGEoY2xpZW50LCBEVzk3NjhfUklOR19QRF9DT05UUk9MX1JFRywNCj4gPiArCQkJCQlEVzk3 NjhfUERfTU9ERV9PRkYpOw0KPiA+ICsJaWYgKHJldCA8IDApDQo+ID4gKwkJcmV0dXJuIHJldDsN Cj4gPiArDQo+ID4gKwkvKg0KPiA+ICsJICogRFc5NzY5IHJlcXVpcmVzIHdhaXRpbmcgZGVsYXkg dGltZSBvZiB0X09QUg0KPiA+ICsJICogYWZ0ZXIgUEQgcmVzZXQgdGFrZXMgcGxhY2UuDQo+ID4g KwkgKi8NCj4gPiArCXVzbGVlcF9yYW5nZShEVzk3NjhfVF9PUFJfVVMsIERXOTc2OF9UX09QUl9V UyArIDEwMCk7DQo+ID4gKw0KPiA+ICsJcmV0ID0gZHc5NzY4X3dyaXRlX2FycmF5KGR3OTc2OCwg ZHc5NzY4X2luaXRfcmVncywNCj4gPiArCQkJCSBBUlJBWV9TSVpFKGR3OTc2OF9pbml0X3JlZ3Mp KTsNCj4gPiArCWlmIChyZXQpDQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArDQo+ID4gKwlmb3Ig KHZhbCA9IGR3OTc2OC0+Zm9jdXMtPnZhbCAlIERXOTc2OF9NT1ZFX1NURVBTOw0KPiA+ICsJICAg ICB2YWwgPD0gZHc5NzY4LT5mb2N1cy0+dmFsOw0KPiA+ICsJICAgICB2YWwgKz0gRFc5NzY4X01P VkVfU1RFUFMpIHsNCj4gPiArCQlyZXQgPSBkdzk3Njhfc2V0X2RhYyhkdzk3NjgsIHZhbCk7DQo+ ID4gKwkJaWYgKHJldCkgew0KPiA+ICsJCQlkZXZfZXJyKCZjbGllbnQtPmRldiwgIiVzIEkyQyBm YWlsdXJlOiAlZCIsDQo+ID4gKwkJCQlfX2Z1bmNfXywgcmV0KTsNCj4gPiArCQkJcmV0dXJuIHJl dDsNCj4gPiArCQl9DQo+ID4gKwkJdXNsZWVwX3JhbmdlKERXOTc2OF9NT1ZFX0RFTEFZX1VTLA0K PiA+ICsJCQkgICAgIERXOTc2OF9NT1ZFX0RFTEFZX1VTICsgMTAwMCk7DQo+ID4gKwl9DQo+ID4g Kw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgZHc5NzY4 X3JlbGVhc2Uoc3RydWN0IGR3OTc2OCAqZHc5NzY4KQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgaTJj X2NsaWVudCAqY2xpZW50ID0gdjRsMl9nZXRfc3ViZGV2ZGF0YSgmZHc5NzY4LT5zZCk7DQo+ID4g KwlpbnQgcmV0LCB2YWw7DQo+ID4gKw0KPiA+ICsJdmFsID0gcm91bmRfZG93bihkdzk3NjgtPmZv Y3VzLT52YWwsIERXOTc2OF9NT1ZFX1NURVBTKTsNCj4gPiArCWZvciAoIDsgdmFsID49IDA7IHZh bCAtPSBEVzk3NjhfTU9WRV9TVEVQUykgew0KPiA+ICsJCXJldCA9IGR3OTc2OF9zZXRfZGFjKGR3 OTc2OCwgdmFsKTsNCj4gPiArCQlpZiAocmV0KSB7DQo+ID4gKwkJCWRldl9lcnIoJmNsaWVudC0+ ZGV2LCAiSTJDIHdyaXRlIGZhaWw6ICVkIiwgcmV0KTsNCj4gPiArCQkJcmV0dXJuIHJldDsNCj4g PiArCQl9DQo+ID4gKwkJdXNsZWVwX3JhbmdlKERXOTc2OF9NT1ZFX0RFTEFZX1VTLCBEVzk3Njhf TU9WRV9ERUxBWV9VUyArIDEwMDApOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCS8qDQo+ID4gKwkg KiBXYWl0IGZvciB0aGUgbW90b3IgdG8gc3RhYmlsaXplIGFmdGVyIHRoZSBsYXN0IG1vdmVtZW50 DQo+ID4gKwkgKiB0byBwcmV2ZW50IHRoZSBtb3RvciBmcm9tIHNoYWtpbmcuDQo+ID4gKwkgKi8N Cj4gPiArCXVzbGVlcF9yYW5nZShEVzk3NjhfU1RBQkxFX1RJTUVfVVMgLSBEVzk3NjhfTU9WRV9E RUxBWV9VUywNCj4gPiArCQkgICAgIERXOTc2OF9TVEFCTEVfVElNRV9VUyAtIERXOTc2OF9NT1ZF X0RFTEFZX1VTICsgMTAwMCk7DQo+ID4gKw0KPiA+ICsJcmV0ID0gaTJjX3NtYnVzX3dyaXRlX2J5 dGVfZGF0YShjbGllbnQsIERXOTc2OF9SSU5HX1BEX0NPTlRST0xfUkVHLA0KPiA+ICsJCQkJCURX OTc2OF9QRF9NT0RFX0VOKTsNCj4gPiArCWlmIChyZXQgPCAwKQ0KPiA+ICsJCXJldHVybiByZXQ7 DQo+ID4gKw0KPiA+ICsJLyoNCj4gPiArCSAqIERXOTc2OSByZXF1aXJlcyB3YWl0aW5nIGRlbGF5 IHRpbWUgb2YgdF9PUFINCj4gPiArCSAqIGFmdGVyIFBEIHJlc2V0IHRha2VzIHBsYWNlLg0KPiA+ ICsJICovDQo+ID4gKwl1c2xlZXBfcmFuZ2UoRFc5NzY4X1RfT1BSX1VTLCBEVzk3NjhfVF9PUFJf VVMgKyAxMDApOw0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtz dGF0aWMgaW50IF9fbWF5YmVfdW51c2VkIGR3OTc2OF9ydW50aW1lX3N1c3BlbmQoc3RydWN0IGRl dmljZSAqZGV2KQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50ID0gdG9f aTJjX2NsaWVudChkZXYpOw0KPiA+ICsJc3RydWN0IHY0bDJfc3ViZGV2ICpzZCA9IGkyY19nZXRf Y2xpZW50ZGF0YShjbGllbnQpOw0KPiA+ICsJc3RydWN0IGR3OTc2OCAqZHc5NzY4ID0gc2RfdG9f ZHc5NzY4KHNkKTsNCj4gPiArDQo+ID4gKwlkdzk3NjhfcmVsZWFzZShkdzk3NjgpOw0KPiA+ICsJ cmVndWxhdG9yX2J1bGtfZGlzYWJsZShBUlJBWV9TSVpFKGR3OTc2OF9zdXBwbHlfbmFtZXMpLA0K PiA+ICsJCQkgICAgICAgZHc5NzY4LT5zdXBwbGllcyk7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7 DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgX19tYXliZV91bnVzZWQgZHc5NzY4X3J1 bnRpbWVfcmVzdW1lKHN0cnVjdCBkZXZpY2UgKmRldikNCj4gPiArew0KPiA+ICsJc3RydWN0IGky Y19jbGllbnQgKmNsaWVudCA9IHRvX2kyY19jbGllbnQoZGV2KTsNCj4gPiArCXN0cnVjdCB2NGwy X3N1YmRldiAqc2QgPSBpMmNfZ2V0X2NsaWVudGRhdGEoY2xpZW50KTsNCj4gPiArCXN0cnVjdCBk dzk3NjggKmR3OTc2OCA9IHNkX3RvX2R3OTc2OChzZCk7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsN Cj4gPiArCXJldCA9IHJlZ3VsYXRvcl9idWxrX2VuYWJsZShBUlJBWV9TSVpFKGR3OTc2OF9zdXBw bHlfbmFtZXMpLA0KPiA+ICsJCQkJICAgIGR3OTc2OC0+c3VwcGxpZXMpOw0KPiA+ICsJaWYgKHJl dCA8IDApIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgImZhaWxlZCB0byBlbmFibGUgcmVndWxhdG9y c1xuIik7DQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwkvKg0KPiA+ ICsJICogVGhlIGRhdGFzaGVldCByZWZlcnMgdG8gdF9PUFIgdGhhdCBuZWVkcyB0byBiZSB3YWl0 ZWQgYmVmb3JlIHNlbmRpbmcNCj4gPiArCSAqIEkyQyBjb21tYW5kcyBhZnRlciBwb3dlci11cC4N Cj4gPiArCSAqLw0KPiA+ICsJdXNsZWVwX3JhbmdlKERXOTc2OF9UX09QUl9VUywgRFc5NzY4X1Rf T1BSX1VTICsgMTAwKTsNCj4gPiArDQo+ID4gKwlyZXQgPSBkdzk3NjhfaW5pdChkdzk3NjgpOw0K PiA+ICsJaWYgKHJldCA8IDApDQo+ID4gKwkJZ290byBkaXNhYmxlX3JlZ3VsYXRvcjsNCj4gPiAr DQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArDQo+ID4gK2Rpc2FibGVfcmVndWxhdG9yOg0KPiA+ICsJ cmVndWxhdG9yX2J1bGtfZGlzYWJsZShBUlJBWV9TSVpFKGR3OTc2OF9zdXBwbHlfbmFtZXMpLA0K PiA+ICsJCQkgICAgICAgZHc5NzY4LT5zdXBwbGllcyk7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIHJl dDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBkdzk3Njhfc2V0X2N0cmwoc3RydWN0 IHY0bDJfY3RybCAqY3RybCkNCj4gPiArew0KPiA+ICsJc3RydWN0IGR3OTc2OCAqZHc5NzY4ID0g dG9fZHc5NzY4KGN0cmwpOw0KPiA+ICsNCj4gPiArCWlmIChjdHJsLT5pZCA9PSBWNEwyX0NJRF9G T0NVU19BQlNPTFVURSkNCj4gPiArCQlyZXR1cm4gZHc5NzY4X3NldF9kYWMoZHc5NzY4LCBjdHJs LT52YWwpOw0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0 aWMgY29uc3Qgc3RydWN0IHY0bDJfY3RybF9vcHMgZHc5NzY4X2N0cmxfb3BzID0gew0KPiA+ICsJ LnNfY3RybCA9IGR3OTc2OF9zZXRfY3RybCwNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBp bnQgZHc5NzY4X29wZW4oc3RydWN0IHY0bDJfc3ViZGV2ICpzZCwgc3RydWN0IHY0bDJfc3ViZGV2 X2ZoICpmaCkNCj4gPiArew0KPiA+ICsJaW50IHJldDsNCj4gPiArDQo+ID4gKwlyZXQgPSBwbV9y dW50aW1lX2dldF9zeW5jKHNkLT5kZXYpOw0KPiA+ICsJaWYgKHJldCA8IDApIHsNCj4gPiArCQlw bV9ydW50aW1lX3B1dF9ub2lkbGUoc2QtPmRldik7DQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiAr CX0NCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGlu dCBkdzk3NjhfY2xvc2Uoc3RydWN0IHY0bDJfc3ViZGV2ICpzZCwgc3RydWN0IHY0bDJfc3ViZGV2 X2ZoICpmaCkNCj4gPiArew0KPiA+ICsJcG1fcnVudGltZV9wdXQoc2QtPmRldik7DQo+ID4gKw0K PiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qg djRsMl9zdWJkZXZfaW50ZXJuYWxfb3BzIGR3OTc2OF9pbnRfb3BzID0gew0KPiA+ICsJLm9wZW4g PSBkdzk3Njhfb3BlbiwNCj4gPiArCS5jbG9zZSA9IGR3OTc2OF9jbG9zZSwNCj4gPiArfTsNCj4g PiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgdjRsMl9zdWJkZXZfb3BzIGR3OTc2OF9vcHMg PSB7IH07DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGR3OTc2OF9pbml0X2NvbnRyb2xzKHN0cnVj dCBkdzk3NjggKmR3OTc2OCkNCj4gPiArew0KPiA+ICsJc3RydWN0IHY0bDJfY3RybF9oYW5kbGVy ICpoZGwgPSAmZHc5NzY4LT5jdHJsczsNCj4gPiArCWNvbnN0IHN0cnVjdCB2NGwyX2N0cmxfb3Bz ICpvcHMgPSAmZHc5NzY4X2N0cmxfb3BzOw0KPiA+ICsNCj4gPiArCXY0bDJfY3RybF9oYW5kbGVy X2luaXQoaGRsLCAxKTsNCj4gPiArDQo+ID4gKwlkdzk3NjgtPmZvY3VzID0gdjRsMl9jdHJsX25l d19zdGQoaGRsLCBvcHMsIFY0TDJfQ0lEX0ZPQ1VTX0FCU09MVVRFLCAwLA0KPiA+ICsJCQkJCSAg RFc5NzY4X01BWF9GT0NVU19QT1MsDQo+ID4gKwkJCQkJICBEVzk3NjhfRk9DVVNfU1RFUFMsIDAp Ow0KPiA+ICsNCj4gPiArCWlmIChoZGwtPmVycm9yKQ0KPiA+ICsJCXJldHVybiBoZGwtPmVycm9y Ow0KPiA+ICsNCj4gPiArCWR3OTc2OC0+c2QuY3RybF9oYW5kbGVyID0gaGRsOw0KPiA+ICsNCj4g PiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGR3OTc2OF9wcm9i ZShzdHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50KQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgZGV2aWNl ICpkZXYgPSAmY2xpZW50LT5kZXY7DQo+ID4gKwlzdHJ1Y3QgZHc5NzY4ICpkdzk3Njg7DQo+ID4g Kwl1bnNpZ25lZCBpbnQgaTsNCj4gPiArCWludCByZXQ7DQo+ID4gKw0KPiA+ICsJZHc5NzY4ID0g ZGV2bV9remFsbG9jKGRldiwgc2l6ZW9mKCpkdzk3NjgpLCBHRlBfS0VSTkVMKTsNCj4gPiArCWlm ICghZHc5NzY4KQ0KPiA+ICsJCXJldHVybiAtRU5PTUVNOw0KPiA+ICsNCj4gPiArCXY0bDJfaTJj X3N1YmRldl9pbml0KCZkdzk3NjgtPnNkLCBjbGllbnQsICZkdzk3Njhfb3BzKTsNCj4gPiArDQo+ ID4gKwlmb3IgKGkgPSAwOyBpIDwgQVJSQVlfU0laRShkdzk3Njhfc3VwcGx5X25hbWVzKTsgaSsr KQ0KPiA+ICsJCWR3OTc2OC0+c3VwcGxpZXNbaV0uc3VwcGx5ID0gZHc5NzY4X3N1cHBseV9uYW1l c1tpXTsNCj4gPiArDQo+ID4gKwlyZXQgPSBkZXZtX3JlZ3VsYXRvcl9idWxrX2dldChkZXYsIEFS UkFZX1NJWkUoZHc5NzY4X3N1cHBseV9uYW1lcyksDQo+ID4gKwkJCQkgICAgICBkdzk3NjgtPnN1 cHBsaWVzKTsNCj4gPiArCWlmIChyZXQpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgImZhaWxlZCB0 byBnZXQgcmVndWxhdG9yc1xuIik7DQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArCX0NCj4gPiAr DQo+ID4gKwlyZXQgPSBkdzk3NjhfaW5pdF9jb250cm9scyhkdzk3NjgpOw0KPiA+ICsJaWYgKHJl dCkNCj4gPiArCQlnb3RvIGVudGl0eV9jbGVhbnVwOw0KPiA+ICsNCj4gPiArCWR3OTc2OC0+c2Qu ZmxhZ3MgfD0gVjRMMl9TVUJERVZfRkxfSEFTX0RFVk5PREU7DQo+ID4gKwlkdzk3NjgtPnNkLmlu dGVybmFsX29wcyA9ICZkdzk3NjhfaW50X29wczsNCj4gPiArDQo+ID4gKwlyZXQgPSBtZWRpYV9l bnRpdHlfcGFkc19pbml0KCZkdzk3NjgtPnNkLmVudGl0eSwgMCwgTlVMTCk7DQo+ID4gKwlpZiAo cmV0IDwgMCkNCj4gPiArCQlnb3RvIGVudGl0eV9jbGVhbnVwOw0KPiA+ICsNCj4gPiArCWR3OTc2 OC0+c2QuZW50aXR5LmZ1bmN0aW9uID0gTUVESUFfRU5UX0ZfTEVOUzsNCj4gPiArDQo+ID4gKwlw bV9ydW50aW1lX2VuYWJsZShkZXYpOw0KPiA+ICsJaWYgKCFwbV9ydW50aW1lX2VuYWJsZWQoZGV2 KSkgew0KPiA+ICsJCXJldCA9IGR3OTc2OF9ydW50aW1lX3Jlc3VtZShkZXYpOw0KPiA+ICsJCWlm IChyZXQgPCAwKSB7DQo+ID4gKwkJCWRldl9lcnIoZGV2LCAiZmFpbGVkIHRvIHBvd2VyIG9uOiAl ZFxuIiwgcmV0KTsNCj4gPiArCQkJZ290byBlbnRpdHlfY2xlYW51cDsNCj4gPiArCQl9DQo+ID4g Kwl9DQo+ID4gKw0KPiA+ICsJcmV0ID0gdjRsMl9hc3luY19yZWdpc3Rlcl9zdWJkZXYoJmR3OTc2 OC0+c2QpOw0KPiA+ICsJaWYgKHJldCA8IDApDQo+ID4gKwkJZ290byBlbnRpdHlfY2xlYW51cDsN Cj4gPiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArDQo+ID4gK2VudGl0eV9jbGVhbnVwOg0KPiA+ ICsJdjRsMl9jdHJsX2hhbmRsZXJfZnJlZSgmZHc5NzY4LT5jdHJscyk7DQo+ID4gKwltZWRpYV9l bnRpdHlfY2xlYW51cCgmZHc5NzY4LT5zZC5lbnRpdHkpOw0KPiA+ICsJcmV0dXJuIHJldDsNCj4g PiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBkdzk3NjhfcmVtb3ZlKHN0cnVjdCBpMmNfY2xp ZW50ICpjbGllbnQpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCB2NGwyX3N1YmRldiAqc2QgPSBpMmNf Z2V0X2NsaWVudGRhdGEoY2xpZW50KTsNCj4gPiArCXN0cnVjdCBkdzk3NjggKmR3OTc2OCA9IHNk X3RvX2R3OTc2OChzZCk7DQo+ID4gKw0KPiA+ICsJcG1fcnVudGltZV9kaXNhYmxlKCZjbGllbnQt PmRldik7DQo+ID4gKwl2NGwyX2FzeW5jX3VucmVnaXN0ZXJfc3ViZGV2KCZkdzk3NjgtPnNkKTsN Cj4gPiArCXY0bDJfY3RybF9oYW5kbGVyX2ZyZWUoJmR3OTc2OC0+Y3RybHMpOw0KPiA+ICsJbWVk aWFfZW50aXR5X2NsZWFudXAoJmR3OTc2OC0+c2QuZW50aXR5KTsNCj4gPiArCWlmICghcG1fcnVu dGltZV9zdGF0dXNfc3VzcGVuZGVkKCZjbGllbnQtPmRldikpDQo+ID4gKwkJZHc5NzY4X3J1bnRp bWVfc3VzcGVuZCgmY2xpZW50LT5kZXYpOw0KPiA+ICsJcG1fcnVudGltZV9zZXRfc3VzcGVuZGVk KCZjbGllbnQtPmRldik7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNlX2lkIGR3OTc2OF9vZl90YWJsZVtdID0g ew0KPiA+ICsJeyAuY29tcGF0aWJsZSA9ICJkb25nd29vbixkdzk3NjgiIH0sDQo+ID4gKwl7fQ0K PiA+ICt9Ow0KPiA+ICtNT0RVTEVfREVWSUNFX1RBQkxFKG9mLCBkdzk3Njhfb2ZfdGFibGUpOw0K PiA+ICsNCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBkZXZfcG1fb3BzIGR3OTc2OF9wbV9vcHMg PSB7DQo+ID4gKwlTRVRfU1lTVEVNX1NMRUVQX1BNX09QUyhwbV9ydW50aW1lX2ZvcmNlX3N1c3Bl bmQsDQo+ID4gKwkJCQlwbV9ydW50aW1lX2ZvcmNlX3Jlc3VtZSkNCj4gPiArCVNFVF9SVU5USU1F X1BNX09QUyhkdzk3NjhfcnVudGltZV9zdXNwZW5kLCBkdzk3NjhfcnVudGltZV9yZXN1bWUsIE5V TEwpDQo+ID4gK307DQo+ID4gKw0KPiA+ICtzdGF0aWMgc3RydWN0IGkyY19kcml2ZXIgZHc5NzY4 X2kyY19kcml2ZXIgPSB7DQo+ID4gKwkuZHJpdmVyID0gew0KPiA+ICsJCS5uYW1lID0gRFc5NzY4 X05BTUUsDQo+ID4gKwkJLnBtID0gJmR3OTc2OF9wbV9vcHMsDQo+ID4gKwkJLm9mX21hdGNoX3Rh YmxlID0gZHc5NzY4X29mX3RhYmxlLA0KPiA+ICsJfSwNCj4gPiArCS5wcm9iZV9uZXcgID0gZHc5 NzY4X3Byb2JlLA0KPiA+ICsJLnJlbW92ZSA9IGR3OTc2OF9yZW1vdmUsDQo+ID4gK307DQo+ID4g K21vZHVsZV9pMmNfZHJpdmVyKGR3OTc2OF9pMmNfZHJpdmVyKTsNCj4gPiArDQo+ID4gK01PRFVM RV9BVVRIT1IoIkRvbmdjaHVuIFpodSA8ZG9uZ2NodW4uemh1QG1lZGlhdGVrLmNvbT4iKTsNCj4g PiArTU9EVUxFX0RFU0NSSVBUSU9OKCJEVzk3NjggVkNNIGRyaXZlciIpOw0KPiA+ICtNT0RVTEVf TElDRU5TRSgiR1BMIHYyIik7DQo+IA0KDQo= From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.2 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY, USER_AGENT_SANE_2 autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0000DC38A24 for ; Thu, 7 May 2020 12:46:54 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C2F332082E for ; Thu, 7 May 2020 12:46:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="IO+sM4B+"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="seEm0ytv" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C2F332082E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=mediatek.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Date:To:From:Subject:Message-ID:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=xGw8DxRg/baAorpPa8b8NjQpNzQJtSwwZzBaCPGG9JU=; b=IO+sM4B+o/Hzub lswbDhTLHRZdr8Q8UaLaKxQ8Fh5IiS5OITu/OAZ+0s1E1OLgp1WdcAIeqg81KHa8gEPlCSMoEP73O GvrW/C/6OI/OGZXaJmS5zFZc4x/BQJHKbm+kG2vDPM4/GDXlF0A6KP7QDeV7sgr1AAdBsRdQVh5G1 CamOTORNp8qfy5FNX13AeKl1cGgxmxsNss+YEU+T1E5b9OUyvxoqnMOEoy4nlD/5Pg0Act119Pb5A mYsKo1WJP6Cq/LwEv8o3I9Pra6zjb6CGhAOFPMBLF1FsP02QgZKs5heEFXrdSc3dFpzz3ILNK1B66 lRVVMkhQbG2nhJkRRC9A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jWfvJ-0003Gm-SU; Thu, 07 May 2020 12:46:45 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jWfvG-0003GJ-LV; Thu, 07 May 2020 12:46:45 +0000 X-UUID: 419f2917e13f4f6586e3b2ac53bf1e38-20200507 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:MIME-Version:Content-Type:References:In-Reply-To:Date:CC:To:From:Subject:Message-ID; bh=Cnyq0ap0od9ETjikpOiyNssrJ6H77vhRUTGnWmVzp7A=; b=seEm0ytv0D8UIHGeeOoS923kMDaWmUNcbSH9qqaeMjW0Qkn/cLupSrllSiFyksHap1XZ7Q1c7vQbVdiXhc4L3aaxXEz0H8y78yYukG0DZkNtm0CrvOYGOkwuTvh9zAURRUhdga5YYJzUesxjS/V640jThTmH9KVMEd84Jek1JaM=; X-UUID: 419f2917e13f4f6586e3b2ac53bf1e38-20200507 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLS) with ESMTP id 1623575976; Thu, 07 May 2020 04:46:38 -0800 Received: from MTKMBS31N1.mediatek.inc (172.27.4.69) by MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 7 May 2020 05:46:31 -0700 Received: from MTKCAS36.mediatek.inc (172.27.4.186) by MTKMBS31N1.mediatek.inc (172.27.4.69) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 7 May 2020 20:46:28 +0800 Received: from [10.17.3.153] (10.17.3.153) by MTKCAS36.mediatek.inc (172.27.4.170) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Thu, 7 May 2020 20:46:29 +0800 Message-ID: <1588855524.8804.168.camel@mhfsdcap03> Subject: Re: [V5, 2/2] media: i2c: dw9768: Add DW9768 VCM driver From: Dongchun Zhu To: Sakari Ailus Date: Thu, 7 May 2020 20:45:24 +0800 In-Reply-To: <20200506151352.GZ9190@paasikivi.fi.intel.com> References: <20200502161727.30463-1-dongchun.zhu@mediatek.com> <20200502161727.30463-3-dongchun.zhu@mediatek.com> <20200506151352.GZ9190@paasikivi.fi.intel.com> X-Mailer: Evolution 3.10.4-0ubuntu2 MIME-Version: 1.0 X-TM-SNTS-SMTP: D1FAE596B3EA16B283DDB710A97CBE78338F679B1D408994C1DC7D551E3354D82000:8 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200507_054642_721136_C5392058 X-CRM114-Status: GOOD ( 30.01 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, drinkcat@chromium.org, andriy.shevchenko@linux.intel.com, srv_heupstream@mediatek.com, devicetree@vger.kernel.org, linus.walleij@linaro.org, shengnan.wang@mediatek.com, tfiga@chromium.org, bgolaszewski@baylibre.com, sj.huang@mediatek.com, robh+dt@kernel.org, linux-mediatek@lists.infradead.org, louis.kuo@mediatek.com, matthias.bgg@gmail.com, bingbu.cao@intel.com, mchehab@kernel.org, linux-arm-kernel@lists.infradead.org, linux-media@vger.kernel.org Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Hi Sakari, Thanks for the review. On Wed, 2020-05-06 at 18:13 +0300, Sakari Ailus wrote: > Hi Dongchun, > > On Sun, May 03, 2020 at 12:17:27AM +0800, Dongchun Zhu wrote: > > Add a V4L2 sub-device driver for DW9768 voice coil motor, providing > > control to set the desired focus via IIC serial interface. > > > > Signed-off-by: Dongchun Zhu > > --- > > MAINTAINERS | 1 + > > drivers/media/i2c/Kconfig | 11 ++ > > drivers/media/i2c/Makefile | 1 + > > drivers/media/i2c/dw9768.c | 440 +++++++++++++++++++++++++++++++++++++++++++++ > > 4 files changed, 453 insertions(+) > > create mode 100644 drivers/media/i2c/dw9768.c > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > index 8d72c41..c92dc99 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -5157,6 +5157,7 @@ L: linux-media@vger.kernel.org > > S: Maintained > > T: git git://linuxtv.org/media_tree.git > > F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9768.yaml > > +F: drivers/media/i2c/dw9768.c > > > > DONGWOON DW9807 LENS VOICE COIL DRIVER > > M: Sakari Ailus > > diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig > > index 125d596..6a3f9da 100644 > > --- a/drivers/media/i2c/Kconfig > > +++ b/drivers/media/i2c/Kconfig > > @@ -1040,6 +1040,17 @@ config VIDEO_DW9714 > > capability. This is designed for linear control of > > voice coil motors, controlled via I2C serial interface. > > > > +config VIDEO_DW9768 > > + tristate "DW9768 lens voice coil support" > > + depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER > > + depends on VIDEO_V4L2_SUBDEV_API > > Please check how this works in the media tree master branch now --- it's > largely select based. > The actuator driver uses some structures that require the VIDEO_V4L2_SUBDEV_API code, so here we add VIDEO_V4L2_SUBDEV_API dependency to avoid possible build error when it's not enabled. > In general the patch seems fine to me, but please see the other comments > below, too. > > > + depends on PM > > + help > > + This is a driver for the DW9768 camera lens voice coil. > > + DW9768 is a 10 bit DAC with 100mA output current sink > > + capability. This is designed for linear control of > > + voice coil motors, controlled via I2C serial interface. > > + > > config VIDEO_DW9807_VCM > > tristate "DW9807 lens voice coil support" > > depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER > > diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile > > index 77bf7d0..4057476 100644 > > --- a/drivers/media/i2c/Makefile > > +++ b/drivers/media/i2c/Makefile > > @@ -24,6 +24,7 @@ obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o > > obj-$(CONFIG_VIDEO_AD5820) += ad5820.o > > obj-$(CONFIG_VIDEO_AK7375) += ak7375.o > > obj-$(CONFIG_VIDEO_DW9714) += dw9714.o > > +obj-$(CONFIG_VIDEO_DW9768) += dw9768.o > > obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o > > obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o > > obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o > > diff --git a/drivers/media/i2c/dw9768.c b/drivers/media/i2c/dw9768.c > > new file mode 100644 > > index 0000000..dd68534 > > --- /dev/null > > +++ b/drivers/media/i2c/dw9768.c > > @@ -0,0 +1,440 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +// Copyright (c) 2020 MediaTek Inc. > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define DW9768_NAME "dw9768" > > +#define DW9768_MAX_FOCUS_POS (1024 - 1) > > +/* > > + * This sets the minimum granularity for the focus positions. > > + * A value of 1 gives maximum accuracy for a desired focus position > > + */ > > +#define DW9768_FOCUS_STEPS 1 > > + > > +/* > > + * Ring control and Power control register > > + * Bit[1] RING_EN > > + * 0: Direct mode > > + * 1: AAC mode (ringing control mode) > > + * Bit[0] PD > > + * 0: Normal operation mode > > + * 1: Power down mode > > + * DW9768 requires waiting time of Topr after PD reset takes place. > > + */ > > +#define DW9768_RING_PD_CONTROL_REG 0x02 > > +#define DW9768_PD_MODE_OFF 0x00 > > +#define DW9768_PD_MODE_EN BIT(0) > > +#define DW9768_AAC_MODE_EN BIT(1) > > + > > +/* > > + * DW9768 separates two registers to control the VCM position. > > + * One for MSB value, another is LSB value. > > + * DAC_MSB: D[9:8] (ADD: 0x03) > > + * DAC_LSB: D[7:0] (ADD: 0x04) > > + * D[9:0] DAC data input: positive output current = D[9:0] / 1023 * 100[mA] > > + */ > > +#define DW9768_MSB_ADDR 0x03 > > +#define DW9768_LSB_ADDR 0x04 > > +#define DW9768_STATUS_ADDR 0x05 > > + > > +/* > > + * AAC mode control & prescale register > > + * Bit[7:5] Namely AC[2:0], decide the VCM mode and operation time. > > + * 000 Direct(default) > > + * 001 AAC2 0.48xTvib > > + * 010 AAC3 0.70xTvib > > + * 011 AAC4 0.75xTvib > > + * 100 Reserved > > + * 101 AAC8 1.13xTvib > > + * 110 Reserved > > + * 111 Reserved > > + * Bit[2:0] Namely PRESC[2:0], set the internal clock dividing rate as follow. > > + * 000 2 > > + * 001 1(default) > > + * 010 1/2 > > + * 011 1/4 > > + * 100 8 > > + * 101 4 > > + * 110 Reserved > > + * 111 Reserved > > + */ > > +#define DW9768_AAC_PRESC_REG 0x06 > > +#define DW9768_AAC3_SELECT_DIVIDING_RATE_1 0x41 > > I guess we can start with these values. But I can't think of another option > than putting them into DT if there are differences between what hardware > platforms require. > Let's have a discussion about this. Now these non-default register settings represent one AAC operation mode, this is one option and works for a given lens or a module. If sometime in the future hardware platforms require another different settings, then DT properties may need to be created. > > + > > +/* > > + * VCM period of vibration register > > + * Bit[5:0] Defined as VCM rising periodic time (Tvib) together with PRESC[2:0] > > + * Tvib = (6.3ms + AACT[5:0] * 0.1ms) * Dividing Rate > > + * Dividing Rate is the internal clock dividing rate that is defined at > > + * PRESCALE register (ADD: 0x06) > > + */ > > +#define DW9768_AAC_TIME_REG 0x07 > > +#define DW9768_AACT_CNT 0x39 > > + > > +/* > > + * DW9768 requires waiting time (delay time) of t_OPR after power-up, > > + * or in the case of PD reset taking place. > > + */ > > +#define DW9768_T_OPR_US 1000 > > + > > +/* > > + * This acts as the minimum granularity of lens movement. > > + * Keep this value power of 2, so the control steps can be > > + * uniformly adjusted for gradual lens movement, with desired > > + * number of control steps. > > + */ > > +#define DW9768_MOVE_STEPS 16 > > + > > +/* > > + * DW9768_AAC_PRESC_REG & DW9768_AAC_TIME_REG determine VCM operation time. > > + * If DW9768_AAC_PRESC_REG is 0x41, and DW9768_AAC_TIME_REG is 0x39, VCM mode > > + * would be AAC3, Operation Time would be 0.70xTvib, that is 8.40ms. > > + */ > > +#define DW9768_MOVE_DELAY_US 8400 > > +#define DW9768_STABLE_TIME_US 20000 > > + > > +static const char * const dw9768_supply_names[] = { > > + "vin", /* I2C I/O interface power */ > > + "vdd", /* VCM power */ > > +}; > > + > > +/* dw9768 device structure */ > > +struct dw9768 { > > + struct regulator_bulk_data supplies[ARRAY_SIZE(dw9768_supply_names)]; > > + struct v4l2_ctrl_handler ctrls; > > + struct v4l2_ctrl *focus; > > + struct v4l2_subdev sd; > > +}; > > + > > +static inline struct dw9768 *to_dw9768(struct v4l2_ctrl *ctrl) > > +{ > > + return container_of(ctrl->handler, struct dw9768, ctrls); > > +} > > This is used in a single place. I'd just use container_of() directly there. > Thanks for the reminder. Fixed in next release. > > + > > +static inline struct dw9768 *sd_to_dw9768(struct v4l2_subdev *subdev) > > +{ > > + return container_of(subdev, struct dw9768, sd); > > +} > > + > > +struct regval_list { > > + u8 reg_num; > > + u8 value; > > +}; > > + > > +static const struct regval_list dw9768_init_regs[] = { > > + {DW9768_RING_PD_CONTROL_REG, DW9768_AAC_MODE_EN}, > > + {DW9768_AAC_PRESC_REG, DW9768_AAC3_SELECT_DIVIDING_RATE_1}, > > + {DW9768_AAC_TIME_REG, DW9768_AACT_CNT}, > > +}; > > + > > +static int dw9768_write_array(struct dw9768 *dw9768, > > + const struct regval_list *vals, size_t len) > > +{ > > + struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd); > > + unsigned int i; > > + int ret; > > + > > + for (i = 0; i < len; i++) { > > + ret = i2c_smbus_write_byte_data(client, vals[i].reg_num, > > + vals[i].value); > > + if (ret < 0) > > + return ret; > > + } > > + return 0; > > +} > > + > > +static int dw9768_set_dac(struct dw9768 *dw9768, u16 val) > > +{ > > + struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd); > > + > > + /* Write VCM position to registers */ > > + return i2c_smbus_write_word_swapped(client, DW9768_MSB_ADDR, val); > > +} > > + > > +static int dw9768_init(struct dw9768 *dw9768) > > +{ > > + struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd); > > + int ret, val; > > + > > + /* Reset DW9768_RING_PD_CONTROL_REG to default status 0x00 */ > > + ret = i2c_smbus_write_byte_data(client, DW9768_RING_PD_CONTROL_REG, > > + DW9768_PD_MODE_OFF); > > + if (ret < 0) > > + return ret; > > + > > + /* > > + * DW9769 requires waiting delay time of t_OPR > > + * after PD reset takes place. > > + */ > > + usleep_range(DW9768_T_OPR_US, DW9768_T_OPR_US + 100); > > + > > + ret = dw9768_write_array(dw9768, dw9768_init_regs, > > + ARRAY_SIZE(dw9768_init_regs)); > > + if (ret) > > + return ret; > > + > > + for (val = dw9768->focus->val % DW9768_MOVE_STEPS; > > + val <= dw9768->focus->val; > > + val += DW9768_MOVE_STEPS) { > > + ret = dw9768_set_dac(dw9768, val); > > + if (ret) { > > + dev_err(&client->dev, "%s I2C failure: %d", > > + __func__, ret); > > + return ret; > > + } > > + usleep_range(DW9768_MOVE_DELAY_US, > > + DW9768_MOVE_DELAY_US + 1000); > > + } > > + > > + return 0; > > +} > > + > > +static int dw9768_release(struct dw9768 *dw9768) > > +{ > > + struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd); > > + int ret, val; > > + > > + val = round_down(dw9768->focus->val, DW9768_MOVE_STEPS); > > + for ( ; val >= 0; val -= DW9768_MOVE_STEPS) { > > + ret = dw9768_set_dac(dw9768, val); > > + if (ret) { > > + dev_err(&client->dev, "I2C write fail: %d", ret); > > + return ret; > > + } > > + usleep_range(DW9768_MOVE_DELAY_US, DW9768_MOVE_DELAY_US + 1000); > > + } > > + > > + /* > > + * Wait for the motor to stabilize after the last movement > > + * to prevent the motor from shaking. > > + */ > > + usleep_range(DW9768_STABLE_TIME_US - DW9768_MOVE_DELAY_US, > > + DW9768_STABLE_TIME_US - DW9768_MOVE_DELAY_US + 1000); > > + > > + ret = i2c_smbus_write_byte_data(client, DW9768_RING_PD_CONTROL_REG, > > + DW9768_PD_MODE_EN); > > + if (ret < 0) > > + return ret; > > + > > + /* > > + * DW9769 requires waiting delay time of t_OPR > > + * after PD reset takes place. > > + */ > > + usleep_range(DW9768_T_OPR_US, DW9768_T_OPR_US + 100); > > + > > + return 0; > > +} > > + > > +static int __maybe_unused dw9768_runtime_suspend(struct device *dev) > > +{ > > + struct i2c_client *client = to_i2c_client(dev); > > + struct v4l2_subdev *sd = i2c_get_clientdata(client); > > + struct dw9768 *dw9768 = sd_to_dw9768(sd); > > + > > + dw9768_release(dw9768); > > + regulator_bulk_disable(ARRAY_SIZE(dw9768_supply_names), > > + dw9768->supplies); > > + > > + return 0; > > +} > > + > > +static int __maybe_unused dw9768_runtime_resume(struct device *dev) > > +{ > > + struct i2c_client *client = to_i2c_client(dev); > > + struct v4l2_subdev *sd = i2c_get_clientdata(client); > > + struct dw9768 *dw9768 = sd_to_dw9768(sd); > > + int ret; > > + > > + ret = regulator_bulk_enable(ARRAY_SIZE(dw9768_supply_names), > > + dw9768->supplies); > > + if (ret < 0) { > > + dev_err(dev, "failed to enable regulators\n"); > > + return ret; > > + } > > + > > + /* > > + * The datasheet refers to t_OPR that needs to be waited before sending > > + * I2C commands after power-up. > > + */ > > + usleep_range(DW9768_T_OPR_US, DW9768_T_OPR_US + 100); > > + > > + ret = dw9768_init(dw9768); > > + if (ret < 0) > > + goto disable_regulator; > > + > > + return 0; > > + > > +disable_regulator: > > + regulator_bulk_disable(ARRAY_SIZE(dw9768_supply_names), > > + dw9768->supplies); > > + > > + return ret; > > +} > > + > > +static int dw9768_set_ctrl(struct v4l2_ctrl *ctrl) > > +{ > > + struct dw9768 *dw9768 = to_dw9768(ctrl); > > + > > + if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) > > + return dw9768_set_dac(dw9768, ctrl->val); > > + > > + return 0; > > +} > > + > > +static const struct v4l2_ctrl_ops dw9768_ctrl_ops = { > > + .s_ctrl = dw9768_set_ctrl, > > +}; > > + > > +static int dw9768_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) > > +{ > > + int ret; > > + > > + ret = pm_runtime_get_sync(sd->dev); > > + if (ret < 0) { > > + pm_runtime_put_noidle(sd->dev); > > + return ret; > > + } > > + > > + return 0; > > +} > > + > > +static int dw9768_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) > > +{ > > + pm_runtime_put(sd->dev); > > + > > + return 0; > > +} > > + > > +static const struct v4l2_subdev_internal_ops dw9768_int_ops = { > > + .open = dw9768_open, > > + .close = dw9768_close, > > +}; > > + > > +static const struct v4l2_subdev_ops dw9768_ops = { }; > > + > > +static int dw9768_init_controls(struct dw9768 *dw9768) > > +{ > > + struct v4l2_ctrl_handler *hdl = &dw9768->ctrls; > > + const struct v4l2_ctrl_ops *ops = &dw9768_ctrl_ops; > > + > > + v4l2_ctrl_handler_init(hdl, 1); > > + > > + dw9768->focus = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE, 0, > > + DW9768_MAX_FOCUS_POS, > > + DW9768_FOCUS_STEPS, 0); > > + > > + if (hdl->error) > > + return hdl->error; > > + > > + dw9768->sd.ctrl_handler = hdl; > > + > > + return 0; > > +} > > + > > +static int dw9768_probe(struct i2c_client *client) > > +{ > > + struct device *dev = &client->dev; > > + struct dw9768 *dw9768; > > + unsigned int i; > > + int ret; > > + > > + dw9768 = devm_kzalloc(dev, sizeof(*dw9768), GFP_KERNEL); > > + if (!dw9768) > > + return -ENOMEM; > > + > > + v4l2_i2c_subdev_init(&dw9768->sd, client, &dw9768_ops); > > + > > + for (i = 0; i < ARRAY_SIZE(dw9768_supply_names); i++) > > + dw9768->supplies[i].supply = dw9768_supply_names[i]; > > + > > + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(dw9768_supply_names), > > + dw9768->supplies); > > + if (ret) { > > + dev_err(dev, "failed to get regulators\n"); > > + return ret; > > + } > > + > > + ret = dw9768_init_controls(dw9768); > > + if (ret) > > + goto entity_cleanup; > > + > > + dw9768->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; > > + dw9768->sd.internal_ops = &dw9768_int_ops; > > + > > + ret = media_entity_pads_init(&dw9768->sd.entity, 0, NULL); > > + if (ret < 0) > > + goto entity_cleanup; > > + > > + dw9768->sd.entity.function = MEDIA_ENT_F_LENS; > > + > > + pm_runtime_enable(dev); > > + if (!pm_runtime_enabled(dev)) { > > + ret = dw9768_runtime_resume(dev); > > + if (ret < 0) { > > + dev_err(dev, "failed to power on: %d\n", ret); > > + goto entity_cleanup; > > + } > > + } > > + > > + ret = v4l2_async_register_subdev(&dw9768->sd); > > + if (ret < 0) > > + goto entity_cleanup; > > + > > + return 0; > > + > > +entity_cleanup: > > + v4l2_ctrl_handler_free(&dw9768->ctrls); > > + media_entity_cleanup(&dw9768->sd.entity); > > + return ret; > > +} > > + > > +static int dw9768_remove(struct i2c_client *client) > > +{ > > + struct v4l2_subdev *sd = i2c_get_clientdata(client); > > + struct dw9768 *dw9768 = sd_to_dw9768(sd); > > + > > + pm_runtime_disable(&client->dev); > > + v4l2_async_unregister_subdev(&dw9768->sd); > > + v4l2_ctrl_handler_free(&dw9768->ctrls); > > + media_entity_cleanup(&dw9768->sd.entity); > > + if (!pm_runtime_status_suspended(&client->dev)) > > + dw9768_runtime_suspend(&client->dev); > > + pm_runtime_set_suspended(&client->dev); > > + > > + return 0; > > +} > > + > > +static const struct of_device_id dw9768_of_table[] = { > > + { .compatible = "dongwoon,dw9768" }, > > + {} > > +}; > > +MODULE_DEVICE_TABLE(of, dw9768_of_table); > > + > > +static const struct dev_pm_ops dw9768_pm_ops = { > > + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, > > + pm_runtime_force_resume) > > + SET_RUNTIME_PM_OPS(dw9768_runtime_suspend, dw9768_runtime_resume, NULL) > > +}; > > + > > +static struct i2c_driver dw9768_i2c_driver = { > > + .driver = { > > + .name = DW9768_NAME, > > + .pm = &dw9768_pm_ops, > > + .of_match_table = dw9768_of_table, > > + }, > > + .probe_new = dw9768_probe, > > + .remove = dw9768_remove, > > +}; > > +module_i2c_driver(dw9768_i2c_driver); > > + > > +MODULE_AUTHOR("Dongchun Zhu "); > > +MODULE_DESCRIPTION("DW9768 VCM driver"); > > +MODULE_LICENSE("GPL v2"); > _______________________________________________ Linux-mediatek mailing list Linux-mediatek@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-mediatek From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.2 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY, URIBL_BLOCKED,USER_AGENT_SANE_2 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0DA3CC54E49 for ; Thu, 7 May 2020 12:46:51 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D4D1C207DD for ; Thu, 7 May 2020 12:46:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="F5db61zP"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="seEm0ytv" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D4D1C207DD Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=mediatek.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Date:To:From:Subject:Message-ID:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=GDjBb6D9L255wTozAL2jeFxSReMyoycXqhvtIO6bmpI=; b=F5db61zPenDlOB 7GJD2YyLoAoZmqWm3JrVqh2neR2zAqLuf3/NKVZEHpzM8s8x85fwpirGfq0321PFjpNFVpYUFGkp5 6HHODC0wvQYtBuZnh7EUEt0yH7+9rtGM1j4rZmpgLlbS/yQSy7VOBuzDpLtvwz0ezX78/6mW2bETJ F/1rC1tJWpKfifrsz4+R/M1gSyBcI+cw7nMNvZ4gaTaXwrSJBtB4CzUJ6MW/hz7ynO1TzDZrisCE5 57tn9VE+UaJflR+98/FT4eikLVyozMk6DDhp3n3ZyEN05mq3vqT5i8GMoXfmF+fZHXdKWTnpOIXAM 9fVbFHuGGMlps+0fG2lg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jWfvK-0003HV-LP; Thu, 07 May 2020 12:46:46 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jWfvG-0003GJ-LV; Thu, 07 May 2020 12:46:45 +0000 X-UUID: 419f2917e13f4f6586e3b2ac53bf1e38-20200507 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:MIME-Version:Content-Type:References:In-Reply-To:Date:CC:To:From:Subject:Message-ID; bh=Cnyq0ap0od9ETjikpOiyNssrJ6H77vhRUTGnWmVzp7A=; b=seEm0ytv0D8UIHGeeOoS923kMDaWmUNcbSH9qqaeMjW0Qkn/cLupSrllSiFyksHap1XZ7Q1c7vQbVdiXhc4L3aaxXEz0H8y78yYukG0DZkNtm0CrvOYGOkwuTvh9zAURRUhdga5YYJzUesxjS/V640jThTmH9KVMEd84Jek1JaM=; X-UUID: 419f2917e13f4f6586e3b2ac53bf1e38-20200507 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLS) with ESMTP id 1623575976; Thu, 07 May 2020 04:46:38 -0800 Received: from MTKMBS31N1.mediatek.inc (172.27.4.69) by MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 7 May 2020 05:46:31 -0700 Received: from MTKCAS36.mediatek.inc (172.27.4.186) by MTKMBS31N1.mediatek.inc (172.27.4.69) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 7 May 2020 20:46:28 +0800 Received: from [10.17.3.153] (10.17.3.153) by MTKCAS36.mediatek.inc (172.27.4.170) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Thu, 7 May 2020 20:46:29 +0800 Message-ID: <1588855524.8804.168.camel@mhfsdcap03> Subject: Re: [V5, 2/2] media: i2c: dw9768: Add DW9768 VCM driver From: Dongchun Zhu To: Sakari Ailus Date: Thu, 7 May 2020 20:45:24 +0800 In-Reply-To: <20200506151352.GZ9190@paasikivi.fi.intel.com> References: <20200502161727.30463-1-dongchun.zhu@mediatek.com> <20200502161727.30463-3-dongchun.zhu@mediatek.com> <20200506151352.GZ9190@paasikivi.fi.intel.com> X-Mailer: Evolution 3.10.4-0ubuntu2 MIME-Version: 1.0 X-TM-SNTS-SMTP: D1FAE596B3EA16B283DDB710A97CBE78338F679B1D408994C1DC7D551E3354D82000:8 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200507_054642_721136_C5392058 X-CRM114-Status: GOOD ( 30.01 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, drinkcat@chromium.org, andriy.shevchenko@linux.intel.com, srv_heupstream@mediatek.com, devicetree@vger.kernel.org, linus.walleij@linaro.org, shengnan.wang@mediatek.com, tfiga@chromium.org, bgolaszewski@baylibre.com, sj.huang@mediatek.com, robh+dt@kernel.org, linux-mediatek@lists.infradead.org, louis.kuo@mediatek.com, matthias.bgg@gmail.com, bingbu.cao@intel.com, mchehab@kernel.org, linux-arm-kernel@lists.infradead.org, linux-media@vger.kernel.org Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org Hi Sakari, Thanks for the review. On Wed, 2020-05-06 at 18:13 +0300, Sakari Ailus wrote: > Hi Dongchun, > > On Sun, May 03, 2020 at 12:17:27AM +0800, Dongchun Zhu wrote: > > Add a V4L2 sub-device driver for DW9768 voice coil motor, providing > > control to set the desired focus via IIC serial interface. > > > > Signed-off-by: Dongchun Zhu > > --- > > MAINTAINERS | 1 + > > drivers/media/i2c/Kconfig | 11 ++ > > drivers/media/i2c/Makefile | 1 + > > drivers/media/i2c/dw9768.c | 440 +++++++++++++++++++++++++++++++++++++++++++++ > > 4 files changed, 453 insertions(+) > > create mode 100644 drivers/media/i2c/dw9768.c > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > index 8d72c41..c92dc99 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -5157,6 +5157,7 @@ L: linux-media@vger.kernel.org > > S: Maintained > > T: git git://linuxtv.org/media_tree.git > > F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9768.yaml > > +F: drivers/media/i2c/dw9768.c > > > > DONGWOON DW9807 LENS VOICE COIL DRIVER > > M: Sakari Ailus > > diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig > > index 125d596..6a3f9da 100644 > > --- a/drivers/media/i2c/Kconfig > > +++ b/drivers/media/i2c/Kconfig > > @@ -1040,6 +1040,17 @@ config VIDEO_DW9714 > > capability. This is designed for linear control of > > voice coil motors, controlled via I2C serial interface. > > > > +config VIDEO_DW9768 > > + tristate "DW9768 lens voice coil support" > > + depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER > > + depends on VIDEO_V4L2_SUBDEV_API > > Please check how this works in the media tree master branch now --- it's > largely select based. > The actuator driver uses some structures that require the VIDEO_V4L2_SUBDEV_API code, so here we add VIDEO_V4L2_SUBDEV_API dependency to avoid possible build error when it's not enabled. > In general the patch seems fine to me, but please see the other comments > below, too. > > > + depends on PM > > + help > > + This is a driver for the DW9768 camera lens voice coil. > > + DW9768 is a 10 bit DAC with 100mA output current sink > > + capability. This is designed for linear control of > > + voice coil motors, controlled via I2C serial interface. > > + > > config VIDEO_DW9807_VCM > > tristate "DW9807 lens voice coil support" > > depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER > > diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile > > index 77bf7d0..4057476 100644 > > --- a/drivers/media/i2c/Makefile > > +++ b/drivers/media/i2c/Makefile > > @@ -24,6 +24,7 @@ obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o > > obj-$(CONFIG_VIDEO_AD5820) += ad5820.o > > obj-$(CONFIG_VIDEO_AK7375) += ak7375.o > > obj-$(CONFIG_VIDEO_DW9714) += dw9714.o > > +obj-$(CONFIG_VIDEO_DW9768) += dw9768.o > > obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o > > obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o > > obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o > > diff --git a/drivers/media/i2c/dw9768.c b/drivers/media/i2c/dw9768.c > > new file mode 100644 > > index 0000000..dd68534 > > --- /dev/null > > +++ b/drivers/media/i2c/dw9768.c > > @@ -0,0 +1,440 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +// Copyright (c) 2020 MediaTek Inc. > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define DW9768_NAME "dw9768" > > +#define DW9768_MAX_FOCUS_POS (1024 - 1) > > +/* > > + * This sets the minimum granularity for the focus positions. > > + * A value of 1 gives maximum accuracy for a desired focus position > > + */ > > +#define DW9768_FOCUS_STEPS 1 > > + > > +/* > > + * Ring control and Power control register > > + * Bit[1] RING_EN > > + * 0: Direct mode > > + * 1: AAC mode (ringing control mode) > > + * Bit[0] PD > > + * 0: Normal operation mode > > + * 1: Power down mode > > + * DW9768 requires waiting time of Topr after PD reset takes place. > > + */ > > +#define DW9768_RING_PD_CONTROL_REG 0x02 > > +#define DW9768_PD_MODE_OFF 0x00 > > +#define DW9768_PD_MODE_EN BIT(0) > > +#define DW9768_AAC_MODE_EN BIT(1) > > + > > +/* > > + * DW9768 separates two registers to control the VCM position. > > + * One for MSB value, another is LSB value. > > + * DAC_MSB: D[9:8] (ADD: 0x03) > > + * DAC_LSB: D[7:0] (ADD: 0x04) > > + * D[9:0] DAC data input: positive output current = D[9:0] / 1023 * 100[mA] > > + */ > > +#define DW9768_MSB_ADDR 0x03 > > +#define DW9768_LSB_ADDR 0x04 > > +#define DW9768_STATUS_ADDR 0x05 > > + > > +/* > > + * AAC mode control & prescale register > > + * Bit[7:5] Namely AC[2:0], decide the VCM mode and operation time. > > + * 000 Direct(default) > > + * 001 AAC2 0.48xTvib > > + * 010 AAC3 0.70xTvib > > + * 011 AAC4 0.75xTvib > > + * 100 Reserved > > + * 101 AAC8 1.13xTvib > > + * 110 Reserved > > + * 111 Reserved > > + * Bit[2:0] Namely PRESC[2:0], set the internal clock dividing rate as follow. > > + * 000 2 > > + * 001 1(default) > > + * 010 1/2 > > + * 011 1/4 > > + * 100 8 > > + * 101 4 > > + * 110 Reserved > > + * 111 Reserved > > + */ > > +#define DW9768_AAC_PRESC_REG 0x06 > > +#define DW9768_AAC3_SELECT_DIVIDING_RATE_1 0x41 > > I guess we can start with these values. But I can't think of another option > than putting them into DT if there are differences between what hardware > platforms require. > Let's have a discussion about this. Now these non-default register settings represent one AAC operation mode, this is one option and works for a given lens or a module. If sometime in the future hardware platforms require another different settings, then DT properties may need to be created. > > + > > +/* > > + * VCM period of vibration register > > + * Bit[5:0] Defined as VCM rising periodic time (Tvib) together with PRESC[2:0] > > + * Tvib = (6.3ms + AACT[5:0] * 0.1ms) * Dividing Rate > > + * Dividing Rate is the internal clock dividing rate that is defined at > > + * PRESCALE register (ADD: 0x06) > > + */ > > +#define DW9768_AAC_TIME_REG 0x07 > > +#define DW9768_AACT_CNT 0x39 > > + > > +/* > > + * DW9768 requires waiting time (delay time) of t_OPR after power-up, > > + * or in the case of PD reset taking place. > > + */ > > +#define DW9768_T_OPR_US 1000 > > + > > +/* > > + * This acts as the minimum granularity of lens movement. > > + * Keep this value power of 2, so the control steps can be > > + * uniformly adjusted for gradual lens movement, with desired > > + * number of control steps. > > + */ > > +#define DW9768_MOVE_STEPS 16 > > + > > +/* > > + * DW9768_AAC_PRESC_REG & DW9768_AAC_TIME_REG determine VCM operation time. > > + * If DW9768_AAC_PRESC_REG is 0x41, and DW9768_AAC_TIME_REG is 0x39, VCM mode > > + * would be AAC3, Operation Time would be 0.70xTvib, that is 8.40ms. > > + */ > > +#define DW9768_MOVE_DELAY_US 8400 > > +#define DW9768_STABLE_TIME_US 20000 > > + > > +static const char * const dw9768_supply_names[] = { > > + "vin", /* I2C I/O interface power */ > > + "vdd", /* VCM power */ > > +}; > > + > > +/* dw9768 device structure */ > > +struct dw9768 { > > + struct regulator_bulk_data supplies[ARRAY_SIZE(dw9768_supply_names)]; > > + struct v4l2_ctrl_handler ctrls; > > + struct v4l2_ctrl *focus; > > + struct v4l2_subdev sd; > > +}; > > + > > +static inline struct dw9768 *to_dw9768(struct v4l2_ctrl *ctrl) > > +{ > > + return container_of(ctrl->handler, struct dw9768, ctrls); > > +} > > This is used in a single place. I'd just use container_of() directly there. > Thanks for the reminder. Fixed in next release. > > + > > +static inline struct dw9768 *sd_to_dw9768(struct v4l2_subdev *subdev) > > +{ > > + return container_of(subdev, struct dw9768, sd); > > +} > > + > > +struct regval_list { > > + u8 reg_num; > > + u8 value; > > +}; > > + > > +static const struct regval_list dw9768_init_regs[] = { > > + {DW9768_RING_PD_CONTROL_REG, DW9768_AAC_MODE_EN}, > > + {DW9768_AAC_PRESC_REG, DW9768_AAC3_SELECT_DIVIDING_RATE_1}, > > + {DW9768_AAC_TIME_REG, DW9768_AACT_CNT}, > > +}; > > + > > +static int dw9768_write_array(struct dw9768 *dw9768, > > + const struct regval_list *vals, size_t len) > > +{ > > + struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd); > > + unsigned int i; > > + int ret; > > + > > + for (i = 0; i < len; i++) { > > + ret = i2c_smbus_write_byte_data(client, vals[i].reg_num, > > + vals[i].value); > > + if (ret < 0) > > + return ret; > > + } > > + return 0; > > +} > > + > > +static int dw9768_set_dac(struct dw9768 *dw9768, u16 val) > > +{ > > + struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd); > > + > > + /* Write VCM position to registers */ > > + return i2c_smbus_write_word_swapped(client, DW9768_MSB_ADDR, val); > > +} > > + > > +static int dw9768_init(struct dw9768 *dw9768) > > +{ > > + struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd); > > + int ret, val; > > + > > + /* Reset DW9768_RING_PD_CONTROL_REG to default status 0x00 */ > > + ret = i2c_smbus_write_byte_data(client, DW9768_RING_PD_CONTROL_REG, > > + DW9768_PD_MODE_OFF); > > + if (ret < 0) > > + return ret; > > + > > + /* > > + * DW9769 requires waiting delay time of t_OPR > > + * after PD reset takes place. > > + */ > > + usleep_range(DW9768_T_OPR_US, DW9768_T_OPR_US + 100); > > + > > + ret = dw9768_write_array(dw9768, dw9768_init_regs, > > + ARRAY_SIZE(dw9768_init_regs)); > > + if (ret) > > + return ret; > > + > > + for (val = dw9768->focus->val % DW9768_MOVE_STEPS; > > + val <= dw9768->focus->val; > > + val += DW9768_MOVE_STEPS) { > > + ret = dw9768_set_dac(dw9768, val); > > + if (ret) { > > + dev_err(&client->dev, "%s I2C failure: %d", > > + __func__, ret); > > + return ret; > > + } > > + usleep_range(DW9768_MOVE_DELAY_US, > > + DW9768_MOVE_DELAY_US + 1000); > > + } > > + > > + return 0; > > +} > > + > > +static int dw9768_release(struct dw9768 *dw9768) > > +{ > > + struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd); > > + int ret, val; > > + > > + val = round_down(dw9768->focus->val, DW9768_MOVE_STEPS); > > + for ( ; val >= 0; val -= DW9768_MOVE_STEPS) { > > + ret = dw9768_set_dac(dw9768, val); > > + if (ret) { > > + dev_err(&client->dev, "I2C write fail: %d", ret); > > + return ret; > > + } > > + usleep_range(DW9768_MOVE_DELAY_US, DW9768_MOVE_DELAY_US + 1000); > > + } > > + > > + /* > > + * Wait for the motor to stabilize after the last movement > > + * to prevent the motor from shaking. > > + */ > > + usleep_range(DW9768_STABLE_TIME_US - DW9768_MOVE_DELAY_US, > > + DW9768_STABLE_TIME_US - DW9768_MOVE_DELAY_US + 1000); > > + > > + ret = i2c_smbus_write_byte_data(client, DW9768_RING_PD_CONTROL_REG, > > + DW9768_PD_MODE_EN); > > + if (ret < 0) > > + return ret; > > + > > + /* > > + * DW9769 requires waiting delay time of t_OPR > > + * after PD reset takes place. > > + */ > > + usleep_range(DW9768_T_OPR_US, DW9768_T_OPR_US + 100); > > + > > + return 0; > > +} > > + > > +static int __maybe_unused dw9768_runtime_suspend(struct device *dev) > > +{ > > + struct i2c_client *client = to_i2c_client(dev); > > + struct v4l2_subdev *sd = i2c_get_clientdata(client); > > + struct dw9768 *dw9768 = sd_to_dw9768(sd); > > + > > + dw9768_release(dw9768); > > + regulator_bulk_disable(ARRAY_SIZE(dw9768_supply_names), > > + dw9768->supplies); > > + > > + return 0; > > +} > > + > > +static int __maybe_unused dw9768_runtime_resume(struct device *dev) > > +{ > > + struct i2c_client *client = to_i2c_client(dev); > > + struct v4l2_subdev *sd = i2c_get_clientdata(client); > > + struct dw9768 *dw9768 = sd_to_dw9768(sd); > > + int ret; > > + > > + ret = regulator_bulk_enable(ARRAY_SIZE(dw9768_supply_names), > > + dw9768->supplies); > > + if (ret < 0) { > > + dev_err(dev, "failed to enable regulators\n"); > > + return ret; > > + } > > + > > + /* > > + * The datasheet refers to t_OPR that needs to be waited before sending > > + * I2C commands after power-up. > > + */ > > + usleep_range(DW9768_T_OPR_US, DW9768_T_OPR_US + 100); > > + > > + ret = dw9768_init(dw9768); > > + if (ret < 0) > > + goto disable_regulator; > > + > > + return 0; > > + > > +disable_regulator: > > + regulator_bulk_disable(ARRAY_SIZE(dw9768_supply_names), > > + dw9768->supplies); > > + > > + return ret; > > +} > > + > > +static int dw9768_set_ctrl(struct v4l2_ctrl *ctrl) > > +{ > > + struct dw9768 *dw9768 = to_dw9768(ctrl); > > + > > + if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) > > + return dw9768_set_dac(dw9768, ctrl->val); > > + > > + return 0; > > +} > > + > > +static const struct v4l2_ctrl_ops dw9768_ctrl_ops = { > > + .s_ctrl = dw9768_set_ctrl, > > +}; > > + > > +static int dw9768_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) > > +{ > > + int ret; > > + > > + ret = pm_runtime_get_sync(sd->dev); > > + if (ret < 0) { > > + pm_runtime_put_noidle(sd->dev); > > + return ret; > > + } > > + > > + return 0; > > +} > > + > > +static int dw9768_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) > > +{ > > + pm_runtime_put(sd->dev); > > + > > + return 0; > > +} > > + > > +static const struct v4l2_subdev_internal_ops dw9768_int_ops = { > > + .open = dw9768_open, > > + .close = dw9768_close, > > +}; > > + > > +static const struct v4l2_subdev_ops dw9768_ops = { }; > > + > > +static int dw9768_init_controls(struct dw9768 *dw9768) > > +{ > > + struct v4l2_ctrl_handler *hdl = &dw9768->ctrls; > > + const struct v4l2_ctrl_ops *ops = &dw9768_ctrl_ops; > > + > > + v4l2_ctrl_handler_init(hdl, 1); > > + > > + dw9768->focus = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE, 0, > > + DW9768_MAX_FOCUS_POS, > > + DW9768_FOCUS_STEPS, 0); > > + > > + if (hdl->error) > > + return hdl->error; > > + > > + dw9768->sd.ctrl_handler = hdl; > > + > > + return 0; > > +} > > + > > +static int dw9768_probe(struct i2c_client *client) > > +{ > > + struct device *dev = &client->dev; > > + struct dw9768 *dw9768; > > + unsigned int i; > > + int ret; > > + > > + dw9768 = devm_kzalloc(dev, sizeof(*dw9768), GFP_KERNEL); > > + if (!dw9768) > > + return -ENOMEM; > > + > > + v4l2_i2c_subdev_init(&dw9768->sd, client, &dw9768_ops); > > + > > + for (i = 0; i < ARRAY_SIZE(dw9768_supply_names); i++) > > + dw9768->supplies[i].supply = dw9768_supply_names[i]; > > + > > + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(dw9768_supply_names), > > + dw9768->supplies); > > + if (ret) { > > + dev_err(dev, "failed to get regulators\n"); > > + return ret; > > + } > > + > > + ret = dw9768_init_controls(dw9768); > > + if (ret) > > + goto entity_cleanup; > > + > > + dw9768->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; > > + dw9768->sd.internal_ops = &dw9768_int_ops; > > + > > + ret = media_entity_pads_init(&dw9768->sd.entity, 0, NULL); > > + if (ret < 0) > > + goto entity_cleanup; > > + > > + dw9768->sd.entity.function = MEDIA_ENT_F_LENS; > > + > > + pm_runtime_enable(dev); > > + if (!pm_runtime_enabled(dev)) { > > + ret = dw9768_runtime_resume(dev); > > + if (ret < 0) { > > + dev_err(dev, "failed to power on: %d\n", ret); > > + goto entity_cleanup; > > + } > > + } > > + > > + ret = v4l2_async_register_subdev(&dw9768->sd); > > + if (ret < 0) > > + goto entity_cleanup; > > + > > + return 0; > > + > > +entity_cleanup: > > + v4l2_ctrl_handler_free(&dw9768->ctrls); > > + media_entity_cleanup(&dw9768->sd.entity); > > + return ret; > > +} > > + > > +static int dw9768_remove(struct i2c_client *client) > > +{ > > + struct v4l2_subdev *sd = i2c_get_clientdata(client); > > + struct dw9768 *dw9768 = sd_to_dw9768(sd); > > + > > + pm_runtime_disable(&client->dev); > > + v4l2_async_unregister_subdev(&dw9768->sd); > > + v4l2_ctrl_handler_free(&dw9768->ctrls); > > + media_entity_cleanup(&dw9768->sd.entity); > > + if (!pm_runtime_status_suspended(&client->dev)) > > + dw9768_runtime_suspend(&client->dev); > > + pm_runtime_set_suspended(&client->dev); > > + > > + return 0; > > +} > > + > > +static const struct of_device_id dw9768_of_table[] = { > > + { .compatible = "dongwoon,dw9768" }, > > + {} > > +}; > > +MODULE_DEVICE_TABLE(of, dw9768_of_table); > > + > > +static const struct dev_pm_ops dw9768_pm_ops = { > > + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, > > + pm_runtime_force_resume) > > + SET_RUNTIME_PM_OPS(dw9768_runtime_suspend, dw9768_runtime_resume, NULL) > > +}; > > + > > +static struct i2c_driver dw9768_i2c_driver = { > > + .driver = { > > + .name = DW9768_NAME, > > + .pm = &dw9768_pm_ops, > > + .of_match_table = dw9768_of_table, > > + }, > > + .probe_new = dw9768_probe, > > + .remove = dw9768_remove, > > +}; > > +module_i2c_driver(dw9768_i2c_driver); > > + > > +MODULE_AUTHOR("Dongchun Zhu "); > > +MODULE_DESCRIPTION("DW9768 VCM driver"); > > +MODULE_LICENSE("GPL v2"); > _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel