Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
0004  * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
0005  */
0006 #include <linux/export.h>
0007 #include <linux/types.h>
0008 #include <linux/errno.h>
0009 #include <linux/io.h>
0010 
0011 #include <video/imx-ipu-v3.h>
0012 #include "ipu-prv.h"
0013 
0014 #define DMFC_RD_CHAN        0x0000
0015 #define DMFC_WR_CHAN        0x0004
0016 #define DMFC_WR_CHAN_DEF    0x0008
0017 #define DMFC_DP_CHAN        0x000c
0018 #define DMFC_DP_CHAN_DEF    0x0010
0019 #define DMFC_GENERAL1       0x0014
0020 #define DMFC_GENERAL2       0x0018
0021 #define DMFC_IC_CTRL        0x001c
0022 #define DMFC_WR_CHAN_ALT    0x0020
0023 #define DMFC_WR_CHAN_DEF_ALT    0x0024
0024 #define DMFC_DP_CHAN_ALT    0x0028
0025 #define DMFC_DP_CHAN_DEF_ALT    0x002c
0026 #define DMFC_GENERAL1_ALT   0x0030
0027 #define DMFC_STAT       0x0034
0028 
0029 #define DMFC_WR_CHAN_1_28       0
0030 #define DMFC_WR_CHAN_2_41       8
0031 #define DMFC_WR_CHAN_1C_42      16
0032 #define DMFC_WR_CHAN_2C_43      24
0033 
0034 #define DMFC_DP_CHAN_5B_23      0
0035 #define DMFC_DP_CHAN_5F_27      8
0036 #define DMFC_DP_CHAN_6B_24      16
0037 #define DMFC_DP_CHAN_6F_29      24
0038 
0039 struct dmfc_channel_data {
0040     int     ipu_channel;
0041     unsigned long   channel_reg;
0042     unsigned long   shift;
0043     unsigned    eot_shift;
0044     unsigned    max_fifo_lines;
0045 };
0046 
0047 static const struct dmfc_channel_data dmfcdata[] = {
0048     {
0049         .ipu_channel    = IPUV3_CHANNEL_MEM_BG_SYNC,
0050         .channel_reg    = DMFC_DP_CHAN,
0051         .shift      = DMFC_DP_CHAN_5B_23,
0052         .eot_shift  = 20,
0053         .max_fifo_lines = 3,
0054     }, {
0055         .ipu_channel    = 24,
0056         .channel_reg    = DMFC_DP_CHAN,
0057         .shift      = DMFC_DP_CHAN_6B_24,
0058         .eot_shift  = 22,
0059         .max_fifo_lines = 1,
0060     }, {
0061         .ipu_channel    = IPUV3_CHANNEL_MEM_FG_SYNC,
0062         .channel_reg    = DMFC_DP_CHAN,
0063         .shift      = DMFC_DP_CHAN_5F_27,
0064         .eot_shift  = 21,
0065         .max_fifo_lines = 2,
0066     }, {
0067         .ipu_channel    = IPUV3_CHANNEL_MEM_DC_SYNC,
0068         .channel_reg    = DMFC_WR_CHAN,
0069         .shift      = DMFC_WR_CHAN_1_28,
0070         .eot_shift  = 16,
0071         .max_fifo_lines = 2,
0072     }, {
0073         .ipu_channel    = 29,
0074         .channel_reg    = DMFC_DP_CHAN,
0075         .shift      = DMFC_DP_CHAN_6F_29,
0076         .eot_shift  = 23,
0077         .max_fifo_lines = 1,
0078     },
0079 };
0080 
0081 #define DMFC_NUM_CHANNELS   ARRAY_SIZE(dmfcdata)
0082 
0083 struct ipu_dmfc_priv;
0084 
0085 struct dmfc_channel {
0086     unsigned            slots;
0087     struct ipu_soc          *ipu;
0088     struct ipu_dmfc_priv        *priv;
0089     const struct dmfc_channel_data  *data;
0090 };
0091 
0092 struct ipu_dmfc_priv {
0093     struct ipu_soc *ipu;
0094     struct device *dev;
0095     struct dmfc_channel channels[DMFC_NUM_CHANNELS];
0096     struct mutex mutex;
0097     void __iomem *base;
0098     int use_count;
0099 };
0100 
0101 int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
0102 {
0103     struct ipu_dmfc_priv *priv = dmfc->priv;
0104     mutex_lock(&priv->mutex);
0105 
0106     if (!priv->use_count)
0107         ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
0108 
0109     priv->use_count++;
0110 
0111     mutex_unlock(&priv->mutex);
0112 
0113     return 0;
0114 }
0115 EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
0116 
0117 void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
0118 {
0119     struct ipu_dmfc_priv *priv = dmfc->priv;
0120 
0121     mutex_lock(&priv->mutex);
0122 
0123     priv->use_count--;
0124 
0125     if (!priv->use_count)
0126         ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
0127 
0128     if (priv->use_count < 0)
0129         priv->use_count = 0;
0130 
0131     mutex_unlock(&priv->mutex);
0132 }
0133 EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
0134 
0135 void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width)
0136 {
0137     struct ipu_dmfc_priv *priv = dmfc->priv;
0138     u32 dmfc_gen1;
0139 
0140     mutex_lock(&priv->mutex);
0141 
0142     dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
0143 
0144     if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
0145         dmfc_gen1 |= 1 << dmfc->data->eot_shift;
0146     else
0147         dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
0148 
0149     writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
0150 
0151     mutex_unlock(&priv->mutex);
0152 }
0153 EXPORT_SYMBOL_GPL(ipu_dmfc_config_wait4eot);
0154 
0155 struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
0156 {
0157     struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
0158     int i;
0159 
0160     for (i = 0; i < DMFC_NUM_CHANNELS; i++)
0161         if (dmfcdata[i].ipu_channel == ipu_channel)
0162             return &priv->channels[i];
0163     return ERR_PTR(-ENODEV);
0164 }
0165 EXPORT_SYMBOL_GPL(ipu_dmfc_get);
0166 
0167 void ipu_dmfc_put(struct dmfc_channel *dmfc)
0168 {
0169 }
0170 EXPORT_SYMBOL_GPL(ipu_dmfc_put);
0171 
0172 int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
0173         struct clk *ipu_clk)
0174 {
0175     struct ipu_dmfc_priv *priv;
0176     int i;
0177 
0178     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0179     if (!priv)
0180         return -ENOMEM;
0181 
0182     priv->base = devm_ioremap(dev, base, PAGE_SIZE);
0183     if (!priv->base)
0184         return -ENOMEM;
0185 
0186     priv->dev = dev;
0187     priv->ipu = ipu;
0188     mutex_init(&priv->mutex);
0189 
0190     ipu->dmfc_priv = priv;
0191 
0192     for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
0193         priv->channels[i].priv = priv;
0194         priv->channels[i].ipu = ipu;
0195         priv->channels[i].data = &dmfcdata[i];
0196 
0197         if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC ||
0198             dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC ||
0199             dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC)
0200             priv->channels[i].slots = 2;
0201     }
0202 
0203     writel(0x00000050, priv->base + DMFC_WR_CHAN);
0204     writel(0x00005654, priv->base + DMFC_DP_CHAN);
0205     writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
0206     writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
0207     writel(0x00000003, priv->base + DMFC_GENERAL1);
0208 
0209     return 0;
0210 }
0211 
0212 void ipu_dmfc_exit(struct ipu_soc *ipu)
0213 {
0214 }