2525#include <linux/input/sparse-keymap.h>
2626#include <linux/kernel.h>
2727#include <linux/leds.h>
28+ #include <linux/minmax.h>
2829#include <linux/module.h>
2930#include <linux/pci.h>
3031#include <linux/pci_hotplug.h>
@@ -127,6 +128,10 @@ module_param(fnlock_default, bool, 0444);
127128#define NVIDIA_TEMP_MIN 75
128129#define NVIDIA_TEMP_MAX 87
129130
131+ #define ASUS_SCREENPAD_BRIGHT_MIN 20
132+ #define ASUS_SCREENPAD_BRIGHT_MAX 255
133+ #define ASUS_SCREENPAD_BRIGHT_DEFAULT 60
134+
130135static const char * const ashs_ids [] = { "ATK4001" , "ATK4002" , NULL };
131136
132137static int throttle_thermal_policy_write (struct asus_wmi * );
@@ -212,6 +217,7 @@ struct asus_wmi {
212217
213218 struct input_dev * inputdev ;
214219 struct backlight_device * backlight_device ;
220+ struct backlight_device * screenpad_backlight_device ;
215221 struct platform_device * platform_device ;
216222
217223 struct led_classdev wlan_led ;
@@ -3776,6 +3782,124 @@ static int is_display_toggle(int code)
37763782 return 0 ;
37773783}
37783784
3785+ /* Screenpad backlight *******************************************************/
3786+
3787+ static int read_screenpad_backlight_power (struct asus_wmi * asus )
3788+ {
3789+ int ret ;
3790+
3791+ ret = asus_wmi_get_devstate_simple (asus , ASUS_WMI_DEVID_SCREENPAD_POWER );
3792+ if (ret < 0 )
3793+ return ret ;
3794+ /* 1 == powered */
3795+ return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN ;
3796+ }
3797+
3798+ static int read_screenpad_brightness (struct backlight_device * bd )
3799+ {
3800+ struct asus_wmi * asus = bl_get_data (bd );
3801+ u32 retval ;
3802+ int err ;
3803+
3804+ err = read_screenpad_backlight_power (asus );
3805+ if (err < 0 )
3806+ return err ;
3807+ /* The device brightness can only be read if powered, so return stored */
3808+ if (err == FB_BLANK_POWERDOWN )
3809+ return asus -> driver -> screenpad_brightness - ASUS_SCREENPAD_BRIGHT_MIN ;
3810+
3811+ err = asus_wmi_get_devstate (asus , ASUS_WMI_DEVID_SCREENPAD_LIGHT , & retval );
3812+ if (err < 0 )
3813+ return err ;
3814+
3815+ return (retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK ) - ASUS_SCREENPAD_BRIGHT_MIN ;
3816+ }
3817+
3818+ static int update_screenpad_bl_status (struct backlight_device * bd )
3819+ {
3820+ struct asus_wmi * asus = bl_get_data (bd );
3821+ int power , err = 0 ;
3822+ u32 ctrl_param ;
3823+
3824+ power = read_screenpad_backlight_power (asus );
3825+ if (power < 0 )
3826+ return power ;
3827+
3828+ if (bd -> props .power != power ) {
3829+ if (power != FB_BLANK_UNBLANK ) {
3830+ /* Only brightness > 0 can power it back on */
3831+ ctrl_param = asus -> driver -> screenpad_brightness - ASUS_SCREENPAD_BRIGHT_MIN ;
3832+ err = asus_wmi_set_devstate (ASUS_WMI_DEVID_SCREENPAD_LIGHT ,
3833+ ctrl_param , NULL );
3834+ } else {
3835+ err = asus_wmi_set_devstate (ASUS_WMI_DEVID_SCREENPAD_POWER , 0 , NULL );
3836+ }
3837+ } else if (power == FB_BLANK_UNBLANK ) {
3838+ /* Only set brightness if powered on or we get invalid/unsync state */
3839+ ctrl_param = bd -> props .brightness + ASUS_SCREENPAD_BRIGHT_MIN ;
3840+ err = asus_wmi_set_devstate (ASUS_WMI_DEVID_SCREENPAD_LIGHT , ctrl_param , NULL );
3841+ }
3842+
3843+ /* Ensure brightness is stored to turn back on with */
3844+ if (err == 0 )
3845+ asus -> driver -> screenpad_brightness = bd -> props .brightness + ASUS_SCREENPAD_BRIGHT_MIN ;
3846+
3847+ return err ;
3848+ }
3849+
3850+ static const struct backlight_ops asus_screenpad_bl_ops = {
3851+ .get_brightness = read_screenpad_brightness ,
3852+ .update_status = update_screenpad_bl_status ,
3853+ .options = BL_CORE_SUSPENDRESUME ,
3854+ };
3855+
3856+ static int asus_screenpad_init (struct asus_wmi * asus )
3857+ {
3858+ struct backlight_device * bd ;
3859+ struct backlight_properties props ;
3860+ int err , power ;
3861+ int brightness = 0 ;
3862+
3863+ power = read_screenpad_backlight_power (asus );
3864+ if (power < 0 )
3865+ return power ;
3866+
3867+ if (power != FB_BLANK_POWERDOWN ) {
3868+ err = asus_wmi_get_devstate (asus , ASUS_WMI_DEVID_SCREENPAD_LIGHT , & brightness );
3869+ if (err < 0 )
3870+ return err ;
3871+ }
3872+ /* default to an acceptable min brightness on boot if too low */
3873+ if (brightness < ASUS_SCREENPAD_BRIGHT_MIN )
3874+ brightness = ASUS_SCREENPAD_BRIGHT_DEFAULT ;
3875+
3876+ memset (& props , 0 , sizeof (struct backlight_properties ));
3877+ props .type = BACKLIGHT_RAW ; /* ensure this bd is last to be picked */
3878+ props .max_brightness = ASUS_SCREENPAD_BRIGHT_MAX - ASUS_SCREENPAD_BRIGHT_MIN ;
3879+ bd = backlight_device_register ("asus_screenpad" ,
3880+ & asus -> platform_device -> dev , asus ,
3881+ & asus_screenpad_bl_ops , & props );
3882+ if (IS_ERR (bd )) {
3883+ pr_err ("Could not register backlight device\n" );
3884+ return PTR_ERR (bd );
3885+ }
3886+
3887+ asus -> screenpad_backlight_device = bd ;
3888+ asus -> driver -> screenpad_brightness = brightness ;
3889+ bd -> props .brightness = brightness - ASUS_SCREENPAD_BRIGHT_MIN ;
3890+ bd -> props .power = power ;
3891+ backlight_update_status (bd );
3892+
3893+ return 0 ;
3894+ }
3895+
3896+ static void asus_screenpad_exit (struct asus_wmi * asus )
3897+ {
3898+ backlight_device_unregister (asus -> screenpad_backlight_device );
3899+
3900+ asus -> screenpad_backlight_device = NULL ;
3901+ }
3902+
37793903/* Fn-lock ********************************************************************/
37803904
37813905static bool asus_wmi_has_fnlock_key (struct asus_wmi * asus )
@@ -4431,6 +4555,12 @@ static int asus_wmi_add(struct platform_device *pdev)
44314555 } else if (asus -> driver -> quirks -> wmi_backlight_set_devstate )
44324556 err = asus_wmi_set_devstate (ASUS_WMI_DEVID_BACKLIGHT , 2 , NULL );
44334557
4558+ if (asus_wmi_dev_is_present (asus , ASUS_WMI_DEVID_SCREENPAD_LIGHT )) {
4559+ err = asus_screenpad_init (asus );
4560+ if (err && err != - ENODEV )
4561+ goto fail_screenpad ;
4562+ }
4563+
44344564 if (asus_wmi_has_fnlock_key (asus )) {
44354565 asus -> fnlock_locked = fnlock_default ;
44364566 asus_wmi_fnlock_update (asus );
@@ -4454,6 +4584,8 @@ static int asus_wmi_add(struct platform_device *pdev)
44544584 asus_wmi_backlight_exit (asus );
44554585fail_backlight :
44564586 asus_wmi_rfkill_exit (asus );
4587+ fail_screenpad :
4588+ asus_screenpad_exit (asus );
44574589fail_rfkill :
44584590 asus_wmi_led_exit (asus );
44594591fail_leds :
@@ -4480,6 +4612,7 @@ static int asus_wmi_remove(struct platform_device *device)
44804612 asus = platform_get_drvdata (device );
44814613 wmi_remove_notify_handler (asus -> driver -> event_guid );
44824614 asus_wmi_backlight_exit (asus );
4615+ asus_screenpad_exit (asus );
44834616 asus_wmi_input_exit (asus );
44844617 asus_wmi_led_exit (asus );
44854618 asus_wmi_rfkill_exit (asus );
0 commit comments