brintos

brintos / linux-shallow public Read only

0
0
Text · 4.8 KiB · ae68208 Raw
215 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>4 * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.5 */6#include <linux/export.h>7#include <linux/types.h>8#include <linux/errno.h>9#include <linux/io.h>10 11#include <video/imx-ipu-v3.h>12#include "ipu-prv.h"13 14#define DMFC_RD_CHAN		0x000015#define DMFC_WR_CHAN		0x000416#define DMFC_WR_CHAN_DEF	0x000817#define DMFC_DP_CHAN		0x000c18#define DMFC_DP_CHAN_DEF	0x001019#define DMFC_GENERAL1		0x001420#define DMFC_GENERAL2		0x001821#define DMFC_IC_CTRL		0x001c22#define DMFC_WR_CHAN_ALT	0x002023#define DMFC_WR_CHAN_DEF_ALT	0x002424#define DMFC_DP_CHAN_ALT	0x002825#define DMFC_DP_CHAN_DEF_ALT	0x002c26#define DMFC_GENERAL1_ALT	0x003027#define DMFC_STAT		0x003428 29#define DMFC_WR_CHAN_1_28		030#define DMFC_WR_CHAN_2_41		831#define DMFC_WR_CHAN_1C_42		1632#define DMFC_WR_CHAN_2C_43		2433 34#define DMFC_DP_CHAN_5B_23		035#define DMFC_DP_CHAN_5F_27		836#define DMFC_DP_CHAN_6B_24		1637#define DMFC_DP_CHAN_6F_29		2438 39struct dmfc_channel_data {40	int		ipu_channel;41	unsigned long	channel_reg;42	unsigned long	shift;43	unsigned	eot_shift;44	unsigned	max_fifo_lines;45};46 47static const struct dmfc_channel_data dmfcdata[] = {48	{49		.ipu_channel	= IPUV3_CHANNEL_MEM_BG_SYNC,50		.channel_reg	= DMFC_DP_CHAN,51		.shift		= DMFC_DP_CHAN_5B_23,52		.eot_shift	= 20,53		.max_fifo_lines	= 3,54	}, {55		.ipu_channel	= 24,56		.channel_reg	= DMFC_DP_CHAN,57		.shift		= DMFC_DP_CHAN_6B_24,58		.eot_shift	= 22,59		.max_fifo_lines	= 1,60	}, {61		.ipu_channel	= IPUV3_CHANNEL_MEM_FG_SYNC,62		.channel_reg	= DMFC_DP_CHAN,63		.shift		= DMFC_DP_CHAN_5F_27,64		.eot_shift	= 21,65		.max_fifo_lines	= 2,66	}, {67		.ipu_channel	= IPUV3_CHANNEL_MEM_DC_SYNC,68		.channel_reg	= DMFC_WR_CHAN,69		.shift		= DMFC_WR_CHAN_1_28,70		.eot_shift	= 16,71		.max_fifo_lines	= 2,72	}, {73		.ipu_channel	= 29,74		.channel_reg	= DMFC_DP_CHAN,75		.shift		= DMFC_DP_CHAN_6F_29,76		.eot_shift	= 23,77		.max_fifo_lines	= 1,78	},79};80 81#define DMFC_NUM_CHANNELS	ARRAY_SIZE(dmfcdata)82 83struct ipu_dmfc_priv;84 85struct dmfc_channel {86	unsigned			slots;87	struct ipu_soc			*ipu;88	struct ipu_dmfc_priv		*priv;89	const struct dmfc_channel_data	*data;90};91 92struct ipu_dmfc_priv {93	struct ipu_soc *ipu;94	struct device *dev;95	struct dmfc_channel channels[DMFC_NUM_CHANNELS];96	struct mutex mutex;97	void __iomem *base;98	int use_count;99};100 101int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)102{103	struct ipu_dmfc_priv *priv = dmfc->priv;104	mutex_lock(&priv->mutex);105 106	if (!priv->use_count)107		ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);108 109	priv->use_count++;110 111	mutex_unlock(&priv->mutex);112 113	return 0;114}115EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);116 117void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)118{119	struct ipu_dmfc_priv *priv = dmfc->priv;120 121	mutex_lock(&priv->mutex);122 123	priv->use_count--;124 125	if (!priv->use_count)126		ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);127 128	if (priv->use_count < 0)129		priv->use_count = 0;130 131	mutex_unlock(&priv->mutex);132}133EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);134 135void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width)136{137	struct ipu_dmfc_priv *priv = dmfc->priv;138	u32 dmfc_gen1;139 140	mutex_lock(&priv->mutex);141 142	dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);143 144	if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)145		dmfc_gen1 |= 1 << dmfc->data->eot_shift;146	else147		dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);148 149	writel(dmfc_gen1, priv->base + DMFC_GENERAL1);150 151	mutex_unlock(&priv->mutex);152}153EXPORT_SYMBOL_GPL(ipu_dmfc_config_wait4eot);154 155struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)156{157	struct ipu_dmfc_priv *priv = ipu->dmfc_priv;158	int i;159 160	for (i = 0; i < DMFC_NUM_CHANNELS; i++)161		if (dmfcdata[i].ipu_channel == ipu_channel)162			return &priv->channels[i];163	return ERR_PTR(-ENODEV);164}165EXPORT_SYMBOL_GPL(ipu_dmfc_get);166 167void ipu_dmfc_put(struct dmfc_channel *dmfc)168{169}170EXPORT_SYMBOL_GPL(ipu_dmfc_put);171 172int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,173		struct clk *ipu_clk)174{175	struct ipu_dmfc_priv *priv;176	int i;177 178	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);179	if (!priv)180		return -ENOMEM;181 182	priv->base = devm_ioremap(dev, base, PAGE_SIZE);183	if (!priv->base)184		return -ENOMEM;185 186	priv->dev = dev;187	priv->ipu = ipu;188	mutex_init(&priv->mutex);189 190	ipu->dmfc_priv = priv;191 192	for (i = 0; i < DMFC_NUM_CHANNELS; i++) {193		priv->channels[i].priv = priv;194		priv->channels[i].ipu = ipu;195		priv->channels[i].data = &dmfcdata[i];196 197		if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC ||198		    dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC ||199		    dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC)200			priv->channels[i].slots = 2;201	}202 203	writel(0x00000050, priv->base + DMFC_WR_CHAN);204	writel(0x00005654, priv->base + DMFC_DP_CHAN);205	writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);206	writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);207	writel(0x00000003, priv->base + DMFC_GENERAL1);208 209	return 0;210}211 212void ipu_dmfc_exit(struct ipu_soc *ipu)213{214}215