aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Ying <gnuiyl@gmail.com>2016-07-08 05:40:54 -0400
committerPhilipp Zabel <p.zabel@pengutronix.de>2016-07-12 12:23:43 -0400
commitd7868cb7ac58640e9c0383205ba31bd6a985cc6f (patch)
treea48b7c406b07eb765f39cb85e63c9a215e7cb1df
parent08a8901882709c6fb9e6158d57f59c1d16eb45cd (diff)
gpu: ipu-v3: ipu-dmfc: Use static DMFC FIFO allocation mechanism
For all video modes we support currently, we always get 2 slots for a plane by using the current existing dynamic DMFC FIFO allocation mechanism. So, let's change to use the static one to simplify the code. This also makes it easier to implement the atomic mode setting as we don't need to handle allocation failure cases then. Signed-off-by: Liu Ying <gnuiyl@gmail.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c26
-rw-r--r--drivers/gpu/ipu-v3/ipu-dmfc.c213
-rw-r--r--include/video/imx-ipu-v3.h3
3 files changed, 7 insertions, 235 deletions
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index cd7eb2658757..02701de370c7 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -53,24 +53,6 @@ int ipu_plane_irq(struct ipu_plane *ipu_plane)
53 IPU_IRQ_EOF); 53 IPU_IRQ_EOF);
54} 54}
55 55
56static int calc_vref(struct drm_display_mode *mode)
57{
58 unsigned long htotal, vtotal;
59
60 htotal = mode->htotal;
61 vtotal = mode->vtotal;
62
63 if (!htotal || !vtotal)
64 return 60;
65
66 return DIV_ROUND_UP(mode->clock * 1000, vtotal * htotal);
67}
68
69static inline int calc_bandwidth(int width, int height, unsigned int vref)
70{
71 return width * height * vref;
72}
73
74int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb, 56int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
75 int x, int y) 57 int x, int y)
76{ 58{
@@ -291,14 +273,6 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
291 } 273 }
292 } 274 }
293 275
294 ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc,
295 calc_bandwidth(crtc_w, crtc_h,
296 calc_vref(mode)), 64);
297 if (ret) {
298 dev_err(dev, "allocating dmfc bandwidth failed with %d\n", ret);
299 return ret;
300 }
301
302 ipu_dmfc_config_wait4eot(ipu_plane->dmfc, crtc_w); 276 ipu_dmfc_config_wait4eot(ipu_plane->dmfc, crtc_w);
303 277
304 ipu_cpmem_zero(ipu_plane->ipu_ch); 278 ipu_cpmem_zero(ipu_plane->ipu_ch);
diff --git a/drivers/gpu/ipu-v3/ipu-dmfc.c b/drivers/gpu/ipu-v3/ipu-dmfc.c
index 837b1ec22800..42705bb5aaa3 100644
--- a/drivers/gpu/ipu-v3/ipu-dmfc.c
+++ b/drivers/gpu/ipu-v3/ipu-dmfc.c
@@ -45,17 +45,6 @@
45#define DMFC_DP_CHAN_6B_24 16 45#define DMFC_DP_CHAN_6B_24 16
46#define DMFC_DP_CHAN_6F_29 24 46#define DMFC_DP_CHAN_6F_29 24
47 47
48#define DMFC_FIFO_SIZE_64 (3 << 3)
49#define DMFC_FIFO_SIZE_128 (2 << 3)
50#define DMFC_FIFO_SIZE_256 (1 << 3)
51#define DMFC_FIFO_SIZE_512 (0 << 3)
52
53#define DMFC_SEGMENT(x) ((x & 0x7) << 0)
54#define DMFC_BURSTSIZE_128 (0 << 6)
55#define DMFC_BURSTSIZE_64 (1 << 6)
56#define DMFC_BURSTSIZE_32 (2 << 6)
57#define DMFC_BURSTSIZE_16 (3 << 6)
58
59struct dmfc_channel_data { 48struct dmfc_channel_data {
60 int ipu_channel; 49 int ipu_channel;
61 unsigned long channel_reg; 50 unsigned long channel_reg;
@@ -104,9 +93,6 @@ struct ipu_dmfc_priv;
104 93
105struct dmfc_channel { 94struct dmfc_channel {
106 unsigned slots; 95 unsigned slots;
107 unsigned slotmask;
108 unsigned segment;
109 int burstsize;
110 struct ipu_soc *ipu; 96 struct ipu_soc *ipu;
111 struct ipu_dmfc_priv *priv; 97 struct ipu_dmfc_priv *priv;
112 const struct dmfc_channel_data *data; 98 const struct dmfc_channel_data *data;
@@ -117,7 +103,6 @@ struct ipu_dmfc_priv {
117 struct device *dev; 103 struct device *dev;
118 struct dmfc_channel channels[DMFC_NUM_CHANNELS]; 104 struct dmfc_channel channels[DMFC_NUM_CHANNELS];
119 struct mutex mutex; 105 struct mutex mutex;
120 unsigned long bandwidth_per_slot;
121 void __iomem *base; 106 void __iomem *base;
122 int use_count; 107 int use_count;
123}; 108};
@@ -172,184 +157,6 @@ void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
172} 157}
173EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel); 158EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
174 159
175static int ipu_dmfc_setup_channel(struct dmfc_channel *dmfc, int slots,
176 int segment, int burstsize)
177{
178 struct ipu_dmfc_priv *priv = dmfc->priv;
179 u32 val, field;
180
181 dev_dbg(priv->dev,
182 "dmfc: using %d slots starting from segment %d for IPU channel %d\n",
183 slots, segment, dmfc->data->ipu_channel);
184
185 switch (slots) {
186 case 1:
187 field = DMFC_FIFO_SIZE_64;
188 break;
189 case 2:
190 field = DMFC_FIFO_SIZE_128;
191 break;
192 case 4:
193 field = DMFC_FIFO_SIZE_256;
194 break;
195 case 8:
196 field = DMFC_FIFO_SIZE_512;
197 break;
198 default:
199 return -EINVAL;
200 }
201
202 switch (burstsize) {
203 case 16:
204 field |= DMFC_BURSTSIZE_16;
205 break;
206 case 32:
207 field |= DMFC_BURSTSIZE_32;
208 break;
209 case 64:
210 field |= DMFC_BURSTSIZE_64;
211 break;
212 case 128:
213 field |= DMFC_BURSTSIZE_128;
214 break;
215 }
216
217 field |= DMFC_SEGMENT(segment);
218
219 val = readl(priv->base + dmfc->data->channel_reg);
220
221 val &= ~(0xff << dmfc->data->shift);
222 val |= field << dmfc->data->shift;
223
224 writel(val, priv->base + dmfc->data->channel_reg);
225
226 dmfc->slots = slots;
227 dmfc->segment = segment;
228 dmfc->burstsize = burstsize;
229 dmfc->slotmask = ((1 << slots) - 1) << segment;
230
231 return 0;
232}
233
234static int dmfc_bandwidth_to_slots(struct ipu_dmfc_priv *priv,
235 unsigned long bandwidth)
236{
237 int slots = 1;
238
239 while (slots * priv->bandwidth_per_slot < bandwidth)
240 slots *= 2;
241
242 return slots;
243}
244
245static int dmfc_find_slots(struct ipu_dmfc_priv *priv, int slots)
246{
247 unsigned slotmask_need, slotmask_used = 0;
248 int i, segment = 0;
249
250 slotmask_need = (1 << slots) - 1;
251
252 for (i = 0; i < DMFC_NUM_CHANNELS; i++)
253 slotmask_used |= priv->channels[i].slotmask;
254
255 while (slotmask_need <= 0xff) {
256 if (!(slotmask_used & slotmask_need))
257 return segment;
258
259 slotmask_need <<= 1;
260 segment++;
261 }
262
263 return -EBUSY;
264}
265
266void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc)
267{
268 struct ipu_dmfc_priv *priv = dmfc->priv;
269 int i;
270
271 dev_dbg(priv->dev, "dmfc: freeing %d slots starting from segment %d\n",
272 dmfc->slots, dmfc->segment);
273
274 mutex_lock(&priv->mutex);
275
276 if (!dmfc->slots)
277 goto out;
278
279 dmfc->slotmask = 0;
280 dmfc->slots = 0;
281 dmfc->segment = 0;
282
283 for (i = 0; i < DMFC_NUM_CHANNELS; i++)
284 priv->channels[i].slotmask = 0;
285
286 for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
287 if (priv->channels[i].slots > 0) {
288 priv->channels[i].segment =
289 dmfc_find_slots(priv, priv->channels[i].slots);
290 priv->channels[i].slotmask =
291 ((1 << priv->channels[i].slots) - 1) <<
292 priv->channels[i].segment;
293 }
294 }
295
296 for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
297 if (priv->channels[i].slots > 0)
298 ipu_dmfc_setup_channel(&priv->channels[i],
299 priv->channels[i].slots,
300 priv->channels[i].segment,
301 priv->channels[i].burstsize);
302 }
303out:
304 mutex_unlock(&priv->mutex);
305}
306EXPORT_SYMBOL_GPL(ipu_dmfc_free_bandwidth);
307
308int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
309 unsigned long bandwidth_pixel_per_second, int burstsize)
310{
311 struct ipu_dmfc_priv *priv = dmfc->priv;
312 int slots = dmfc_bandwidth_to_slots(priv, bandwidth_pixel_per_second);
313 int segment = -1, ret = 0;
314
315 dev_dbg(priv->dev, "dmfc: trying to allocate %ldMpixel/s for IPU channel %d\n",
316 bandwidth_pixel_per_second / 1000000,
317 dmfc->data->ipu_channel);
318
319 ipu_dmfc_free_bandwidth(dmfc);
320
321 mutex_lock(&priv->mutex);
322
323 if (slots > 8) {
324 ret = -EBUSY;
325 goto out;
326 }
327
328 /* For the MEM_BG channel, first try to allocate twice the slots */
329 if (dmfc->data->ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC)
330 segment = dmfc_find_slots(priv, slots * 2);
331 else if (slots < 2)
332 /* Always allocate at least 128*4 bytes (2 slots) */
333 slots = 2;
334
335 if (segment >= 0)
336 slots *= 2;
337 else
338 segment = dmfc_find_slots(priv, slots);
339 if (segment < 0) {
340 ret = -EBUSY;
341 goto out;
342 }
343
344 ipu_dmfc_setup_channel(dmfc, slots, segment, burstsize);
345
346out:
347 mutex_unlock(&priv->mutex);
348
349 return ret;
350}
351EXPORT_SYMBOL_GPL(ipu_dmfc_alloc_bandwidth);
352
353void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width) 160void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width)
354{ 161{
355 struct ipu_dmfc_priv *priv = dmfc->priv; 162 struct ipu_dmfc_priv *priv = dmfc->priv;
@@ -384,7 +191,6 @@ EXPORT_SYMBOL_GPL(ipu_dmfc_get);
384 191
385void ipu_dmfc_put(struct dmfc_channel *dmfc) 192void ipu_dmfc_put(struct dmfc_channel *dmfc)
386{ 193{
387 ipu_dmfc_free_bandwidth(dmfc);
388} 194}
389EXPORT_SYMBOL_GPL(ipu_dmfc_put); 195EXPORT_SYMBOL_GPL(ipu_dmfc_put);
390 196
@@ -412,20 +218,15 @@ int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
412 priv->channels[i].priv = priv; 218 priv->channels[i].priv = priv;
413 priv->channels[i].ipu = ipu; 219 priv->channels[i].ipu = ipu;
414 priv->channels[i].data = &dmfcdata[i]; 220 priv->channels[i].data = &dmfcdata[i];
415 }
416
417 writel(0x0, priv->base + DMFC_WR_CHAN);
418 writel(0x0, priv->base + DMFC_DP_CHAN);
419 221
420 /* 222 if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC ||
421 * We have a total bandwidth of clkrate * 4pixel divided 223 dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC ||
422 * into 8 slots. 224 dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC)
423 */ 225 priv->channels[i].slots = 2;
424 priv->bandwidth_per_slot = clk_get_rate(ipu_clk) * 4 / 8; 226 }
425
426 dev_dbg(dev, "dmfc: 8 slots with %ldMpixel/s bandwidth each\n",
427 priv->bandwidth_per_slot / 1000000);
428 227
228 writel(0x00000050, priv->base + DMFC_WR_CHAN);
229 writel(0x00005654, priv->base + DMFC_DP_CHAN);
429 writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF); 230 writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
430 writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF); 231 writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
431 writel(0x00000003, priv->base + DMFC_GENERAL1); 232 writel(0x00000003, priv->base + DMFC_GENERAL1);
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 3a2a79401789..7adeaae06961 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -235,9 +235,6 @@ int ipu_di_init_sync_panel(struct ipu_di *, struct ipu_di_signal_cfg *sig);
235struct dmfc_channel; 235struct dmfc_channel;
236int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc); 236int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc);
237void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc); 237void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc);
238int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
239 unsigned long bandwidth_mbs, int burstsize);
240void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc);
241void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width); 238void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width);
242struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipuv3_channel); 239struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipuv3_channel);
243void ipu_dmfc_put(struct dmfc_channel *dmfc); 240void ipu_dmfc_put(struct dmfc_channel *dmfc);