Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
[linux-2.6-block.git] / drivers / gpu / ipu-v3 / ipu-common.c
index 719788ce7d9f7d56f4e605a3b79fdc1e102047c6..04e7b2eafbdd7b127fd540873cd334693f4f4d40 100644 (file)
@@ -730,6 +730,12 @@ int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
 }
 EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
 
+bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno)
+{
+       return (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(chno)) & idma_mask(chno));
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_channel_busy);
+
 int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
 {
        struct ipu_soc *ipu = channel->ipu;
@@ -747,6 +753,22 @@ int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
 }
 EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
 
+int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms)
+{
+       unsigned long timeout;
+
+       timeout = jiffies + msecs_to_jiffies(ms);
+       ipu_cm_write(ipu, BIT(irq % 32), IPU_INT_STAT(irq / 32));
+       while (!(ipu_cm_read(ipu, IPU_INT_STAT(irq / 32) & BIT(irq % 32)))) {
+               if (time_after(jiffies, timeout))
+                       return -ETIMEDOUT;
+               cpu_relax();
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_wait_interrupt);
+
 int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
 {
        struct ipu_soc *ipu = channel->ipu;
@@ -942,7 +964,8 @@ static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs)
                status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i]));
 
                for_each_set_bit(bit, &status, 32) {
-                       irq = irq_linear_revmap(ipu->domain, regs[i] * 32 + bit);
+                       irq = irq_linear_revmap(ipu->domain,
+                                               regs[i] * 32 + bit);
                        if (irq)
                                generic_handle_irq(irq);
                }
@@ -975,15 +998,22 @@ static void ipu_err_irq_handler(unsigned int irq, struct irq_desc *desc)
        chained_irq_exit(chip, desc);
 }
 
-int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
-               enum ipu_channel_irq irq_type)
+int ipu_map_irq(struct ipu_soc *ipu, int irq)
 {
-       int irq = irq_linear_revmap(ipu->domain, irq_type + channel->num);
+       int virq;
 
-       if (!irq)
-               irq = irq_create_mapping(ipu->domain, irq_type + channel->num);
+       virq = irq_linear_revmap(ipu->domain, irq);
+       if (!virq)
+               virq = irq_create_mapping(ipu->domain, irq);
 
-       return irq;
+       return virq;
+}
+EXPORT_SYMBOL_GPL(ipu_map_irq);
+
+int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
+               enum ipu_channel_irq irq_type)
+{
+       return ipu_map_irq(ipu, irq_type + channel->num);
 }
 EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
 
@@ -1123,7 +1153,8 @@ static int ipu_irq_init(struct ipu_soc *ipu)
        }
 
        ret = irq_alloc_domain_generic_chips(ipu->domain, 32, 1, "IPU",
-                                            handle_level_irq, 0, IRQF_VALID, 0);
+                                            handle_level_irq, 0,
+                                            IRQF_VALID, 0);
        if (ret < 0) {
                dev_err(ipu->dev, "failed to alloc generic irq chips\n");
                irq_domain_remove(ipu->domain);