Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Liu Ying and committed by
Philipp Zabel
d7868cb7 08a89018

+7 -235
-26
drivers/gpu/drm/imx/ipuv3-plane.c
··· 53 53 IPU_IRQ_EOF); 54 54 } 55 55 56 - static 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 - 69 - static inline int calc_bandwidth(int width, int height, unsigned int vref) 70 - { 71 - return width * height * vref; 72 - } 73 - 74 56 int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb, 75 57 int x, int y) 76 58 { ··· 271 289 default: 272 290 break; 273 291 } 274 - } 275 - 276 - ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc, 277 - calc_bandwidth(crtc_w, crtc_h, 278 - calc_vref(mode)), 64); 279 - if (ret) { 280 - dev_err(dev, "allocating dmfc bandwidth failed with %d\n", ret); 281 - return ret; 282 292 } 283 293 284 294 ipu_dmfc_config_wait4eot(ipu_plane->dmfc, crtc_w);
+7 -206
drivers/gpu/ipu-v3/ipu-dmfc.c
··· 45 45 #define DMFC_DP_CHAN_6B_24 16 46 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 - 59 48 struct dmfc_channel_data { 60 49 int ipu_channel; 61 50 unsigned long channel_reg; ··· 93 104 94 105 struct dmfc_channel { 95 106 unsigned slots; 96 - unsigned slotmask; 97 - unsigned segment; 98 - int burstsize; 99 107 struct ipu_soc *ipu; 100 108 struct ipu_dmfc_priv *priv; 101 109 const struct dmfc_channel_data *data; ··· 103 117 struct device *dev; 104 118 struct dmfc_channel channels[DMFC_NUM_CHANNELS]; 105 119 struct mutex mutex; 106 - unsigned long bandwidth_per_slot; 107 120 void __iomem *base; 108 121 int use_count; 109 122 }; ··· 157 172 } 158 173 EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel); 159 174 160 - static int ipu_dmfc_setup_channel(struct dmfc_channel *dmfc, int slots, 161 - int segment, int burstsize) 162 - { 163 - struct ipu_dmfc_priv *priv = dmfc->priv; 164 - u32 val, field; 165 - 166 - dev_dbg(priv->dev, 167 - "dmfc: using %d slots starting from segment %d for IPU channel %d\n", 168 - slots, segment, dmfc->data->ipu_channel); 169 - 170 - switch (slots) { 171 - case 1: 172 - field = DMFC_FIFO_SIZE_64; 173 - break; 174 - case 2: 175 - field = DMFC_FIFO_SIZE_128; 176 - break; 177 - case 4: 178 - field = DMFC_FIFO_SIZE_256; 179 - break; 180 - case 8: 181 - field = DMFC_FIFO_SIZE_512; 182 - break; 183 - default: 184 - return -EINVAL; 185 - } 186 - 187 - switch (burstsize) { 188 - case 16: 189 - field |= DMFC_BURSTSIZE_16; 190 - break; 191 - case 32: 192 - field |= DMFC_BURSTSIZE_32; 193 - break; 194 - case 64: 195 - field |= DMFC_BURSTSIZE_64; 196 - break; 197 - case 128: 198 - field |= DMFC_BURSTSIZE_128; 199 - break; 200 - } 201 - 202 - field |= DMFC_SEGMENT(segment); 203 - 204 - val = readl(priv->base + dmfc->data->channel_reg); 205 - 206 - val &= ~(0xff << dmfc->data->shift); 207 - val |= field << dmfc->data->shift; 208 - 209 - writel(val, priv->base + dmfc->data->channel_reg); 210 - 211 - dmfc->slots = slots; 212 - dmfc->segment = segment; 213 - dmfc->burstsize = burstsize; 214 - dmfc->slotmask = ((1 << slots) - 1) << segment; 215 - 216 - return 0; 217 - } 218 - 219 - static int dmfc_bandwidth_to_slots(struct ipu_dmfc_priv *priv, 220 - unsigned long bandwidth) 221 - { 222 - int slots = 1; 223 - 224 - while (slots * priv->bandwidth_per_slot < bandwidth) 225 - slots *= 2; 226 - 227 - return slots; 228 - } 229 - 230 - static int dmfc_find_slots(struct ipu_dmfc_priv *priv, int slots) 231 - { 232 - unsigned slotmask_need, slotmask_used = 0; 233 - int i, segment = 0; 234 - 235 - slotmask_need = (1 << slots) - 1; 236 - 237 - for (i = 0; i < DMFC_NUM_CHANNELS; i++) 238 - slotmask_used |= priv->channels[i].slotmask; 239 - 240 - while (slotmask_need <= 0xff) { 241 - if (!(slotmask_used & slotmask_need)) 242 - return segment; 243 - 244 - slotmask_need <<= 1; 245 - segment++; 246 - } 247 - 248 - return -EBUSY; 249 - } 250 - 251 - void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc) 252 - { 253 - struct ipu_dmfc_priv *priv = dmfc->priv; 254 - int i; 255 - 256 - dev_dbg(priv->dev, "dmfc: freeing %d slots starting from segment %d\n", 257 - dmfc->slots, dmfc->segment); 258 - 259 - mutex_lock(&priv->mutex); 260 - 261 - if (!dmfc->slots) 262 - goto out; 263 - 264 - dmfc->slotmask = 0; 265 - dmfc->slots = 0; 266 - dmfc->segment = 0; 267 - 268 - for (i = 0; i < DMFC_NUM_CHANNELS; i++) 269 - priv->channels[i].slotmask = 0; 270 - 271 - for (i = 0; i < DMFC_NUM_CHANNELS; i++) { 272 - if (priv->channels[i].slots > 0) { 273 - priv->channels[i].segment = 274 - dmfc_find_slots(priv, priv->channels[i].slots); 275 - priv->channels[i].slotmask = 276 - ((1 << priv->channels[i].slots) - 1) << 277 - priv->channels[i].segment; 278 - } 279 - } 280 - 281 - for (i = 0; i < DMFC_NUM_CHANNELS; i++) { 282 - if (priv->channels[i].slots > 0) 283 - ipu_dmfc_setup_channel(&priv->channels[i], 284 - priv->channels[i].slots, 285 - priv->channels[i].segment, 286 - priv->channels[i].burstsize); 287 - } 288 - out: 289 - mutex_unlock(&priv->mutex); 290 - } 291 - EXPORT_SYMBOL_GPL(ipu_dmfc_free_bandwidth); 292 - 293 - int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc, 294 - unsigned long bandwidth_pixel_per_second, int burstsize) 295 - { 296 - struct ipu_dmfc_priv *priv = dmfc->priv; 297 - int slots = dmfc_bandwidth_to_slots(priv, bandwidth_pixel_per_second); 298 - int segment = -1, ret = 0; 299 - 300 - dev_dbg(priv->dev, "dmfc: trying to allocate %ldMpixel/s for IPU channel %d\n", 301 - bandwidth_pixel_per_second / 1000000, 302 - dmfc->data->ipu_channel); 303 - 304 - ipu_dmfc_free_bandwidth(dmfc); 305 - 306 - mutex_lock(&priv->mutex); 307 - 308 - if (slots > 8) { 309 - ret = -EBUSY; 310 - goto out; 311 - } 312 - 313 - /* For the MEM_BG channel, first try to allocate twice the slots */ 314 - if (dmfc->data->ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC) 315 - segment = dmfc_find_slots(priv, slots * 2); 316 - else if (slots < 2) 317 - /* Always allocate at least 128*4 bytes (2 slots) */ 318 - slots = 2; 319 - 320 - if (segment >= 0) 321 - slots *= 2; 322 - else 323 - segment = dmfc_find_slots(priv, slots); 324 - if (segment < 0) { 325 - ret = -EBUSY; 326 - goto out; 327 - } 328 - 329 - ipu_dmfc_setup_channel(dmfc, slots, segment, burstsize); 330 - 331 - out: 332 - mutex_unlock(&priv->mutex); 333 - 334 - return ret; 335 - } 336 - EXPORT_SYMBOL_GPL(ipu_dmfc_alloc_bandwidth); 337 - 338 175 void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width) 339 176 { 340 177 struct ipu_dmfc_priv *priv = dmfc->priv; ··· 191 384 192 385 void ipu_dmfc_put(struct dmfc_channel *dmfc) 193 386 { 194 - ipu_dmfc_free_bandwidth(dmfc); 195 387 } 196 388 EXPORT_SYMBOL_GPL(ipu_dmfc_put); 197 389 ··· 218 412 priv->channels[i].priv = priv; 219 413 priv->channels[i].ipu = ipu; 220 414 priv->channels[i].data = &dmfcdata[i]; 415 + 416 + if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC || 417 + dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC || 418 + dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC) 419 + priv->channels[i].slots = 2; 221 420 } 222 421 223 - writel(0x0, priv->base + DMFC_WR_CHAN); 224 - writel(0x0, priv->base + DMFC_DP_CHAN); 225 - 226 - /* 227 - * We have a total bandwidth of clkrate * 4pixel divided 228 - * into 8 slots. 229 - */ 230 - priv->bandwidth_per_slot = clk_get_rate(ipu_clk) * 4 / 8; 231 - 232 - dev_dbg(dev, "dmfc: 8 slots with %ldMpixel/s bandwidth each\n", 233 - priv->bandwidth_per_slot / 1000000); 234 - 422 + writel(0x00000050, priv->base + DMFC_WR_CHAN); 423 + writel(0x00005654, priv->base + DMFC_DP_CHAN); 235 424 writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF); 236 425 writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF); 237 426 writel(0x00000003, priv->base + DMFC_GENERAL1);
-3
include/video/imx-ipu-v3.h
··· 235 235 struct dmfc_channel; 236 236 int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc); 237 237 void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc); 238 - int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc, 239 - unsigned long bandwidth_mbs, int burstsize); 240 - void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc); 241 238 void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width); 242 239 struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipuv3_channel); 243 240 void ipu_dmfc_put(struct dmfc_channel *dmfc);