Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions drivers/platform/surface/surface_platform_profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ enum ssam_fan_profile {
SSAM_FAN_PROFILE_BEST_PERFORMANCE = 4,
};

enum ssam_fan_state {
SSAM_FAN_STATE_NORMAL = 1,
SSAM_FAN_STATE_STANDBY = 2,
};

struct ssam_tmp_profile_info {
__le32 profile;
__le16 unknown1;
Expand Down Expand Up @@ -61,6 +66,13 @@ SSAM_DEFINE_SYNC_REQUEST_W(__ssam_fan_profile_set, u8, {
.instance_id = 0x01,
});

SSAM_DEFINE_SYNC_REQUEST_W(__ssam_fan_state_set, u8, {
.target_category = SSAM_SSH_TC_FAN,
.target_id = SSAM_SSH_TID_SAM,
.command_id = 0x0f,
.instance_id = 0x01,
});

static int ssam_tmp_profile_get(struct ssam_device *sdev, enum ssam_tmp_profile *p)
{
struct ssam_tmp_profile_info info;
Expand Down Expand Up @@ -88,6 +100,13 @@ static int ssam_fan_profile_set(struct ssam_device *sdev, enum ssam_fan_profile
return ssam_retry(__ssam_fan_profile_set, sdev->ctrl, &profile);
}

static int ssam_fan_state_set(struct ssam_device *sdev, enum ssam_fan_state s)
{
const u8 state = s;

return ssam_retry(__ssam_fan_state_set, sdev->ctrl, &state);
}

static int convert_ssam_tmp_to_profile(struct ssam_device *sdev, enum ssam_tmp_profile p)
{
switch (p) {
Expand Down Expand Up @@ -236,6 +255,49 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
return PTR_ERR_OR_ZERO(tpd->ppdev);
}

#ifdef CONFIG_PM_SLEEP

static int surface_platform_profile_pm_prepare(struct device *dev)
{
struct ssam_platform_profile_device *tpd;
int status;

tpd = dev_get_drvdata(dev);

if (tpd->has_fan) {
status = ssam_fan_state_set(tpd->sdev, SSAM_FAN_STATE_STANDBY);
if (status)
dev_err(&tpd->sdev->dev, "pm: fan standby notification failed");
}

return status;
}

static void surface_platform_profile_pm_complete(struct device *dev)
{
struct ssam_platform_profile_device *tpd;
int status;

tpd = dev_get_drvdata(dev);

if (tpd->has_fan) {
status = ssam_fan_state_set(tpd->sdev, SSAM_FAN_STATE_NORMAL);
if (status)
dev_err(&tpd->sdev->dev, "pm: fan resume notification failed");
}
}

static const struct dev_pm_ops surface_platform_profile_pm_ops = {
.prepare = surface_platform_profile_pm_prepare,
.complete = surface_platform_profile_pm_complete,
};

#else /* CONFIG_PM_SLEEP */

static const struct dev_pm_ops surface_platform_profile_pm_ops = { };

#endif /* CONFIG_PM_SLEEP */

static const struct ssam_device_id ssam_platform_profile_match[] = {
{ SSAM_SDEV(TMP, SAM, 0x00, 0x01) },
{ },
Expand All @@ -247,6 +309,7 @@ static struct ssam_device_driver surface_platform_profile = {
.match_table = ssam_platform_profile_match,
.driver = {
.name = "surface_platform_profile",
.pm = &surface_platform_profile_pm_ops,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
};
Expand Down