plane.c (8632987380765dee716d460640aa58d58d52998e) plane.c (c6aeaf56f468a565f6d2f27325fc07d35cdcd3cb)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2017 NVIDIA CORPORATION. All rights reserved.
4 */
5
6#include <linux/iommu.h>
7#include <linux/interconnect.h>
8

--- 60 unchanged lines hidden (view full) ---

69 copy->peak_memory_bandwidth = state->peak_memory_bandwidth;
70 copy->avg_memory_bandwidth = state->avg_memory_bandwidth;
71
72 for (i = 0; i < 2; i++)
73 copy->blending[i] = state->blending[i];
74
75 for (i = 0; i < 3; i++) {
76 copy->iova[i] = DMA_MAPPING_ERROR;
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2017 NVIDIA CORPORATION. All rights reserved.
4 */
5
6#include <linux/iommu.h>
7#include <linux/interconnect.h>
8

--- 60 unchanged lines hidden (view full) ---

69 copy->peak_memory_bandwidth = state->peak_memory_bandwidth;
70 copy->avg_memory_bandwidth = state->avg_memory_bandwidth;
71
72 for (i = 0; i < 2; i++)
73 copy->blending[i] = state->blending[i];
74
75 for (i = 0; i < 3; i++) {
76 copy->iova[i] = DMA_MAPPING_ERROR;
77 copy->sgt[i] = NULL;
77 copy->map[i] = NULL;
78 }
79
80 return &copy->base;
81}
82
83static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
84 struct drm_plane_state *state)
85{

--- 47 unchanged lines hidden (view full) ---

133 .reset = tegra_plane_reset,
134 .atomic_duplicate_state = tegra_plane_atomic_duplicate_state,
135 .atomic_destroy_state = tegra_plane_atomic_destroy_state,
136 .format_mod_supported = tegra_plane_format_mod_supported,
137};
138
139static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state)
140{
78 }
79
80 return &copy->base;
81}
82
83static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
84 struct drm_plane_state *state)
85{

--- 47 unchanged lines hidden (view full) ---

133 .reset = tegra_plane_reset,
134 .atomic_duplicate_state = tegra_plane_atomic_duplicate_state,
135 .atomic_destroy_state = tegra_plane_atomic_destroy_state,
136 .format_mod_supported = tegra_plane_format_mod_supported,
137};
138
139static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state)
140{
141 struct iommu_domain *domain = iommu_get_domain_for_dev(dc->dev);
142 unsigned int i;
143 int err;
144
145 for (i = 0; i < state->base.fb->format->num_planes; i++) {
146 struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i);
141 unsigned int i;
142 int err;
143
144 for (i = 0; i < state->base.fb->format->num_planes; i++) {
145 struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i);
147 dma_addr_t phys_addr, *phys;
148 struct sg_table *sgt;
146 struct host1x_bo_mapping *map;
149
147
150 /*
151 * If we're not attached to a domain, we already stored the
152 * physical address when the buffer was allocated. If we're
153 * part of a group that's shared between all display
154 * controllers, we've also already mapped the framebuffer
155 * through the SMMU. In both cases we can short-circuit the
156 * code below and retrieve the stored IOV address.
157 */
158 if (!domain || dc->client.group)
159 phys = &phys_addr;
160 else
161 phys = NULL;
162
163 sgt = host1x_bo_pin(dc->dev, &bo->base, phys);
164 if (IS_ERR(sgt)) {
165 err = PTR_ERR(sgt);
148 map = host1x_bo_pin(dc->dev, &bo->base, DMA_TO_DEVICE);
149 if (IS_ERR(map)) {
150 err = PTR_ERR(map);
166 goto unpin;
167 }
168
151 goto unpin;
152 }
153
169 if (sgt) {
170 err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
171 if (err)
172 goto unpin;
173
154 if (!dc->client.group) {
174 /*
175 * The display controller needs contiguous memory, so
176 * fail if the buffer is discontiguous and we fail to
177 * map its SG table to a single contiguous chunk of
178 * I/O virtual memory.
179 */
155 /*
156 * The display controller needs contiguous memory, so
157 * fail if the buffer is discontiguous and we fail to
158 * map its SG table to a single contiguous chunk of
159 * I/O virtual memory.
160 */
180 if (sgt->nents > 1) {
161 if (map->chunks > 1) {
181 err = -EINVAL;
182 goto unpin;
183 }
184
162 err = -EINVAL;
163 goto unpin;
164 }
165
185 state->iova[i] = sg_dma_address(sgt->sgl);
186 state->sgt[i] = sgt;
166 state->iova[i] = map->phys;
187 } else {
167 } else {
188 state->iova[i] = phys_addr;
168 state->iova[i] = bo->iova;
189 }
169 }
170
171 state->map[i] = map;
190 }
191
192 return 0;
193
194unpin:
195 dev_err(dc->dev, "failed to map plane %u: %d\n", i, err);
196
197 while (i--) {
172 }
173
174 return 0;
175
176unpin:
177 dev_err(dc->dev, "failed to map plane %u: %d\n", i, err);
178
179 while (i--) {
198 struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i);
199 struct sg_table *sgt = state->sgt[i];
200
201 if (sgt)
202 dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
203
204 host1x_bo_unpin(dc->dev, &bo->base, sgt);
180 host1x_bo_unpin(state->map[i]);
205 state->iova[i] = DMA_MAPPING_ERROR;
181 state->iova[i] = DMA_MAPPING_ERROR;
206 state->sgt[i] = NULL;
182 state->map[i] = NULL;
207 }
208
209 return err;
210}
211
212static void tegra_dc_unpin(struct tegra_dc *dc, struct tegra_plane_state *state)
213{
214 unsigned int i;
215
216 for (i = 0; i < state->base.fb->format->num_planes; i++) {
183 }
184
185 return err;
186}
187
188static void tegra_dc_unpin(struct tegra_dc *dc, struct tegra_plane_state *state)
189{
190 unsigned int i;
191
192 for (i = 0; i < state->base.fb->format->num_planes; i++) {
217 struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i);
218 struct sg_table *sgt = state->sgt[i];
219
220 if (sgt)
221 dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
222
223 host1x_bo_unpin(dc->dev, &bo->base, sgt);
193 host1x_bo_unpin(state->map[i]);
224 state->iova[i] = DMA_MAPPING_ERROR;
194 state->iova[i] = DMA_MAPPING_ERROR;
225 state->sgt[i] = NULL;
195 state->map[i] = NULL;
226 }
227}
228
229int tegra_plane_prepare_fb(struct drm_plane *plane,
230 struct drm_plane_state *state)
231{
232 struct tegra_dc *dc = to_tegra_dc(state->crtc);
233

--- 532 unchanged lines hidden ---
196 }
197}
198
199int tegra_plane_prepare_fb(struct drm_plane *plane,
200 struct drm_plane_state *state)
201{
202 struct tegra_dc *dc = to_tegra_dc(state->crtc);
203

--- 532 unchanged lines hidden ---