aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Longerbeam <slongerbeam@gmail.com>2014-06-25 21:05:34 -0400
committerPhilipp Zabel <p.zabel@pengutronix.de>2014-09-02 08:55:44 -0400
commit7fafa8f06f9bdf32b806b4612bfe387de8e34125 (patch)
treeb201e57c619e16ff10cfa8183a76af617abe1173
parentfc4353559e587f5962f22c24ca7e015bdbea1e49 (diff)
gpu: ipu-v3: smfc: Convert to per-channel
Convert the smfc object to be specific to a single smfc channel. Add ipu_smfc_{get|put} to retrieve and release a single smfc channel for exclusive use, and add use counter to ipu_smfc_{enable|disable}. Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
-rw-r--r--drivers/gpu/ipu-v3/ipu-smfc.c132
-rw-r--r--include/video/imx-ipu-v3.h10
2 files changed, 112 insertions, 30 deletions
diff --git a/drivers/gpu/ipu-v3/ipu-smfc.c b/drivers/gpu/ipu-v3/ipu-smfc.c
index 87ac624dd7ca..a6429ca913c1 100644
--- a/drivers/gpu/ipu-v3/ipu-smfc.c
+++ b/drivers/gpu/ipu-v3/ipu-smfc.c
@@ -21,9 +21,18 @@
21 21
22#include "ipu-prv.h" 22#include "ipu-prv.h"
23 23
24struct ipu_smfc {
25 struct ipu_smfc_priv *priv;
26 int chno;
27 bool inuse;
28};
29
24struct ipu_smfc_priv { 30struct ipu_smfc_priv {
25 void __iomem *base; 31 void __iomem *base;
26 spinlock_t lock; 32 spinlock_t lock;
33 struct ipu_soc *ipu;
34 struct ipu_smfc channel[4];
35 int use_count;
27}; 36};
28 37
29/*SMFC Registers */ 38/*SMFC Registers */
@@ -31,75 +40,146 @@ struct ipu_smfc_priv {
31#define SMFC_WMC 0x0004 40#define SMFC_WMC 0x0004
32#define SMFC_BS 0x0008 41#define SMFC_BS 0x0008
33 42
34int ipu_smfc_set_burstsize(struct ipu_soc *ipu, int channel, int burstsize) 43int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
35{ 44{
36 struct ipu_smfc_priv *smfc = ipu->smfc_priv; 45 struct ipu_smfc_priv *priv = smfc->priv;
37 unsigned long flags; 46 unsigned long flags;
38 u32 val, shift; 47 u32 val, shift;
39 48
40 spin_lock_irqsave(&smfc->lock, flags); 49 spin_lock_irqsave(&priv->lock, flags);
41 50
42 shift = channel * 4; 51 shift = smfc->chno * 4;
43 val = readl(smfc->base + SMFC_BS); 52 val = readl(priv->base + SMFC_BS);
44 val &= ~(0xf << shift); 53 val &= ~(0xf << shift);
45 val |= burstsize << shift; 54 val |= burstsize << shift;
46 writel(val, smfc->base + SMFC_BS); 55 writel(val, priv->base + SMFC_BS);
47 56
48 spin_unlock_irqrestore(&smfc->lock, flags); 57 spin_unlock_irqrestore(&priv->lock, flags);
49 58
50 return 0; 59 return 0;
51} 60}
52EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize); 61EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
53 62
54int ipu_smfc_map_channel(struct ipu_soc *ipu, int channel, int csi_id, int mipi_id) 63int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
55{ 64{
56 struct ipu_smfc_priv *smfc = ipu->smfc_priv; 65 struct ipu_smfc_priv *priv = smfc->priv;
57 unsigned long flags; 66 unsigned long flags;
58 u32 val, shift; 67 u32 val, shift;
59 68
60 spin_lock_irqsave(&smfc->lock, flags); 69 spin_lock_irqsave(&priv->lock, flags);
61 70
62 shift = channel * 3; 71 shift = smfc->chno * 3;
63 val = readl(smfc->base + SMFC_MAP); 72 val = readl(priv->base + SMFC_MAP);
64 val &= ~(0x7 << shift); 73 val &= ~(0x7 << shift);
65 val |= ((csi_id << 2) | mipi_id) << shift; 74 val |= ((csi_id << 2) | mipi_id) << shift;
66 writel(val, smfc->base + SMFC_MAP); 75 writel(val, priv->base + SMFC_MAP);
67 76
68 spin_unlock_irqrestore(&smfc->lock, flags); 77 spin_unlock_irqrestore(&priv->lock, flags);
69 78
70 return 0; 79 return 0;
71} 80}
72EXPORT_SYMBOL_GPL(ipu_smfc_map_channel); 81EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
73 82
74int ipu_smfc_enable(struct ipu_soc *ipu) 83int ipu_smfc_enable(struct ipu_smfc *smfc)
75{ 84{
76 return ipu_module_enable(ipu, IPU_CONF_SMFC_EN); 85 struct ipu_smfc_priv *priv = smfc->priv;
86 unsigned long flags;
87
88 spin_lock_irqsave(&priv->lock, flags);
89
90 if (!priv->use_count)
91 ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
92
93 priv->use_count++;
94
95 spin_unlock_irqrestore(&priv->lock, flags);
96
97 return 0;
77} 98}
78EXPORT_SYMBOL_GPL(ipu_smfc_enable); 99EXPORT_SYMBOL_GPL(ipu_smfc_enable);
79 100
80int ipu_smfc_disable(struct ipu_soc *ipu) 101int ipu_smfc_disable(struct ipu_smfc *smfc)
81{ 102{
82 return ipu_module_disable(ipu, IPU_CONF_SMFC_EN); 103 struct ipu_smfc_priv *priv = smfc->priv;
104 unsigned long flags;
105
106 spin_lock_irqsave(&priv->lock, flags);
107
108 priv->use_count--;
109
110 if (!priv->use_count)
111 ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
112
113 if (priv->use_count < 0)
114 priv->use_count = 0;
115
116 spin_unlock_irqrestore(&priv->lock, flags);
117
118 return 0;
83} 119}
84EXPORT_SYMBOL_GPL(ipu_smfc_disable); 120EXPORT_SYMBOL_GPL(ipu_smfc_disable);
85 121
122struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
123{
124 struct ipu_smfc_priv *priv = ipu->smfc_priv;
125 struct ipu_smfc *smfc, *ret;
126 unsigned long flags;
127
128 if (chno >= 4)
129 return ERR_PTR(-EINVAL);
130
131 smfc = &priv->channel[chno];
132 ret = smfc;
133
134 spin_lock_irqsave(&priv->lock, flags);
135
136 if (smfc->inuse) {
137 ret = ERR_PTR(-EBUSY);
138 goto unlock;
139 }
140
141 smfc->inuse = true;
142unlock:
143 spin_unlock_irqrestore(&priv->lock, flags);
144 return ret;
145}
146EXPORT_SYMBOL_GPL(ipu_smfc_get);
147
148void ipu_smfc_put(struct ipu_smfc *smfc)
149{
150 struct ipu_smfc_priv *priv = smfc->priv;
151 unsigned long flags;
152
153 spin_lock_irqsave(&priv->lock, flags);
154 smfc->inuse = false;
155 spin_unlock_irqrestore(&priv->lock, flags);
156}
157EXPORT_SYMBOL_GPL(ipu_smfc_put);
158
86int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, 159int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
87 unsigned long base) 160 unsigned long base)
88{ 161{
89 struct ipu_smfc_priv *smfc; 162 struct ipu_smfc_priv *priv;
163 int i;
90 164
91 smfc = devm_kzalloc(dev, sizeof(*smfc), GFP_KERNEL); 165 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
92 if (!smfc) 166 if (!priv)
93 return -ENOMEM; 167 return -ENOMEM;
94 168
95 ipu->smfc_priv = smfc; 169 ipu->smfc_priv = priv;
96 spin_lock_init(&smfc->lock); 170 spin_lock_init(&priv->lock);
171 priv->ipu = ipu;
97 172
98 smfc->base = devm_ioremap(dev, base, PAGE_SIZE); 173 priv->base = devm_ioremap(dev, base, PAGE_SIZE);
99 if (!smfc->base) 174 if (!priv->base)
100 return -ENOMEM; 175 return -ENOMEM;
101 176
102 pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, smfc->base); 177 for (i = 0; i < 4; i++) {
178 priv->channel[i].priv = priv;
179 priv->channel[i].chno = i;
180 }
181
182 pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
103 183
104 return 0; 184 return 0;
105} 185}
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index a477814a03af..a695ee83e4e1 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -290,10 +290,12 @@ void ipu_ic_dump(struct ipu_ic *ic);
290/* 290/*
291 * IPU Sensor Multiple FIFO Controller (SMFC) functions 291 * IPU Sensor Multiple FIFO Controller (SMFC) functions
292 */ 292 */
293int ipu_smfc_enable(struct ipu_soc *ipu); 293struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno);
294int ipu_smfc_disable(struct ipu_soc *ipu); 294void ipu_smfc_put(struct ipu_smfc *smfc);
295int ipu_smfc_map_channel(struct ipu_soc *ipu, int channel, int csi_id, int mipi_id); 295int ipu_smfc_enable(struct ipu_smfc *smfc);
296int ipu_smfc_set_burstsize(struct ipu_soc *ipu, int channel, int burstsize); 296int ipu_smfc_disable(struct ipu_smfc *smfc);
297int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id);
298int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize);
297 299
298enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc); 300enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc);
299enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat); 301enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat);