ipu-smfc.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
  3. *
  4. * The code contained herein is licensed under the GNU General Public
  5. * License. You may obtain a copy of the GNU General Public License
  6. * Version 2 or later at the following locations:
  7. *
  8. * http://www.opensource.org/licenses/gpl-license.html
  9. * http://www.gnu.org/copyleft/gpl.html
  10. */
  11. #include <linux/export.h>
  12. #include <linux/types.h>
  13. #include <linux/init.h>
  14. #include <linux/io.h>
  15. #include <linux/errno.h>
  16. #include <linux/spinlock.h>
  17. #include <linux/delay.h>
  18. #include <linux/clk.h>
  19. #include <video/imx-ipu-v3.h>
  20. #include "ipu-prv.h"
  21. struct ipu_smfc {
  22. struct ipu_smfc_priv *priv;
  23. int chno;
  24. bool inuse;
  25. };
  26. struct ipu_smfc_priv {
  27. void __iomem *base;
  28. spinlock_t lock;
  29. struct ipu_soc *ipu;
  30. struct ipu_smfc channel[4];
  31. int use_count;
  32. };
  33. /*SMFC Registers */
  34. #define SMFC_MAP 0x0000
  35. #define SMFC_WMC 0x0004
  36. #define SMFC_BS 0x0008
  37. int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
  38. {
  39. struct ipu_smfc_priv *priv = smfc->priv;
  40. unsigned long flags;
  41. u32 val, shift;
  42. spin_lock_irqsave(&priv->lock, flags);
  43. shift = smfc->chno * 4;
  44. val = readl(priv->base + SMFC_BS);
  45. val &= ~(0xf << shift);
  46. val |= burstsize << shift;
  47. writel(val, priv->base + SMFC_BS);
  48. spin_unlock_irqrestore(&priv->lock, flags);
  49. return 0;
  50. }
  51. EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
  52. int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
  53. {
  54. struct ipu_smfc_priv *priv = smfc->priv;
  55. unsigned long flags;
  56. u32 val, shift;
  57. spin_lock_irqsave(&priv->lock, flags);
  58. shift = smfc->chno * 3;
  59. val = readl(priv->base + SMFC_MAP);
  60. val &= ~(0x7 << shift);
  61. val |= ((csi_id << 2) | mipi_id) << shift;
  62. writel(val, priv->base + SMFC_MAP);
  63. spin_unlock_irqrestore(&priv->lock, flags);
  64. return 0;
  65. }
  66. EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
  67. int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
  68. {
  69. struct ipu_smfc_priv *priv = smfc->priv;
  70. unsigned long flags;
  71. u32 val, shift;
  72. spin_lock_irqsave(&priv->lock, flags);
  73. shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
  74. val = readl(priv->base + SMFC_WMC);
  75. val &= ~(0x3f << shift);
  76. val |= ((clr_level << 3) | set_level) << shift;
  77. writel(val, priv->base + SMFC_WMC);
  78. spin_unlock_irqrestore(&priv->lock, flags);
  79. return 0;
  80. }
  81. EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
  82. int ipu_smfc_enable(struct ipu_smfc *smfc)
  83. {
  84. struct ipu_smfc_priv *priv = smfc->priv;
  85. unsigned long flags;
  86. spin_lock_irqsave(&priv->lock, flags);
  87. if (!priv->use_count)
  88. ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
  89. priv->use_count++;
  90. spin_unlock_irqrestore(&priv->lock, flags);
  91. return 0;
  92. }
  93. EXPORT_SYMBOL_GPL(ipu_smfc_enable);
  94. int ipu_smfc_disable(struct ipu_smfc *smfc)
  95. {
  96. struct ipu_smfc_priv *priv = smfc->priv;
  97. unsigned long flags;
  98. spin_lock_irqsave(&priv->lock, flags);
  99. priv->use_count--;
  100. if (!priv->use_count)
  101. ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
  102. if (priv->use_count < 0)
  103. priv->use_count = 0;
  104. spin_unlock_irqrestore(&priv->lock, flags);
  105. return 0;
  106. }
  107. EXPORT_SYMBOL_GPL(ipu_smfc_disable);
  108. struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
  109. {
  110. struct ipu_smfc_priv *priv = ipu->smfc_priv;
  111. struct ipu_smfc *smfc, *ret;
  112. unsigned long flags;
  113. if (chno >= 4)
  114. return ERR_PTR(-EINVAL);
  115. smfc = &priv->channel[chno];
  116. ret = smfc;
  117. spin_lock_irqsave(&priv->lock, flags);
  118. if (smfc->inuse) {
  119. ret = ERR_PTR(-EBUSY);
  120. goto unlock;
  121. }
  122. smfc->inuse = true;
  123. unlock:
  124. spin_unlock_irqrestore(&priv->lock, flags);
  125. return ret;
  126. }
  127. EXPORT_SYMBOL_GPL(ipu_smfc_get);
  128. void ipu_smfc_put(struct ipu_smfc *smfc)
  129. {
  130. struct ipu_smfc_priv *priv = smfc->priv;
  131. unsigned long flags;
  132. spin_lock_irqsave(&priv->lock, flags);
  133. smfc->inuse = false;
  134. spin_unlock_irqrestore(&priv->lock, flags);
  135. }
  136. EXPORT_SYMBOL_GPL(ipu_smfc_put);
  137. int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
  138. unsigned long base)
  139. {
  140. struct ipu_smfc_priv *priv;
  141. int i;
  142. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  143. if (!priv)
  144. return -ENOMEM;
  145. ipu->smfc_priv = priv;
  146. spin_lock_init(&priv->lock);
  147. priv->ipu = ipu;
  148. priv->base = devm_ioremap(dev, base, PAGE_SIZE);
  149. if (!priv->base)
  150. return -ENOMEM;
  151. for (i = 0; i < 4; i++) {
  152. priv->channel[i].priv = priv;
  153. priv->channel[i].chno = i;
  154. }
  155. pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
  156. return 0;
  157. }
  158. void ipu_smfc_exit(struct ipu_soc *ipu)
  159. {
  160. }