root/drivers/gpu/ipu-v3/ipu-smfc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ipu_smfc_set_burstsize
  2. ipu_smfc_map_channel
  3. ipu_smfc_set_watermark
  4. ipu_smfc_enable
  5. ipu_smfc_disable
  6. ipu_smfc_get
  7. ipu_smfc_put
  8. ipu_smfc_init
  9. ipu_smfc_exit

   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 
  17 struct ipu_smfc {
  18         struct ipu_smfc_priv *priv;
  19         int chno;
  20         bool inuse;
  21 };
  22 
  23 struct 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 
  36 int 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 }
  54 EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
  55 
  56 int 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 }
  74 EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
  75 
  76 int 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 }
  94 EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
  95 
  96 int 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 }
 112 EXPORT_SYMBOL_GPL(ipu_smfc_enable);
 113 
 114 int 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 }
 133 EXPORT_SYMBOL_GPL(ipu_smfc_disable);
 134 
 135 struct 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;
 155 unlock:
 156         spin_unlock_irqrestore(&priv->lock, flags);
 157         return ret;
 158 }
 159 EXPORT_SYMBOL_GPL(ipu_smfc_get);
 160 
 161 void 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 }
 170 EXPORT_SYMBOL_GPL(ipu_smfc_put);
 171 
 172 int 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 
 200 void ipu_smfc_exit(struct ipu_soc *ipu)
 201 {
 202 }

/* [<][>][^][v][top][bottom][index][help] */