Linux Audio

Check our new training course

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