Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ab15365 authored by Zhang Rui's avatar Zhang Rui
Browse files

Thermal: int3400 thermal: register to thermal framework



Signed-off-by: default avatarZhang Rui <rui.zhang@intel.com>
parent c5738ddd
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -237,6 +237,7 @@ config INTEL_SOC_DTS_THERMAL
config INT340X_THERMAL
config INT340X_THERMAL
	tristate "ACPI INT340X thermal drivers"
	tristate "ACPI INT340X thermal drivers"
	depends on X86 && ACPI
	depends on X86 && ACPI
	select THERMAL_GOV_USER_SPACE
	help
	help
	  Newer laptops and tablets that use ACPI may have thermal sensors and
	  Newer laptops and tablets that use ACPI may have thermal sensors and
	  other devices with thermal control capabilities outside the core
	  other devices with thermal control capabilities outside the core
+103 −0
Original line number Original line Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/acpi.h>
#include <linux/thermal.h>


struct art {
struct art {
	acpi_handle source;
	acpi_handle source;
@@ -60,6 +61,8 @@ static u8 *int3400_thermal_uuids[INT3400_THERMAL_MAXIMUM_UUID] = {


struct int3400_thermal_priv {
struct int3400_thermal_priv {
	struct acpi_device *adev;
	struct acpi_device *adev;
	struct thermal_zone_device *thermal;
	int mode;
	int art_count;
	int art_count;
	struct art *arts;
	struct art *arts;
	int trt_count;
	int trt_count;
@@ -114,6 +117,36 @@ static int int3400_thermal_get_uuids(struct int3400_thermal_priv *priv)
	return result;
	return result;
}
}


static int int3400_thermal_run_osc(acpi_handle handle,
				enum int3400_thermal_uuid uuid, bool enable)
{
	u32 ret, buf[2];
	acpi_status status;
	int result = 0;
	struct acpi_osc_context context = {
		.uuid_str = int3400_thermal_uuids[uuid],
		.rev = 1,
		.cap.length = 8,
	};

	buf[OSC_QUERY_DWORD] = 0;
	buf[OSC_SUPPORT_DWORD] = enable;

	context.cap.pointer = buf;

	status = acpi_run_osc(handle, &context);
	if (ACPI_SUCCESS(status)) {
		ret = *((u32 *)(context.ret.pointer + 4));
		if (ret != enable)
			result = -EPERM;
	} else
		result = -EPERM;

	kfree(context.ret.pointer);
	return result;
}


static int parse_art(struct int3400_thermal_priv *priv)
static int parse_art(struct int3400_thermal_priv *priv)
{
{
	acpi_handle handle = priv->adev->handle;
	acpi_handle handle = priv->adev->handle;
@@ -243,6 +276,61 @@ static int parse_trt(struct int3400_thermal_priv *priv)
	return result;
	return result;
}
}


static int int3400_thermal_get_temp(struct thermal_zone_device *thermal,
			unsigned long *temp)
{
	*temp = 20 * 1000; /* faked temp sensor with 20C */
	return 0;
}

static int int3400_thermal_get_mode(struct thermal_zone_device *thermal,
				enum thermal_device_mode *mode)
{
	struct int3400_thermal_priv *priv = thermal->devdata;

	if (!priv)
		return -EINVAL;

	*mode = priv->mode;

	return 0;
}

static int int3400_thermal_set_mode(struct thermal_zone_device *thermal,
				enum thermal_device_mode mode)
{
	struct int3400_thermal_priv *priv = thermal->devdata;
	bool enable;
	int result = 0;

	if (!priv)
		return -EINVAL;

	if (mode == THERMAL_DEVICE_ENABLED)
		enable = true;
	else if (mode == THERMAL_DEVICE_DISABLED)
		enable = false;
	else
		return -EINVAL;

	if (enable != priv->mode) {
		priv->mode = enable;
		/* currently, only PASSIVE COOLING is supported */
		result = int3400_thermal_run_osc(priv->adev->handle,
					INT3400_THERMAL_PASSIVE_1, enable);
	}
	return result;
}

static struct thermal_zone_device_ops int3400_thermal_ops = {
	.get_temp = int3400_thermal_get_temp,
};

static struct thermal_zone_params int3400_thermal_params = {
	.governor_name = "user_space",
	.no_hwmon = true,
};

static int int3400_thermal_probe(struct platform_device *pdev)
static int int3400_thermal_probe(struct platform_device *pdev)
{
{
	struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
	struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
@@ -272,7 +360,21 @@ static int int3400_thermal_probe(struct platform_device *pdev)


	platform_set_drvdata(pdev, priv);
	platform_set_drvdata(pdev, priv);


	if (priv->uuid_bitmap & 1 << INT3400_THERMAL_PASSIVE_1) {
		int3400_thermal_ops.get_mode = int3400_thermal_get_mode;
		int3400_thermal_ops.set_mode = int3400_thermal_set_mode;
	}
	priv->thermal = thermal_zone_device_register("INT3400 Thermal", 0, 0,
						priv, &int3400_thermal_ops,
						&int3400_thermal_params, 0, 0);
	if (IS_ERR(priv->thermal)) {
		result = PTR_ERR(priv->thermal);
		goto free_trt;
	}

	return 0;
	return 0;
free_trt:
	kfree(priv->trts);
free_art:
free_art:
	kfree(priv->arts);
	kfree(priv->arts);
free_priv:
free_priv:
@@ -284,6 +386,7 @@ static int int3400_thermal_remove(struct platform_device *pdev)
{
{
	struct int3400_thermal_priv *priv = platform_get_drvdata(pdev);
	struct int3400_thermal_priv *priv = platform_get_drvdata(pdev);


	thermal_zone_device_unregister(priv->thermal);
	kfree(priv->trts);
	kfree(priv->trts);
	kfree(priv->arts);
	kfree(priv->arts);
	kfree(priv);
	kfree(priv);