linux/drivers/gpu/drm/lima/lima_devfreq.c
Linus Torvalds 68a32ba141 drm for 5.13-rc1
- printk fourcc modifier support added %p4cc
 
 core:
 - drm_crtc_commit_wait
 - atomic plane state helpers reworked for full state
 - dma-buf heaps API rework
 - edid: rework and improvements for displayid
 
 dp-mst:
  - better topology logging
 
 bridge:
 - Chipone ICN6211
 - Lontium LT8912B
 - anx7625 regulator support
 
 panel:
 - fix lt9611 4k panels handling
 
 simple-kms:
 - add plane state helpers
 
 ttm:
 - debugfs support
 - removal of unused sysfs
 - ignore signaled moved fences
 - ioremap buffer according to mem caching
 
 i915:
 - Alderlake S enablement
 - Conversion to dma_resv_locking
 - Bring back watchdog timeout support
 - legacy ioctl cleanups
 - add GEM TDDO and RFC process
 - DG1 LMEM preparation work
 - intel_display.c refactoring
 - Gen9/TGL PCH combination support
 - eDP MSO Support
 - multiple PSR instance support
 - Link training debug updates
 - Disable PSR2 support on JSL/EHL
 - DDR5/LPDDR5 support for bw calcs
 - LSPCON limited to gen9/10 platforms
 - HSW/BDW async flip/VTd corruption workaround
 = SAGV watermakr fixes
 - SNB hard hang on ring resume fix
 - Limit imported dma-buf size
 - move to use new tasklet API
 - refactor KBL/TGL/ADL-S display/gt steppings
 - refactoring legacy DP/HDMI, FB plane code out
 
 amdgpu:
 - uapi: add ioctl to query video capabilities
 - Iniital AMD Freesync HDMI support
 - Initial Adebaran support
 - 10bpc dithering improvements
 - DCN secure display support
 - Drop legacy IO BAR requirements
 - PCIE/S0ix/RAS/Prime/Reset fixes
 - Display ASSR support
 - SMU gfx busy queues for RV/PCO
 - Initial LTTPR display work
 
 amdkfd:
 - MMU notifier fixes
 - APU fixes
 
 radeon:
 - debugfs cleanps
 - fw error handling ifix
 - Flexible array cleanups
 
 msm:
 - big DSI phy/pll cleanup
 - sc7280 initial support
 - commong bandwidth scaling path
 - shrinker locking contention fixes
 - unpin/swap support for GEM objcets
 
 ast:
 - cursor plane handling reworked
 
 tegra:
 - don't register DP AUX channels before connectors
 
 zynqmp:
 - fix OOB struct padding memset
 
 gma500:
 - drop ttm and medfield support
 
 exynos:
 - request_irq cleanup function
 
 mediatek:
 - fine tune line time for EOTp
 - MT8192 dpi support
 - atomic crtc config updates
 - don't support HDMI connector creation
 
 mxsdb:
 - imx8mm support
 
 panfrost:
 -= MMU IRQ handling rework
 
 qxl:
 - locking fixes
 - resource deallocation changes
 
 sun4i:
 - add alpha properties to UI/VI layers
 
 vc4:
 - RPi4 CEC support
 
 vmwgfx:
 - doc cleanups
 
 arc:
 - moved to drm/tiny
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJgiNSVAAoJEAx081l5xIa+fvYP/1206BfOYOx5opt5K3By06ZY
 zrOsbeaqFdHzfUR7xVwO4vqQNhkX4Pt8H/U7uYZx8PRdrXzGENwWLIaIskyUrKOd
 BtwNqUr0ZXJGDlGg26StnUHKeAXuYXlpBKLta5y4LUTkI+bm6V/oVaDMq4dnah70
 2CXS4C2mnaFRLBzuRlraxoGFN4eZkz6Waeyo6PJxn/l2GE2gw+jho0Yrh8e8F2w5
 EjQeNF22/uHwznov03XFJlyugecuBDbE8A6Ma/znnkVdBXcT94eUMugbKOKi4Nn6
 PuJOEdJxmj/9s3oi6kBERc8dvpOj0O+8Vp+xOzn2U3BVXebvu7VoJsq6FcAvL5lN
 ltj4iErxUlEud2GRIVUMx8OTFiKj4ThRFJ2/8Uf22r3P7RHO5E9BLnZBzqIAhDVr
 s2cDBMItcxcVHRCmE04h12XAO4libZBb2TVjbqG94Acq7beR76pMszFrmxPmHBEm
 NGe1s7+ajxMzsq/NIsk4XAhqSmJo6+ujKyyVnrgvKUVeEaWW1U4YvjhJaetnP4fB
 47gF24wOSNFwiCUZlqaIpp/MR4Z8YmaJ7tayWQq4Oj/neWe/yc8xQgQIuE8GL20j
 P9eNQNvlBnoxkz275M9x4kVhJ5FRjr7OYnd3sFVnALuj6fnL3Z1RXLqI1lNtIz1d
 YM89veZuNxMaiDz8roPH
 =bLWZ
 -----END PGP SIGNATURE-----

