From nobody Tue Jun 16 11:20:35 2026 Received: from mail-lf1-f42.google.com (mail-lf1-f42.google.com [209.85.167.42]) (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 17297379EE4 for ; Sat, 25 Apr 2026 12:54:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777121693; cv=none; b=dSe9ltraz2/7LKhy0QrEUcIVwN4JAl5zb7DtWxFO4ghdijKqmZF4XkCZ02Do8C3KVy/RtDEAoAUpy8I9ACH6XIwqeeofHH1LLLgQAX33EJPS0eSB6g4Mpmf3z358VLY0R3LuLSx0tF3J7hNKlrvQCQ6P9jZBavbTIZSA2amCKYE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777121693; c=relaxed/simple; bh=s1LkY4RG/HBml6jhtGQ2WI6dyTLJTlmZW5O0MgLl3uE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Gip2XfwNJ7jJbFqazmybmS14R1Z8Ih9vjriF4G8J8ksSKFjAv+p6nrR23myrXw6AbkFkiP3iQozv5C2Ldk4gHU71Cd3UvtHOQ3dSrWYNVIGC1jHsrPKpksHDbIb9WzKZDcU4C6UtcCf9SqVdqbz7DtiyxVc9adDhQQ8abn4Jfyw= 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=QHmgnSKe; arc=none smtp.client-ip=209.85.167.42 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="QHmgnSKe" Received: by mail-lf1-f42.google.com with SMTP id 2adb3069b0e04-5a3d1561e38so7245402e87.0 for ; Sat, 25 Apr 2026 05:54:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777121690; x=1777726490; 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=cle9rd5kldHX8L+jS2LOdlUtcsTtC25NJ0LIkE2xZTk=; b=QHmgnSKe0EB8bgS6ZPnKR3TXX3oUwUAO3w7pAWZRiuWW7g8AK67EEAUIKB4QiUc6ej 9XWJC9NDPxM0YWwqFbKqL17nEzKDyBeWNb1qMuNxrG6dDfHheFDfnXoKbrg5jqXZAWbc DiNZDZdyECuw3X86ATuvjkJM8+hRBpwj36YXhLlx44N8oUabybdi0ZKZNDXvnrdmvuqQ iBapytdTsUX5oarkJLsvgTF3moEQbCLrix5UmIDszxihvsA4t+u/QVn9Fyat7iFgHOPm lVeowKPB7wNe65QY86zIiDE6ROmIb7bvSt0gkz7s1F/RygnzbElcI5g+uyRWC5sshAL0 KH5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777121690; x=1777726490; 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=cle9rd5kldHX8L+jS2LOdlUtcsTtC25NJ0LIkE2xZTk=; b=JRVrD+wphxKiPHnpEbddfAEV3KzlNtL0E3wJuPdy9yjIDgloRgiqxjgIVVQ2sX68/C 4tMiKiPIMlU4ydCRMtQe51Fka8dyfcs1Xovfe57Oo8qSbgKNxFqM0k84ifBf//v3+yHv SvZZT/H+SnY9KszDBafbOtFt6DRSQqmdYe9ejnXUlBtx7kIPF5RUw5TkMLV7mwq/njwb 8YApHQVhXWRE3FX7ikaUXD2HOAEF9HmK+7G0uL5Y/49VratqlTiTV5BTqfbopL3wm8JU N7qX91DHDW3y/bZtrt98jDuK8mM7cyUWnj+6yYx3QgldPU5YCCYDRStwLH9UR8B9HYQS BGiA== X-Forwarded-Encrypted: i=1; AFNElJ8OJ1xeBPgJGt7KSu3pW4bO0RavwhA6oOdLwaCEO7ILKjg0l/2dvdyvi/3tukOJqtyh/VVbN/15cZTIBK8=@vger.kernel.org X-Gm-Message-State: AOJu0YxRZgkMwwkEY8Q6MRrmGoxRRTugU/jgoep6QLDl99AoMD4dUEwW 6O870T1eO44Rxxw25MCP1vaKrvaq8tetsUrFdOTJlrz4HSnvhvU9/6EF X-Gm-Gg: AeBDieuK2LnkGgAdaJVaSx2ufaqR+eeJjYJv+vZe3CKMs+1QZZ1cIqjtQLCwwH0Vr9i XQBWpfX1hW5DoonZ4rFLTS422FUfJ/IDVfFQedngVlHorRyR2LgNRgjQVzLtlN31D3riXTs0MVj T4+Wih108r6WeTVt9xmN6i3xiSTyMX1jZVBjlkJiCrgEx+KipqChfnfzDB1Ng/uj5QuvdBLrPP9 5tmnEtaDz92nSQ5zYbVIEg+NTwQEnLZahSCakqd6tTHHS6NE8/wcEvfJ0O0IPKQEq5kZtrfdnse hNY8OJWUX91jqdX6jQfQAqaAkilJCOcZTiXKqc7+B6Lwj7/qrWmv4fxXDsAH6JXYH49EnPyMfYO lmEybcZGojVZv1shm0v8CqeC+uR7eVcfxKQ7htPlNYAFGq5v5Of1VzRp7HzM8V8v9cZ4gCXKWpq l5KYTVsRAV73tB5kZr8P1o4rI= X-Received: by 2002:ac2:50b2:0:b0:5a4:18cb:884f with SMTP id 2adb3069b0e04-5a418cb88d1mr8643626e87.24.1777121690073; Sat, 25 Apr 2026 05:54:50 -0700 (PDT) Received: from xeon ([188.163.112.56]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-38ecb5f6b20sm58334271fa.18.2026.04.25.05.54.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 05:54: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 v3 1/3] dt-bindings: iio: light: Document Avago APDS9900/9901 ALS/Proximity sensor Date: Sat, 25 Apr 2026 15:54:27 +0300 Message-ID: <20260425125429.65154-2-clamor95@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260425125429.65154-1-clamor95@gmail.com> References: <20260425125429.65154-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:35 2026 Received: from mail-lj1-f176.google.com (mail-lj1-f176.google.com [209.85.208.176]) (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 28BC137E2F2 for ; Sat, 25 Apr 2026 12:54:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777121695; cv=none; b=HzpV0wSrSX4/MjwS5Vqvqfu3LUIPthuQRSjkWw6euXh5/HB3BSk3gxJGPBt3idT7vvAckwdc0+CHGL2ss7ErjkSFl7bU99/2ru0aRMbqXEfl2DLhg71jR5FoaSAf1L9pjeDdZDCweEHayIeUflKhiz8KAcbMjvsQOm0EJ6l7jYs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777121695; c=relaxed/simple; bh=os3bytxGw2AOC8T4LmbMOxb3v9WrfYXIrI2AmuC6D7g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Iv/C+whYXW5w+F96ezLVH7k6QBOqjTTV2ra8AUNoupQ1nbWp8Kw6CGsX1lQyYibLAXg6v8aiylW7ANRq/0XRNf4uGd/d8eGq/c2JF2ntAvanfqR6mbv6VssnAhF/EO1GoWfALKddeywWA2JjjyOZ9emI2rmLqIA7CAeyAMGU9Qc= 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=IiTns9ZR; arc=none smtp.client-ip=209.85.208.176 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="IiTns9ZR" Received: by mail-lj1-f176.google.com with SMTP id 38308e7fff4ca-38e7b0903cdso78094061fa.3 for ; Sat, 25 Apr 2026 05:54:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777121691; x=1777726491; 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=INZTHDtHLu0hLsiQAV4hWhdKZ29geUdagZMSnUDNr8g=; b=IiTns9ZRAfG3wTFDcgGbF3Zast0cvspVDYk1f/LThMDGDBrV+3iJHUZgDOpJ+TfHtl giSi2niMe3oBmvzvUeHA3julqD1x3j471i0i8x/WW6n7lSALRVUqmYQCjeeN9tCc+h9l GE4FPQDQI+GeQKmLr/zR8pjJOGTAPwtW67mj0Lm7Dsl/XjbcikBn4ifCDTbqbwWlyaaM Sl46Yr2/seaU4pOWTibQK/7Ux53YPPs35eeVWpF+ynZvlR4YbQWvB15EH/7NrqV6NhQN t+ic61PLvTrRbKuxakUMRoU0llkDVCHCAKBBuKtd5dknaephRgqNbgv8BPuVtNhCUo7E /fkA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777121691; x=1777726491; 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=INZTHDtHLu0hLsiQAV4hWhdKZ29geUdagZMSnUDNr8g=; b=Tay7vlBdXAw4tBqr7vyxL7OuNB3lMAVuE/xmjrp9E6r6xqTkhbn88zQ65q7gNM5anS hLyjkaYUOyTK9Kmm6qo6ShWHmMf5vtSwLGhXVsUOc0uSGDxQo1GA/RUwfuvhKfUCPDej oKAQ37q8b+9qNq51rbBaNW9KKsCvd8GrsLbnrpTunQ3rCDX5mjcQuP5oHUI/G63plBDI jtZGZLPGaEMkOj1N0CnWgzWYJ6Pe7nU1yjp9wGZQl4LJbrpGr2NIRXuO2XnEPPh14YFf jli5ic5xE6BNgCHeB/mpq/3z2iG+OARdhMZEA6+CfI+BOVAU15RHrCtt5E764BZVJx0C eZcA== X-Forwarded-Encrypted: i=1; AFNElJ/2mJxF2Sji7aZbh4hSWPu8a3m/oSpNBnHYYidhEoHm5fEXJ+8ZDeON/GXb3m771g2Sy2nELjiCZd0jtk8=@vger.kernel.org X-Gm-Message-State: AOJu0YzoVQvMXS9GR+PdY1xuezZmewIZLU3p75OLP5z6NCeftI2fNCJT 8FkFP8POvM0lAC82EV5gkYMSb0RaYEBRVyjJl/t/fUxklAtobj2LSY4q X-Gm-Gg: AeBDies2TzZUtu7WpJBJzv7JEayoM24uHytvstaCFSf+yyCxeMF14nbziL4YBW7XLS8 7adJ2rD4hBNj/AiWhGMTDfJz9PLLvp1CcNyjBtw49CBoLsd40eG39y9Xj2n2GqnNx/Drz+lgs2v mcBwKVr0ajD4+L90UmotN+0CyQfvT/31OhmnEg6cxUtdT/G0WaqECUJ+PoTbSLQW5gk+G8c7KV0 SA1qxuEgxElJF84CIpewN9PoIeNkionEhpc0d+/kSybemHLaUT36XhVFUz/mc7+gzpQQMX9BWyQ CadCkmL7YkdS/MbnJ63VMNoukbpvGEPB6UQcBVVuBwoOHqtpPNqaZGIYdWhaw7AWwc0ZNQf0G1P eMCUUkyXYoA9f9XS9DOdcdkFXxZ/YPDRC2sYYsCQ4HbYKRLGdwuyQGpMOCGq8/BX3cYQEJGnpjm bQA6VZgEiDxr3umOP+VS4G791Jx5S/UAN7sg== X-Received: by 2002:a05:651c:420e:b0:38e:2aa7:3984 with SMTP id 38308e7fff4ca-38ec781824cmr101464481fa.11.1777121691174; Sat, 25 Apr 2026 05:54:51 -0700 (PDT) Received: from xeon ([188.163.112.56]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-38ecb5f6b20sm58334271fa.18.2026.04.25.05.54.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 05:54: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 v3 2/3] iio: tsl2772: Add support for Avago APDS9900/9901 ALS/Proximity sensor Date: Sat, 25 Apr 2026 15:54:28 +0300 Message-ID: <20260425125429.65154-3-clamor95@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260425125429.65154-1-clamor95@gmail.com> References: <20260425125429.65154-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 has a similar register layout to the TAOS/AMS TSL2772 but features a unique set of configurations. Add support for the APDS9900/9901 into the TSL2772 driver by adding the required device-specific configurations. 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..9ba8140c8bc1 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -127,6 +127,7 @@ enum { tmd2672, tsl2772, tmd2772, + apds9900, 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 apds9900_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, + [apds9900] =3D apds9900_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 }, + [apds9900] =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, + [apds9900] =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 apds9900: 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 apds9900: 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", apds9900 }, + { "apds9901", apds9900 }, { "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:35 2026 Received: from mail-lf1-f51.google.com (mail-lf1-f51.google.com [209.85.167.51]) (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 F0FFF35BDD5 for ; Sat, 25 Apr 2026 12:54:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777121707; cv=none; b=EKATDr+KtoF7QZ1/BkbJsrJGXLIGfKpMo5X5knFyuI2uxYicH2CuBGBPeuTFvckHCjRo1c5gBDQZNqWb57UZHAyOE1qDTC0ZJr9TENwFNHGZx5PR3AuII3tCoxwJj7ESYSLqhCtMhQcNeeiExpCWOFFEWbSaZNC35hZDZcOmHy8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777121707; c=relaxed/simple; bh=QqxplZ0pPnLP/IrSMTDyy0YWZWoGJUap+SEbSdt5gfk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SgVeTs0xHE7ST+yuW0cAssAyzmXX2UfpJ6qXbMuCt/Z0vloI9aKdQvAPwFY4WIOTptRmm8/TEJnWyoMDrFZ9P+5lGiz5FLsf6vqooz7ca48Sk6o93guRYTWP19SwvquPSZtDSiiVm860uEehV5ftbqFUzPvEc5sZBE4jz0nplSs= 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=RXB4Z1rF; arc=none smtp.client-ip=209.85.167.51 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="RXB4Z1rF" Received: by mail-lf1-f51.google.com with SMTP id 2adb3069b0e04-5a4113ab355so9291457e87.1 for ; Sat, 25 Apr 2026 05:54:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777121693; x=1777726493; 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=KDxVBg0fGCM+SURqQbscrVoYETf1y9vwTTg0uEeS5bs=; b=RXB4Z1rFHJYk3RH0mMC3T9qG0UU6lJPgsvmuZMGFvkXbzltcfki1Xm0UR+k6NXcopT 7Swf/E3r8nUZI+JSDFl/42aSDkGXCvvw7MrPkDiS4M30w1k6+2HnAsEuj7aK1OJzzX/a erRhCIoNZUztYk52prl1ZcGMml7V0eYOjeQJQXkRcDPo025Bb9URosCNhHv2AQaM3Ra5 9rTXk9dXB08ju+rYrL6q2sIRSSyZiK4zD9eCM9PCpc12YHel6bAbBXz5LbSx7KeY6gJr FQrBQWJ1Si2czdM8bzF9DiAM7tgGPRXIx3phvMRZFuyelZdTv6ORtVFCDmbvhiyXHBWp /h9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777121693; x=1777726493; 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=KDxVBg0fGCM+SURqQbscrVoYETf1y9vwTTg0uEeS5bs=; b=J4zUC3rZ7uGMzdUOd5JIOYFhzwciD1BC34g9/PliXtpnGzXl021S3eTV9l1lDOE+Uv dLaPJb6sbkQqPGBKr4cIeH6pzVRt28W4tN/HqEY1orPWgCmcs7/Wnxt+noLehhGHtuLs Csk289L+f6PlzHgysfR1uChNCdBO/R96wIgWokrX70vLqNyXdvZBdcdV3Ot26F+AFWsB cwFydLCTz4po/NQYwh0YIufV9Lq3VDH+6+cuiqEggkZ3Vj3t22SaaE3peRheH3IY2PIn UOZdQJSVIXpq0e6FNIcLpvMkfuKCfnZ+nkPauRFtSjzl3CPzNN02odRRY1FISgFSN4wU UdnQ== X-Forwarded-Encrypted: i=1; AFNElJ+0IzuvvEnzgzjI8MHacoUhyPaHghEF4GRCLhxRj+oPgPmozRRtFUjoHS74GkskCfqB+TrXtyzijSVxa2U=@vger.kernel.org X-Gm-Message-State: AOJu0YwRHarEBIoSWlYq3HkdIh8Zjw0T3KTnyubaNMe5jVu2ZneGNd9o ekOx22RLhoHzZ5/ksh0WLqiZ/H0b04g5xpBDfunhYA/f43GG0zhNTvql X-Gm-Gg: AeBDietVA5obFdt0MzvlpKygcvqiZZNXQJc45pOZQeCzkc1BctlaqCJ+21ddTpI9cvK xl1PgbM0Wui6q9rFQCkxOVhlY/e3S12iFP1KL/zWBFYQahmRowdx27vxNyJmtIn+hc+d5ZqtgbJ 2nYvBIcBFkqf1pKxa5fI5Mmect1UOlckDFZMpKAOStX/gS/S86t8nMiKgAI/s2G7WTfUZ0+SupD H3M+QiYORRdUXcaU3MJpXGKU69mElcYECLIJiYHhCVKLfLiv//umdBc/uvj3EViwDQ17WagZa8a TFz+KjkbuDLUGltysT5Zz8+VtimO2nPbeZoYPtYXTaakWgCYv64coB/RXBZqrUJw+NtLA6u4tO9 2OM0MfqyuFyEQVyQgCz8fvwGTpNFElRQIdLy4heV+p3cuxqeHkbHJrtovFcxVeK9HZEvPRXJJ1P QUb0YAdjQ72xbLwOGx8nbhJXg= X-Received: by 2002:a05:6512:108d:b0:5a4:1add:c583 with SMTP id 2adb3069b0e04-5a41addc69dmr10702042e87.41.1777121692510; Sat, 25 Apr 2026 05:54:52 -0700 (PDT) Received: from xeon ([188.163.112.56]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-38ecb5f6b20sm58334271fa.18.2026.04.25.05.54.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Apr 2026 05:54: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 v3 3/3] misc: Remove old APDS990x driver Date: Sat, 25 Apr 2026 15:54:29 +0300 Message-ID: <20260425125429.65154-4-clamor95@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260425125429.65154-1-clamor95@gmail.com> References: <20260425125429.65154-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 APDS990x driver in misc lacks DeviceTree support, and no mainline pre-DT board files configured this device using apds990x_platform_data. This driver belongs to a legacy group of ambient light sensor drivers in drivers/misc/ that predates the migration to DT and the standard IIO ABI. Since the Avago APDS9900/9901 ALS/Proximity sensor is now supported by the tsl2772 IIO driver and there are no active users in the kernel tree, remove this old implementation. Acked-by: Greg Kroah-Hartman Signed-off-by: Svyatoslav Ryhel --- Documentation/misc-devices/apds990x.rst | 128 --- Documentation/misc-devices/index.rst | 1 - drivers/misc/Kconfig | 10 - drivers/misc/Makefile | 1 - drivers/misc/apds990x.c | 1284 ----------------------- include/linux/platform_data/apds990x.h | 65 -- 6 files changed, 1489 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/Documentation/misc-devices/index.rst b/Documentation/misc-devi= ces/index.rst index 081e79415e38..f911edaecbfa 100644 --- a/Documentation/misc-devices/index.rst +++ b/Documentation/misc-devices/index.rst @@ -13,7 +13,6 @@ fit into other categories. =20 ad525x_dpot amd-sbi - apds990x bh1770glc c2port dw-xdata-pcie diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 00683bf06258..390256ed91f4 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -381,16 +381,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 b32a2597d246..fed47c7672b9 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