forked from mirrors/linux
		
	hwmon: (oxp-sensors) Add tt_toggle attribute on supported boards
OneXPlayer boards from the last generation (both for OneXPlayer and AOK ZOE brands) have a toggle in the EC to switch the "Turbo/Silent" button into a different keyboard event. Add a means to use that "Turbo button takeover" function and expose it to userspace in a custom sysfs `tt_toggle` attribute. It can be read to take the current state. Write 1|0 to activate the function. The specific keycode is dependent on the board but can be checked by running `evtest` utility. Newer BIOS on the OneXPlayer added this function aside from string changes. Add a board enum to differentiate it from the old OneXplayer Mini AMD BIOS. Currently known supported boards: - AOK ZOE A1 - OneXPlayer Mini AMD (only newer BIOS version supported) - OneXPlayer Mini Pro Signed-off-by: Joaquín Ignacio Aramendía <samsagax@gmail.com> Link: https://lore.kernel.org/r/20230611143332.40590-2-samsagax@gmail.com Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
		
							parent
							
								
									fbb5a7fee0
								
							
						
					
					
						commit
						be144ee491
					
				
					 2 changed files with 150 additions and 1 deletions
				
			
		|  | @ -19,6 +19,11 @@ out the EC registers and values to write to since the EC layout and model is | |||
| different. Aya Neo devices preceding the AIR may not be supportable as the EC | ||||
| model is different and do not appear to have manual control capabilities. | ||||
| 
 | ||||
| Some models have a toggle for changing the behaviour of the "Turbo/Silent" | ||||
| button of the device. It will change the key event that it triggers with | ||||
| a flip of the `tt_toggle` attribute. See below for boards that support this | ||||
| function. | ||||
| 
 | ||||
| Supported devices | ||||
| ----------------- | ||||
| 
 | ||||
|  | @ -33,6 +38,11 @@ Currently the driver supports the following handhelds: | |||
|  - OneXPlayer mini AMD | ||||
|  - OneXPlayer mini AMD PRO | ||||
| 
 | ||||
| "Turbo/Silent" button behaviour toggle is only supported on: | ||||
|  - AOK ZOE A1 | ||||
|  - OneXPlayer mini AMD (only with updated alpha BIOS) | ||||
|  - OneXPlayer mini AMD PRO | ||||
| 
 | ||||
| Sysfs entries | ||||
| ------------- | ||||
| 
 | ||||
|  | @ -49,3 +59,10 @@ pwm1 | |||
|   Read Write. Read this attribute to see current duty cycle in the range [0-255]. | ||||
|   When pwm1_enable is set to "1" (manual) write any value in the range [0-255] | ||||
|   to set fan speed. | ||||
| 
 | ||||
| tt_toggle | ||||
|   Read Write. Read this attribute to check the status of the turbo/silent | ||||
|   button behaviour function. Write "1" to activate the switch and "0" to | ||||
|   deactivate it. The specific keycodes and behaviour is specific to the device | ||||
|   both with this function on and off. This attribute is attached to the platform | ||||
|   driver and not to the hwmon driver (/sys/devices/platform/oxp-platform/tt_toggle) | ||||
|  |  | |||
|  | @ -47,15 +47,29 @@ enum oxp_board { | |||
| 	aya_neo_air_pro, | ||||
| 	aya_neo_geek, | ||||
| 	oxp_mini_amd, | ||||
| 	oxp_mini_amd_a07, | ||||
| 	oxp_mini_amd_pro, | ||||
| }; | ||||
| 
 | ||||
| static enum oxp_board board; | ||||
| 
 | ||||
| /* Fan reading and PWM */ | ||||
| #define OXP_SENSOR_FAN_REG		0x76 /* Fan reading is 2 registers long */ | ||||
| #define OXP_SENSOR_PWM_ENABLE_REG	0x4A /* PWM enable is 1 register long */ | ||||
| #define OXP_SENSOR_PWM_REG		0x4B /* PWM reading is 1 register long */ | ||||
| 
 | ||||
