aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2017-06-15 20:05:38 -0400
committerDave Airlie <airlied@redhat.com>2017-06-15 20:05:38 -0400
commita6821698918a579e7219d706092e83f367f01ba2 (patch)
treeeb15f422a6306872aa20118e7e9ec42096281869
parent033fd3256f5aef7cbc0df0d747377be6c4349f48 (diff)
parentadd1318723a0d7b1ec974d2d9ba309cc24bb298a (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.c39
-rw-r--r--drivers/gpu/ipu-v3/ipu-cpmem.c6
-rw-r--r--drivers/gpu/ipu-v3/ipu-prg.c2
-rw-r--r--drivers/gpu/ipu-v3/ipu-prv.h9
-rw-r--r--drivers/gpu/ipu-v3/ipu-vdi.c4
-rw-r--r--include/video/imx-ipu-v3.h1
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
287out: 294out:
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}
590EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy); 598EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
591 599
592int 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}
606EXPORT_SYMBOL_GPL(ipu_wait_interrupt);
607
608int ipu_idmac_disable_channel(struct ipuv3_channel *channel) 600int 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}
225EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution); 225EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution);
226 226
227void ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel *ch)
228{
229 ipu_ch_param_write_field(ch, IPU_FIELD_RDRW, 1);
230}
231EXPORT_SYMBOL_GPL(ipu_cpmem_skip_odd_chroma_rows);
232
227void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride) 233void 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
158struct ipuv3_channel { 158struct 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
167struct ipu_cpmem; 164struct 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);
229int ipu_module_disable(struct ipu_soc *ipu, u32 mask); 225int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
230 226
231bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno); 227bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
232int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms);
233 228
234int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id, 229int 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
251void ipu_cpmem_zero(struct ipuv3_channel *ch); 251void ipu_cpmem_zero(struct ipuv3_channel *ch);
252void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres); 252void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres);
253void ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel *ch);
253void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride); 254void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride);
254void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch); 255void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch);
255void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf); 256void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf);