diff options
| author | Dave Airlie <airlied@redhat.com> | 2017-06-15 20:05:38 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2017-06-15 20:05:38 -0400 |
| commit | a6821698918a579e7219d706092e83f367f01ba2 (patch) | |
| tree | eb15f422a6306872aa20118e7e9ec42096281869 | |
| parent | 033fd3256f5aef7cbc0df0d747377be6c4349f48 (diff) | |
| parent | add1318723a0d7b1ec974d2d9ba309cc24bb298a (diff) | |
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
| -rw-r--r-- | drivers/gpu/ipu-v3/ipu-common.c | 39 | ||||
| -rw-r--r-- | drivers/gpu/ipu-v3/ipu-cpmem.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/ipu-v3/ipu-prg.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/ipu-v3/ipu-prv.h | 9 | ||||
| -rw-r--r-- | drivers/gpu/ipu-v3/ipu-vdi.c | 4 | ||||
| -rw-r--r-- | include/video/imx-ipu-v3.h | 1 |
6 files changed, 26 insertions, 35 deletions
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index 16d556816b5f..22e0a3eca7b1 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c | |||
| @@ -274,15 +274,22 @@ struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num) | |||
| 274 | 274 | ||
| 275 | mutex_lock(&ipu->channel_lock); | 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) { | 284 | channel = kzalloc(sizeof(*channel), GFP_KERNEL); |
| 280 | channel = ERR_PTR(-EBUSY); | 285 | if (!channel) { |
| 286 | channel = ERR_PTR(-ENOMEM); | ||
| 281 | goto out; | 287 | goto out; |
| 282 | } | 288 | } |
| 283 | 289 | ||
| 284 | channel->busy = true; | ||
| 285 | channel->num = num; | 290 | channel->num = num; |
| 291 | channel->ipu = ipu; | ||
| 292 | list_add(&channel->list, &ipu->channels); | ||
| 286 | 293 | ||
| 287 | out: | 294 | out: |
| 288 | mutex_unlock(&ipu->channel_lock); | 295 | mutex_unlock(&ipu->channel_lock); |
| @@ -299,7 +306,8 @@ void ipu_idmac_put(struct ipuv3_channel *channel) | |||
| 299 | 306 | ||
| 300 | mutex_lock(&ipu->channel_lock); | 307 | mutex_lock(&ipu->channel_lock); |
| 301 | 308 | ||
| 302 | channel->busy = false; | 309 | list_del(&channel->list); |
| 310 | kfree(channel); | ||
| 303 | 311 | ||
| 304 | mutex_unlock(&ipu->channel_lock); | 312 | mutex_unlock(&ipu->channel_lock); |
| 305 | } | 313 | } |
| @@ -589,22 +597,6 @@ int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms) | |||
| 589 | } | 597 | } |
| 590 | EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy); | 598 | EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy); |
| 591 | 599 | ||
| 592 | int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms) | ||
| 593 | { | ||
| 594 | unsigned long timeout; | ||
| 595 | |||
| 596 | timeout = jiffies + msecs_to_jiffies(ms); | ||
| 597 | ipu_cm_write(ipu, BIT(irq % 32), IPU_INT_STAT(irq / 32)); | ||
| 598 | while (!(ipu_cm_read(ipu, IPU_INT_STAT(irq / 32) & BIT(irq % 32)))) { | ||
| 599 | if (time_after(jiffies, timeout)) | ||
| 600 | return -ETIMEDOUT; | ||
| 601 | cpu_relax(); | ||
| 602 | } | ||
| 603 | |||
| 604 | return 0; | ||
| 605 | } | ||
| 606 | EXPORT_SYMBOL_GPL(ipu_wait_interrupt); | ||
| 607 | |||
| 608 | int ipu_idmac_disable_channel(struct ipuv3_channel *channel) | 600 | int ipu_idmac_disable_channel(struct ipuv3_channel *channel) |
| 609 | { | 601 | { |
| 610 | struct ipu_soc *ipu = channel->ipu; | 602 | struct ipu_soc *ipu = channel->ipu; |
| @@ -1376,7 +1368,7 @@ static int ipu_probe(struct platform_device *pdev) | |||
| 1376 | struct ipu_soc *ipu; | 1368 | struct ipu_soc *ipu; |
| 1377 | struct resource *res; | 1369 | struct resource *res; |
| 1378 | unsigned long ipu_base; | 1370 | unsigned long ipu_base; |
| 1379 | int i, ret, irq_sync, irq_err; | 1371 | int ret, irq_sync, irq_err; |
| 1380 | const struct ipu_devtype *devtype; | 1372 | const struct ipu_devtype *devtype; |
| 1381 | 1373 | ||
| 1382 | devtype = of_device_get_match_data(&pdev->dev); | 1374 | devtype = of_device_get_match_data(&pdev->dev); |
| @@ -1409,13 +1401,12 @@ static int ipu_probe(struct platform_device *pdev) | |||
| 1409 | return -EPROBE_DEFER; | 1401 | return -EPROBE_DEFER; |
| 1410 | } | 1402 | } |
| 1411 | 1403 | ||
| 1412 | for (i = 0; i < 64; i++) | ||
| 1413 | ipu->channel[i].ipu = ipu; | ||
| 1414 | ipu->devtype = devtype; | 1404 | ipu->devtype = devtype; |
| 1415 | ipu->ipu_type = devtype->type; | 1405 | ipu->ipu_type = devtype->type; |
| 1416 | 1406 | ||
| 1417 | spin_lock_init(&ipu->lock); | 1407 | spin_lock_init(&ipu->lock); |
| 1418 | mutex_init(&ipu->channel_lock); | 1408 | mutex_init(&ipu->channel_lock); |
| 1409 | INIT_LIST_HEAD(&ipu->channels); | ||
| 1419 | 1410 | ||
| 1420 | dev_dbg(&pdev->dev, "cm_reg: 0x%08lx\n", | 1411 | dev_dbg(&pdev->dev, "cm_reg: 0x%08lx\n", |
| 1421 | ipu_base + devtype->cm_ofs); | 1412 | ipu_base + devtype->cm_ofs); |
diff --git a/drivers/gpu/ipu-v3/ipu-cpmem.c b/drivers/gpu/ipu-v3/ipu-cpmem.c index 114160dfc3ad..1cb82f445f91 100644 --- a/drivers/gpu/ipu-v3/ipu-cpmem.c +++ b/drivers/gpu/ipu-v3/ipu-cpmem.c | |||
| @@ -224,6 +224,12 @@ void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres) | |||
| 224 | } | 224 | } |
| 225 | EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution); | 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 | void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride) | 233 | void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride) |
| 228 | { | 234 | { |
| 229 | ipu_ch_param_write_field(ch, IPU_FIELD_SLY, stride - 1); | 235 | ipu_ch_param_write_field(ch, IPU_FIELD_SLY, stride - 1); |
diff --git a/drivers/gpu/ipu-v3/ipu-prg.c b/drivers/gpu/ipu-v3/ipu-prg.c index caca57febbd6..ecc9ea44dc50 100644 --- a/drivers/gpu/ipu-v3/ipu-prg.c +++ b/drivers/gpu/ipu-v3/ipu-prg.c | |||
| @@ -318,8 +318,6 @@ int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan, | |||
| 318 | writel(val, prg->regs + IPU_PRG_BADDR(prg_chan)); | 318 | writel(val, prg->regs + IPU_PRG_BADDR(prg_chan)); |
| 319 | 319 | ||
| 320 | val = readl(prg->regs + IPU_PRG_CTL); | 320 | val = readl(prg->regs + IPU_PRG_CTL); |
| 321 | /* counter load enable */ | ||
| 322 | val |= IPU_PRG_CTL_CNT_LOAD_EN(prg_chan); | ||
| 323 | /* config AXI ID */ | 321 | /* config AXI ID */ |
| 324 | val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK << | 322 | val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK << |
| 325 | IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan)); | 323 | IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan)); |
diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h index ca2a223a0d1e..ac4b8d658500 100644 --- a/drivers/gpu/ipu-v3/ipu-prv.h +++ b/drivers/gpu/ipu-v3/ipu-prv.h | |||
| @@ -157,11 +157,8 @@ enum ipu_modules { | |||
| 157 | 157 | ||
| 158 | struct ipuv3_channel { | 158 | struct ipuv3_channel { |
| 159 | unsigned int num; | 159 | unsigned int num; |
| 160 | |||
| 161 | bool enabled; | ||
| 162 | bool busy; | ||
| 163 | |||
| 164 | struct ipu_soc *ipu; | 160 | struct ipu_soc *ipu; |
| 161 | struct list_head list; | ||
| 165 | }; | 162 | }; |
| 166 | 163 | ||
| 167 | struct ipu_cpmem; | 164 | struct ipu_cpmem; |
| @@ -184,6 +181,7 @@ struct ipu_soc { | |||
| 184 | enum ipuv3_type ipu_type; | 181 | enum ipuv3_type ipu_type; |
| 185 | spinlock_t lock; | 182 | spinlock_t lock; |
| 186 | struct mutex channel_lock; | 183 | struct mutex channel_lock; |
| 184 | struct list_head channels; | ||
| 187 | 185 | ||
| 188 | void __iomem *cm_reg; | 186 | void __iomem *cm_reg; |
| 189 | void __iomem *idmac_reg; | 187 | void __iomem *idmac_reg; |
| @@ -193,8 +191,6 @@ struct ipu_soc { | |||
| 193 | 191 | ||
| 194 | struct clk *clk; | 192 | struct clk *clk; |
| 195 | 193 | ||
| 196 | struct ipuv3_channel channel[64]; | ||
| 197 | |||
| 198 | int irq_sync; | 194 | int irq_sync; |
| 199 | int irq_err; | 195 | int irq_err; |
| 200 | struct irq_domain *domain; | 196 | struct irq_domain *domain; |
| @@ -229,7 +225,6 @@ int ipu_module_enable(struct ipu_soc *ipu, u32 mask); | |||
| 229 | int ipu_module_disable(struct ipu_soc *ipu, u32 mask); | 225 | int ipu_module_disable(struct ipu_soc *ipu, u32 mask); |
| 230 | 226 | ||
| 231 | bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno); | 227 | bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno); |
| 232 | int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms); | ||
| 233 | 228 | ||
| 234 | int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id, | 229 | int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id, |
| 235 | unsigned long base, u32 module, struct clk *clk_ipu); | 230 | unsigned long base, u32 module, struct clk *clk_ipu); |
diff --git a/drivers/gpu/ipu-v3/ipu-vdi.c b/drivers/gpu/ipu-v3/ipu-vdi.c index f27bf5a12ebc..a66389366af7 100644 --- a/drivers/gpu/ipu-v3/ipu-vdi.c +++ b/drivers/gpu/ipu-v3/ipu-vdi.c | |||
| @@ -88,9 +88,9 @@ void ipu_vdi_set_field_order(struct ipu_vdi *vdi, v4l2_std_id std, u32 field) | |||
| 88 | 88 | ||
| 89 | reg = ipu_vdi_read(vdi, VDI_C); | 89 | reg = ipu_vdi_read(vdi, VDI_C); |
| 90 | if (top_field_0) | 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 | else | 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 | ipu_vdi_write(vdi, reg, VDI_C); | 94 | ipu_vdi_write(vdi, reg, VDI_C); |
| 95 | 95 | ||
| 96 | spin_unlock_irqrestore(&vdi->lock, flags); | 96 | spin_unlock_irqrestore(&vdi->lock, flags); |
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h index 8cb07680fb41..ce4c07688b13 100644 --- a/include/video/imx-ipu-v3.h +++ b/include/video/imx-ipu-v3.h | |||
| @@ -250,6 +250,7 @@ struct ipu_image { | |||
| 250 | 250 | ||
| 251 | void ipu_cpmem_zero(struct ipuv3_channel *ch); | 251 | void ipu_cpmem_zero(struct ipuv3_channel *ch); |
| 252 | void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres); | 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 | void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride); | 254 | void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride); |
| 254 | void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch); | 255 | void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch); |
| 255 | void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf); | 256 | void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf); |
