ADRENO_CHIPID_PATCH(adreno_dev->chipid) + 1);
}
+static void adreno_suspend_device(struct kgsl_device *device,
+ pm_message_t pm_state)
+{
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
+ int pm_event = pm_state.event;
+
+ adreno_dispatcher_halt(device);
+
+ if ((pm_event == PM_EVENT_FREEZE) ||
+ (pm_event == PM_EVENT_QUIESCE) ||
+ (pm_event == PM_EVENT_HIBERNATE))
+ if (gpudev->zap_shader_unload != NULL)
+ gpudev->zap_shader_unload(adreno_dev);
+}
+
+static void adreno_resume_device(struct kgsl_device *device)
+{
+ adreno_dispatcher_unhalt(device);
+}
+
static const struct kgsl_functable adreno_functable = {
/* Mandatory functions */
.regread = adreno_regread,
.clk_set_options = adreno_clk_set_options,
.gpu_model = adreno_gpu_model,
.stop_fault_timer = adreno_dispatcher_stop_fault_timer,
- .dispatcher_halt = adreno_dispatcher_halt,
- .dispatcher_unhalt = adreno_dispatcher_unhalt,
+ .suspend_device = adreno_suspend_device,
+ .resume_device = adreno_resume_device,
};
static struct platform_driver adreno_platform_driver = {
void (*enable_64bit)(struct adreno_device *);
void (*clk_set_options)(struct adreno_device *,
const char *, struct clk *, bool on);
+ void (*zap_shader_unload)(struct adreno_device *);
};
/**
#include "adreno_a5xx_packets.h"
static int zap_ucode_loaded;
+static void *zap_handle_ptr;
static int critical_packet_constructed;
static struct kgsl_memdesc crit_pkts;
*/
static int a5xx_microcode_load(struct adreno_device *adreno_dev)
{
- void *ptr;
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
uint64_t gpuaddr;
/* Load the zap shader firmware through PIL if its available */
if (adreno_dev->gpucore->zap_name && !zap_ucode_loaded) {
- ptr = subsystem_get(adreno_dev->gpucore->zap_name);
+ zap_handle_ptr = subsystem_get(adreno_dev->gpucore->zap_name);
/* Return error if the zap shader cannot be loaded */
- if (IS_ERR_OR_NULL(ptr))
- return (ptr == NULL) ? -ENODEV : PTR_ERR(ptr);
+ if (IS_ERR_OR_NULL(zap_handle_ptr))
+ return (zap_handle_ptr == NULL) ?
+ -ENODEV : PTR_ERR(zap_handle_ptr);
zap_ucode_loaded = 1;
}
return 0;
}
+static void a5xx_zap_shader_unload(struct adreno_device *adreno_dev)
+{
+ if (!IS_ERR_OR_NULL(zap_handle_ptr)) {
+ subsystem_put(zap_handle_ptr);
+ zap_handle_ptr = NULL;
+ zap_ucode_loaded = 0;
+ }
+}
+
static int _me_init_ucode_workarounds(struct adreno_device *adreno_dev)
{
switch (ADRENO_GPUREV(adreno_dev)) {
.preemption_schedule = a5xx_preemption_schedule,
.enable_64bit = a5xx_enable_64bit,
.clk_set_options = a5xx_clk_set_options,
+ .zap_shader_unload = a5xx_zap_shader_unload,
};
mutex_lock(&device->mutex);
status = kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
if (status == 0)
- device->ftbl->dispatcher_halt(device);
+ device->ftbl->suspend_device(device, state);
mutex_unlock(&device->mutex);
return status;
mutex_lock(&device->mutex);
if (device->state == KGSL_STATE_SUSPEND) {
- device->ftbl->dispatcher_unhalt(device);
+ device->ftbl->resume_device(device);
kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
} else if (device->state != KGSL_STATE_INIT) {
/*
static int kgsl_suspend(struct device *dev)
{
+ struct kgsl_device *device = dev_get_drvdata(dev);
+
+ return kgsl_suspend_device(device, PMSG_SUSPEND);
+}
+
+static int kgsl_freeze(struct device *dev)
+{
+ struct kgsl_device *device = dev_get_drvdata(dev);
+
+ return kgsl_suspend_device(device, PMSG_FREEZE);
+}
- pm_message_t arg = {0};
+static int kgsl_poweroff(struct device *dev)
+{
struct kgsl_device *device = dev_get_drvdata(dev);
- return kgsl_suspend_device(device, arg);
+
+ return kgsl_suspend_device(device, PMSG_HIBERNATE);
}
static int kgsl_resume(struct device *dev)
}
const struct dev_pm_ops kgsl_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(kgsl_suspend, kgsl_resume)
+ .suspend = kgsl_suspend,
+ .resume = kgsl_resume,
+ .freeze = kgsl_freeze,
+ .thaw = kgsl_resume,
+ .poweroff = kgsl_poweroff,
+ .restore = kgsl_resume,
.runtime_suspend = kgsl_runtime_suspend,
.runtime_resume = kgsl_runtime_resume,
};
#include <linux/slab.h>
#include <linux/idr.h>
+#include <linux/pm.h>
#include <linux/pm_qos.h>
#include <linux/sched.h>
void (*gpu_model)(struct kgsl_device *device, char *str,
size_t bufsz);
void (*stop_fault_timer)(struct kgsl_device *device);
- void (*dispatcher_halt)(struct kgsl_device *device);
- void (*dispatcher_unhalt)(struct kgsl_device *device);
+ void (*suspend_device)(struct kgsl_device *device,
+ pm_message_t pm_state);
+ void (*resume_device)(struct kgsl_device *device);
};
struct kgsl_ioctl {