Merge tag 'drm-next-2021-04-28' of git://anongit.freedesktop.org/drm/drm

Pull drm updates from Dave Airlie:
 "The usual lots of work all over the place.

  i915 has gotten some Alderlake work and prelim DG1 code, along with a
  major locking rework over the GEM code, and brings back the property
  of timing out long running jobs using a watchdog. amdgpu has some
  Alderbran support (new GPU), freesync HDMI support along with a lot
  other fixes.

  Outside of the drm, there is a new printf specifier added which should
  have all the correct acks/sobs:

   - printk fourcc modifier support added %p4cc

  Summary:

  core:
   - drm_crtc_commit_wait
   - atomic plane state helpers reworked for full state
   - dma-buf heaps API rework
   - edid: rework and improvements for displayid

  dp-mst:
   - better topology logging

  bridge:
   - Chipone ICN6211
   - Lontium LT8912B
   - anx7625 regulator support

  panel:
   - fix lt9611 4k panels handling

  simple-kms:
   - add plane state helpers

  ttm:
   - debugfs support
   - removal of unused sysfs
   - ignore signaled moved fences
   - ioremap buffer according to mem caching

  i915:
   - Alderlake S enablement
   - Conversion to dma_resv_locking
   - Bring back watchdog timeout support
   - legacy ioctl cleanups
   - add GEM TDDO and RFC process
   - DG1 LMEM preparation work
   - intel_display.c refactoring
   - Gen9/TGL PCH combination support
   - eDP MSO Support
   - multiple PSR instance support
   - Link training debug updates
   - Disable PSR2 support on JSL/EHL
   - DDR5/LPDDR5 support for bw calcs
   - LSPCON limited to gen9/10 platforms
   - HSW/BDW async flip/VTd corruption workaround
   - SAGV watermark fixes
   - SNB hard hang on ring resume fix
   - Limit imported dma-buf size
   - move to use new tasklet API
   - refactor KBL/TGL/ADL-S display/gt steppings
   - refactoring legacy DP/HDMI, FB plane code out

  amdgpu:
   - uapi: add ioctl to query video capabilities
   - Iniital AMD Freesync HDMI support
   - Initial Adebaran support
   - 10bpc dithering improvements
   - DCN secure display support
   - Drop legacy IO BAR requirements
   - PCIE/S0ix/RAS/Prime/Reset fixes
   - Display ASSR support
   - SMU gfx busy queues for RV/PCO
   - Initial LTTPR display work

  amdkfd:
   - MMU notifier fixes
   - APU fixes

  radeon:
   - debugfs cleanps
   - fw error handling ifix
   - Flexible array cleanups

  msm:
   - big DSI phy/pll cleanup
   - sc7280 initial support
   - commong bandwidth scaling path
   - shrinker locking contention fixes
   - unpin/swap support for GEM objcets

  ast:
   - cursor plane handling reworked

  tegra:
   - don't register DP AUX channels before connectors

  zynqmp:
   - fix OOB struct padding memset

  gma500:
   - drop ttm and medfield support

  exynos:
   - request_irq cleanup function

  mediatek:
   - fine tune line time for EOTp
   - MT8192 dpi support
   - atomic crtc config updates
   - don't support HDMI connector creation

  mxsdb:
   - imx8mm support

  panfrost:
   - MMU IRQ handling rework

  qxl:
   - locking fixes
   - resource deallocation changes

  sun4i:
   - add alpha properties to UI/VI layers

  vc4:
   - RPi4 CEC support

  vmwgfx:
   - doc cleanups

  arc:
   - moved to drm/tiny"

