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

Merge tag 'imx-drm-next-2017-06-08' of git://git.pengutronix.de/git/pza/linux into drm-next

imx-drm: cleanups and YUV 4:2:0 memory read/write reduction support

- Remove counter load enable form PRE, which has no effect.
- Add support for setting the double read/write reduction flag in channel
parameter memory. This can be used to save some memory bandwidth when
capturing in YUV 4:2:0 chroma subsampled formats.
- Allocate DMA channel structures as needed, most of the 64 channels are
unused or even reserved.
- Remove unused interrupt busy waiting routine.
- Set VDIC field order for both AUTO and MAN inputs simultaneously as
both can't be active at the same time.

* tag 'imx-drm-next-2017-06-08' of git://git.pengutronix.de/git/pza/linux:
gpu: ipu-v3: vdic: include AUTO field order bit in ipu_vdi_set_field_order
gpu: ipu-v3: remove interrupt busy waiting routine
gpu: ipu-v3: allocate ipuv3_channels as needed
gpu: ipu-v3: Add support for double read/write reduction
gpu: ipu-v3: prg: remove counter load enable

+26 -35
+15 -24
drivers/gpu/ipu-v3/ipu-common.c
··· 274 274 275 275 mutex_lock(&ipu->channel_lock); 276 276 277 - channel = &ipu->channel[num]; 277 + list_for_each_entry(channel, &ipu->channels, list) { 278 + if (channel->num == num) { 279 + channel = ERR_PTR(-EBUSY); 280 + goto out; 281 + } 282 + } 278 283 279 - if (channel->busy) { 280 - channel = ERR_PTR(-EBUSY); 284 + channel = kzalloc(sizeof(*channel), GFP_KERNEL); 285 + if (!channel) { 286 + channel = ERR_PTR(-ENOMEM); 281 287 goto out; 282 288 } 283 289 284 - channel->busy = true; 285 290 channel->num = num; 291 + channel->ipu = ipu; 292 + list_add(&channel->list, &ipu->channels); 286 293 287 294 out: 288 295 mutex_unlock(&ipu->channel_lock); ··· 306 299 307 300 mutex_lock(&ipu->channel_lock); 308 301 309 - channel->busy = false; 302 + list_del(&channel->list); 303 + kfree(channel); 310 304 311 305 mutex_unlock(&ipu->channel_lock); 312 306 } ··· 596 588 return 0; 597 589 } 598 590 EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy); 599 - 600 - int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms) 601 - { 602 - unsigned long timeout; 603 - 604 - timeout = jiffies + msecs_to_jiffies(ms); 605 - ipu_cm_write(ipu, BIT(irq % 32), IPU_INT_STAT(irq / 32)); 606 - while (!(ipu_cm_read(ipu, IPU_INT_STAT(irq / 32) & BIT(irq % 32)))) { 607 - if (time_after(jiffies, timeout)) 608 - return -ETIMEDOUT; 609 - cpu_relax(); 610 - } 611 - 612 - return 0; 613 - } 614 - EXPORT_SYMBOL_GPL(ipu_wait_interrupt); 615 591 616 592 int ipu_idmac_disable_channel(struct ipuv3_channel *channel) 617 593 { ··· 1368 1376 struct ipu_soc *ipu; 1369 1377 struct resource *res; 1370 1378 unsigned long ipu_base; 1371 - int i, ret, irq_sync, irq_err; 1379 + int ret, irq_sync, irq_err; 1372 1380 const struct ipu_devtype *devtype; 1373 1381 1374 1382 devtype = of_device_get_match_data(&pdev->dev); ··· 1401 1409 return -EPROBE_DEFER; 1402 1410 } 1403 1411 1404 - for (i = 0; i < 64; i++) 1405 - ipu->channel[i].ipu = ipu; 1406 1412 ipu->devtype = devtype; 1407 1413 ipu->ipu_type = devtype->type; 1408 1414 1409 1415 spin_lock_init(&ipu->lock); 1410 1416 mutex_init(&ipu->channel_lock); 1417 + INIT_LIST_HEAD(&ipu->channels); 1411 1418 1412 1419 dev_dbg(&pdev->dev, "cm_reg: 0x%08lx\n", 1413 1420 ipu_base + devtype->cm_ofs);
+6
drivers/gpu/ipu-v3/ipu-cpmem.c
··· 224 224 } 225 225 EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution); 226 226 227 + void ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel *ch) 228 + { 229 + ipu_ch_param_write_field(ch, IPU_FIELD_RDRW, 1); 230 + } 231 + EXPORT_SYMBOL_GPL(ipu_cpmem_skip_odd_chroma_rows); 232 + 227 233 void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride) 228 234 { 229 235 ipu_ch_param_write_field(ch, IPU_FIELD_SLY, stride - 1);
-2
drivers/gpu/ipu-v3/ipu-prg.c
··· 318 318 writel(val, prg->regs + IPU_PRG_BADDR(prg_chan)); 319 319 320 320 val = readl(prg->regs + IPU_PRG_CTL); 321 - /* counter load enable */ 322 - val |= IPU_PRG_CTL_CNT_LOAD_EN(prg_chan); 323 321 /* config AXI ID */ 324 322 val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK << 325 323 IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan));
+2 -7
drivers/gpu/ipu-v3/ipu-prv.h
··· 157 157 158 158 struct ipuv3_channel { 159 159 unsigned int num; 160 - 161 - bool enabled; 162 - bool busy; 163 - 164 160 struct ipu_soc *ipu; 161 + struct list_head list; 165 162 }; 166 163 167 164 struct ipu_cpmem; ··· 181 184 enum ipuv3_type ipu_type; 182 185 spinlock_t lock; 183 186 struct mutex channel_lock; 187 + struct list_head channels; 184 188 185 189 void __iomem *cm_reg; 186 190 void __iomem *idmac_reg; ··· 190 192 int usecount; 191 193 192 194 struct clk *clk; 193 - 194 - struct ipuv3_channel channel[64]; 195 195 196 196 int irq_sync; 197 197 int irq_err; ··· 225 229 int ipu_module_disable(struct ipu_soc *ipu, u32 mask); 226 230 227 231 bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno); 228 - int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms); 229 232 230 233 int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id, 231 234 unsigned long base, u32 module, struct clk *clk_ipu);
+2 -2
drivers/gpu/ipu-v3/ipu-vdi.c
··· 88 88 89 89 reg = ipu_vdi_read(vdi, VDI_C); 90 90 if (top_field_0) 91 - reg &= ~VDI_C_TOP_FIELD_MAN_1; 91 + reg &= ~(VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1); 92 92 else 93 - reg |= VDI_C_TOP_FIELD_MAN_1; 93 + reg |= VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1; 94 94 ipu_vdi_write(vdi, reg, VDI_C); 95 95 96 96 spin_unlock_irqrestore(&vdi->lock, flags);
+1
include/video/imx-ipu-v3.h
··· 250 250 251 251 void ipu_cpmem_zero(struct ipuv3_channel *ch); 252 252 void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres); 253 + void ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel *ch); 253 254 void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride); 254 255 void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch); 255 256 void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf);