| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2014 The Linux Foundation. All rights reserved. |
|---|
| 3 | 4 | * Copyright (C) 2013 Red Hat |
|---|
| 4 | 5 | * Author: Rob Clark <robdclark@gmail.com> |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 7 | | - * under the terms of the GNU General Public License version 2 as published by |
|---|
| 8 | | - * the Free Software Foundation. |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
|---|
| 11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 13 | | - * more details. |
|---|
| 14 | | - * |
|---|
| 15 | | - * You should have received a copy of the GNU General Public License along with |
|---|
| 16 | | - * this program. If not, see <http://www.gnu.org/licenses/>. |
|---|
| 17 | 6 | */ |
|---|
| 18 | 7 | |
|---|
| 19 | 8 | #include <linux/clk.h> |
|---|
| 20 | 9 | #include <linux/component.h> |
|---|
| 10 | +#include <linux/platform_device.h> |
|---|
| 21 | 11 | #include <linux/pm_runtime.h> |
|---|
| 12 | + |
|---|
| 13 | +#include <drm/drm_irq.h> |
|---|
| 14 | + |
|---|
| 22 | 15 | #include "vc4_drv.h" |
|---|
| 23 | 16 | #include "vc4_regs.h" |
|---|
| 24 | 17 | |
|---|
| 25 | | -#ifdef CONFIG_DEBUG_FS |
|---|
| 26 | | -#define REGDEF(reg) { reg, #reg } |
|---|
| 27 | | -static const struct { |
|---|
| 28 | | - uint32_t reg; |
|---|
| 29 | | - const char *name; |
|---|
| 30 | | -} vc4_reg_defs[] = { |
|---|
| 31 | | - REGDEF(V3D_IDENT0), |
|---|
| 32 | | - REGDEF(V3D_IDENT1), |
|---|
| 33 | | - REGDEF(V3D_IDENT2), |
|---|
| 34 | | - REGDEF(V3D_SCRATCH), |
|---|
| 35 | | - REGDEF(V3D_L2CACTL), |
|---|
| 36 | | - REGDEF(V3D_SLCACTL), |
|---|
| 37 | | - REGDEF(V3D_INTCTL), |
|---|
| 38 | | - REGDEF(V3D_INTENA), |
|---|
| 39 | | - REGDEF(V3D_INTDIS), |
|---|
| 40 | | - REGDEF(V3D_CT0CS), |
|---|
| 41 | | - REGDEF(V3D_CT1CS), |
|---|
| 42 | | - REGDEF(V3D_CT0EA), |
|---|
| 43 | | - REGDEF(V3D_CT1EA), |
|---|
| 44 | | - REGDEF(V3D_CT0CA), |
|---|
| 45 | | - REGDEF(V3D_CT1CA), |
|---|
| 46 | | - REGDEF(V3D_CT00RA0), |
|---|
| 47 | | - REGDEF(V3D_CT01RA0), |
|---|
| 48 | | - REGDEF(V3D_CT0LC), |
|---|
| 49 | | - REGDEF(V3D_CT1LC), |
|---|
| 50 | | - REGDEF(V3D_CT0PC), |
|---|
| 51 | | - REGDEF(V3D_CT1PC), |
|---|
| 52 | | - REGDEF(V3D_PCS), |
|---|
| 53 | | - REGDEF(V3D_BFC), |
|---|
| 54 | | - REGDEF(V3D_RFC), |
|---|
| 55 | | - REGDEF(V3D_BPCA), |
|---|
| 56 | | - REGDEF(V3D_BPCS), |
|---|
| 57 | | - REGDEF(V3D_BPOA), |
|---|
| 58 | | - REGDEF(V3D_BPOS), |
|---|
| 59 | | - REGDEF(V3D_BXCF), |
|---|
| 60 | | - REGDEF(V3D_SQRSV0), |
|---|
| 61 | | - REGDEF(V3D_SQRSV1), |
|---|
| 62 | | - REGDEF(V3D_SQCNTL), |
|---|
| 63 | | - REGDEF(V3D_SRQPC), |
|---|
| 64 | | - REGDEF(V3D_SRQUA), |
|---|
| 65 | | - REGDEF(V3D_SRQUL), |
|---|
| 66 | | - REGDEF(V3D_SRQCS), |
|---|
| 67 | | - REGDEF(V3D_VPACNTL), |
|---|
| 68 | | - REGDEF(V3D_VPMBASE), |
|---|
| 69 | | - REGDEF(V3D_PCTRC), |
|---|
| 70 | | - REGDEF(V3D_PCTRE), |
|---|
| 71 | | - REGDEF(V3D_PCTR(0)), |
|---|
| 72 | | - REGDEF(V3D_PCTRS(0)), |
|---|
| 73 | | - REGDEF(V3D_PCTR(1)), |
|---|
| 74 | | - REGDEF(V3D_PCTRS(1)), |
|---|
| 75 | | - REGDEF(V3D_PCTR(2)), |
|---|
| 76 | | - REGDEF(V3D_PCTRS(2)), |
|---|
| 77 | | - REGDEF(V3D_PCTR(3)), |
|---|
| 78 | | - REGDEF(V3D_PCTRS(3)), |
|---|
| 79 | | - REGDEF(V3D_PCTR(4)), |
|---|
| 80 | | - REGDEF(V3D_PCTRS(4)), |
|---|
| 81 | | - REGDEF(V3D_PCTR(5)), |
|---|
| 82 | | - REGDEF(V3D_PCTRS(5)), |
|---|
| 83 | | - REGDEF(V3D_PCTR(6)), |
|---|
| 84 | | - REGDEF(V3D_PCTRS(6)), |
|---|
| 85 | | - REGDEF(V3D_PCTR(7)), |
|---|
| 86 | | - REGDEF(V3D_PCTRS(7)), |
|---|
| 87 | | - REGDEF(V3D_PCTR(8)), |
|---|
| 88 | | - REGDEF(V3D_PCTRS(8)), |
|---|
| 89 | | - REGDEF(V3D_PCTR(9)), |
|---|
| 90 | | - REGDEF(V3D_PCTRS(9)), |
|---|
| 91 | | - REGDEF(V3D_PCTR(10)), |
|---|
| 92 | | - REGDEF(V3D_PCTRS(10)), |
|---|
| 93 | | - REGDEF(V3D_PCTR(11)), |
|---|
| 94 | | - REGDEF(V3D_PCTRS(11)), |
|---|
| 95 | | - REGDEF(V3D_PCTR(12)), |
|---|
| 96 | | - REGDEF(V3D_PCTRS(12)), |
|---|
| 97 | | - REGDEF(V3D_PCTR(13)), |
|---|
| 98 | | - REGDEF(V3D_PCTRS(13)), |
|---|
| 99 | | - REGDEF(V3D_PCTR(14)), |
|---|
| 100 | | - REGDEF(V3D_PCTRS(14)), |
|---|
| 101 | | - REGDEF(V3D_PCTR(15)), |
|---|
| 102 | | - REGDEF(V3D_PCTRS(15)), |
|---|
| 103 | | - REGDEF(V3D_DBGE), |
|---|
| 104 | | - REGDEF(V3D_FDBGO), |
|---|
| 105 | | - REGDEF(V3D_FDBGB), |
|---|
| 106 | | - REGDEF(V3D_FDBGR), |
|---|
| 107 | | - REGDEF(V3D_FDBGS), |
|---|
| 108 | | - REGDEF(V3D_ERRSTAT), |
|---|
| 18 | +static const struct debugfs_reg32 v3d_regs[] = { |
|---|
| 19 | + VC4_REG32(V3D_IDENT0), |
|---|
| 20 | + VC4_REG32(V3D_IDENT1), |
|---|
| 21 | + VC4_REG32(V3D_IDENT2), |
|---|
| 22 | + VC4_REG32(V3D_SCRATCH), |
|---|
| 23 | + VC4_REG32(V3D_L2CACTL), |
|---|
| 24 | + VC4_REG32(V3D_SLCACTL), |
|---|
| 25 | + VC4_REG32(V3D_INTCTL), |
|---|
| 26 | + VC4_REG32(V3D_INTENA), |
|---|
| 27 | + VC4_REG32(V3D_INTDIS), |
|---|
| 28 | + VC4_REG32(V3D_CT0CS), |
|---|
| 29 | + VC4_REG32(V3D_CT1CS), |
|---|
| 30 | + VC4_REG32(V3D_CT0EA), |
|---|
| 31 | + VC4_REG32(V3D_CT1EA), |
|---|
| 32 | + VC4_REG32(V3D_CT0CA), |
|---|
| 33 | + VC4_REG32(V3D_CT1CA), |
|---|
| 34 | + VC4_REG32(V3D_CT00RA0), |
|---|
| 35 | + VC4_REG32(V3D_CT01RA0), |
|---|
| 36 | + VC4_REG32(V3D_CT0LC), |
|---|
| 37 | + VC4_REG32(V3D_CT1LC), |
|---|
| 38 | + VC4_REG32(V3D_CT0PC), |
|---|
| 39 | + VC4_REG32(V3D_CT1PC), |
|---|
| 40 | + VC4_REG32(V3D_PCS), |
|---|
| 41 | + VC4_REG32(V3D_BFC), |
|---|
| 42 | + VC4_REG32(V3D_RFC), |
|---|
| 43 | + VC4_REG32(V3D_BPCA), |
|---|
| 44 | + VC4_REG32(V3D_BPCS), |
|---|
| 45 | + VC4_REG32(V3D_BPOA), |
|---|
| 46 | + VC4_REG32(V3D_BPOS), |
|---|
| 47 | + VC4_REG32(V3D_BXCF), |
|---|
| 48 | + VC4_REG32(V3D_SQRSV0), |
|---|
| 49 | + VC4_REG32(V3D_SQRSV1), |
|---|
| 50 | + VC4_REG32(V3D_SQCNTL), |
|---|
| 51 | + VC4_REG32(V3D_SRQPC), |
|---|
| 52 | + VC4_REG32(V3D_SRQUA), |
|---|
| 53 | + VC4_REG32(V3D_SRQUL), |
|---|
| 54 | + VC4_REG32(V3D_SRQCS), |
|---|
| 55 | + VC4_REG32(V3D_VPACNTL), |
|---|
| 56 | + VC4_REG32(V3D_VPMBASE), |
|---|
| 57 | + VC4_REG32(V3D_PCTRC), |
|---|
| 58 | + VC4_REG32(V3D_PCTRE), |
|---|
| 59 | + VC4_REG32(V3D_PCTR(0)), |
|---|
| 60 | + VC4_REG32(V3D_PCTRS(0)), |
|---|
| 61 | + VC4_REG32(V3D_PCTR(1)), |
|---|
| 62 | + VC4_REG32(V3D_PCTRS(1)), |
|---|
| 63 | + VC4_REG32(V3D_PCTR(2)), |
|---|
| 64 | + VC4_REG32(V3D_PCTRS(2)), |
|---|
| 65 | + VC4_REG32(V3D_PCTR(3)), |
|---|
| 66 | + VC4_REG32(V3D_PCTRS(3)), |
|---|
| 67 | + VC4_REG32(V3D_PCTR(4)), |
|---|
| 68 | + VC4_REG32(V3D_PCTRS(4)), |
|---|
| 69 | + VC4_REG32(V3D_PCTR(5)), |
|---|
| 70 | + VC4_REG32(V3D_PCTRS(5)), |
|---|
| 71 | + VC4_REG32(V3D_PCTR(6)), |
|---|
| 72 | + VC4_REG32(V3D_PCTRS(6)), |
|---|
| 73 | + VC4_REG32(V3D_PCTR(7)), |
|---|
| 74 | + VC4_REG32(V3D_PCTRS(7)), |
|---|
| 75 | + VC4_REG32(V3D_PCTR(8)), |
|---|
| 76 | + VC4_REG32(V3D_PCTRS(8)), |
|---|
| 77 | + VC4_REG32(V3D_PCTR(9)), |
|---|
| 78 | + VC4_REG32(V3D_PCTRS(9)), |
|---|
| 79 | + VC4_REG32(V3D_PCTR(10)), |
|---|
| 80 | + VC4_REG32(V3D_PCTRS(10)), |
|---|
| 81 | + VC4_REG32(V3D_PCTR(11)), |
|---|
| 82 | + VC4_REG32(V3D_PCTRS(11)), |
|---|
| 83 | + VC4_REG32(V3D_PCTR(12)), |
|---|
| 84 | + VC4_REG32(V3D_PCTRS(12)), |
|---|
| 85 | + VC4_REG32(V3D_PCTR(13)), |
|---|
| 86 | + VC4_REG32(V3D_PCTRS(13)), |
|---|
| 87 | + VC4_REG32(V3D_PCTR(14)), |
|---|
| 88 | + VC4_REG32(V3D_PCTRS(14)), |
|---|
| 89 | + VC4_REG32(V3D_PCTR(15)), |
|---|
| 90 | + VC4_REG32(V3D_PCTRS(15)), |
|---|
| 91 | + VC4_REG32(V3D_DBGE), |
|---|
| 92 | + VC4_REG32(V3D_FDBGO), |
|---|
| 93 | + VC4_REG32(V3D_FDBGB), |
|---|
| 94 | + VC4_REG32(V3D_FDBGR), |
|---|
| 95 | + VC4_REG32(V3D_FDBGS), |
|---|
| 96 | + VC4_REG32(V3D_ERRSTAT), |
|---|
| 109 | 97 | }; |
|---|
| 110 | 98 | |
|---|
| 111 | | -int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused) |
|---|
| 99 | +static int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused) |
|---|
| 112 | 100 | { |
|---|
| 113 | 101 | struct drm_info_node *node = (struct drm_info_node *)m->private; |
|---|
| 114 | 102 | struct drm_device *dev = node->minor->dev; |
|---|
| 115 | 103 | struct vc4_dev *vc4 = to_vc4_dev(dev); |
|---|
| 116 | | - int i; |
|---|
| 104 | + int ret = vc4_v3d_pm_get(vc4); |
|---|
| 117 | 105 | |
|---|
| 118 | | - for (i = 0; i < ARRAY_SIZE(vc4_reg_defs); i++) { |
|---|
| 119 | | - seq_printf(m, "%s (0x%04x): 0x%08x\n", |
|---|
| 120 | | - vc4_reg_defs[i].name, vc4_reg_defs[i].reg, |
|---|
| 121 | | - V3D_READ(vc4_reg_defs[i].reg)); |
|---|
| 106 | + if (ret == 0) { |
|---|
| 107 | + uint32_t ident1 = V3D_READ(V3D_IDENT1); |
|---|
| 108 | + uint32_t nslc = VC4_GET_FIELD(ident1, V3D_IDENT1_NSLC); |
|---|
| 109 | + uint32_t tups = VC4_GET_FIELD(ident1, V3D_IDENT1_TUPS); |
|---|
| 110 | + uint32_t qups = VC4_GET_FIELD(ident1, V3D_IDENT1_QUPS); |
|---|
| 111 | + |
|---|
| 112 | + seq_printf(m, "Revision: %d\n", |
|---|
| 113 | + VC4_GET_FIELD(ident1, V3D_IDENT1_REV)); |
|---|
| 114 | + seq_printf(m, "Slices: %d\n", nslc); |
|---|
| 115 | + seq_printf(m, "TMUs: %d\n", nslc * tups); |
|---|
| 116 | + seq_printf(m, "QPUs: %d\n", nslc * qups); |
|---|
| 117 | + seq_printf(m, "Semaphores: %d\n", |
|---|
| 118 | + VC4_GET_FIELD(ident1, V3D_IDENT1_NSEM)); |
|---|
| 119 | + vc4_v3d_pm_put(vc4); |
|---|
| 122 | 120 | } |
|---|
| 123 | 121 | |
|---|
| 124 | 122 | return 0; |
|---|
| 125 | 123 | } |
|---|
| 126 | 124 | |
|---|
| 127 | | -int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused) |
|---|
| 125 | +/** |
|---|
| 126 | + * Wraps pm_runtime_get_sync() in a refcount, so that we can reliably |
|---|
| 127 | + * get the pm_runtime refcount to 0 in vc4_reset(). |
|---|
| 128 | + */ |
|---|
| 129 | +int |
|---|
| 130 | +vc4_v3d_pm_get(struct vc4_dev *vc4) |
|---|
| 128 | 131 | { |
|---|
| 129 | | - struct drm_info_node *node = (struct drm_info_node *)m->private; |
|---|
| 130 | | - struct drm_device *dev = node->minor->dev; |
|---|
| 131 | | - struct vc4_dev *vc4 = to_vc4_dev(dev); |
|---|
| 132 | | - uint32_t ident1 = V3D_READ(V3D_IDENT1); |
|---|
| 133 | | - uint32_t nslc = VC4_GET_FIELD(ident1, V3D_IDENT1_NSLC); |
|---|
| 134 | | - uint32_t tups = VC4_GET_FIELD(ident1, V3D_IDENT1_TUPS); |
|---|
| 135 | | - uint32_t qups = VC4_GET_FIELD(ident1, V3D_IDENT1_QUPS); |
|---|
| 132 | + mutex_lock(&vc4->power_lock); |
|---|
| 133 | + if (vc4->power_refcount++ == 0) { |
|---|
| 134 | + int ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); |
|---|
| 136 | 135 | |
|---|
| 137 | | - seq_printf(m, "Revision: %d\n", |
|---|
| 138 | | - VC4_GET_FIELD(ident1, V3D_IDENT1_REV)); |
|---|
| 139 | | - seq_printf(m, "Slices: %d\n", nslc); |
|---|
| 140 | | - seq_printf(m, "TMUs: %d\n", nslc * tups); |
|---|
| 141 | | - seq_printf(m, "QPUs: %d\n", nslc * qups); |
|---|
| 142 | | - seq_printf(m, "Semaphores: %d\n", |
|---|
| 143 | | - VC4_GET_FIELD(ident1, V3D_IDENT1_NSEM)); |
|---|
| 136 | + if (ret < 0) { |
|---|
| 137 | + vc4->power_refcount--; |
|---|
| 138 | + mutex_unlock(&vc4->power_lock); |
|---|
| 139 | + return ret; |
|---|
| 140 | + } |
|---|
| 141 | + } |
|---|
| 142 | + mutex_unlock(&vc4->power_lock); |
|---|
| 144 | 143 | |
|---|
| 145 | 144 | return 0; |
|---|
| 146 | 145 | } |
|---|
| 147 | | -#endif /* CONFIG_DEBUG_FS */ |
|---|
| 146 | + |
|---|
| 147 | +void |
|---|
| 148 | +vc4_v3d_pm_put(struct vc4_dev *vc4) |
|---|
| 149 | +{ |
|---|
| 150 | + mutex_lock(&vc4->power_lock); |
|---|
| 151 | + if (--vc4->power_refcount == 0) { |
|---|
| 152 | + pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); |
|---|
| 153 | + pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); |
|---|
| 154 | + } |
|---|
| 155 | + mutex_unlock(&vc4->power_lock); |
|---|
| 156 | +} |
|---|
| 148 | 157 | |
|---|
| 149 | 158 | static void vc4_v3d_init_hw(struct drm_device *dev) |
|---|
| 150 | 159 | { |
|---|
| .. | .. |
|---|
| 159 | 168 | |
|---|
| 160 | 169 | int vc4_v3d_get_bin_slot(struct vc4_dev *vc4) |
|---|
| 161 | 170 | { |
|---|
| 162 | | - struct drm_device *dev = vc4->dev; |
|---|
| 171 | + struct drm_device *dev = &vc4->base; |
|---|
| 163 | 172 | unsigned long irqflags; |
|---|
| 164 | 173 | int slot; |
|---|
| 165 | 174 | uint64_t seqno = 0; |
|---|
| .. | .. |
|---|
| 197 | 206 | } |
|---|
| 198 | 207 | |
|---|
| 199 | 208 | /** |
|---|
| 200 | | - * vc4_allocate_bin_bo() - allocates the memory that will be used for |
|---|
| 209 | + * bin_bo_alloc() - allocates the memory that will be used for |
|---|
| 201 | 210 | * tile binning. |
|---|
| 202 | 211 | * |
|---|
| 203 | 212 | * The binner has a limitation that the addresses in the tile state |
|---|
| .. | .. |
|---|
| 218 | 227 | * overall CMA pool before they make scenes complicated enough to run |
|---|
| 219 | 228 | * out of bin space. |
|---|
| 220 | 229 | */ |
|---|
| 221 | | -static int vc4_allocate_bin_bo(struct drm_device *drm) |
|---|
| 230 | +static int bin_bo_alloc(struct vc4_dev *vc4) |
|---|
| 222 | 231 | { |
|---|
| 223 | | - struct vc4_dev *vc4 = to_vc4_dev(drm); |
|---|
| 224 | 232 | struct vc4_v3d *v3d = vc4->v3d; |
|---|
| 225 | 233 | uint32_t size = 16 * 1024 * 1024; |
|---|
| 226 | 234 | int ret = 0; |
|---|
| 227 | 235 | struct list_head list; |
|---|
| 236 | + |
|---|
| 237 | + if (!v3d) |
|---|
| 238 | + return -ENODEV; |
|---|
| 228 | 239 | |
|---|
| 229 | 240 | /* We may need to try allocating more than once to get a BO |
|---|
| 230 | 241 | * that doesn't cross 256MB. Track the ones we've allocated |
|---|
| .. | .. |
|---|
| 235 | 246 | INIT_LIST_HEAD(&list); |
|---|
| 236 | 247 | |
|---|
| 237 | 248 | while (true) { |
|---|
| 238 | | - struct vc4_bo *bo = vc4_bo_create(drm, size, true, |
|---|
| 249 | + struct vc4_bo *bo = vc4_bo_create(&vc4->base, size, true, |
|---|
| 239 | 250 | VC4_BO_TYPE_BIN); |
|---|
| 240 | 251 | |
|---|
| 241 | 252 | if (IS_ERR(bo)) { |
|---|
| .. | .. |
|---|
| 276 | 287 | WARN_ON_ONCE(sizeof(vc4->bin_alloc_used) * 8 != |
|---|
| 277 | 288 | bo->base.base.size / vc4->bin_alloc_size); |
|---|
| 278 | 289 | |
|---|
| 290 | + kref_init(&vc4->bin_bo_kref); |
|---|
| 291 | + |
|---|
| 292 | + /* Enable the out-of-memory interrupt to set our |
|---|
| 293 | + * newly-allocated binner BO, potentially from an |
|---|
| 294 | + * already-pending-but-masked interrupt. |
|---|
| 295 | + */ |
|---|
| 296 | + V3D_WRITE(V3D_INTENA, V3D_INT_OUTOMEM); |
|---|
| 297 | + |
|---|
| 279 | 298 | break; |
|---|
| 280 | 299 | } |
|---|
| 281 | 300 | |
|---|
| .. | .. |
|---|
| 289 | 308 | struct vc4_bo, unref_head); |
|---|
| 290 | 309 | |
|---|
| 291 | 310 | list_del(&bo->unref_head); |
|---|
| 292 | | - drm_gem_object_put_unlocked(&bo->base.base); |
|---|
| 311 | + drm_gem_object_put(&bo->base.base); |
|---|
| 293 | 312 | } |
|---|
| 294 | 313 | |
|---|
| 295 | 314 | return ret; |
|---|
| 315 | +} |
|---|
| 316 | + |
|---|
| 317 | +int vc4_v3d_bin_bo_get(struct vc4_dev *vc4, bool *used) |
|---|
| 318 | +{ |
|---|
| 319 | + int ret = 0; |
|---|
| 320 | + |
|---|
| 321 | + mutex_lock(&vc4->bin_bo_lock); |
|---|
| 322 | + |
|---|
| 323 | + if (used && *used) |
|---|
| 324 | + goto complete; |
|---|
| 325 | + |
|---|
| 326 | + if (vc4->bin_bo) |
|---|
| 327 | + kref_get(&vc4->bin_bo_kref); |
|---|
| 328 | + else |
|---|
| 329 | + ret = bin_bo_alloc(vc4); |
|---|
| 330 | + |
|---|
| 331 | + if (ret == 0 && used) |
|---|
| 332 | + *used = true; |
|---|
| 333 | + |
|---|
| 334 | +complete: |
|---|
| 335 | + mutex_unlock(&vc4->bin_bo_lock); |
|---|
| 336 | + |
|---|
| 337 | + return ret; |
|---|
| 338 | +} |
|---|
| 339 | + |
|---|
| 340 | +static void bin_bo_release(struct kref *ref) |
|---|
| 341 | +{ |
|---|
| 342 | + struct vc4_dev *vc4 = container_of(ref, struct vc4_dev, bin_bo_kref); |
|---|
| 343 | + |
|---|
| 344 | + if (WARN_ON_ONCE(!vc4->bin_bo)) |
|---|
| 345 | + return; |
|---|
| 346 | + |
|---|
| 347 | + drm_gem_object_put(&vc4->bin_bo->base.base); |
|---|
| 348 | + vc4->bin_bo = NULL; |
|---|
| 349 | +} |
|---|
| 350 | + |
|---|
| 351 | +void vc4_v3d_bin_bo_put(struct vc4_dev *vc4) |
|---|
| 352 | +{ |
|---|
| 353 | + mutex_lock(&vc4->bin_bo_lock); |
|---|
| 354 | + kref_put(&vc4->bin_bo_kref, bin_bo_release); |
|---|
| 355 | + mutex_unlock(&vc4->bin_bo_lock); |
|---|
| 296 | 356 | } |
|---|
| 297 | 357 | |
|---|
| 298 | 358 | #ifdef CONFIG_PM |
|---|
| .. | .. |
|---|
| 301 | 361 | struct vc4_v3d *v3d = dev_get_drvdata(dev); |
|---|
| 302 | 362 | struct vc4_dev *vc4 = v3d->vc4; |
|---|
| 303 | 363 | |
|---|
| 304 | | - vc4_irq_uninstall(vc4->dev); |
|---|
| 305 | | - |
|---|
| 306 | | - drm_gem_object_put_unlocked(&vc4->bin_bo->base.base); |
|---|
| 307 | | - vc4->bin_bo = NULL; |
|---|
| 364 | + vc4_irq_uninstall(&vc4->base); |
|---|
| 308 | 365 | |
|---|
| 309 | 366 | clk_disable_unprepare(v3d->clk); |
|---|
| 310 | 367 | |
|---|
| .. | .. |
|---|
| 317 | 374 | struct vc4_dev *vc4 = v3d->vc4; |
|---|
| 318 | 375 | int ret; |
|---|
| 319 | 376 | |
|---|
| 320 | | - ret = vc4_allocate_bin_bo(vc4->dev); |
|---|
| 321 | | - if (ret) |
|---|
| 322 | | - return ret; |
|---|
| 323 | | - |
|---|
| 324 | 377 | ret = clk_prepare_enable(v3d->clk); |
|---|
| 325 | 378 | if (ret != 0) |
|---|
| 326 | 379 | return ret; |
|---|
| 327 | 380 | |
|---|
| 328 | | - vc4_v3d_init_hw(vc4->dev); |
|---|
| 381 | + vc4_v3d_init_hw(&vc4->base); |
|---|
| 329 | 382 | |
|---|
| 330 | 383 | /* We disabled the IRQ as part of vc4_irq_uninstall in suspend. */ |
|---|
| 331 | | - enable_irq(vc4->dev->irq); |
|---|
| 332 | | - vc4_irq_postinstall(vc4->dev); |
|---|
| 384 | + enable_irq(vc4->base.irq); |
|---|
| 385 | + vc4_irq_postinstall(&vc4->base); |
|---|
| 333 | 386 | |
|---|
| 334 | 387 | return 0; |
|---|
| 335 | 388 | } |
|---|
| .. | .. |
|---|
| 354 | 407 | v3d->regs = vc4_ioremap_regs(pdev, 0); |
|---|
| 355 | 408 | if (IS_ERR(v3d->regs)) |
|---|
| 356 | 409 | return PTR_ERR(v3d->regs); |
|---|
| 410 | + v3d->regset.base = v3d->regs; |
|---|
| 411 | + v3d->regset.regs = v3d_regs; |
|---|
| 412 | + v3d->regset.nregs = ARRAY_SIZE(v3d_regs); |
|---|
| 357 | 413 | |
|---|
| 358 | 414 | vc4->v3d = v3d; |
|---|
| 359 | 415 | v3d->vc4 = vc4; |
|---|
| .. | .. |
|---|
| 384 | 440 | if (ret != 0) |
|---|
| 385 | 441 | return ret; |
|---|
| 386 | 442 | |
|---|
| 387 | | - ret = vc4_allocate_bin_bo(drm); |
|---|
| 388 | | - if (ret) { |
|---|
| 389 | | - clk_disable_unprepare(v3d->clk); |
|---|
| 390 | | - return ret; |
|---|
| 391 | | - } |
|---|
| 392 | | - |
|---|
| 393 | 443 | /* Reset the binner overflow address/size at setup, to be sure |
|---|
| 394 | 444 | * we don't reuse an old one. |
|---|
| 395 | 445 | */ |
|---|
| .. | .. |
|---|
| 408 | 458 | pm_runtime_use_autosuspend(dev); |
|---|
| 409 | 459 | pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */ |
|---|
| 410 | 460 | pm_runtime_enable(dev); |
|---|
| 461 | + |
|---|
| 462 | + vc4_debugfs_add_file(drm, "v3d_ident", vc4_v3d_debugfs_ident, NULL); |
|---|
| 463 | + vc4_debugfs_add_regset32(drm, "v3d_regs", &v3d->regset); |
|---|
| 411 | 464 | |
|---|
| 412 | 465 | return 0; |
|---|
| 413 | 466 | } |
|---|
| .. | .. |
|---|
| 452 | 505 | return 0; |
|---|
| 453 | 506 | } |
|---|
| 454 | 507 | |
|---|
| 455 | | -static const struct of_device_id vc4_v3d_dt_match[] = { |
|---|
| 508 | +const struct of_device_id vc4_v3d_dt_match[] = { |
|---|
| 456 | 509 | { .compatible = "brcm,bcm2835-v3d" }, |
|---|
| 457 | 510 | { .compatible = "brcm,cygnus-v3d" }, |
|---|
| 458 | 511 | { .compatible = "brcm,vc4-v3d" }, |
|---|