forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'bits/250-aop' into asahi-wip
- Loading branch information
Showing
28 changed files
with
2,592 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# SPDX-License-Identifier: GPL-2.0-only OR MIT | ||
|
||
config IIO_AOP_SENSOR_LAS | ||
tristate "AOP Lid angle sensor" | ||
depends on ARCH_APPLE || COMPILE_TEST | ||
depends on RUST | ||
depends on SYSFS | ||
select APPLE_AOP | ||
default m if ARCH_APPLE | ||
help | ||
Module to handle the lid angle sensor attached to the AOP | ||
coprocessor on Apple laptops. | ||
|
||
config IIO_AOP_SENSOR_ALS | ||
tristate "AOP Ambient light sensor" | ||
depends on ARCH_APPLE || COMPILE_TEST | ||
depends on RUST | ||
depends on SYSFS | ||
select APPLE_AOP | ||
default m if ARCH_APPLE | ||
help | ||
Module to handle the ambient light sensor attached to the AOP | ||
coprocessor on Apple laptops. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# SPDX-License-Identifier: GPL-2.0-only OR MIT | ||
|
||
obj-$(CONFIG_IIO_AOP_SENSOR_LAS) += aop_las.o | ||
obj-$(CONFIG_IIO_AOP_SENSOR_ALS) += aop_als.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only OR MIT | ||
|
||
//! Apple AOP ambient light sensor driver | ||
//! | ||
//! Copyright (C) The Asahi Linux Contributors | ||
use kernel::{ | ||
bindings, c_str, device, | ||
iio::common::aop_sensors::{AopSensorData, IIORegistration, MessageProcessor}, | ||
module_platform_driver, | ||
of::{self, Node}, | ||
platform, | ||
prelude::*, | ||
soc::apple::aop::{EPICService, AOP}, | ||
sync::Arc, | ||
types::{ARef, ForeignOwnable}, | ||
}; | ||
|
||
const EPIC_SUBTYPE_SET_ALS_PROPERTY: u16 = 0x4; | ||
|
||
fn enable_als( | ||
aop: &dyn AOP, | ||
dev: &ARef<device::Device>, | ||
of: &Node, | ||
svc: &EPICService, | ||
) -> Result<()> { | ||
if let Some(prop) = of.find_property(c_str!("apple,als-calibration")) { | ||
set_als_property(aop, svc, 0xb, prop.value())?; | ||
set_als_property(aop, svc, 0, &200000u32.to_le_bytes())?; | ||
} else { | ||
dev_warn!(dev, "ALS Calibration not found, will not enable it"); | ||
} | ||
Ok(()) | ||
} | ||
fn set_als_property(aop: &dyn AOP, svc: &EPICService, tag: u32, data: &[u8]) -> Result<u32> { | ||
let mut buf = KVec::new(); | ||
buf.resize(data.len() + 8, 0, GFP_KERNEL)?; | ||
buf[8..].copy_from_slice(data); | ||
buf[4..8].copy_from_slice(&tag.to_le_bytes()); | ||
aop.epic_call(svc, EPIC_SUBTYPE_SET_ALS_PROPERTY, &buf) | ||
} | ||
|
||
fn f32_to_u32(f: u32) -> u32 { | ||
if f & 0x80000000 != 0 { | ||
return 0; | ||
} | ||
let exp = ((f & 0x7f800000) >> 23) as i32 - 127; | ||
if exp < 0 { | ||
return 0; | ||
} | ||
if exp == 128 && f & 0x7fffff != 0 { | ||
return 0; | ||
} | ||
let mant = f & 0x7fffff | 0x800000; | ||
if exp <= 23 { | ||
return mant >> (23 - exp); | ||
} | ||
if exp >= 32 { | ||
return u32::MAX; | ||
} | ||
mant << (exp - 23) | ||
} | ||
|
||
struct MsgProc(usize); | ||
|
||
impl MessageProcessor for MsgProc { | ||
fn process(&self, message: &[u8]) -> u32 { | ||
let offset = self.0; | ||
let raw = u32::from_le_bytes(message[offset..offset + 4].try_into().unwrap()); | ||
f32_to_u32(raw) | ||
} | ||
} | ||
|
||
#[repr(transparent)] | ||
struct IIOAopAlsDriver(IIORegistration<MsgProc>); | ||
|
||
kernel::of_device_table!(OF_TABLE, MODULE_OF_TABLE, (), [] as [(of::DeviceId, ()); 0]); | ||
|
||
impl platform::Driver for IIOAopAlsDriver { | ||
type IdInfo = (); | ||
|
||
const ID_TABLE: platform::IdTable<()> = &OF_TABLE; | ||
|
||
fn probe( | ||
pdev: &mut platform::Device, | ||
_info: Option<&()>, | ||
) -> Result<Pin<KBox<IIOAopAlsDriver>>> { | ||
let dev = pdev.get_device(); | ||
let parent = dev.parent().unwrap(); | ||
// SAFETY: our parent is AOP, and AopDriver is repr(transparent) for Arc<dyn Aop> | ||
let adata_ptr = unsafe { Pin::<KBox<Arc<dyn AOP>>>::borrow(parent.get_drvdata()) }; | ||
let adata = (&*adata_ptr).clone(); | ||
// SAFETY: AOP sets the platform data correctly | ||
let service = unsafe { *((*dev.as_raw()).platform_data as *const EPICService) }; | ||
let of = parent | ||
.of_node() | ||
.ok_or(EIO)? | ||
.get_child_by_name(c_str!("als")) | ||
.ok_or(EIO)?; | ||
let ty = bindings::BINDINGS_IIO_LIGHT; | ||
let data = AopSensorData::new(dev.clone(), ty, MsgProc(40))?; | ||
adata.add_fakehid_listener(service, data.clone())?; | ||
enable_als(adata.as_ref(), &dev, &of, &service)?; | ||
let info_mask = 1 << bindings::BINDINGS_IIO_CHAN_INFO_PROCESSED; | ||
Ok(KBox::pin( | ||
IIOAopAlsDriver(IIORegistration::<MsgProc>::new( | ||
data, | ||
c_str!("aop-sensors-als"), | ||
ty, | ||
info_mask, | ||
&THIS_MODULE, | ||
)?), | ||
GFP_KERNEL, | ||
)?) | ||
} | ||
} | ||
|
||
module_platform_driver! { | ||
type: IIOAopAlsDriver, | ||
name: "iio_aop_als", | ||
license: "Dual MIT/GPL", | ||
alias: ["platform:iio_aop_als"], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only OR MIT | ||
|
||
//! Apple AOP lid angle sensor driver | ||
//! | ||
//! Copyright (C) The Asahi Linux Contributors | ||
use kernel::{ | ||
bindings, c_str, | ||
iio::common::aop_sensors::{AopSensorData, IIORegistration, MessageProcessor}, | ||
module_platform_driver, of, platform, | ||
prelude::*, | ||
soc::apple::aop::{EPICService, AOP}, | ||
sync::Arc, | ||
types::ForeignOwnable, | ||
}; | ||
|
||
struct MsgProc; | ||
|
||
impl MessageProcessor for MsgProc { | ||
fn process(&self, message: &[u8]) -> u32 { | ||
message[1] as u32 | ||
} | ||
} | ||
|
||
#[repr(transparent)] | ||
struct IIOAopLasDriver(IIORegistration<MsgProc>); | ||
|
||
kernel::of_device_table!(OF_TABLE, MODULE_OF_TABLE, (), [] as [(of::DeviceId, ()); 0]); | ||
|
||
impl platform::Driver for IIOAopLasDriver { | ||
type IdInfo = (); | ||
|
||
const ID_TABLE: platform::IdTable<()> = &OF_TABLE; | ||
|
||
fn probe( | ||
pdev: &mut platform::Device, | ||
_info: Option<&()>, | ||
) -> Result<Pin<KBox<IIOAopLasDriver>>> { | ||
let dev = pdev.get_device(); | ||
let parent = dev.parent().unwrap(); | ||
// SAFETY: our parent is AOP, and AopDriver is repr(transparent) for Arc<dyn Aop> | ||
let adata_ptr = unsafe { Pin::<KBox<Arc<dyn AOP>>>::borrow(parent.get_drvdata()) }; | ||
let adata = (&*adata_ptr).clone(); | ||
// SAFETY: AOP sets the platform data correctly | ||
let service = unsafe { *((*dev.as_raw()).platform_data as *const EPICService) }; | ||
|
||
let ty = bindings::BINDINGS_IIO_ANGL; | ||
let data = AopSensorData::new(dev, ty, MsgProc)?; | ||
adata.add_fakehid_listener(service, data.clone())?; | ||
let info_mask = 1 << bindings::BINDINGS_IIO_CHAN_INFO_RAW; | ||
Ok(KBox::pin( | ||
IIOAopLasDriver(IIORegistration::<MsgProc>::new( | ||
data, | ||
c_str!("aop-sensors-las"), | ||
ty, | ||
info_mask, | ||
&THIS_MODULE, | ||
)?), | ||
GFP_KERNEL, | ||
)?) | ||
} | ||
} | ||
|
||
module_platform_driver! { | ||
type: IIOAopLasDriver, | ||
name: "iio_aop_las", | ||
license: "Dual MIT/GPL", | ||
alias: ["platform:iio_aop_las"], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.