xref: /openbmc/linux/drivers/gpu/ipu-v3/ipu-dmfc.c (revision d7a3d85e)
1 /*
2  * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
3  * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; either version 2 of the License, or (at your
8  * option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  */
15 #include <linux/export.h>
16 #include <linux/types.h>
17 #include <linux/errno.h>
18 #include <linux/io.h>
19 
20 #include <video/imx-ipu-v3.h>
21 #include "ipu-prv.h"
22 
23 #define DMFC_RD_CHAN		0x0000
24 #define DMFC_WR_CHAN		0x0004
25 #define DMFC_WR_CHAN_DEF	0x0008
26 #define DMFC_DP_CHAN		0x000c
27 #define DMFC_DP_CHAN_DEF	0x0010
28 #define DMFC_GENERAL1		0x0014
29 #define DMFC_GENERAL2		0x0018
30 #define DMFC_IC_CTRL		0x001c
31 #define DMFC_WR_CHAN_ALT	0x0020
32 #define DMFC_WR_CHAN_DEF_ALT	0x0024
33 #define DMFC_DP_CHAN_ALT	0x0028
34 #define DMFC_DP_CHAN_DEF_ALT	0x002c
35 #define DMFC_GENERAL1_ALT	0x0030
36 #define DMFC_STAT		0x0034
37 
38 #define DMFC_WR_CHAN_1_28		0
39 #define DMFC_WR_CHAN_2_41		8
40 #define DMFC_WR_CHAN_1C_42		16
41 #define DMFC_WR_CHAN_2C_43		24
42 
43 #define DMFC_DP_CHAN_5B_23		0
44 #define DMFC_DP_CHAN_5F_27		8
45 #define DMFC_DP_CHAN_6B_24		16
46 #define DMFC_DP_CHAN_6F_29		24
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 
59 struct dmfc_channel_data {
60 	int		ipu_channel;
61 	unsigned long	channel_reg;
62 	unsigned long	shift;
63 	unsigned	eot_shift;
64 	unsigned	max_fifo_lines;
65 };
66 
67 static const struct dmfc_channel_data dmfcdata[] = {
68 	{
69 		.ipu_channel	= IPUV3_CHANNEL_MEM_BG_SYNC,
70 		.channel_reg	= DMFC_DP_CHAN,
71 		.shift		= DMFC_DP_CHAN_5B_23,
72 		.eot_shift	= 20,
73 		.max_fifo_lines	= 3,
74 	}, {
75 		.ipu_channel	= 24,
76 		.channel_reg	= DMFC_DP_CHAN,
77 		.shift		= DMFC_DP_CHAN_6B_24,
78 		.eot_shift	= 22,
79 		.max_fifo_lines	= 1,
80 	}, {
81 		.ipu_channel	= IPUV3_CHANNEL_MEM_FG_SYNC,
82 		.channel_reg	= DMFC_DP_CHAN,
83 		.shift		= DMFC_DP_CHAN_5F_27,
84 		.eot_shift	= 21,
85 		.max_fifo_lines	= 2,
86 	}, {
87 		.ipu_channel	= IPUV3_CHANNEL_MEM_DC_SYNC,
88 		.channel_reg	= DMFC_WR_CHAN,
89 		.shift		= DMFC_WR_CHAN_1_28,
90 		.eot_shift	= 16,
91 		.max_fifo_lines	= 2,
92 	}, {
93 		.ipu_channel	= 29,
94 		.channel_reg	= DMFC_DP_CHAN,
95 		.shift		= DMFC_DP_CHAN_6F_29,
96 		.eot_shift	= 23,
97 		.max_fifo_lines	= 1,
98 	},
99 };
100 
101 #define DMFC_NUM_CHANNELS	ARRAY_SIZE(dmfcdata)
102 
103 struct ipu_dmfc_priv;
104 
105 struct dmfc_channel {
106 	unsigned			slots;
107 	unsigned			slotmask;
108 	unsigned			segment;
109 	int				burstsize;
110 	struct ipu_soc			*ipu;
111 	struct ipu_dmfc_priv		*priv;
112 	const struct dmfc_channel_data	*data;
113 };
114 
115 struct ipu_dmfc_priv {
116 	struct ipu_soc *ipu;
117 	struct device *dev;
118 	struct dmfc_channel channels[DMFC_NUM_CHANNELS];
119 	struct mutex mutex;
120 	unsigned long bandwidth_per_slot;
121 	void __iomem *base;
122 	int use_count;
123 };
124 
125 int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
126 {
127 	struct ipu_dmfc_priv *priv = dmfc->priv;
128 	mutex_lock(&priv->mutex);
129 
130 	if (!priv->use_count)
131 		ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
132 
133 	priv->use_count++;
134 
135 	mutex_unlock(&priv->mutex);
136 
137 	return 0;
138 }
139 EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
140 
141 static void ipu_dmfc_wait_fifos(struct ipu_dmfc_priv *priv)
142 {
143 	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
144 
145 	while ((readl(priv->base + DMFC_STAT) & 0x02fff000) != 0x02fff000) {
146 		if (time_after(jiffies, timeout)) {
147 			dev_warn(priv->dev,
148 				 "Timeout waiting for DMFC FIFOs to clear\n");
149 			break;
150 		}
151 		cpu_relax();
152 	}
153 }
154 
155 void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
156 {
157 	struct ipu_dmfc_priv *priv = dmfc->priv;
158 
159 	mutex_lock(&priv->mutex);
160 
161 	priv->use_count--;
162 
163 	if (!priv->use_count) {
164 		ipu_dmfc_wait_fifos(priv);
165 		ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
166 	}
167 
168 	if (priv->use_count < 0)
169 		priv->use_count = 0;
170 
171 	mutex_unlock(&priv->mutex);
172 }
173 EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
174 
175 static 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 
234 static 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 
245 static 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 
266 void 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 	}
303 out:
304 	mutex_unlock(&priv->mutex);
305 }
306 EXPORT_SYMBOL_GPL(ipu_dmfc_free_bandwidth);
307 
308 int 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 
346 out:
347 	mutex_unlock(&priv->mutex);
348 
349 	return ret;
350 }
351 EXPORT_SYMBOL_GPL(ipu_dmfc_alloc_bandwidth);
352 
353 int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width)
354 {
355 	struct ipu_dmfc_priv *priv = dmfc->priv;
356 	u32 dmfc_gen1;
357 
358 	dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
359 
360 	if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
361 		dmfc_gen1 |= 1 << dmfc->data->eot_shift;
362 	else
363 		dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
364 
365 	writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
366 
367 	return 0;
368 }
369 EXPORT_SYMBOL_GPL(ipu_dmfc_init_channel);
370 
371 struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
372 {
373 	struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
374 	int i;
375 
376 	for (i = 0; i < DMFC_NUM_CHANNELS; i++)
377 		if (dmfcdata[i].ipu_channel == ipu_channel)
378 			return &priv->channels[i];
379 	return ERR_PTR(-ENODEV);
380 }
381 EXPORT_SYMBOL_GPL(ipu_dmfc_get);
382 
383 void ipu_dmfc_put(struct dmfc_channel *dmfc)
384 {
385 	ipu_dmfc_free_bandwidth(dmfc);
386 }
387 EXPORT_SYMBOL_GPL(ipu_dmfc_put);
388 
389 int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
390 		struct clk *ipu_clk)
391 {
392 	struct ipu_dmfc_priv *priv;
393 	int i;
394 
395 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
396 	if (!priv)
397 		return -ENOMEM;
398 
399 	priv->base = devm_ioremap(dev, base, PAGE_SIZE);
400 	if (!priv->base)
401 		return -ENOMEM;
402 
403 	priv->dev = dev;
404 	priv->ipu = ipu;
405 	mutex_init(&priv->mutex);
406 
407 	ipu->dmfc_priv = priv;
408 
409 	for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
410 		priv->channels[i].priv = priv;
411 		priv->channels[i].ipu = ipu;
412 		priv->channels[i].data = &dmfcdata[i];
413 	}
414 
415 	writel(0x0, priv->base + DMFC_WR_CHAN);
416 	writel(0x0, priv->base + DMFC_DP_CHAN);
417 
418 	/*
419 	 * We have a total bandwidth of clkrate * 4pixel divided
420 	 * into 8 slots.
421 	 */
422 	priv->bandwidth_per_slot = clk_get_rate(ipu_clk) * 4 / 8;
423 
424 	dev_dbg(dev, "dmfc: 8 slots with %ldMpixel/s bandwidth each\n",
425 			priv->bandwidth_per_slot / 1000000);
426 
427 	writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
428 	writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
429 	writel(0x00000003, priv->base + DMFC_GENERAL1);
430 
431 	return 0;
432 }
433 
434 void ipu_dmfc_exit(struct ipu_soc *ipu)
435 {
436 }
437