Commit ce3cf821 authored by Luca Tettamanti's avatar Luca Tettamanti Committed by Alex Deucher
Browse files

drm/radeon: implement wrapper for GET_SYSTEM_PARAMS



Use GET_SYSTEM_PARAMS for retrieving the configuration for the system
BIOS notifications.
v2: packed struct (Lee, Chun-Yi <jlee@suse.com>)
v3: fix enable with device specific command code

Signed-off-by: default avatarLuca Tettamanti <kronos.it@gmail.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent fd64ca8a
Loading
Loading
Loading
Loading
+83 −2
Original line number Diff line number Diff line
@@ -43,6 +43,18 @@ struct atif_verify_interface {
	u32 function_bits;	/* supported functions bit vector */
} __packed;

struct atif_system_params {
	u16 size;
	u32 valid_mask;
	u32 flags;
	u8 command_code;
} __packed;

#define ATIF_NOTIFY_MASK	0x3
#define ATIF_NOTIFY_NONE	0
#define ATIF_NOTIFY_81		1
#define ATIF_NOTIFY_N		2

/* Call the ATIF method
 */
static union acpi_object *radeon_atif_call(acpi_handle handle, int function,
@@ -144,10 +156,57 @@ static int radeon_atif_verify_interface(acpi_handle handle,
	return err;
}

static int radeon_atif_get_notification_params(acpi_handle handle,
		struct radeon_atif_notification_cfg *n)
{
	union acpi_object *info;
	struct atif_system_params params;
	size_t size;
	int err = 0;

	info = radeon_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS, NULL);
	if (!info) {
		err = -EIO;
		goto out;
	}

	size = *(u16 *) info->buffer.pointer;
	if (size < 10) {
		err = -EINVAL;
		goto out;
	}

	memset(&params, 0, sizeof(params));
	size = min(sizeof(params), size);
	memcpy(&params, info->buffer.pointer, size);

	params.flags = params.flags & params.valid_mask;

	if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_NONE) {
		n->enabled = false;
		n->command_code = 0;
	} else if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_81) {
		n->enabled = true;
		n->command_code = 0x81;
	} else {
		if (size < 11) {
			err = -EINVAL;
			goto out;
		}
		n->enabled = true;
		n->command_code = params.command_code;
	}

out:
	kfree(info);
	return err;
}

/* Call all ACPI methods here */
int radeon_acpi_init(struct radeon_device *rdev)
{
	acpi_handle handle;
	struct radeon_atif *atif = &rdev->atif;
	int ret;

	/* Get the device handle */
@@ -158,10 +217,32 @@ int radeon_acpi_init(struct radeon_device *rdev)
		return 0;

	/* Call the ATIF method */
	ret = radeon_atif_verify_interface(handle, &rdev->atif);
	if (ret)
	ret = radeon_atif_verify_interface(handle, atif);
	if (ret) {
		DRM_DEBUG_DRIVER("Call to verify_interface failed: %d\n", ret);
		goto out;
	}

	if (atif->functions.sbios_requests && !atif->functions.system_params) {
		/* XXX check this workraround, if sbios request function is
		 * present we have to see how it's configured in the system
		 * params
		 */
		atif->functions.system_params = true;
	}

	if (atif->functions.system_params) {
		ret = radeon_atif_get_notification_params(handle,
				&atif->notification_cfg);
		if (ret) {
			DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n",
					ret);
			/* Disable notification */
			atif->notification_cfg.enabled = false;
		}
	}

out:
	return ret;
}