diff options
author | Dave Airlie <airlied@redhat.com> | 2020-05-08 15:16:36 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2020-05-08 15:17:08 +1000 |
commit | 3fd911b69b3117e03181262fc19ae6c3ef6962ce (patch) | |
tree | 7c1f253b56715cd6f19b8c53301c44279bd58c55 /drivers/gpu/drm/lima/lima_device.c | |
parent | 370fb6b0aaf07c66a3317d5b35fba4345b31035c (diff) | |
parent | 0ea2ea42b31abc1141f2fd3911f952a97d401fcb (diff) | |
download | linux-3fd911b69b3117e03181262fc19ae6c3ef6962ce.tar.bz2 |
Merge tag 'drm-misc-next-2020-05-07' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 5.8:
UAPI Changes:
Cross-subsystem Changes:
* MAINTAINERS: restore alphabetical order; update cirrus driver
* Dcomuentation: document visionix, chronteli, ite vendor prefices; update
documentation for Chrontel CH7033, IT6505, IVO, BOE,
Panasonic, Chunghwa, AUO bindings; convert dw_mipi_dsi.txt
to YAML; remove todo item for drm_display_mode.hsync removal;
Core Changes:
* drm: add devm_drm_dev_alloc() for managed allocations of drm_device;
use DRM_MODESET_LOCK_ALL_*() in mode-object code; remove
drm_display_mode.hsync; small cleanups of unused variables,
compiler warnings and static functions
* drm/client: dual-lincensing: GPL-2.0 or MIT
* drm/mm: optimize tree searches in rb_hole_addr()
Driver Changes:
* drm/{many}: use devm_drm_dev_alloc(); don't use drm_device.dev_private
* drm/ast: don't double-assign to drm_crtc_funcs.set_config; drop
drm_connector_register()
* drm/bochs: drop drm_connector_register()
* drm/bridge: add support for Chrontel ch7033; fix stack usage with
old gccs; return error pointer in drm_panel_bridge_add()
* drm/cirrus: Move to tiny
* drm/dp_mst: don't use 2nd sideband tx slot; revert "Remove single tx
msg restriction"
* drm/lima: support runtime PM;
* drm/meson: limit modes wrt chipset
* drm/panel: add support for Visionox rm69299; fix clock on
boe-tv101wum-n16; fix panel type for AUO G101EVN10;
add support for Ivo M133NFW4 R0; add support for BOE
NV133FHM-N61; add support for AUO G121EAN01.4, G156XTN01.0,
G190EAN01
* drm/pl111: improve vexpress init; fix module auto-loading
* drm/stm: read number of endpoints from device tree
* drm/vboxvideo: use managed PCI functions; drop DRM_MTRR_WC
* drm/vkms: fix use-after-free in vkms_gem_create(); enable cursor
support by default
* fbdev: use boolean values in several drivers
* fbdev/controlfb: fix COMPILE_TEST
* fbdev/w100fb: fix double-free bug
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20200507072503.GA10979@linux-uq9g
Diffstat (limited to 'drivers/gpu/drm/lima/lima_device.c')
-rw-r--r-- | drivers/gpu/drm/lima/lima_device.c | 211 |
1 files changed, 169 insertions, 42 deletions
diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c index 247f51fd40a2..65fdca366e41 100644 --- a/drivers/gpu/drm/lima/lima_device.c +++ b/drivers/gpu/drm/lima/lima_device.c @@ -25,6 +25,8 @@ struct lima_ip_desc { int (*init)(struct lima_ip *ip); void (*fini)(struct lima_ip *ip); + int (*resume)(struct lima_ip *ip); + void (*suspend)(struct lima_ip *ip); }; #define LIMA_IP_DESC(ipname, mst0, mst1, off0, off1, func, irq) \ @@ -41,6 +43,8 @@ struct lima_ip_desc { }, \ .init = lima_##func##_init, \ .fini = lima_##func##_fini, \ + .resume = lima_##func##_resume, \ + .suspend = lima_##func##_suspend, \ } static struct lima_ip_desc lima_ip_desc[lima_ip_num] = { @@ -77,26 +81,10 @@ const char *lima_ip_name(struct lima_ip *ip) return lima_ip_desc[ip->id].name; } -static int lima_clk_init(struct lima_device *dev) +static int lima_clk_enable(struct lima_device *dev) { int err; - dev->clk_bus = devm_clk_get(dev->dev, "bus"); - if (IS_ERR(dev->clk_bus)) { - err = PTR_ERR(dev->clk_bus); - if (err != -EPROBE_DEFER) - dev_err(dev->dev, "get bus clk failed %d\n", err); - return err; - } - - dev->clk_gpu = devm_clk_get(dev->dev, "core"); - if (IS_ERR(dev->clk_gpu)) { - err = PTR_ERR(dev->clk_gpu); - if (err != -EPROBE_DEFER) - dev_err(dev->dev, "get core clk failed %d\n", err); - return err; - } - err = clk_prepare_enable(dev->clk_bus); if (err) return err; @@ -105,15 +93,7 @@ static int lima_clk_init(struct lima_device *dev) if (err) goto error_out0; - dev->reset = devm_reset_control_array_get_optional_shared(dev->dev); - - if (IS_ERR(dev->reset)) { - err = PTR_ERR(dev->reset); - if (err != -EPROBE_DEFER) - dev_err(dev->dev, "get reset controller failed %d\n", - err); - goto error_out1; - } else if (dev->reset != NULL) { + if (dev->reset) { err = reset_control_deassert(dev->reset); if (err) { dev_err(dev->dev, @@ -131,14 +111,76 @@ error_out0: return err; } -static void lima_clk_fini(struct lima_device *dev) +static void lima_clk_disable(struct lima_device *dev) { - if (dev->reset != NULL) + if (dev->reset) reset_control_assert(dev->reset); clk_disable_unprepare(dev->clk_gpu); clk_disable_unprepare(dev->clk_bus); } +static int lima_clk_init(struct lima_device *dev) +{ + int err; + + dev->clk_bus = devm_clk_get(dev->dev, "bus"); + if (IS_ERR(dev->clk_bus)) { + err = PTR_ERR(dev->clk_bus); + if (err != -EPROBE_DEFER) + dev_err(dev->dev, "get bus clk failed %d\n", err); + dev->clk_bus = NULL; + return err; + } + + dev->clk_gpu = devm_clk_get(dev->dev, "core"); + if (IS_ERR(dev->clk_gpu)) { + err = PTR_ERR(dev->clk_gpu); + if (err != -EPROBE_DEFER) + dev_err(dev->dev, "get core clk failed %d\n", err); + dev->clk_gpu = NULL; + return err; + } + + dev->reset = devm_reset_control_array_get_optional_shared(dev->dev); + if (IS_ERR(dev->reset)) { + err = PTR_ERR(dev->reset); + if (err != -EPROBE_DEFER) + dev_err(dev->dev, "get reset controller failed %d\n", + err); + dev->reset = NULL; + return err; + } + + return lima_clk_enable(dev); +} + +static void lima_clk_fini(struct lima_device *dev) +{ + lima_clk_disable(dev); +} + +static int lima_regulator_enable(struct lima_device *dev) +{ + int ret; + + if (!dev->regulator) + return 0; + + ret = regulator_enable(dev->regulator); + if (ret < 0) { + dev_err(dev->dev, "failed to enable regulator: %d\n", ret); + return ret; + } + + return 0; +} + +static void lima_regulator_disable(struct lima_device *dev) +{ + if (dev->regulator) + regulator_disable(dev->regulator); +} + static int lima_regulator_init(struct lima_device *dev) { int ret; @@ -154,25 +196,20 @@ static int lima_regulator_init(struct lima_device *dev) return ret; } - ret = regulator_enable(dev->regulator); - if (ret < 0) { - dev_err(dev->dev, "failed to enable regulator: %d\n", ret); - return ret; - } - - return 0; + return lima_regulator_enable(dev); } static void lima_regulator_fini(struct lima_device *dev) { - if (dev->regulator) - regulator_disable(dev->regulator); + lima_regulator_disable(dev); } static int lima_init_ip(struct lima_device *dev, int index) { + struct platform_device *pdev = to_platform_device(dev->dev); struct lima_ip_desc *desc = lima_ip_desc + index; struct lima_ip *ip = dev->ip + index; + const char *irq_name = desc->irq_name; int offset = desc->offset[dev->id]; bool must = desc->must_have[dev->id]; int err; @@ -183,8 +220,9 @@ static int lima_init_ip(struct lima_device *dev, int index) ip->dev = dev; ip->id = index; ip->iomem = dev->iomem + offset; - if (desc->irq_name) { - err = platform_get_irq_byname(dev->pdev, desc->irq_name); + if (irq_name) { + err = must ? platform_get_irq_byname(pdev, irq_name) : + platform_get_irq_byname_optional(pdev, irq_name); if (err < 0) goto out; ip->irq = err; @@ -209,6 +247,27 @@ static void lima_fini_ip(struct lima_device *ldev, int index) desc->fini(ip); } +static int lima_resume_ip(struct lima_device *ldev, int index) +{ + struct lima_ip_desc *desc = lima_ip_desc + index; + struct lima_ip *ip = ldev->ip + index; + int ret = 0; + + if (ip->present) + ret = desc->resume(ip); + + return ret; +} + +static void lima_suspend_ip(struct lima_device *ldev, int index) +{ + struct lima_ip_desc *desc = lima_ip_desc + index; + struct lima_ip *ip = ldev->ip + index; + + if (ip->present) + desc->suspend(ip); +} + static int lima_init_gp_pipe(struct lima_device *dev) { struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp; @@ -294,8 +353,8 @@ static void lima_fini_pp_pipe(struct lima_device *dev) int lima_device_init(struct lima_device *ldev) { + struct platform_device *pdev = to_platform_device(ldev->dev); int err, i; - struct resource *res; dma_set_coherent_mask(ldev->dev, DMA_BIT_MASK(32)); @@ -326,8 +385,7 @@ int lima_device_init(struct lima_device *ldev) } else ldev->va_end = LIMA_VA_RESERVE_END; - res = platform_get_resource(ldev->pdev, IORESOURCE_MEM, 0); - ldev->iomem = devm_ioremap_resource(ldev->dev, res); + ldev->iomem = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ldev->iomem)) { dev_err(ldev->dev, "fail to ioremap iomem\n"); err = PTR_ERR(ldev->iomem); @@ -404,3 +462,72 @@ void lima_device_fini(struct lima_device *ldev) lima_clk_fini(ldev); } + +int lima_device_resume(struct device *dev) +{ + struct lima_device *ldev = dev_get_drvdata(dev); + int i, err; + + err = lima_clk_enable(ldev); + if (err) { + dev_err(dev, "resume clk fail %d\n", err); + return err; + } + + err = lima_regulator_enable(ldev); + if (err) { + dev_err(dev, "resume regulator fail %d\n", err); + goto err_out0; + } + + for (i = 0; i < lima_ip_num; i++) { + err = lima_resume_ip(ldev, i); + if (err) { + dev_err(dev, "resume ip %d fail\n", i); + goto err_out1; + } + } + + err = lima_devfreq_resume(&ldev->devfreq); + if (err) { + dev_err(dev, "devfreq resume fail\n"); + goto err_out1; + } + + return 0; + +err_out1: + while (--i >= 0) + lima_suspend_ip(ldev, i); + lima_regulator_disable(ldev); +err_out0: + lima_clk_disable(ldev); + return err; +} + +int lima_device_suspend(struct device *dev) +{ + struct lima_device *ldev = dev_get_drvdata(dev); + int i, err; + + /* check any task running */ + for (i = 0; i < lima_pipe_num; i++) { + if (atomic_read(&ldev->pipe[i].base.hw_rq_count)) + return -EBUSY; + } + + err = lima_devfreq_suspend(&ldev->devfreq); + if (err) { + dev_err(dev, "devfreq suspend fail\n"); + return err; + } + + for (i = lima_ip_num - 1; i >= 0; i--) + lima_suspend_ip(ldev, i); + + lima_regulator_disable(ldev); + + lima_clk_disable(ldev); + + return 0; +} |