aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/ipu-v3
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 /drivers/gpu/ipu-v3
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>
Diffstat (limited to 'drivers/gpu/ipu-v3')
-rw-r--r--drivers/gpu/ipu-v3/ipu-dmfc.c213
1 files changed, 7 insertions, 206 deletions
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);