* tag 'drm-next-2021-04-28' of git://anongit.freedesktop.org/drm/drm: (1390 commits)
  drm/ttm: Don't count pages in SG BOs against pages_limit
  drm/ttm: fix return value check
  drm/bridge: lt8912b: fix incorrect handling of of_* return values
  drm: bridge: fix LONTIUM use of mipi_dsi_() functions
  drm: bridge: fix ANX7625 use of mipi_dsi_() functions
  drm/amdgpu: page retire over debugfs mechanism
  drm/radeon: Fix a missing check bug in radeon_dp_mst_detect()
  drm/amd/display: Fix the Wunused-function warning
  drm/radeon/r600: Fix variables that are not used after assignment
  drm/amdgpu/smu7: fix CAC setting on TOPAZ
  drm/amd/display: Update DCN302 SR Exit Latency
  drm/amdgpu: enable ras eeprom on aldebaran
  drm/amdgpu: RAS harvest on driver load
  drm/amdgpu: add ras aldebaran ras eeprom driver
  drm/amd/pm: increase time out value when sending msg to SMU
  drm/amdgpu: add DMUB outbox event IRQ source define/complete/debug flag
  drm/amd/pm: add the callback to get vbios bootup values for vangogh
  drm/radeon: Fix size overflow
  drm/amdgpu: Fix size overflow
  drm/amdgpu: move mmhub ras_func init to ip specific file
  ...
2021-04-28 10:01:40 -07:00

