Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ipu-dmfc.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010 Sascha Hauer <[email protected]>
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 "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_STAT 0x0020
32 
33 #define DMFC_WR_CHAN_1_28 0
34 #define DMFC_WR_CHAN_2_41 8
35 #define DMFC_WR_CHAN_1C_42 16
36 #define DMFC_WR_CHAN_2C_43 24
37 
38 #define DMFC_DP_CHAN_5B_23 0
39 #define DMFC_DP_CHAN_5F_27 8
40 #define DMFC_DP_CHAN_6B_24 16
41 #define DMFC_DP_CHAN_6F_29 24
42 
43 #define DMFC_FIFO_SIZE_64 (3 << 3)
44 #define DMFC_FIFO_SIZE_128 (2 << 3)
45 #define DMFC_FIFO_SIZE_256 (1 << 3)
46 #define DMFC_FIFO_SIZE_512 (0 << 3)
47 
48 #define DMFC_SEGMENT(x) ((x & 0x7) << 0)
49 #define DMFC_BURSTSIZE_128 (0 << 6)
50 #define DMFC_BURSTSIZE_64 (1 << 6)
51 #define DMFC_BURSTSIZE_32 (2 << 6)
52 #define DMFC_BURSTSIZE_16 (3 << 6)
53 
56  unsigned long channel_reg;
57  unsigned long shift;
58  unsigned eot_shift;
59  unsigned max_fifo_lines;
60 };
61 
62 static const struct dmfc_channel_data dmfcdata[] = {
63  {
64  .ipu_channel = 23,
65  .channel_reg = DMFC_DP_CHAN,
66  .shift = DMFC_DP_CHAN_5B_23,
67  .eot_shift = 20,
68  .max_fifo_lines = 3,
69  }, {
70  .ipu_channel = 24,
71  .channel_reg = DMFC_DP_CHAN,
72  .shift = DMFC_DP_CHAN_6B_24,
73  .eot_shift = 22,
74  .max_fifo_lines = 1,
75  }, {
76  .ipu_channel = 27,
77  .channel_reg = DMFC_DP_CHAN,
78  .shift = DMFC_DP_CHAN_5F_27,
79  .eot_shift = 21,
80  .max_fifo_lines = 2,
81  }, {
82  .ipu_channel = 28,
83  .channel_reg = DMFC_WR_CHAN,
84  .shift = DMFC_WR_CHAN_1_28,
85  .eot_shift = 16,
86  .max_fifo_lines = 2,
87  }, {
88  .ipu_channel = 29,
89  .channel_reg = DMFC_DP_CHAN,
90  .shift = DMFC_DP_CHAN_6F_29,
91  .eot_shift = 23,
92  .max_fifo_lines = 1,
93  },
94 };
95 
96 #define DMFC_NUM_CHANNELS ARRAY_SIZE(dmfcdata)
97 
98 struct ipu_dmfc_priv;
99 
100 struct dmfc_channel {
101  unsigned slots;
102  unsigned slotmask;
103  unsigned segment;
105  struct ipu_soc *ipu;
107  const struct dmfc_channel_data *data;
108 };
109 
111  struct ipu_soc *ipu;
112  struct device *dev;
114  struct mutex mutex;
115  unsigned long bandwidth_per_slot;
116  void __iomem *base;
118 };
119 
121 {
122  struct ipu_dmfc_priv *priv = dmfc->priv;
123  mutex_lock(&priv->mutex);
124 
125  if (!priv->use_count)
127 
128  priv->use_count++;
129 
130  mutex_unlock(&priv->mutex);
131 
132  return 0;
133 }
135 
137 {
138  struct ipu_dmfc_priv *priv = dmfc->priv;
139 
140  mutex_lock(&priv->mutex);
141 
142  priv->use_count--;
143 
144  if (!priv->use_count)
146 
147  if (priv->use_count < 0)
148  priv->use_count = 0;
149 
150  mutex_unlock(&priv->mutex);
151 }
153 
154 static int ipu_dmfc_setup_channel(struct dmfc_channel *dmfc, int slots,
155  int segment, int burstsize)
156 {
157  struct ipu_dmfc_priv *priv = dmfc->priv;
158  u32 val, field;
159 
160  dev_dbg(priv->dev,
161  "dmfc: using %d slots starting from segment %d for IPU channel %d\n",
162  slots, segment, dmfc->data->ipu_channel);
163 
164  if (!dmfc)
165  return -EINVAL;
166 
167  switch (slots) {
168  case 1:
169  field = DMFC_FIFO_SIZE_64;
170  break;
171  case 2:
172  field = DMFC_FIFO_SIZE_128;
173  break;
174  case 4:
175  field = DMFC_FIFO_SIZE_256;
176  break;
177  case 8:
178  field = DMFC_FIFO_SIZE_512;
179  break;
180  default:
181  return -EINVAL;
182  }
183 
184  switch (burstsize) {
185  case 16:
186  field |= DMFC_BURSTSIZE_16;
187  break;
188  case 32:
189  field |= DMFC_BURSTSIZE_32;
190  break;
191  case 64:
192  field |= DMFC_BURSTSIZE_64;
193  break;
194  case 128:
195  field |= DMFC_BURSTSIZE_128;
196  break;
197  }
198 
199  field |= DMFC_SEGMENT(segment);
200 
201  val = readl(priv->base + dmfc->data->channel_reg);
202 
203  val &= ~(0xff << dmfc->data->shift);
204  val |= field << dmfc->data->shift;
205 
206  writel(val, priv->base + dmfc->data->channel_reg);
207 
208  dmfc->slots = slots;
209  dmfc->segment = segment;
210  dmfc->burstsize = burstsize;
211  dmfc->slotmask = ((1 << slots) - 1) << segment;
212 
213  return 0;
214 }
215 
216 static int dmfc_bandwidth_to_slots(struct ipu_dmfc_priv *priv,
217  unsigned long bandwidth)
218 {
219  int slots = 1;
220 
221  while (slots * priv->bandwidth_per_slot < bandwidth)
222  slots *= 2;
223 
224  return slots;
225 }
226 
227 static int dmfc_find_slots(struct ipu_dmfc_priv *priv, int slots)
228 {
229  unsigned slotmask_need, slotmask_used = 0;
230  int i, segment = 0;
231 
232  slotmask_need = (1 << slots) - 1;
233 
234  for (i = 0; i < DMFC_NUM_CHANNELS; i++)
235  slotmask_used |= priv->channels[i].slotmask;
236 
237  while (slotmask_need <= 0xff) {
238  if (!(slotmask_used & slotmask_need))
239  return segment;
240 
241  slotmask_need <<= 1;
242  segment++;
243  }
244 
245  return -EBUSY;
246 }
247 
249 {
250  struct ipu_dmfc_priv *priv = dmfc->priv;
251  int i;
252 
253  dev_dbg(priv->dev, "dmfc: freeing %d slots starting from segment %d\n",
254  dmfc->slots, dmfc->segment);
255 
256  mutex_lock(&priv->mutex);
257 
258  if (!dmfc->slots)
259  goto out;
260 
261  dmfc->slotmask = 0;
262  dmfc->slots = 0;
263  dmfc->segment = 0;
264 
265  for (i = 0; i < DMFC_NUM_CHANNELS; i++)
266  priv->channels[i].slotmask = 0;
267 
268  for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
269  if (priv->channels[i].slots > 0) {
270  priv->channels[i].segment =
271  dmfc_find_slots(priv, priv->channels[i].slots);
272  priv->channels[i].slotmask =
273  ((1 << priv->channels[i].slots) - 1) <<
274  priv->channels[i].segment;
275  }
276  }
277 
278  for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
279  if (priv->channels[i].slots > 0)
280  ipu_dmfc_setup_channel(&priv->channels[i],
281  priv->channels[i].slots,
282  priv->channels[i].segment,
283  priv->channels[i].burstsize);
284  }
285 out:
286  mutex_unlock(&priv->mutex);
287 }
289 
291  unsigned long bandwidth_pixel_per_second, int burstsize)
292 {
293  struct ipu_dmfc_priv *priv = dmfc->priv;
294  int slots = dmfc_bandwidth_to_slots(priv, bandwidth_pixel_per_second);
295  int segment = 0, ret = 0;
296 
297  dev_dbg(priv->dev, "dmfc: trying to allocate %ldMpixel/s for IPU channel %d\n",
298  bandwidth_pixel_per_second / 1000000,
299  dmfc->data->ipu_channel);
300 
302 
303  mutex_lock(&priv->mutex);
304 
305  if (slots > 8) {
306  ret = -EBUSY;
307  goto out;
308  }
309 
310  segment = dmfc_find_slots(priv, slots);
311  if (segment < 0) {
312  ret = -EBUSY;
313  goto out;
314  }
315 
316  ipu_dmfc_setup_channel(dmfc, slots, segment, burstsize);
317 
318 out:
319  mutex_unlock(&priv->mutex);
320 
321  return ret;
322 }
324 
326 {
327  struct ipu_dmfc_priv *priv = dmfc->priv;
328  u32 dmfc_gen1;
329 
330  dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
331 
332  if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
333  dmfc_gen1 |= 1 << dmfc->data->eot_shift;
334  else
335  dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
336 
337  writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
338 
339  return 0;
340 }
342 
344 {
345  struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
346  int i;
347 
348  for (i = 0; i < DMFC_NUM_CHANNELS; i++)
349  if (dmfcdata[i].ipu_channel == ipu_channel)
350  return &priv->channels[i];
351  return ERR_PTR(-ENODEV);
352 }
354 
355 void ipu_dmfc_put(struct dmfc_channel *dmfc)
356 {
358 }
360 
361 int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
362  struct clk *ipu_clk)
363 {
364  struct ipu_dmfc_priv *priv;
365  int i;
366 
367  priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
368  if (!priv)
369  return -ENOMEM;
370 
371  priv->base = devm_ioremap(dev, base, PAGE_SIZE);
372  if (!priv->base)
373  return -ENOMEM;
374 
375  priv->dev = dev;
376  priv->ipu = ipu;
377  mutex_init(&priv->mutex);
378 
379  ipu->dmfc_priv = priv;
380 
381  for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
382  priv->channels[i].priv = priv;
383  priv->channels[i].ipu = ipu;
384  priv->channels[i].data = &dmfcdata[i];
385  }
386 
387  writel(0x0, priv->base + DMFC_WR_CHAN);
388  writel(0x0, priv->base + DMFC_DP_CHAN);
389 
390  /*
391  * We have a total bandwidth of clkrate * 4pixel divided
392  * into 8 slots.
393  */
394  priv->bandwidth_per_slot = clk_get_rate(ipu_clk) / 8;
395 
396  dev_dbg(dev, "dmfc: 8 slots with %ldMpixel/s bandwidth each\n",
397  priv->bandwidth_per_slot / 1000000);
398 
399  writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
400  writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
401  writel(0x00000003, priv->base + DMFC_GENERAL1);
402 
403  return 0;
404 }
405 
406 void ipu_dmfc_exit(struct ipu_soc *ipu)
407 {
408 }