From nobody Tue Jun 16 11:20:51 2026 Received: from mail-lj1-f169.google.com (mail-lj1-f169.google.com [209.85.208.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 056383793B8 for ; Sun, 19 Apr 2026 08:31:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776587514; cv=none; b=rNMzS6DPC5POXCeMkMLwRZmunt9BuVK+ybcUnjYhokS+bpsI2EmSDqElKyY9yQtDOs5sdjZ2FXCbvaHkLwDWRfozJ8rB4lWW6hLIZU31KfEyZIZYk8xHobiokmrBp3tMytUbO+cNDJT5Cy5WBCFWlPZc2t9DImfCBPEKN62TX3E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776587514; c=relaxed/simple; bh=1Jgb6/GbiYn+9y/qY8drz0ojO4Ovh+iCQsfw7Ms1hyY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XuWeOt7MXV/yn4Q8A5QUKgpNO2PWYRm/62AHyIaDfCfqZrSrEEPZrtVqJJGpCsCjBazOkshlyhzagArLtm/6ePZgt0y4oBEQCd5a/k/A2XDenPOdGzsfjKjgRod+H8DJ8JLBph/eb2BkW3z1JPO906WU4LR8Eycf9j7o6hauYyY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=XpDw5u+u; arc=none smtp.client-ip=209.85.208.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="XpDw5u+u" Received: by mail-lj1-f169.google.com with SMTP id 38308e7fff4ca-38e9653b580so20999961fa.2 for ; Sun, 19 Apr 2026 01:31:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776587510; x=1777192310; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=4TOenN1wWv7IAES6T4cFxNtUEJCBx2lMIL+l6+xDZLc=; b=XpDw5u+uX96w2pPAr/Yi8wsVCRona4gYll24j58DMOUWWWKbRsQMjHeda4BvbTRrJY CybB88R+M+YR2onpaYBrKycBS6p2O3RYBXeFXVBvDJmuzGP0az6ubYvz/hsSvWly4FWU lJJI2ZaNDdEMeMNQZZYTaoLjIX/SpF1oYDRKHDKDuqx0U6/pepXpyeYhxEuzFu3Own9G WEyN1FQUSKoNtvuupq5WnZ9Qxnro8FTYg/62jWKL+ejLSQmjHQUURye++3hv5i5Taanz di6URAnML3bb1c038d7fsSOwc/xa2rxr+UoZ8UitHTX8gGownd96UR3uCNs7IE+uJ7KA oVOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776587510; x=1777192310; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=4TOenN1wWv7IAES6T4cFxNtUEJCBx2lMIL+l6+xDZLc=; b=QyqNRC3YuFcTCF3BoaeBfeIFqtbqY8rmWSlepRNDr8/DT6NCOLY76hykzZ1MIej6ZA pWLScyxMHbjcTvxdb+ycgMxxM1tkJdl6i3bOdkc+HWzor+pia9agMmySACg3mRT1srMt GhrdkIUvFRXq/JdKQnWgCAKVgXFJ04t8oRjZ2dgJR2ELvi46P5HA75FGDANkeTLt+AzI H6WFsoIGJeb4ZXWQhE5TefeC8qnl4gLlpzX2EtVjFzdNiTxvCxFO6TUREfVMM238kC3L dyHvoBd6KZnkE9gGS7zFXTRu6kTqLL0n2bK6a2+YPhskgB8nTeMsABu9uUveIFBJpt6A xIZQ== X-Forwarded-Encrypted: i=1; AFNElJ+2jC+e5xq3aetDM8dV5sdMdUvRFGJXuvkSLoaJUq9mOt0z5T5ZG/JV7M7qdITo4IFv6aPhM88PeXnDzoQ=@vger.kernel.org X-Gm-Message-State: AOJu0Yz09FW5chOTckLmqYXiBGgEEp2VrgPdA7fYm4y0+tWcGt7RU8UB 2QtFUoOMJJvA42eo/SQhGz5mUHI1fE3DWBzZ3H5RSpwl7UGHnvha0ces X-Gm-Gg: AeBDievEQ2sEkmz4zc/PEDIrFyq6hnCCg7rexV68JxCMVuuuSqubmFexy/VQ0AnF5B2 +5EQ0yizUWw2ly4aM79Zq107Ncy4Lv6VPZ6BNEN/K6eOWEIbzgw+QsqRxs17M2d+bhqe0PKgeov hSQwx7F8LYz9GtsdfE8EaM4GcEJqAHemWLt6J5C1vhTstzrUyTLfzABUrDvR7Ddoa5vsqrt6OfN hPki3KPoV0OUR+QK1EpYKrX1U9un/l+xrkY9/izihLYTiU6TA7PnyXhP1ZU5vrqrtHJ2gUXwCSL xghKu7AJ1xAzHbKH584WMr9rAfHHmjudSErgOfbVerOy5UJEKvy+BrOVBn7Bn40/HzkIdxfd0jB tdpMI3Cg5CWrSfnnsnwXdGzV7NPLXPeK/hKROUZPLte05fT6YThOOBfN+mU0vjt1stqtOmV8jvY 5WCwwqJcXgQ2dv9Oo16F73JlM= X-Received: by 2002:a2e:2e09:0:b0:38e:94e3:206e with SMTP id 38308e7fff4ca-38ec7af74a5mr20338171fa.26.1776587509823; Sun, 19 Apr 2026 01:31:49 -0700 (PDT) Received: from xeon ([188.163.112.56]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-38ecb7613a9sm17852101fa.41.2026.04.19.01.31.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 Apr 2026 01:31:49 -0700 (PDT) From: Svyatoslav Ryhel To: Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Shuah Khan , Arnd Bergmann , Greg Kroah-Hartman , Svyatoslav Ryhel , Randy Dunlap Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org Subject: [PATCH v2 1/3] dt-bindings: iio: light: Document Avago APDS9900/9901 ALS/Proximity sensor Date: Sun, 19 Apr 2026 11:31:22 +0300 Message-ID: <20260419083125.35572-2-clamor95@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260419083125.35572-1-clamor95@gmail.com> References: <20260419083125.35572-1-clamor95@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Document Avago APDS-9900/9901 combined ALS/IR-LED/Proximity sensor. Signed-off-by: Svyatoslav Ryhel Acked-by: Rob Herring (Arm) --- Documentation/devicetree/bindings/iio/light/tsl2772.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/light/tsl2772.yaml b/Doc= umentation/devicetree/bindings/iio/light/tsl2772.yaml index d81229857944..9921ccaa64a0 100644 --- a/Documentation/devicetree/bindings/iio/light/tsl2772.yaml +++ b/Documentation/devicetree/bindings/iio/light/tsl2772.yaml @@ -26,6 +26,8 @@ properties: - amstaos,tmd2672 - amstaos,tsl2772 - amstaos,tmd2772 + - avago,apds9900 + - avago,apds9901 - avago,apds9930 =20 reg: --=20 2.51.0 From nobody Tue Jun 16 11:20:51 2026 Received: from mail-lj1-f173.google.com (mail-lj1-f173.google.com [209.85.208.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 75EBE379EDC for ; Sun, 19 Apr 2026 08:31:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776587517; cv=none; b=MgIF1X3mdAlFZY/T3Z9K2vkUwQRFtx6N31m3gK6UQ1+CGeLhlPPGmiGX3Fn3U1SgQgVrDBLqGNTdcgW6l28pIkwbbFLGBhJ/51ZMcIaE93IEZtbFL3Jv5lrx2LSX694diB+m/4O3cR5YPPkIHrNEJ2RP2o3AwyFnTr1K5aeaS8M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776587517; c=relaxed/simple; bh=ToECUiy6IO+Oym1nO2YydJJYfMv9Ti7cR0ZGWkKhXvk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EZzd1tuXdFKIUbPD/8LNnCGllJreGIlFaDUhWfqdqEVBxIoujXxSbfO0Kplfb4xKS/4tPI/DXoEDra4Pn3QK++uc45O96X1iOwi1JUf7KxqbGJCO7FjlL2f3KUOea5kWSn9OeNFlMuYjzqijhyDM0gD+zGY5KmtLB1Qj6+3hCr0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QMKbqasm; arc=none smtp.client-ip=209.85.208.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QMKbqasm" Received: by mail-lj1-f173.google.com with SMTP id 38308e7fff4ca-38e800deae4so16450921fa.0 for ; Sun, 19 Apr 2026 01:31:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776587512; x=1777192312; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vKUPlAlvFmlfkR1oHbcDc9OOKBpu5sVGNnqNv91gVHc=; b=QMKbqasm3q8gyVoc9dQtQ7meBR5pc8W6yceOsf6EYUCQg4oppSafICrF1uHxsIrUNf wZD+h9i2r+VBkYjmntdbV5GTAXMg/RPGNPZf9LjLaj9HRzGKKJGR4sAHtMkTLrqdCj4G Bcyy2Qt1vAl+MiL1GS89Scmsxi5yxelfaJbwvm/U+mSIHQ2UMUuOk5RMUtwx5N3beu+p S5njZ45LgKBdTtrroaFgjtpVXKEnVFSi1IqYrcLyPENF1SxHTDgWRvwlep8pamZQxRb4 dYxuFdPgv2iddaLS7Js1qz9Uc0AQBjqAbVHR09W23vkLGc8ZEOmc78t2GwAtLvrvEjxW UNAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776587512; x=1777192312; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=vKUPlAlvFmlfkR1oHbcDc9OOKBpu5sVGNnqNv91gVHc=; b=kqznYd/FIXNUvUIwiOTVwMg1I6vnwH67u82Ms9rNNWNhGkTiPRbr/avfSrLQSsh+dt khQZB34nhGxcDyqdeHoL2XwsENBOyiJpXBL8+NjmQrISxcpUOxvNk46vjYAYs3OCTzMK jrNwVRbzmUjNcpf/NnFKQTNQxlIzjviVUj7Dcxlh+HctvVa7gjrofx3eZRWgEHWdS2fF CngSzQaJFYgcSC7ioW8jg0dvaAXEUUtWxm9gUppbbZJz2a3Ec6DzHG4VuX18yD1Da02t TANspl7bBtly+KuLqyDmi/qupE3oXd2HvvDzt3SMUO43LPnmt9u841iCEv/4ZRTHdD4d T0BQ== X-Forwarded-Encrypted: i=1; AFNElJ/aVoP9etxuEiMFqk0Po5F6alqiMEolYPUWmNgnF06nVFaWjqucFcs+t+wq2Qne0WJOLq0c7F8rZYXOXXA=@vger.kernel.org X-Gm-Message-State: AOJu0Yz+yYGdtWt6xzffxNJAh278tTBGo6tPPClhntUux/ejBP3mHPB6 N9QPErakeOtR/YjhYQjbRXxgtUK6McbKI2Yn7diQkQUF3mPnc0yxRR0r X-Gm-Gg: AeBDieutnvjv2YcTgYNn6AaAjhR/uiwBv46l5CY31Jla//ZM0ZjRhLXLAch1rIPIPK3 69RF5Sn3QJXBkFUA5wljlAWr0toklBCv6zfiAzxkDxRVZDJjKkrl1z/K6vOnK5BN5af2DlnmtLd xjr5eaRRy2SC4yphm9MmY0BBp5i+5AvGOs7NrWv79iTuJmguQ2VTniW46zA/W99yV4VFB5Md7w4 fO35r7gMk1Xl3/1+rYdEimiuCGTcXGsO+XoShzU0Npv/XnaKx9rfRHgYWYdzD+mGVSgOaDWxmwz QmYI2MLJQNY80LrKJiRPLckTIt4fIQJXw6CcKqQdoPi9T22PAKS/bz3+57UuXwDDT2FiE1gfLuK t5NgDfkrM47xIe9VbDKT4CyTS9MKumAbg7FD4lle6GcW3wXxH/XHYhoohKulz7GdTs7sMOecWtl ZMGM/j6uuKB5Qu93k9ku7Fjz2bjOXgDptkAQ== X-Received: by 2002:a05:651c:e18:b0:38e:d8a3:e08a with SMTP id 38308e7fff4ca-38ed8a3e2bemr17458471fa.3.1776587511839; Sun, 19 Apr 2026 01:31:51 -0700 (PDT) Received: from xeon ([188.163.112.56]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-38ecb7613a9sm17852101fa.41.2026.04.19.01.31.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 Apr 2026 01:31:50 -0700 (PDT) From: Svyatoslav Ryhel To: Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Shuah Khan , Arnd Bergmann , Greg Kroah-Hartman , Svyatoslav Ryhel , Randy Dunlap Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org Subject: [PATCH v2 2/3] iio: tsl2772: add support for Avago APDS9900/9901 ALS/Proximity sensor Date: Sun, 19 Apr 2026 11:31:23 +0300 Message-ID: <20260419083125.35572-3-clamor95@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260419083125.35572-1-clamor95@gmail.com> References: <20260419083125.35572-1-clamor95@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The Avago APDS990x has the same register set as the TAOS/AMS TSL2772 so just add the correct bindings and the appropriate LUX table derived from the values in the datasheet. Driver was tested on the LG Optimus Vu P895. Signed-off-by: Svyatoslav Ryhel --- drivers/iio/light/tsl2772.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c index c8f15ba95267..8dab34bf00ca 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -127,6 +127,7 @@ enum { tmd2672, tsl2772, tmd2772, + apds990x, apds9930, }; =20 @@ -221,6 +222,12 @@ static const struct tsl2772_lux tmd2x72_lux_table[TSL2= 772_DEF_LUX_TABLE_SZ] =3D { { 0, 0 }, }; =20 +static const struct tsl2772_lux apds990x_lux_table[TSL2772_DEF_LUX_TABLE_S= Z] =3D { + { 52000, 115960 }, + { 36400, 73840 }, + { 0, 0 }, +}; + static const struct tsl2772_lux apds9930_lux_table[TSL2772_DEF_LUX_TABLE_S= Z] =3D { { 52000, 96824 }, { 38792, 67132 }, @@ -238,6 +245,7 @@ static const struct tsl2772_lux *tsl2772_default_lux_ta= ble_group[] =3D { [tmd2672] =3D tmd2x72_lux_table, [tsl2772] =3D tsl2x72_lux_table, [tmd2772] =3D tmd2x72_lux_table, + [apds990x] =3D apds990x_lux_table, [apds9930] =3D apds9930_lux_table, }; =20 @@ -289,6 +297,7 @@ static const int tsl2772_int_time_avail[][6] =3D { [tmd2672] =3D { 0, 2730, 0, 2730, 0, 699000 }, [tsl2772] =3D { 0, 2730, 0, 2730, 0, 699000 }, [tmd2772] =3D { 0, 2730, 0, 2730, 0, 699000 }, + [apds990x] =3D { 0, 2720, 0, 2720, 0, 696000 }, [apds9930] =3D { 0, 2730, 0, 2730, 0, 699000 }, }; =20 @@ -316,6 +325,7 @@ static const u8 device_channel_config[] =3D { [tmd2672] =3D PRX2, [tsl2772] =3D ALSPRX2, [tmd2772] =3D ALSPRX2, + [apds990x] =3D ALSPRX, [apds9930] =3D ALSPRX2, }; =20 @@ -530,6 +540,7 @@ static int tsl2772_get_prox(struct iio_dev *indio_dev) case tmd2672: case tsl2772: case tmd2772: + case apds990x: case apds9930: if (!(ret & TSL2772_STA_PRX_VALID)) { ret =3D -EINVAL; @@ -1367,6 +1378,7 @@ static int tsl2772_device_id_verif(int id, int target) return (id & 0xf0) =3D=3D TRITON_ID; case tmd2671: case tmd2771: + case apds990x: return (id & 0xf0) =3D=3D HALIBUT_ID; case tsl2572: case tsl2672: @@ -1898,6 +1910,8 @@ static const struct i2c_device_id tsl2772_idtable[] = =3D { { "tmd2672", tmd2672 }, { "tsl2772", tsl2772 }, { "tmd2772", tmd2772 }, + { "apds9900", apds990x }, + { "apds9901", apds990x }, { "apds9930", apds9930 }, { } }; @@ -1915,6 +1929,8 @@ static const struct of_device_id tsl2772_of_match[] = =3D { { .compatible =3D "amstaos,tmd2672" }, { .compatible =3D "amstaos,tsl2772" }, { .compatible =3D "amstaos,tmd2772" }, + { .compatible =3D "avago,apds9900" }, + { .compatible =3D "avago,apds9901" }, { .compatible =3D "avago,apds9930" }, { } }; --=20 2.51.0 From nobody Tue Jun 16 11:20:51 2026 Received: from mail-lj1-f178.google.com (mail-lj1-f178.google.com [209.85.208.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EDEA5359FAA for ; Sun, 19 Apr 2026 08:31:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776587521; cv=none; b=Ih4WV4fEERT6GZmiIfauMUikRkTMaDV3uybKD7JgOLHhV2MAEEY+RDPF/375UKdvhaBE6onTf/4j3KWL+BcB9HhtfC9M3WfkWiknmZdjiZoKCIB/g2Hef9DriqdEeB0vj8Xc6WWdo0rHPwX7R+qzLBQMkYfcWAFl8xF04DBOpuQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776587521; c=relaxed/simple; bh=0BhgzDqb6rJDW4LGQTJn0i8vdcqdgicTXWyBEp8Xu30=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p8btRz3MFgAXR0Elf1juLMwxazjRxER+vg/CnADMSHeTtpGrM7wvbYR0gkeWuDMfg1YGZq6urOT8R88lQv/JgpAmkKA7b3RtXfKgDGznrsBF3h4B7KL0qFb9VyqZe2e0fq3txNGBJ1UXMiBxozIW9G7SoFr9vQs8mHpJmyQtJZA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=SqZrwKHh; arc=none smtp.client-ip=209.85.208.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="SqZrwKHh" Received: by mail-lj1-f178.google.com with SMTP id 38308e7fff4ca-38e7d983f91so22655571fa.2 for ; Sun, 19 Apr 2026 01:31:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776587514; x=1777192314; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MmzmyQbQPVKtla/uKYGoixAEK+PU/KkFrPIcbgFY0Yw=; b=SqZrwKHhOl6+45NEEBkkTTqQSUXFL2Y0APQQUfxLU8qzTPgBeZKg7hCQks6z3aOqa5 PAvYEG28IYTAjkQjxi+OeeJ3oajdi2J2XjX9QstzTqiQf152D7hq2i3/A+STUw9pO8aS 9Od0d4lqTwWIO9cF5M6oeyy6W9BkemApV3sD0Fi1vSktwbsGceCPz8QaeDkx4D6DU9oi 8eytHBFmS11xFD4txBIdFixK9sEpkR0SCMKDoEsxxz/GYx8zShzdCA1Bl5f2Oi4Q1+A4 VTAOcPnwUn3gjENwc00HIcMzjWkqdifVlT9pBj2Yf32OkLe6F2QsA7exSqu/aCTwHNYr +Fjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776587514; x=1777192314; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=MmzmyQbQPVKtla/uKYGoixAEK+PU/KkFrPIcbgFY0Yw=; b=VaSDk2XxDaanNgXwCI290PtSbSbiyvfuX95e6hN+T2MccInWIINmoCiBFYfNpVTdS+ cFQTxekFEIqcnhMiYG3ChrwIeCrz6pdlcechTs+0ogOc4cR7MSvl7dCAn1Lii+DXXb1J mmCZhY9Xv9qWulkuoFVVA1HuIXUYfJ5lagfTKAof6xVxKa0ZfhAYmFvkmBUn4y9qcT7G sfbfg84uV84qzPLiZQz5D4ucoQgkLEC1m6nZcXfqTG9+VSySWTFyiCOosvrNfS/N+lSF 25TLUPJm/dhZ2qP7H2v+KbpgMKOb+LWTLrWmFZdF+eFYOEh2fAhOEj9mkaJ19XHoOika TZtQ== X-Forwarded-Encrypted: i=1; AFNElJ9uZpHnWrAuuF5HPj1aL2kC5YQgrFg31HbwcPHEEFPWYXVVA4ZxRj2sIRnwb+8Im7Q+p2n2vfM7Hq4LlTU=@vger.kernel.org X-Gm-Message-State: AOJu0YzEh4lDEoWCAx6yjwwYCtyszdk/h/GdVka4sT993M60rycvDBgn VHebcBguqA39PD1BJrApA78mboyZveH2q+EXmm6B/RqO6GWdED4bL3Dr X-Gm-Gg: AeBDietU5RxmC36l7kmDXbKgKWSHt8M8B+1n4p3omfhJl8mYl2t4XIypFTsqhitN6T9 XEagOkblKE5nv7NZPq17e0ugYIKT8s66CwUGOFfnyVphlG1yQQa53bFnzZJWShU9yHDcuYQUuhU Kc1CIKPx6lZj/GeEg3GHcKDHcPUsP2bEkfmLo+40kv+dbfZ3Ty3XrKRnL7+d/lW4Kf6ycI/0Sw4 1gmpmLBRuQTjeg+9rP4wLWaoAQEeRMWUeILDLZP0rO1E/+urXVZ5rbmSm+dqW/reykX7+d1+SYF SQmufH43COKqT/ALX3fY/7zRMfFAKhE7ofop7/8xgpdyNoO45q3Xgupi6268ljl2odZoGSkY9xV s/eutJGjOT8DuamSxASBGdTbxRvGvOYePfnXj3b1EQLe7ovSFszkWQC31HIzxDo22NTsIuZ1SWE 9ALwXJc8bh4/mK9AS3CKgQP7sMeBUvmThYjw== X-Received: by 2002:a05:6512:61db:10b0:5a4:19df:48de with SMTP id 2adb3069b0e04-5a419df497fmr1891645e87.26.1776587513991; Sun, 19 Apr 2026 01:31:53 -0700 (PDT) Received: from xeon ([188.163.112.56]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-38ecb7613a9sm17852101fa.41.2026.04.19.01.31.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 Apr 2026 01:31:52 -0700 (PDT) From: Svyatoslav Ryhel To: Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Shuah Khan , Arnd Bergmann , Greg Kroah-Hartman , Svyatoslav Ryhel , Randy Dunlap Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org Subject: [PATCH v2 3/3] misc: Remove old APDS990x driver Date: Sun, 19 Apr 2026 11:31:24 +0300 Message-ID: <20260419083125.35572-4-clamor95@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260419083125.35572-1-clamor95@gmail.com> References: <20260419083125.35572-1-clamor95@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The Avago APDS9900/9901 ALS/Proximity sensor is now supported by tsl2772 IIO driver so there is no need to keep this old implementation. Remove it. Signed-off-by: Svyatoslav Ryhel Acked-by: Greg Kroah-Hartman --- Documentation/misc-devices/apds990x.rst | 128 --- drivers/misc/Kconfig | 10 - drivers/misc/Makefile | 1 - drivers/misc/apds990x.c | 1284 ----------------------- include/linux/platform_data/apds990x.h | 65 -- 5 files changed, 1488 deletions(-) delete mode 100644 Documentation/misc-devices/apds990x.rst delete mode 100644 drivers/misc/apds990x.c delete mode 100644 include/linux/platform_data/apds990x.h diff --git a/Documentation/misc-devices/apds990x.rst b/Documentation/misc-d= evices/apds990x.rst deleted file mode 100644 index e2f75577f731..000000000000 --- a/Documentation/misc-devices/apds990x.rst +++ /dev/null @@ -1,128 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D -Kernel driver apds990x -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D - -Supported chips: -Avago APDS990X - -Data sheet: -Not freely available - -Author: -Samu Onkalo - -Description ------------ - -APDS990x is a combined ambient light and proximity sensor. ALS and proximi= ty -functionality are highly connected. ALS measurement path must be running -while the proximity functionality is enabled. - -ALS produces raw measurement values for two channels: Clear channel -(infrared + visible light) and IR only. However, threshold comparisons hap= pen -using clear channel only. Lux value and the threshold level on the HW -might vary quite much depending the spectrum of the light source. - -Driver makes necessary conversions to both directions so that user handles -only lux values. Lux value is calculated using information from the both -channels. HW threshold level is calculated from the given lux value to mat= ch -with current type of the lightning. Sometimes inaccuracy of the estimations -lead to false interrupt, but that doesn't harm. - -ALS contains 4 different gain steps. Driver automatically -selects suitable gain step. After each measurement, reliability of the res= ults -is estimated and new measurement is triggered if necessary. - -Platform data can provide tuned values to the conversion formulas if -values are known. Otherwise plain sensor default values are used. - -Proximity side is little bit simpler. There is no need for complex convers= ions. -It produces directly usable values. - -Driver controls chip operational state using pm_runtime framework. -Voltage regulators are controlled based on chip operational state. - -SYSFS ------ - - -chip_id - RO - shows detected chip type and version - -power_state - RW - enable / disable chip. Uses counting logic - - 1 enables the chip - 0 disables the chip -lux0_input - RO - measured lux value - - sysfs_notify called when threshold interrupt occurs - -lux0_sensor_range - RO - lux0_input max value. - - Actually never reaches since sensor tends - to saturate much before that. Real max value varies depending - on the light spectrum etc. - -lux0_rate - RW - measurement rate in Hz - -lux0_rate_avail - RO - supported measurement rates - -lux0_calibscale - RW - calibration value. - - Set to neutral value by default. - Output results are multiplied with calibscale / calibscale_default - value. - -lux0_calibscale_default - RO - neutral calibration value - -lux0_thresh_above_value - RW - HI level threshold value. - - All results above the value - trigs an interrupt. 65535 (i.e. sensor_range) disables the above - interrupt. - -lux0_thresh_below_value - RW - LO level threshold value. - - All results below the value - trigs an interrupt. 0 disables the below interrupt. - -prox0_raw - RO - measured proximity value - - sysfs_notify called when threshold interrupt occurs - -prox0_sensor_range - RO - prox0_raw max value (1023) - -prox0_raw_en - RW - enable / disable proximity - uses counting logic - - - 1 enables the proximity - - 0 disables the proximity - -prox0_reporting_mode - RW - trigger / periodic. - - In "trigger" mode the driver tells two possible - values: 0 or prox0_sensor_range value. 0 means no proximity, - 1023 means proximity. This causes minimal number of interrupts. - In "periodic" mode the driver reports all values above - prox0_thresh_above. This causes more interrupts, but it can give - _rough_ estimate about the distance. - -prox0_reporting_mode_avail - RO - accepted values to prox0_reporting_mode (trigger, periodic) - -prox0_thresh_above_value - RW - threshold level which trigs proximity events. diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 8cbd71a0dc35..051cf2c44b90 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -392,16 +392,6 @@ config SENSORS_BH1770 To compile this driver as a module, choose M here: the module will be called bh1770glc. If unsure, say N here. =20 -config SENSORS_APDS990X - tristate "APDS990X combined als and proximity sensors" - depends on I2C - help - Say Y here if you want to build a driver for Avago APDS990x - combined ambient light and proximity sensor chip. - - To compile this driver as a module, choose M here: the - module will be called apds990x. If unsure, say N here. - config HMC6352 tristate "Honeywell HMC6352 compass" depends on I2C diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 62c3d03206e9..bfad6982591c 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -20,7 +20,6 @@ obj-$(CONFIG_RPMB) +=3D rpmb-core.o obj-$(CONFIG_QCOM_COINCELL) +=3D qcom-coincell.o obj-$(CONFIG_QCOM_FASTRPC) +=3D fastrpc.o obj-$(CONFIG_SENSORS_BH1770) +=3D bh1770glc.o -obj-$(CONFIG_SENSORS_APDS990X) +=3D apds990x.o obj-$(CONFIG_ENCLOSURE_SERVICES) +=3D enclosure.o obj-$(CONFIG_KGDB_TESTS) +=3D kgdbts.o obj-$(CONFIG_SGI_XP) +=3D sgi-xp/ diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c deleted file mode 100644 index b69c3a1c94d1..000000000000 --- a/drivers/misc/apds990x.c +++ /dev/null @@ -1,1284 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * This file is part of the APDS990x sensor driver. - * Chip is combined proximity and ambient light sensor. - * - * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: Samu Onkalo - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Register map */ -#define APDS990X_ENABLE 0x00 /* Enable of states and interrupts */ -#define APDS990X_ATIME 0x01 /* ALS ADC time */ -#define APDS990X_PTIME 0x02 /* Proximity ADC time */ -#define APDS990X_WTIME 0x03 /* Wait time */ -#define APDS990X_AILTL 0x04 /* ALS interrupt low threshold low byte */ -#define APDS990X_AILTH 0x05 /* ALS interrupt low threshold hi byte */ -#define APDS990X_AIHTL 0x06 /* ALS interrupt hi threshold low byte */ -#define APDS990X_AIHTH 0x07 /* ALS interrupt hi threshold hi byte */ -#define APDS990X_PILTL 0x08 /* Proximity interrupt low threshold low byte= */ -#define APDS990X_PILTH 0x09 /* Proximity interrupt low threshold hi byte = */ -#define APDS990X_PIHTL 0x0a /* Proximity interrupt hi threshold low byte = */ -#define APDS990X_PIHTH 0x0b /* Proximity interrupt hi threshold hi byte */ -#define APDS990X_PERS 0x0c /* Interrupt persistence filters */ -#define APDS990X_CONFIG 0x0d /* Configuration */ -#define APDS990X_PPCOUNT 0x0e /* Proximity pulse count */ -#define APDS990X_CONTROL 0x0f /* Gain control register */ -#define APDS990X_REV 0x11 /* Revision Number */ -#define APDS990X_ID 0x12 /* Device ID */ -#define APDS990X_STATUS 0x13 /* Device status */ -#define APDS990X_CDATAL 0x14 /* Clear ADC low data register */ -#define APDS990X_CDATAH 0x15 /* Clear ADC high data register */ -#define APDS990X_IRDATAL 0x16 /* IR ADC low data register */ -#define APDS990X_IRDATAH 0x17 /* IR ADC high data register */ -#define APDS990X_PDATAL 0x18 /* Proximity ADC low data register */ -#define APDS990X_PDATAH 0x19 /* Proximity ADC high data register */ - -/* Control */ -#define APDS990X_MAX_AGAIN 3 - -/* Enable register */ -#define APDS990X_EN_PIEN (0x1 << 5) -#define APDS990X_EN_AIEN (0x1 << 4) -#define APDS990X_EN_WEN (0x1 << 3) -#define APDS990X_EN_PEN (0x1 << 2) -#define APDS990X_EN_AEN (0x1 << 1) -#define APDS990X_EN_PON (0x1 << 0) -#define APDS990X_EN_DISABLE_ALL 0 - -/* Status register */ -#define APDS990X_ST_PINT (0x1 << 5) -#define APDS990X_ST_AINT (0x1 << 4) - -/* I2C access types */ -#define APDS990x_CMD_TYPE_MASK (0x03 << 5) -#define APDS990x_CMD_TYPE_RB (0x00 << 5) /* Repeated byte */ -#define APDS990x_CMD_TYPE_INC (0x01 << 5) /* Auto increment */ -#define APDS990x_CMD_TYPE_SPE (0x03 << 5) /* Special function */ - -#define APDS990x_ADDR_SHIFT 0 -#define APDS990x_CMD 0x80 - -/* Interrupt ack commands */ -#define APDS990X_INT_ACK_ALS 0x6 -#define APDS990X_INT_ACK_PS 0x5 -#define APDS990X_INT_ACK_BOTH 0x7 - -/* ptime */ -#define APDS990X_PTIME_DEFAULT 0xff /* Recommended conversion time 2.7ms*/ - -/* wtime */ -#define APDS990X_WTIME_DEFAULT 0xee /* ~50ms wait time */ - -#define APDS990X_TIME_TO_ADC 1024 /* One timetick as ADC count value */ - -/* Persistence */ -#define APDS990X_APERS_SHIFT 0 -#define APDS990X_PPERS_SHIFT 4 - -/* Supported ID:s */ -#define APDS990X_ID_0 0x0 -#define APDS990X_ID_4 0x4 -#define APDS990X_ID_29 0x29 - -/* pgain and pdiode settings */ -#define APDS_PGAIN_1X 0x0 -#define APDS_PDIODE_IR 0x2 - -#define APDS990X_LUX_OUTPUT_SCALE 10 - -/* Reverse chip factors for threshold calculation */ -struct reverse_factors { - u32 afactor; - int cf1; - int irf1; - int cf2; - int irf2; -}; - -struct apds990x_chip { - struct apds990x_platform_data *pdata; - struct i2c_client *client; - struct mutex mutex; /* avoid parallel access */ - struct regulator_bulk_data regs[2]; - wait_queue_head_t wait; - - int prox_en; - bool prox_continuous_mode; - bool lux_wait_fresh_res; - - /* Chip parameters */ - struct apds990x_chip_factors cf; - struct reverse_factors rcf; - u16 atime; /* als integration time */ - u16 arate; /* als reporting rate */ - u16 a_max_result; /* Max possible ADC value with current atime */ - u8 again_meas; /* Gain used in last measurement */ - u8 again_next; /* Next calculated gain */ - u8 pgain; - u8 pdiode; - u8 pdrive; - u8 lux_persistence; - u8 prox_persistence; - - u32 lux_raw; - u32 lux; - u16 lux_clear; - u16 lux_ir; - u16 lux_calib; - u32 lux_thres_hi; - u32 lux_thres_lo; - - u32 prox_thres; - u16 prox_data; - u16 prox_calib; - - char chipname[10]; - u8 revision; -}; - -#define APDS_CALIB_SCALER 8192 -#define APDS_LUX_NEUTRAL_CALIB_VALUE (1 * APDS_CALIB_SCALER) -#define APDS_PROX_NEUTRAL_CALIB_VALUE (1 * APDS_CALIB_SCALER) - -#define APDS_PROX_DEF_THRES 600 -#define APDS_PROX_HYSTERESIS 50 -#define APDS_LUX_DEF_THRES_HI 101 -#define APDS_LUX_DEF_THRES_LO 100 -#define APDS_DEFAULT_PROX_PERS 1 - -#define APDS_TIMEOUT 2000 -#define APDS_STARTUP_DELAY 25000 /* us */ -#define APDS_RANGE 65535 -#define APDS_PROX_RANGE 1023 -#define APDS_LUX_GAIN_LO_LIMIT 100 -#define APDS_LUX_GAIN_LO_LIMIT_STRICT 25 - -#define TIMESTEP 87 /* 2.7ms is about 87 / 32 */ -#define TIME_STEP_SCALER 32 - -#define APDS_LUX_AVERAGING_TIME 50 /* tolerates 50/60Hz ripple */ -#define APDS_LUX_DEFAULT_RATE 200 - -static const u8 again[] =3D {1, 8, 16, 120}; /* ALS gain steps */ - -/* Following two tables must match i.e 10Hz rate means 1 as persistence va= lue */ -static const u16 arates_hz[] =3D {10, 5, 2, 1}; -static const u8 apersis[] =3D {1, 2, 4, 5}; - -/* Regulators */ -static const char reg_vcc[] =3D "Vdd"; -static const char reg_vled[] =3D "Vled"; - -static int apds990x_read_byte(struct apds990x_chip *chip, u8 reg, u8 *data) -{ - struct i2c_client *client =3D chip->client; - s32 ret; - - reg &=3D ~APDS990x_CMD_TYPE_MASK; - reg |=3D APDS990x_CMD | APDS990x_CMD_TYPE_RB; - - ret =3D i2c_smbus_read_byte_data(client, reg); - *data =3D ret; - return (int)ret; -} - -static int apds990x_read_word(struct apds990x_chip *chip, u8 reg, u16 *dat= a) -{ - struct i2c_client *client =3D chip->client; - s32 ret; - - reg &=3D ~APDS990x_CMD_TYPE_MASK; - reg |=3D APDS990x_CMD | APDS990x_CMD_TYPE_INC; - - ret =3D i2c_smbus_read_word_data(client, reg); - *data =3D ret; - return (int)ret; -} - -static int apds990x_write_byte(struct apds990x_chip *chip, u8 reg, u8 data) -{ - struct i2c_client *client =3D chip->client; - s32 ret; - - reg &=3D ~APDS990x_CMD_TYPE_MASK; - reg |=3D APDS990x_CMD | APDS990x_CMD_TYPE_RB; - - ret =3D i2c_smbus_write_byte_data(client, reg, data); - return (int)ret; -} - -static int apds990x_write_word(struct apds990x_chip *chip, u8 reg, u16 dat= a) -{ - struct i2c_client *client =3D chip->client; - s32 ret; - - reg &=3D ~APDS990x_CMD_TYPE_MASK; - reg |=3D APDS990x_CMD | APDS990x_CMD_TYPE_INC; - - ret =3D i2c_smbus_write_word_data(client, reg, data); - return (int)ret; -} - -static int apds990x_mode_on(struct apds990x_chip *chip) -{ - /* ALS is mandatory, proximity optional */ - u8 reg =3D APDS990X_EN_AIEN | APDS990X_EN_PON | APDS990X_EN_AEN | - APDS990X_EN_WEN; - - if (chip->prox_en) - reg |=3D APDS990X_EN_PIEN | APDS990X_EN_PEN; - - return apds990x_write_byte(chip, APDS990X_ENABLE, reg); -} - -static u16 apds990x_lux_to_threshold(struct apds990x_chip *chip, u32 lux) -{ - u32 thres; - u32 cpl; - u32 ir; - - if (lux =3D=3D 0) - return 0; - else if (lux =3D=3D APDS_RANGE) - return APDS_RANGE; - - /* - * Reported LUX value is a combination of the IR and CLEAR channel - * values. However, interrupt threshold is only for clear channel. - * This function approximates needed HW threshold value for a given - * LUX value in the current lightning type. - * IR level compared to visible light varies heavily depending on the - * source of the light - * - * Calculate threshold value for the next measurement period. - * Math: threshold =3D lux * cpl where - * cpl =3D atime * again / (glass_attenuation * device_factor) - * (count-per-lux) - * - * First remove calibration. Division by four is to avoid overflow - */ - lux =3D lux * (APDS_CALIB_SCALER / 4) / (chip->lux_calib / 4); - - /* Multiplication by 64 is to increase accuracy */ - cpl =3D ((u32)chip->atime * (u32)again[chip->again_next] * - APDS_PARAM_SCALE * 64) / (chip->cf.ga * chip->cf.df); - - thres =3D lux * cpl / 64; - /* - * Convert IR light from the latest result to match with - * new gain step. This helps to adapt with the current - * source of light. - */ - ir =3D (u32)chip->lux_ir * (u32)again[chip->again_next] / - (u32)again[chip->again_meas]; - - /* - * Compensate count with IR light impact - * IAC1 > IAC2 (see apds990x_get_lux for formulas) - */ - if (chip->lux_clear * APDS_PARAM_SCALE >=3D - chip->rcf.afactor * chip->lux_ir) - thres =3D (chip->rcf.cf1 * thres + chip->rcf.irf1 * ir) / - APDS_PARAM_SCALE; - else - thres =3D (chip->rcf.cf2 * thres + chip->rcf.irf2 * ir) / - APDS_PARAM_SCALE; - - if (thres >=3D chip->a_max_result) - thres =3D chip->a_max_result - 1; - return thres; -} - -static inline int apds990x_set_atime(struct apds990x_chip *chip, u32 time_= ms) -{ - u8 reg_value; - - chip->atime =3D time_ms; - /* Formula is specified in the data sheet */ - reg_value =3D 256 - ((time_ms * TIME_STEP_SCALER) / TIMESTEP); - /* Calculate max ADC value for given integration time */ - chip->a_max_result =3D (u16)(256 - reg_value) * APDS990X_TIME_TO_ADC; - return apds990x_write_byte(chip, APDS990X_ATIME, reg_value); -} - -/* Called always with mutex locked */ -static int apds990x_refresh_pthres(struct apds990x_chip *chip, int data) -{ - int ret, lo, hi; - - /* If the chip is not in use, don't try to access it */ - if (pm_runtime_suspended(&chip->client->dev)) - return 0; - - if (data < chip->prox_thres) { - lo =3D 0; - hi =3D chip->prox_thres; - } else { - lo =3D chip->prox_thres - APDS_PROX_HYSTERESIS; - if (chip->prox_continuous_mode) - hi =3D chip->prox_thres; - else - hi =3D APDS_RANGE; - } - - ret =3D apds990x_write_word(chip, APDS990X_PILTL, lo); - ret |=3D apds990x_write_word(chip, APDS990X_PIHTL, hi); - return ret; -} - -/* Called always with mutex locked */ -static int apds990x_refresh_athres(struct apds990x_chip *chip) -{ - int ret; - /* If the chip is not in use, don't try to access it */ - if (pm_runtime_suspended(&chip->client->dev)) - return 0; - - ret =3D apds990x_write_word(chip, APDS990X_AILTL, - apds990x_lux_to_threshold(chip, chip->lux_thres_lo)); - ret |=3D apds990x_write_word(chip, APDS990X_AIHTL, - apds990x_lux_to_threshold(chip, chip->lux_thres_hi)); - - return ret; -} - -/* Called always with mutex locked */ -static void apds990x_force_a_refresh(struct apds990x_chip *chip) -{ - /* This will force ALS interrupt after the next measurement. */ - apds990x_write_word(chip, APDS990X_AILTL, APDS_LUX_DEF_THRES_LO); - apds990x_write_word(chip, APDS990X_AIHTL, APDS_LUX_DEF_THRES_HI); -} - -/* Called always with mutex locked */ -static void apds990x_force_p_refresh(struct apds990x_chip *chip) -{ - /* This will force proximity interrupt after the next measurement. */ - apds990x_write_word(chip, APDS990X_PILTL, APDS_PROX_DEF_THRES - 1); - apds990x_write_word(chip, APDS990X_PIHTL, APDS_PROX_DEF_THRES); -} - -/* Called always with mutex locked */ -static int apds990x_calc_again(struct apds990x_chip *chip) -{ - int curr_again =3D chip->again_meas; - int next_again =3D chip->again_meas; - int ret =3D 0; - - /* Calculate suitable als gain */ - if (chip->lux_clear =3D=3D chip->a_max_result) - next_again -=3D 2; /* ALS saturated. Decrease gain by 2 steps */ - else if (chip->lux_clear > chip->a_max_result / 2) - next_again--; - else if (chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT_STRICT) - next_again +=3D 2; /* Too dark. Increase gain by 2 steps */ - else if (chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT) - next_again++; - - /* Limit gain to available range */ - if (next_again < 0) - next_again =3D 0; - else if (next_again > APDS990X_MAX_AGAIN) - next_again =3D APDS990X_MAX_AGAIN; - - /* Let's check can we trust the measured result */ - if (chip->lux_clear =3D=3D chip->a_max_result) - /* Result can be totally garbage due to saturation */ - ret =3D -ERANGE; - else if (next_again !=3D curr_again && - chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT_STRICT) - /* - * Gain is changed and measurement result is very small. - * Result can be totally garbage due to underflow - */ - ret =3D -ERANGE; - - chip->again_next =3D next_again; - apds990x_write_byte(chip, APDS990X_CONTROL, - (chip->pdrive << 6) | - (chip->pdiode << 4) | - (chip->pgain << 2) | - (chip->again_next << 0)); - - /* - * Error means bad result -> re-measurement is needed. The forced - * refresh uses fastest possible persistence setting to get result - * as soon as possible. - */ - if (ret < 0) - apds990x_force_a_refresh(chip); - else - apds990x_refresh_athres(chip); - - return ret; -} - -/* Called always with mutex locked */ -static int apds990x_get_lux(struct apds990x_chip *chip, int clear, int ir) -{ - int iac, iac1, iac2; /* IR adjusted counts */ - u32 lpc; /* Lux per count */ - - /* Formulas: - * iac1 =3D CF1 * CLEAR_CH - IRF1 * IR_CH - * iac2 =3D CF2 * CLEAR_CH - IRF2 * IR_CH - */ - iac1 =3D (chip->cf.cf1 * clear - chip->cf.irf1 * ir) / APDS_PARAM_SCALE; - iac2 =3D (chip->cf.cf2 * clear - chip->cf.irf2 * ir) / APDS_PARAM_SCALE; - - iac =3D max(iac1, iac2); - iac =3D max(iac, 0); - - lpc =3D APDS990X_LUX_OUTPUT_SCALE * (chip->cf.df * chip->cf.ga) / - (u32)(again[chip->again_meas] * (u32)chip->atime); - - return (iac * lpc) / APDS_PARAM_SCALE; -} - -static int apds990x_ack_int(struct apds990x_chip *chip, u8 mode) -{ - struct i2c_client *client =3D chip->client; - s32 ret; - u8 reg =3D APDS990x_CMD | APDS990x_CMD_TYPE_SPE; - - switch (mode & (APDS990X_ST_AINT | APDS990X_ST_PINT)) { - case APDS990X_ST_AINT: - reg |=3D APDS990X_INT_ACK_ALS; - break; - case APDS990X_ST_PINT: - reg |=3D APDS990X_INT_ACK_PS; - break; - default: - reg |=3D APDS990X_INT_ACK_BOTH; - break; - } - - ret =3D i2c_smbus_read_byte_data(client, reg); - return (int)ret; -} - -static irqreturn_t apds990x_irq(int irq, void *data) -{ - struct apds990x_chip *chip =3D data; - u8 status; - - apds990x_read_byte(chip, APDS990X_STATUS, &status); - apds990x_ack_int(chip, status); - - mutex_lock(&chip->mutex); - if (!pm_runtime_suspended(&chip->client->dev)) { - if (status & APDS990X_ST_AINT) { - apds990x_read_word(chip, APDS990X_CDATAL, - &chip->lux_clear); - apds990x_read_word(chip, APDS990X_IRDATAL, - &chip->lux_ir); - /* Store used gain for calculations */ - chip->again_meas =3D chip->again_next; - - chip->lux_raw =3D apds990x_get_lux(chip, - chip->lux_clear, - chip->lux_ir); - - if (apds990x_calc_again(chip) =3D=3D 0) { - /* Result is valid */ - chip->lux =3D chip->lux_raw; - chip->lux_wait_fresh_res =3D false; - wake_up(&chip->wait); - sysfs_notify(&chip->client->dev.kobj, - NULL, "lux0_input"); - } - } - - if ((status & APDS990X_ST_PINT) && chip->prox_en) { - u16 clr_ch; - - apds990x_read_word(chip, APDS990X_CDATAL, &clr_ch); - /* - * If ALS channel is saturated at min gain, - * proximity gives false posivite values. - * Just ignore them. - */ - if (chip->again_meas =3D=3D 0 && - clr_ch =3D=3D chip->a_max_result) - chip->prox_data =3D 0; - else - apds990x_read_word(chip, - APDS990X_PDATAL, - &chip->prox_data); - - apds990x_refresh_pthres(chip, chip->prox_data); - if (chip->prox_data < chip->prox_thres) - chip->prox_data =3D 0; - else if (!chip->prox_continuous_mode) - chip->prox_data =3D APDS_PROX_RANGE; - sysfs_notify(&chip->client->dev.kobj, - NULL, "prox0_raw"); - } - } - mutex_unlock(&chip->mutex); - return IRQ_HANDLED; -} - -static int apds990x_configure(struct apds990x_chip *chip) -{ - /* It is recommended to use disabled mode during these operations */ - apds990x_write_byte(chip, APDS990X_ENABLE, APDS990X_EN_DISABLE_ALL); - - /* conversion and wait times for different state machince states */ - apds990x_write_byte(chip, APDS990X_PTIME, APDS990X_PTIME_DEFAULT); - apds990x_write_byte(chip, APDS990X_WTIME, APDS990X_WTIME_DEFAULT); - apds990x_set_atime(chip, APDS_LUX_AVERAGING_TIME); - - apds990x_write_byte(chip, APDS990X_CONFIG, 0); - - /* Persistence levels */ - apds990x_write_byte(chip, APDS990X_PERS, - (chip->lux_persistence << APDS990X_APERS_SHIFT) | - (chip->prox_persistence << APDS990X_PPERS_SHIFT)); - - apds990x_write_byte(chip, APDS990X_PPCOUNT, chip->pdata->ppcount); - - /* Start with relatively small gain */ - chip->again_meas =3D 1; - chip->again_next =3D 1; - apds990x_write_byte(chip, APDS990X_CONTROL, - (chip->pdrive << 6) | - (chip->pdiode << 4) | - (chip->pgain << 2) | - (chip->again_next << 0)); - return 0; -} - -static int apds990x_detect(struct apds990x_chip *chip) -{ - struct i2c_client *client =3D chip->client; - int ret; - u8 id; - - ret =3D apds990x_read_byte(chip, APDS990X_ID, &id); - if (ret < 0) { - dev_err(&client->dev, "ID read failed\n"); - return ret; - } - - ret =3D apds990x_read_byte(chip, APDS990X_REV, &chip->revision); - if (ret < 0) { - dev_err(&client->dev, "REV read failed\n"); - return ret; - } - - switch (id) { - case APDS990X_ID_0: - case APDS990X_ID_4: - case APDS990X_ID_29: - snprintf(chip->chipname, sizeof(chip->chipname), "APDS-990x"); - break; - default: - ret =3D -ENODEV; - break; - } - return ret; -} - -#ifdef CONFIG_PM -static int apds990x_chip_on(struct apds990x_chip *chip) -{ - int err =3D regulator_bulk_enable(ARRAY_SIZE(chip->regs), - chip->regs); - if (err < 0) - return err; - - usleep_range(APDS_STARTUP_DELAY, 2 * APDS_STARTUP_DELAY); - - /* Refresh all configs in case of regulators were off */ - chip->prox_data =3D 0; - apds990x_configure(chip); - apds990x_mode_on(chip); - return 0; -} -#endif - -static int apds990x_chip_off(struct apds990x_chip *chip) -{ - apds990x_write_byte(chip, APDS990X_ENABLE, APDS990X_EN_DISABLE_ALL); - regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); - return 0; -} - -static ssize_t apds990x_lux_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - ssize_t ret; - u32 result; - long time_left; - - if (pm_runtime_suspended(dev)) - return -EIO; - - time_left =3D wait_event_interruptible_timeout(chip->wait, - !chip->lux_wait_fresh_res, - msecs_to_jiffies(APDS_TIMEOUT)); - if (!time_left) - return -EIO; - - mutex_lock(&chip->mutex); - result =3D (chip->lux * chip->lux_calib) / APDS_CALIB_SCALER; - if (result > (APDS_RANGE * APDS990X_LUX_OUTPUT_SCALE)) - result =3D APDS_RANGE * APDS990X_LUX_OUTPUT_SCALE; - - ret =3D sprintf(buf, "%d.%d\n", - result / APDS990X_LUX_OUTPUT_SCALE, - result % APDS990X_LUX_OUTPUT_SCALE); - mutex_unlock(&chip->mutex); - return ret; -} - -static DEVICE_ATTR(lux0_input, S_IRUGO, apds990x_lux_show, NULL); - -static ssize_t apds990x_lux_range_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%u\n", APDS_RANGE); -} - -static DEVICE_ATTR(lux0_sensor_range, S_IRUGO, apds990x_lux_range_show, NU= LL); - -static ssize_t apds990x_lux_calib_format_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%u\n", APDS_CALIB_SCALER); -} - -static DEVICE_ATTR(lux0_calibscale_default, S_IRUGO, - apds990x_lux_calib_format_show, NULL); - -static ssize_t apds990x_lux_calib_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", chip->lux_calib); -} - -static ssize_t apds990x_lux_calib_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - unsigned long value; - int ret; - - ret =3D kstrtoul(buf, 0, &value); - if (ret) - return ret; - - chip->lux_calib =3D value; - - return len; -} - -static DEVICE_ATTR(lux0_calibscale, S_IRUGO | S_IWUSR, apds990x_lux_calib_= show, - apds990x_lux_calib_store); - -static ssize_t apds990x_rate_avail(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int i; - int pos =3D 0; - - for (i =3D 0; i < ARRAY_SIZE(arates_hz); i++) - pos +=3D sprintf(buf + pos, "%d ", arates_hz[i]); - sprintf(buf + pos - 1, "\n"); - return pos; -} - -static ssize_t apds990x_rate_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", chip->arate); -} - -static int apds990x_set_arate(struct apds990x_chip *chip, int rate) -{ - int i; - - for (i =3D 0; i < ARRAY_SIZE(arates_hz); i++) - if (rate >=3D arates_hz[i]) - break; - - if (i =3D=3D ARRAY_SIZE(arates_hz)) - return -EINVAL; - - /* Pick up corresponding persistence value */ - chip->lux_persistence =3D apersis[i]; - chip->arate =3D arates_hz[i]; - - /* If the chip is not in use, don't try to access it */ - if (pm_runtime_suspended(&chip->client->dev)) - return 0; - - /* Persistence levels */ - return apds990x_write_byte(chip, APDS990X_PERS, - (chip->lux_persistence << APDS990X_APERS_SHIFT) | - (chip->prox_persistence << APDS990X_PPERS_SHIFT)); -} - -static ssize_t apds990x_rate_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - unsigned long value; - int ret; - - ret =3D kstrtoul(buf, 0, &value); - if (ret) - return ret; - - mutex_lock(&chip->mutex); - ret =3D apds990x_set_arate(chip, value); - mutex_unlock(&chip->mutex); - - if (ret < 0) - return ret; - return len; -} - -static DEVICE_ATTR(lux0_rate_avail, S_IRUGO, apds990x_rate_avail, NULL); - -static DEVICE_ATTR(lux0_rate, S_IRUGO | S_IWUSR, apds990x_rate_show, - apds990x_rate_store); - -static ssize_t apds990x_prox_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - ssize_t ret; - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - - if (pm_runtime_suspended(dev) || !chip->prox_en) - return -EIO; - - mutex_lock(&chip->mutex); - ret =3D sprintf(buf, "%d\n", chip->prox_data); - mutex_unlock(&chip->mutex); - return ret; -} - -static DEVICE_ATTR(prox0_raw, S_IRUGO, apds990x_prox_show, NULL); - -static ssize_t apds990x_prox_range_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%u\n", APDS_PROX_RANGE); -} - -static DEVICE_ATTR(prox0_sensor_range, S_IRUGO, apds990x_prox_range_show, = NULL); - -static ssize_t apds990x_prox_enable_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", chip->prox_en); -} - -static ssize_t apds990x_prox_enable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - unsigned long value; - int ret; - - ret =3D kstrtoul(buf, 0, &value); - if (ret) - return ret; - - mutex_lock(&chip->mutex); - - if (!chip->prox_en) - chip->prox_data =3D 0; - - if (value) - chip->prox_en++; - else if (chip->prox_en > 0) - chip->prox_en--; - - if (!pm_runtime_suspended(dev)) - apds990x_mode_on(chip); - mutex_unlock(&chip->mutex); - return len; -} - -static DEVICE_ATTR(prox0_raw_en, S_IRUGO | S_IWUSR, apds990x_prox_enable_s= how, - apds990x_prox_enable_store); - -static const char *reporting_modes[] =3D {"trigger", "periodic"}; - -static ssize_t apds990x_prox_reporting_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", - reporting_modes[!!chip->prox_continuous_mode]); -} - -static ssize_t apds990x_prox_reporting_mode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - int ret; - - ret =3D sysfs_match_string(reporting_modes, buf); - if (ret < 0) - return ret; - - chip->prox_continuous_mode =3D ret; - return len; -} - -static DEVICE_ATTR(prox0_reporting_mode, S_IRUGO | S_IWUSR, - apds990x_prox_reporting_mode_show, - apds990x_prox_reporting_mode_store); - -static ssize_t apds990x_prox_reporting_avail_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%s %s\n", reporting_modes[0], reporting_modes[1]); -} - -static DEVICE_ATTR(prox0_reporting_mode_avail, S_IRUGO | S_IWUSR, - apds990x_prox_reporting_avail_show, NULL); - - -static ssize_t apds990x_lux_thresh_above_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", chip->lux_thres_hi); -} - -static ssize_t apds990x_lux_thresh_below_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", chip->lux_thres_lo); -} - -static ssize_t apds990x_set_lux_thresh(struct apds990x_chip *chip, u32 *ta= rget, - const char *buf) -{ - unsigned long thresh; - int ret; - - ret =3D kstrtoul(buf, 0, &thresh); - if (ret) - return ret; - - if (thresh > APDS_RANGE) - return -EINVAL; - - mutex_lock(&chip->mutex); - *target =3D thresh; - /* - * Don't update values in HW if we are still waiting for - * first interrupt to come after device handle open call. - */ - if (!chip->lux_wait_fresh_res) - apds990x_refresh_athres(chip); - mutex_unlock(&chip->mutex); - return ret; - -} - -static ssize_t apds990x_lux_thresh_above_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - int ret =3D apds990x_set_lux_thresh(chip, &chip->lux_thres_hi, buf); - - if (ret < 0) - return ret; - return len; -} - -static ssize_t apds990x_lux_thresh_below_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - int ret =3D apds990x_set_lux_thresh(chip, &chip->lux_thres_lo, buf); - - if (ret < 0) - return ret; - return len; -} - -static DEVICE_ATTR(lux0_thresh_above_value, S_IRUGO | S_IWUSR, - apds990x_lux_thresh_above_show, - apds990x_lux_thresh_above_store); - -static DEVICE_ATTR(lux0_thresh_below_value, S_IRUGO | S_IWUSR, - apds990x_lux_thresh_below_show, - apds990x_lux_thresh_below_store); - -static ssize_t apds990x_prox_threshold_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", chip->prox_thres); -} - -static ssize_t apds990x_prox_threshold_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - unsigned long value; - int ret; - - ret =3D kstrtoul(buf, 0, &value); - if (ret) - return ret; - - if ((value > APDS_RANGE) || (value =3D=3D 0) || - (value < APDS_PROX_HYSTERESIS)) - return -EINVAL; - - mutex_lock(&chip->mutex); - chip->prox_thres =3D value; - - apds990x_force_p_refresh(chip); - mutex_unlock(&chip->mutex); - return len; -} - -static DEVICE_ATTR(prox0_thresh_above_value, S_IRUGO | S_IWUSR, - apds990x_prox_threshold_show, - apds990x_prox_threshold_store); - -static ssize_t apds990x_power_state_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", !pm_runtime_suspended(dev)); -} - -static ssize_t apds990x_power_state_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - unsigned long value; - int ret; - - ret =3D kstrtoul(buf, 0, &value); - if (ret) - return ret; - - if (value) { - pm_runtime_get_sync(dev); - mutex_lock(&chip->mutex); - chip->lux_wait_fresh_res =3D true; - apds990x_force_a_refresh(chip); - apds990x_force_p_refresh(chip); - mutex_unlock(&chip->mutex); - } else { - if (!pm_runtime_suspended(dev)) - pm_runtime_put(dev); - } - return len; -} - -static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, - apds990x_power_state_show, - apds990x_power_state_store); - -static ssize_t apds990x_chip_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct apds990x_chip *chip =3D dev_get_drvdata(dev); - - return sprintf(buf, "%s %d\n", chip->chipname, chip->revision); -} - -static DEVICE_ATTR(chip_id, S_IRUGO, apds990x_chip_id_show, NULL); - -static struct attribute *sysfs_attrs_ctrl[] =3D { - &dev_attr_lux0_calibscale.attr, - &dev_attr_lux0_calibscale_default.attr, - &dev_attr_lux0_input.attr, - &dev_attr_lux0_sensor_range.attr, - &dev_attr_lux0_rate.attr, - &dev_attr_lux0_rate_avail.attr, - &dev_attr_lux0_thresh_above_value.attr, - &dev_attr_lux0_thresh_below_value.attr, - &dev_attr_prox0_raw_en.attr, - &dev_attr_prox0_raw.attr, - &dev_attr_prox0_sensor_range.attr, - &dev_attr_prox0_thresh_above_value.attr, - &dev_attr_prox0_reporting_mode.attr, - &dev_attr_prox0_reporting_mode_avail.attr, - &dev_attr_chip_id.attr, - &dev_attr_power_state.attr, - NULL -}; - -static const struct attribute_group apds990x_attribute_group[] =3D { - {.attrs =3D sysfs_attrs_ctrl }, -}; - -static int apds990x_probe(struct i2c_client *client) -{ - struct apds990x_chip *chip; - int err; - - chip =3D kzalloc_obj(*chip); - if (!chip) - return -ENOMEM; - - i2c_set_clientdata(client, chip); - chip->client =3D client; - - init_waitqueue_head(&chip->wait); - mutex_init(&chip->mutex); - chip->pdata =3D client->dev.platform_data; - - if (chip->pdata =3D=3D NULL) { - dev_err(&client->dev, "platform data is mandatory\n"); - err =3D -EINVAL; - goto fail1; - } - - if (chip->pdata->cf.ga =3D=3D 0) { - /* set uncovered sensor default parameters */ - chip->cf.ga =3D 1966; /* 0.48 * APDS_PARAM_SCALE */ - chip->cf.cf1 =3D 4096; /* 1.00 * APDS_PARAM_SCALE */ - chip->cf.irf1 =3D 9134; /* 2.23 * APDS_PARAM_SCALE */ - chip->cf.cf2 =3D 2867; /* 0.70 * APDS_PARAM_SCALE */ - chip->cf.irf2 =3D 5816; /* 1.42 * APDS_PARAM_SCALE */ - chip->cf.df =3D 52; - } else { - chip->cf =3D chip->pdata->cf; - } - - /* precalculate inverse chip factors for threshold control */ - chip->rcf.afactor =3D - (chip->cf.irf1 - chip->cf.irf2) * APDS_PARAM_SCALE / - (chip->cf.cf1 - chip->cf.cf2); - chip->rcf.cf1 =3D APDS_PARAM_SCALE * APDS_PARAM_SCALE / - chip->cf.cf1; - chip->rcf.irf1 =3D chip->cf.irf1 * APDS_PARAM_SCALE / - chip->cf.cf1; - chip->rcf.cf2 =3D APDS_PARAM_SCALE * APDS_PARAM_SCALE / - chip->cf.cf2; - chip->rcf.irf2 =3D chip->cf.irf2 * APDS_PARAM_SCALE / - chip->cf.cf2; - - /* Set something to start with */ - chip->lux_thres_hi =3D APDS_LUX_DEF_THRES_HI; - chip->lux_thres_lo =3D APDS_LUX_DEF_THRES_LO; - chip->lux_calib =3D APDS_LUX_NEUTRAL_CALIB_VALUE; - - chip->prox_thres =3D APDS_PROX_DEF_THRES; - chip->pdrive =3D chip->pdata->pdrive; - chip->pdiode =3D APDS_PDIODE_IR; - chip->pgain =3D APDS_PGAIN_1X; - chip->prox_calib =3D APDS_PROX_NEUTRAL_CALIB_VALUE; - chip->prox_persistence =3D APDS_DEFAULT_PROX_PERS; - chip->prox_continuous_mode =3D false; - - chip->regs[0].supply =3D reg_vcc; - chip->regs[1].supply =3D reg_vled; - - err =3D regulator_bulk_get(&client->dev, - ARRAY_SIZE(chip->regs), chip->regs); - if (err < 0) { - dev_err(&client->dev, "Cannot get regulators\n"); - goto fail1; - } - - err =3D regulator_bulk_enable(ARRAY_SIZE(chip->regs), chip->regs); - if (err < 0) { - dev_err(&client->dev, "Cannot enable regulators\n"); - goto fail2; - } - - usleep_range(APDS_STARTUP_DELAY, 2 * APDS_STARTUP_DELAY); - - err =3D apds990x_detect(chip); - if (err < 0) { - dev_err(&client->dev, "APDS990X not found\n"); - goto fail3; - } - - pm_runtime_set_active(&client->dev); - - apds990x_configure(chip); - apds990x_set_arate(chip, APDS_LUX_DEFAULT_RATE); - apds990x_mode_on(chip); - - pm_runtime_enable(&client->dev); - - if (chip->pdata->setup_resources) { - err =3D chip->pdata->setup_resources(); - if (err) { - err =3D -EINVAL; - goto fail4; - } - } - - err =3D sysfs_create_group(&chip->client->dev.kobj, - apds990x_attribute_group); - if (err < 0) { - dev_err(&chip->client->dev, "Sysfs registration failed\n"); - goto fail5; - } - - err =3D request_threaded_irq(client->irq, NULL, - apds990x_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW | - IRQF_ONESHOT, - "apds990x", chip); - if (err) { - dev_err(&client->dev, "could not get IRQ %d\n", - client->irq); - goto fail6; - } - return err; -fail6: - sysfs_remove_group(&chip->client->dev.kobj, - &apds990x_attribute_group[0]); -fail5: - if (chip->pdata && chip->pdata->release_resources) - chip->pdata->release_resources(); -fail4: - pm_runtime_disable(&client->dev); -fail3: - regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); -fail2: - regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs); -fail1: - kfree(chip); - return err; -} - -static void apds990x_remove(struct i2c_client *client) -{ - struct apds990x_chip *chip =3D i2c_get_clientdata(client); - - free_irq(client->irq, chip); - sysfs_remove_group(&chip->client->dev.kobj, - apds990x_attribute_group); - - if (chip->pdata && chip->pdata->release_resources) - chip->pdata->release_resources(); - - if (!pm_runtime_suspended(&client->dev)) - apds990x_chip_off(chip); - - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); - - regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs); - - kfree(chip); -} - -#ifdef CONFIG_PM_SLEEP -static int apds990x_suspend(struct device *dev) -{ - struct i2c_client *client =3D to_i2c_client(dev); - struct apds990x_chip *chip =3D i2c_get_clientdata(client); - - apds990x_chip_off(chip); - return 0; -} - -static int apds990x_resume(struct device *dev) -{ - struct i2c_client *client =3D to_i2c_client(dev); - struct apds990x_chip *chip =3D i2c_get_clientdata(client); - - /* - * If we were enabled at suspend time, it is expected - * everything works nice and smoothly. Chip_on is enough - */ - apds990x_chip_on(chip); - - return 0; -} -#endif - -#ifdef CONFIG_PM -static int apds990x_runtime_suspend(struct device *dev) -{ - struct i2c_client *client =3D to_i2c_client(dev); - struct apds990x_chip *chip =3D i2c_get_clientdata(client); - - apds990x_chip_off(chip); - return 0; -} - -static int apds990x_runtime_resume(struct device *dev) -{ - struct i2c_client *client =3D to_i2c_client(dev); - struct apds990x_chip *chip =3D i2c_get_clientdata(client); - - apds990x_chip_on(chip); - return 0; -} - -#endif - -static const struct i2c_device_id apds990x_id[] =3D { - { "apds990x" }, - {} -}; - -MODULE_DEVICE_TABLE(i2c, apds990x_id); - -static const struct dev_pm_ops apds990x_pm_ops =3D { - SET_SYSTEM_SLEEP_PM_OPS(apds990x_suspend, apds990x_resume) - SET_RUNTIME_PM_OPS(apds990x_runtime_suspend, - apds990x_runtime_resume, - NULL) -}; - -static struct i2c_driver apds990x_driver =3D { - .driver =3D { - .name =3D "apds990x", - .pm =3D &apds990x_pm_ops, - }, - .probe =3D apds990x_probe, - .remove =3D apds990x_remove, - .id_table =3D apds990x_id, -}; - -module_i2c_driver(apds990x_driver); - -MODULE_DESCRIPTION("APDS990X combined ALS and proximity sensor"); -MODULE_AUTHOR("Samu Onkalo, Nokia Corporation"); -MODULE_LICENSE("GPL v2"); diff --git a/include/linux/platform_data/apds990x.h b/include/linux/platfor= m_data/apds990x.h deleted file mode 100644 index 37684f68c04f..000000000000 --- a/include/linux/platform_data/apds990x.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * This file is part of the APDS990x sensor driver. - * Chip is combined proximity and ambient light sensor. - * - * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: Samu Onkalo - */ - -#ifndef __APDS990X_H__ -#define __APDS990X_H__ - - -#define APDS_IRLED_CURR_12mA 0x3 -#define APDS_IRLED_CURR_25mA 0x2 -#define APDS_IRLED_CURR_50mA 0x1 -#define APDS_IRLED_CURR_100mA 0x0 - -/** - * struct apds990x_chip_factors - defines effect of the cover window - * @ga: Total glass attenuation - * @cf1: clear channel factor 1 for raw to lux conversion - * @irf1: IR channel factor 1 for raw to lux conversion - * @cf2: clear channel factor 2 for raw to lux conversion - * @irf2: IR channel factor 2 for raw to lux conversion - * @df: device factor for conversion formulas - * - * Structure for tuning ALS calculation to match with environment. - * Values depend on the material above the sensor and the sensor - * itself. If the GA is zero, driver will use uncovered sensor default val= ues - * format: decimal value * APDS_PARAM_SCALE except df which is plain integ= er. - */ -struct apds990x_chip_factors { - int ga; - int cf1; - int irf1; - int cf2; - int irf2; - int df; -}; -#define APDS_PARAM_SCALE 4096 - -/** - * struct apds990x_platform_data - platform data for apsd990x.c driver - * @cf: chip factor data - * @pdrive: IR-led driving current - * @ppcount: number of IR pulses used for proximity estimation - * @setup_resources: interrupt line setup call back function - * @release_resources: interrupt line release call back function - * - * Proximity detection result depends heavily on correct ppcount, pdrive - * and cover window. - * - */ - -struct apds990x_platform_data { - struct apds990x_chip_factors cf; - u8 pdrive; - u8 ppcount; - int (*setup_resources)(void); - int (*release_resources)(void); -}; - -#endif --=20 2.51.0