linux/drivers/gpu/ipu-v3/ipu-dmfc.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
   3 * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of the GNU General Public License as published by the
   7 * Free Software Foundation; either version 2 of the License, or (at your
   8 * option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful, but
  11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  12 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13 * for more details.
  14 */
  15#include <linux/export.h>
  16#include <linux/types.h>
  17#include <linux/errno.h>
  18#include <linux/io.h>
  19
  20#include <video/imx-ipu-v3.h>
  21#include "ipu-prv.h"
  22
  23#define DMFC_RD_CHAN            0x0000
  24#define DMFC_WR_CHAN            0x0004
  25#define DMFC_WR_CHAN_DEF        0x0008
  26#define DMFC_DP_CHAN            0x000c
  27#define DMFC_DP_CHAN_DEF        0x0010
  28#define DMFC_GENERAL1           0x0014
  29#define DMFC_GENERAL2           0x0018
  30#define DMFC_IC_CTRL            0x001c
  31#define DMFC_WR_CHAN_ALT        0x0020
  32#define DMFC_WR_CHAN_DEF_ALT    0x0024
  33#define DMFC_DP_CHAN_ALT        0x0028
  34#define DMFC_DP_CHAN_DEF_ALT    0x002c
  35#define DMFC_GENERAL1_ALT       0x0030
  36#define DMFC_STAT               0x0034
  37
  38#define DMFC_WR_CHAN_1_28               0
  39#define DMFC_WR_CHAN_2_41               8
  40#define DMFC_WR_CHAN_1C_42              16
  41#define DMFC_WR_CHAN_2C_43              24
  42
  43#define DMFC_DP_CHAN_5B_23              0
  44#define DMFC_DP_CHAN_5F_27              8
  45#define DMFC_DP_CHAN_6B_24              16
  46#define DMFC_DP_CHAN_6F_29              24
  47
  48struct dmfc_channel_data {
  49        int             ipu_channel;
  50        unsigned long   channel_reg;
  51        unsigned long   shift;
  52        unsigned        eot_shift;
  53        unsigned        max_fifo_lines;
  54};
  55
  56static const struct dmfc_channel_data dmfcdata[] = {
  57        {
  58                .ipu_channel    = IPUV3_CHANNEL_MEM_BG_SYNC,
  59                .channel_reg    = DMFC_DP_CHAN,
  60                .shift          = DMFC_DP_CHAN_5B_23,
  61                .eot_shift      = 20,
  62                .max_fifo_lines = 3,
  63        }, {
  64                .ipu_channel    = 24,
  65                .channel_reg    = DMFC_DP_CHAN,
  66                .shift          = DMFC_DP_CHAN_6B_24,
  67                .eot_shift      = 22,
  68                .max_fifo_lines = 1,
  69        }, {
  70                .ipu_channel    = IPUV3_CHANNEL_MEM_FG_SYNC,
  71                .channel_reg    = DMFC_DP_CHAN,
  72                .shift          = DMFC_DP_CHAN_5F_27,
  73                .eot_shift      = 21,
  74                .max_fifo_lines = 2,
  75        }, {
  76                .ipu_channel    = IPUV3_CHANNEL_MEM_DC_SYNC,
  77                .channel_reg    = DMFC_WR_CHAN,
  78                .shift          = DMFC_WR_CHAN_1_28,
  79                .eot_shift      = 16,
  80                .max_fifo_lines = 2,
  81        }, {
  82                .ipu_channel    = 29,
  83                .channel_reg    = DMFC_DP_CHAN,
  84                .shift          = DMFC_DP_CHAN_6F_29,
  85                .eot_shift      = 23,
  86                .max_fifo_lines = 1,
  87        },
  88};
  89
  90#define DMFC_NUM_CHANNELS       ARRAY_SIZE(dmfcdata)
  91
  92struct ipu_dmfc_priv;
  93
  94struct dmfc_channel {
  95        unsigned                        slots;
  96        struct ipu_soc                  *ipu;
  97        struct ipu_dmfc_priv            *priv;
  98        const struct dmfc_channel_data  *data;
  99};
 100
 101struct ipu_dmfc_priv {
 102        struct ipu_soc *ipu;
 103        struct device *dev;
 104        struct dmfc_channel channels[DMFC_NUM_CHANNELS];
 105        struct mutex mutex;
 106        void __iomem *base;
 107        int use_count;
 108};
 109
 110int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
 111{
 112        struct ipu_dmfc_priv *priv = dmfc->priv;
 113        mutex_lock(&priv->mutex);
 114
 115        if (!priv->use_count)
 116                ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
 117
 118        priv->use_count++;
 119
 120        mutex_unlock(&priv->mutex);
 121
 122        return 0;
 123}
 124EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
 125
 126void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
 127{
 128        struct ipu_dmfc_priv *priv = dmfc->priv;
 129
 130        mutex_lock(&priv->mutex);
 131
 132        priv->use_count--;
 133
 134        if (!priv->use_count)
 135                ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
 136
 137        if (priv->use_count < 0)
 138                priv->use_count = 0;
 139
 140        mutex_unlock(&priv->mutex);
 141}
 142EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
 143
 144void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width)
 145{
 146        struct ipu_dmfc_priv *priv = dmfc->priv;
 147        u32 dmfc_gen1;
 148
 149        mutex_lock(&priv->mutex);
 150
 151        dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
 152
 153        if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
 154                dmfc_gen1 |= 1 << dmfc->data->eot_shift;
 155        else
 156                dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
 157
 158        writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
 159
 160        mutex_unlock(&priv->mutex);
 161}
 162EXPORT_SYMBOL_GPL(ipu_dmfc_config_wait4eot);
 163
 164struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
 165{
 166        struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
 167        int i;
 168
 169        for (i = 0; i < DMFC_NUM_CHANNELS; i++)
 170                if (dmfcdata[i].ipu_channel == ipu_channel)
 171                        return &priv->channels[i];
 172        return ERR_PTR(-ENODEV);
 173}
 174EXPORT_SYMBOL_GPL(ipu_dmfc_get);
 175
 176void ipu_dmfc_put(struct dmfc_channel *dmfc)
 177{
 178}
 179EXPORT_SYMBOL_GPL(ipu_dmfc_put);
 180
 181int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
 182                struct clk *ipu_clk)
 183{
 184        struct ipu_dmfc_priv *priv;
 185        int i;
 186
 187        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 188        if (!priv)
 189                return -ENOMEM;
 190
 191        priv->base = devm_ioremap(dev, base, PAGE_SIZE);
 192        if (!priv->base)
 193                return -ENOMEM;
 194
 195        priv->dev = dev;
 196        priv->ipu = ipu;
 197        mutex_init(&priv->mutex);
 198
 199        ipu->dmfc_priv = priv;
 200
 201        for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
 202                priv->channels[i].priv = priv;
 203                priv->channels[i].ipu = ipu;
 204                priv->channels[i].data = &dmfcdata[i];
 205
 206                if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC ||
 207                    dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC ||
 208                    dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC)
 209                        priv->channels[i].slots = 2;
 210        }
 211
 212        writel(0x00000050, priv->base + DMFC_WR_CHAN);
 213        writel(0x00005654, priv->base + DMFC_DP_CHAN);
 214        writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
 215        writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
 216        writel(0x00000003, priv->base + DMFC_GENERAL1);
 217
 218        return 0;
 219}
 220
 221void ipu_dmfc_exit(struct ipu_soc *ipu)
 222{
 223}
 224