228 lines
5.1 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2020 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
*
* Based on panfrost_devfreq.c:
* Copyright 2019 Collabora ltd.
*/
#include <linux/clk.h>
#include <linux/devfreq.h>
#include <linux/devfreq_cooling.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/property.h>
#include "lima_device.h"
#include "lima_devfreq.h"
static void lima_devfreq_update_utilization(struct lima_devfreq *devfreq)
{
ktime_t now, last;
now = ktime_get();
last = devfreq->time_last_update;
if (devfreq->busy_count > 0)
devfreq->busy_time += ktime_sub(now, last);
else
devfreq->idle_time += ktime_sub(now, last);
devfreq->time_last_update = now;
}
static int lima_devfreq_target(struct device *dev, unsigned long *freq,
u32 flags)
{
struct dev_pm_opp *opp;
opp = devfreq_recommended_opp(dev, freq, flags);
if (IS_ERR(opp))
return PTR_ERR(opp);
dev_pm_opp_put(opp);
return dev_pm_opp_set_rate(dev, *freq);
}
static void lima_devfreq_reset(struct lima_devfreq *devfreq)
{
devfreq->busy_time = 0;
devfreq->idle_time = 0;
devfreq->time_last_update = ktime_get();
}
static int lima_devfreq_get_dev_status(struct device *dev,
struct devfreq_dev_status *status)
{
struct lima_device *ldev = dev_get_drvdata(dev);
struct lima_devfreq *devfreq = &ldev->devfreq;
unsigned long irqflags;
status->current_frequency = clk_get_rate(ldev->clk_gpu);
spin_lock_irqsave(&devfreq->lock, irqflags);
lima_devfreq_update_utilization(devfreq);
status->total_time = ktime_to_ns(ktime_add(devfreq->busy_time,
devfreq->idle_time));
status->busy_time = ktime_to_ns(devfreq->busy_time);
lima_devfreq_reset(devfreq);
spin_unlock_irqrestore(&devfreq->lock, irqflags);
dev_dbg(ldev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n",
status->busy_time, status->total_time,
status->busy_time / (status->total_time / 100),
status->current_frequency / 1000 / 1000);
return 0;
}
static struct devfreq_dev_profile lima_devfreq_profile = {
.timer = DEVFREQ_TIMER_DELAYED,
.polling_ms = 50, /* ~3 frames */
.target = lima_devfreq_target,
.get_dev_status = lima_devfreq_get_dev_status,
};
void lima_devfreq_fini(struct lima_device *ldev)
{
struct lima_devfreq *devfreq = &ldev->devfreq;
if (devfreq->cooling) {
devfreq_cooling_unregister(devfreq->cooling);
devfreq->cooling = NULL;
}
if (devfreq->devfreq) {
devm_devfreq_remove_device(ldev->dev, devfreq->devfreq);
devfreq->devfreq = NULL;
}
}
int lima_devfreq_init(struct lima_device *ldev)
{
struct thermal_cooling_device *cooling;
struct device *dev = ldev->dev;
struct devfreq *devfreq;
struct lima_devfreq *ldevfreq = &ldev->devfreq;
struct dev_pm_opp *opp;
unsigned long cur_freq;
int ret;
if (!device_property_present(dev, "operating-points-v2"))
/* Optional, continue without devfreq */
return 0;
spin_lock_init(&ldevfreq->lock);
ret = devm_pm_opp_set_clkname(dev, "core");
if (ret)
return ret;
ret = devm_pm_opp_set_regulators(dev, (const char *[]){ "mali" }, 1);
if (ret) {
/* Continue if the optional regulator is missing */
if (ret != -ENODEV)
return ret;
}
ret = devm_pm_opp_of_add_table(dev);
if (ret)
return ret;
lima_devfreq_reset(ldevfreq);
cur_freq = clk_get_rate(ldev->clk_gpu);
opp = devfreq_recommended_opp(dev, &cur_freq, 0);
if (IS_ERR(opp))
return PTR_ERR(opp);
lima_devfreq_profile.initial_freq = cur_freq;
dev_pm_opp_put(opp);
/*
* Setup default thresholds for the simple_ondemand governor.
* The values are chosen based on experiments.
*/
ldevfreq->gov_data.upthreshold = 30;
ldevfreq->gov_data.downdifferential = 5;
devfreq = devm_devfreq_add_device(dev, &lima_devfreq_profile,
DEVFREQ_GOV_SIMPLE_ONDEMAND,
&ldevfreq->gov_data);
if (IS_ERR(devfreq)) {
dev_err(dev, "Couldn't initialize GPU devfreq\n");
return PTR_ERR(devfreq);
}
ldevfreq->devfreq = devfreq;
cooling = of_devfreq_cooling_register(dev->of_node, devfreq);
if (IS_ERR(cooling))
dev_info(dev, "Failed to register cooling device\n");
else
ldevfreq->cooling = cooling;
return 0;
}
void lima_devfreq_record_busy(struct lima_devfreq *devfreq)
{
unsigned long irqflags;
if (!devfreq->devfreq)
return;
spin_lock_irqsave(&devfreq->lock, irqflags);
lima_devfreq_update_utilization(devfreq);
devfreq->busy_count++;
spin_unlock_irqrestore(&devfreq->lock, irqflags);
}
void lima_devfreq_record_idle(struct lima_devfreq *devfreq)
{
unsigned long irqflags;
if (!devfreq->devfreq)
return;
spin_lock_irqsave(&devfreq->lock, irqflags);
lima_devfreq_update_utilization(devfreq);
WARN_ON(--devfreq->busy_count < 0);
spin_unlock_irqrestore(&devfreq->lock, irqflags);
}
int lima_devfreq_resume(struct lima_devfreq *devfreq)
{
unsigned long irqflags;
if (!devfreq->devfreq)
return 0;
spin_lock_irqsave(&devfreq->lock, irqflags);
lima_devfreq_reset(devfreq);
spin_unlock_irqrestore(&devfreq->lock, irqflags);
return devfreq_resume_device(devfreq->devfreq);
}
int lima_devfreq_suspend(struct lima_devfreq *devfreq)
{
if (!devfreq->devfreq)
return 0;
return devfreq_suspend_device(devfreq->devfreq);
}