| /* Turbo button takeover function
 | ||||
|  * Older boards have different values and EC registers | ||||
|  * for the same function | ||||
|  */ | ||||
| #define OXP_OLD_TURBO_SWITCH_REG	0x1E | ||||
| #define OXP_OLD_TURBO_TAKE_VAL		0x01 | ||||
| #define OXP_OLD_TURBO_RETURN_VAL	0x00 | ||||
| 
 | ||||
| #define OXP_TURBO_SWITCH_REG		0xF1 | ||||
| #define OXP_TURBO_TAKE_VAL		0x40 | ||||
| #define OXP_TURBO_RETURN_VAL		0x00 | ||||
| 
 | ||||
| static const struct dmi_system_id dmi_table[] = { | ||||
| 	{ | ||||
| 		.matches = { | ||||
|  | @ -104,7 +118,7 @@ static const struct dmi_system_id dmi_table[] = { | |||
| 			DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"), | ||||
| 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER mini A07"), | ||||
| 		}, | ||||
| 		.driver_data = (void *)oxp_mini_amd, | ||||
| 		.driver_data = (void *)oxp_mini_amd_a07, | ||||
| 	}, | ||||
| 	{ | ||||
| 		.matches = { | ||||
|  | @ -156,6 +170,102 @@ static int write_to_ec(u8 reg, u8 value) | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /* Turbo button toggle functions */ | ||||
| static int tt_toggle_enable(void) | ||||
| { | ||||
| 	u8 reg; | ||||
| 	u8 val; | ||||
| 
 | ||||
| 	switch (board) { | ||||
| 	case oxp_mini_amd_a07: | ||||
| 		reg = OXP_OLD_TURBO_SWITCH_REG; | ||||
| 		val = OXP_OLD_TURBO_TAKE_VAL; | ||||
| 		break; | ||||
| 	case oxp_mini_amd_pro: | ||||
| 	case aok_zoe_a1: | ||||
| 		reg = OXP_TURBO_SWITCH_REG; | ||||
| 		val = OXP_TURBO_TAKE_VAL; | ||||
| 		break; | ||||
| 	default: | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	return write_to_ec(reg, val); | ||||
| } | ||||
| 
 | ||||
| static int tt_toggle_disable(void) | ||||
| { | ||||
| 	u8 reg; | ||||
| 	u8 val; | ||||
| 
 | ||||
| 	switch (board) { | ||||
| 	case oxp_mini_amd_a07: | ||||
| 		reg = OXP_OLD_TURBO_SWITCH_REG; | ||||
| 		val = OXP_OLD_TURBO_RETURN_VAL; | ||||
| 		break; | ||||
| 	case oxp_mini_amd_pro: | ||||
| 	case aok_zoe_a1: | ||||
| 		reg = OXP_TURBO_SWITCH_REG; | ||||
| 		val = OXP_TURBO_RETURN_VAL; | ||||
| 		break; | ||||
| 	default: | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	return write_to_ec(reg, val); | ||||
| } | ||||
| 
 | ||||
| /* Callbacks for turbo toggle attribute */ | ||||
| static ssize_t tt_toggle_store(struct device *dev, | ||||
| 			       struct device_attribute *attr, const char *buf, | ||||
| 			       size_t count) | ||||
| { | ||||
| 	int rval; | ||||
| 	bool value; | ||||
| 
 | ||||
| 	rval = kstrtobool(buf, &value); | ||||
| 	if (rval) | ||||
| 		return rval; | ||||
| 
 | ||||
| 	if (value) { | ||||
| 		rval = tt_toggle_enable(); | ||||
| 		if (rval) | ||||
| 			return rval; | ||||
| 	} else { | ||||
| 		rval = tt_toggle_disable(); | ||||
| 		if (rval) | ||||
| 			return rval; | ||||
| 	} | ||||
| 	return count; | ||||
| } | ||||
| 
 | ||||
| static ssize_t tt_toggle_show(struct device *dev, | ||||
| 			      struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	int retval; | ||||
| 	u8 reg; | ||||
| 	long val; | ||||
| 
 | ||||
| 	switch (board) { | ||||
| 	case oxp_mini_amd_a07: | ||||
| 		reg = OXP_OLD_TURBO_SWITCH_REG; | ||||
| 		break; | ||||
| 	case oxp_mini_amd_pro: | ||||
| 	case aok_zoe_a1: | ||||
| 		reg = OXP_TURBO_SWITCH_REG; | ||||
| 		break; | ||||
| 	default: | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	retval = read_from_ec(reg, 1, &val); | ||||
| 	if (retval) | ||||
| 		return retval; | ||||
| 
 | ||||
| 	return sysfs_emit(buf, "%d\n", !!val); | ||||
| } | ||||
| 
 | ||||
| static DEVICE_ATTR_RW(tt_toggle); | ||||
| 
 | ||||
| /* PWM enable/disable functions */ | ||||
| static int oxp_pwm_enable(void) | ||||
| { | ||||
| 	return write_to_ec(OXP_SENSOR_PWM_ENABLE_REG, 0x01); | ||||
|  | @ -206,6 +316,7 @@ static int oxp_platform_read(struct device *dev, enum hwmon_sensor_types type, | |||
| 			case aya_neo_air_pro: | ||||
| 			case aya_neo_geek: | ||||
| 			case oxp_mini_amd: | ||||
| 			case oxp_mini_amd_a07: | ||||
| 				*val = (*val * 255) / 100; | ||||
| 				break; | ||||
| 			case oxp_mini_amd_pro: | ||||
|  | @ -247,6 +358,7 @@ static int oxp_platform_write(struct device *dev, enum hwmon_sensor_types type, | |||
| 			case aya_neo_air_pro: | ||||
| 			case aya_neo_geek: | ||||
| 			case oxp_mini_amd: | ||||
| 			case oxp_mini_amd_a07: | ||||
| 				val = (val * 100) / 255; | ||||
| 				break; | ||||
| 			case aok_zoe_a1: | ||||
|  | @ -274,6 +386,13 @@ static const struct hwmon_channel_info * const oxp_platform_sensors[] = { | |||
| 	NULL, | ||||
| }; | ||||
| 
 | ||||
| static struct attribute *oxp_ec_attrs[] = { | ||||
| 	&dev_attr_tt_toggle.attr, | ||||
| 	NULL | ||||
| }; | ||||
| 
 | ||||
| ATTRIBUTE_GROUPS(oxp_ec); | ||||
| 
 | ||||
| static const struct hwmon_ops oxp_ec_hwmon_ops = { | ||||
| 	.is_visible = oxp_ec_hwmon_is_visible, | ||||
| 	.read = oxp_platform_read, | ||||
|  | @ -291,6 +410,7 @@ static int oxp_platform_probe(struct platform_device *pdev) | |||
| 	const struct dmi_system_id *dmi_entry; | ||||
| 	struct device *dev = &pdev->dev; | ||||
| 	struct device *hwdev; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Have to check for AMD processor here because DMI strings are the | ||||
|  | @ -305,6 +425,18 @@ static int oxp_platform_probe(struct platform_device *pdev) | |||
| 
 | ||||
| 	board = (enum oxp_board)(unsigned long)dmi_entry->driver_data; | ||||
| 
 | ||||
| 	switch (board) { | ||||
| 	case aok_zoe_a1: | ||||
| 	case oxp_mini_amd_a07: | ||||
| 	case oxp_mini_amd_pro: | ||||
| 		ret = devm_device_add_groups(dev, oxp_ec_groups); | ||||
| 		if (ret) | ||||
| 			return ret; | ||||
| 		break; | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	hwdev = devm_hwmon_device_register_with_info(dev, "oxpec", NULL, | ||||
| 						     &oxp_ec_chip_info, NULL); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Joaquín Ignacio Aramendía
						Joaquín Ignacio Aramendía