Linux Audio

Check our new training course

Loading...
v4.6
  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
 21#include "ipu-prv.h"
 22
 23struct ipu_smfc {
 24	struct ipu_smfc_priv *priv;
 25	int chno;
 26	bool inuse;
 27};
 28
 29struct ipu_smfc_priv {
 30	void __iomem *base;
 31	spinlock_t lock;
 32	struct ipu_soc *ipu;
 33	struct ipu_smfc channel[4];
 34	int use_count;
 35};
 36
 37/*SMFC Registers */
 38#define SMFC_MAP	0x0000
 39#define SMFC_WMC	0x0004
 40#define SMFC_BS		0x0008
 41
 42int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
 43{
 44	struct ipu_smfc_priv *priv = smfc->priv;
 45	unsigned long flags;
 46	u32 val, shift;
 47
 48	spin_lock_irqsave(&priv->lock, flags);
 49
 50	shift = smfc->chno * 4;
 51	val = readl(priv->base + SMFC_BS);
 52	val &= ~(0xf << shift);
 53	val |= burstsize << shift;
 54	writel(val, priv->base + SMFC_BS);
 55
 56	spin_unlock_irqrestore(&priv->lock, flags);
 57
 58	return 0;
 59}
 60EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
 61
 62int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
 63{
 64	struct ipu_smfc_priv *priv = smfc->priv;
 65	unsigned long flags;
 66	u32 val, shift;
 67
 68	spin_lock_irqsave(&priv->lock, flags);
 69
 70	shift = smfc->chno * 3;
 71	val = readl(priv->base + SMFC_MAP);
 72	val &= ~(0x7 << shift);
 73	val |= ((csi_id << 2) | mipi_id) << shift;
 74	writel(val, priv->base + SMFC_MAP);
 75
 76	spin_unlock_irqrestore(&priv->lock, flags);
 77
 78	return 0;
 79}
 80EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
 81
 82int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
 83{
 84	struct ipu_smfc_priv *priv = smfc->priv;
 85	unsigned long flags;
 86	u32 val, shift;
 87
 88	spin_lock_irqsave(&priv->lock, flags);
 89
 90	shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
 91	val = readl(priv->base + SMFC_WMC);
 92	val &= ~(0x3f << shift);
 93	val |= ((clr_level << 3) | set_level) << shift;
 94	writel(val, priv->base + SMFC_WMC);
 95
 96	spin_unlock_irqrestore(&priv->lock, flags);
 97
 98	return 0;
 99}
100EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
101
102int ipu_smfc_enable(struct ipu_smfc *smfc)
103{
104	struct ipu_smfc_priv *priv = smfc->priv;
105	unsigned long flags;
106
107	spin_lock_irqsave(&priv->lock, flags);
108
109	if (!priv->use_count)
110		ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
111
112	priv->use_count++;
113
114	spin_unlock_irqrestore(&priv->lock, flags);
115
116	return 0;
117}
118EXPORT_SYMBOL_GPL(ipu_smfc_enable);
119
120int ipu_smfc_disable(struct ipu_smfc *smfc)
121{
122	struct ipu_smfc_priv *priv = smfc->priv;
123	unsigned long flags;
124
125	spin_lock_irqsave(&priv->lock, flags);
126
127	priv->use_count--;
128
129	if (!priv->use_count)
130		ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
131
132	if (priv->use_count < 0)
133		priv->use_count = 0;
134
135	spin_unlock_irqrestore(&priv->lock, flags);
136
137	return 0;
138}
139EXPORT_SYMBOL_GPL(ipu_smfc_disable);
140
141struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
142{
143	struct ipu_smfc_priv *priv = ipu->smfc_priv;
144	struct ipu_smfc *smfc, *ret;
145	unsigned long flags;
146
147	if (chno >= 4)
148		return ERR_PTR(-EINVAL);
149
150	smfc = &priv->channel[chno];
151	ret = smfc;
152
153	spin_lock_irqsave(&priv->lock, flags);
154
155	if (smfc->inuse) {
156		ret = ERR_PTR(-EBUSY);
157		goto unlock;
158	}
159
160	smfc->inuse = true;
161unlock:
162	spin_unlock_irqrestore(&priv->lock, flags);
163	return ret;
164}
165EXPORT_SYMBOL_GPL(ipu_smfc_get);
166
167void ipu_smfc_put(struct ipu_smfc *smfc)
168{
169	struct ipu_smfc_priv *priv = smfc->priv;
170	unsigned long flags;
171
172	spin_lock_irqsave(&priv->lock, flags);
173	smfc->inuse = false;
174	spin_unlock_irqrestore(&priv->lock, flags);
175}
176EXPORT_SYMBOL_GPL(ipu_smfc_put);
177
178int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
179		  unsigned long base)
180{
181	struct ipu_smfc_priv *priv;
182	int i;
183
184	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
185	if (!priv)
186		return -ENOMEM;
187
188	ipu->smfc_priv = priv;
189	spin_lock_init(&priv->lock);
190	priv->ipu = ipu;
191
192	priv->base = devm_ioremap(dev, base, PAGE_SIZE);
193	if (!priv->base)
194		return -ENOMEM;
195
196	for (i = 0; i < 4; i++) {
197		priv->channel[i].priv = priv;
198		priv->channel[i].chno = i;
199	}
200
201	pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
202
203	return 0;
204}
205
206void ipu_smfc_exit(struct ipu_soc *ipu)
207{
208}
v4.10.11
  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
 21#include "ipu-prv.h"
 22
 23struct ipu_smfc {
 24	struct ipu_smfc_priv *priv;
 25	int chno;
 26	bool inuse;
 27};
 28
 29struct ipu_smfc_priv {
 30	void __iomem *base;
 31	spinlock_t lock;
 32	struct ipu_soc *ipu;
 33	struct ipu_smfc channel[4];
 34	int use_count;
 35};
 36
 37/*SMFC Registers */
 38#define SMFC_MAP	0x0000
 39#define SMFC_WMC	0x0004
 40#define SMFC_BS		0x0008
 41
 42int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
 43{
 44	struct ipu_smfc_priv *priv = smfc->priv;
 45	unsigned long flags;
 46	u32 val, shift;
 47
 48	spin_lock_irqsave(&priv->lock, flags);
 49
 50	shift = smfc->chno * 4;
 51	val = readl(priv->base + SMFC_BS);
 52	val &= ~(0xf << shift);
 53	val |= burstsize << shift;
 54	writel(val, priv->base + SMFC_BS);
 55
 56	spin_unlock_irqrestore(&priv->lock, flags);
 57
 58	return 0;
 59}
 60EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
 61
 62int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
 63{
 64	struct ipu_smfc_priv *priv = smfc->priv;
 65	unsigned long flags;
 66	u32 val, shift;
 67
 68	spin_lock_irqsave(&priv->lock, flags);
 69
 70	shift = smfc->chno * 3;
 71	val = readl(priv->base + SMFC_MAP);
 72	val &= ~(0x7 << shift);
 73	val |= ((csi_id << 2) | mipi_id) << shift;
 74	writel(val, priv->base + SMFC_MAP);
 75
 76	spin_unlock_irqrestore(&priv->lock, flags);
 77
 78	return 0;
 79}
 80EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
 81
 82int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
 83{
 84	struct ipu_smfc_priv *priv = smfc->priv;
 85	unsigned long flags;
 86	u32 val, shift;
 87
 88	spin_lock_irqsave(&priv->lock, flags);
 89
 90	shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
 91	val = readl(priv->base + SMFC_WMC);
 92	val &= ~(0x3f << shift);
 93	val |= ((clr_level << 3) | set_level) << shift;
 94	writel(val, priv->base + SMFC_WMC);
 95
 96	spin_unlock_irqrestore(&priv->lock, flags);
 97
 98	return 0;
 99}
100EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
101
102int ipu_smfc_enable(struct ipu_smfc *smfc)
103{
104	struct ipu_smfc_priv *priv = smfc->priv;
105	unsigned long flags;
106
107	spin_lock_irqsave(&priv->lock, flags);
108
109	if (!priv->use_count)
110		ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
111
112	priv->use_count++;
113
114	spin_unlock_irqrestore(&priv->lock, flags);
115
116	return 0;
117}
118EXPORT_SYMBOL_GPL(ipu_smfc_enable);
119
120int ipu_smfc_disable(struct ipu_smfc *smfc)
121{
122	struct ipu_smfc_priv *priv = smfc->priv;
123	unsigned long flags;
124
125	spin_lock_irqsave(&priv->lock, flags);
126
127	priv->use_count--;
128
129	if (!priv->use_count)
130		ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
131
132	if (priv->use_count < 0)
133		priv->use_count = 0;
134
135	spin_unlock_irqrestore(&priv->lock, flags);
136
137	return 0;
138}
139EXPORT_SYMBOL_GPL(ipu_smfc_disable);
140
141struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
142{
143	struct ipu_smfc_priv *priv = ipu->smfc_priv;
144	struct ipu_smfc *smfc, *ret;
145	unsigned long flags;
146
147	if (chno >= 4)
148		return ERR_PTR(-EINVAL);
149
150	smfc = &priv->channel[chno];
151	ret = smfc;
152
153	spin_lock_irqsave(&priv->lock, flags);
154
155	if (smfc->inuse) {
156		ret = ERR_PTR(-EBUSY);
157		goto unlock;
158	}
159
160	smfc->inuse = true;
161unlock:
162	spin_unlock_irqrestore(&priv->lock, flags);
163	return ret;
164}
165EXPORT_SYMBOL_GPL(ipu_smfc_get);
166
167void ipu_smfc_put(struct ipu_smfc *smfc)
168{
169	struct ipu_smfc_priv *priv = smfc->priv;
170	unsigned long flags;
171
172	spin_lock_irqsave(&priv->lock, flags);
173	smfc->inuse = false;
174	spin_unlock_irqrestore(&priv->lock, flags);
175}
176EXPORT_SYMBOL_GPL(ipu_smfc_put);
177
178int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
179		  unsigned long base)
180{
181	struct ipu_smfc_priv *priv;
182	int i;
183
184	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
185	if (!priv)
186		return -ENOMEM;
187
188	ipu->smfc_priv = priv;
189	spin_lock_init(&priv->lock);
190	priv->ipu = ipu;
191
192	priv->base = devm_ioremap(dev, base, PAGE_SIZE);
193	if (!priv->base)
194		return -ENOMEM;
195
196	for (i = 0; i < 4; i++) {
197		priv->channel[i].priv = priv;
198		priv->channel[i].chno = i;
199	}
200
201	pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
202
203	return 0;
204}
205
206void ipu_smfc_exit(struct ipu_soc *ipu)
207{
208}