Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2016-2017 Lucas Stach, Pengutronix
0004  */
0005 
0006 #include <drm/drm_fourcc.h>
0007 #include <linux/clk.h>
0008 #include <linux/err.h>
0009 #include <linux/iopoll.h>
0010 #include <linux/mfd/syscon.h>
0011 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/regmap.h>
0017 #include <video/imx-ipu-v3.h>
0018 
0019 #include "ipu-prv.h"
0020 
0021 #define IPU_PRG_CTL             0x00
0022 #define  IPU_PRG_CTL_BYPASS(i)          (1 << (0 + i))
0023 #define  IPU_PRG_CTL_SOFT_ARID_MASK     0x3
0024 #define  IPU_PRG_CTL_SOFT_ARID_SHIFT(i)     (8 + i * 2)
0025 #define  IPU_PRG_CTL_SOFT_ARID(i, v)        ((v & 0x3) << (8 + 2 * i))
0026 #define  IPU_PRG_CTL_SO(i)          (1 << (16 + i))
0027 #define  IPU_PRG_CTL_VFLIP(i)           (1 << (19 + i))
0028 #define  IPU_PRG_CTL_BLOCK_MODE(i)      (1 << (22 + i))
0029 #define  IPU_PRG_CTL_CNT_LOAD_EN(i)     (1 << (25 + i))
0030 #define  IPU_PRG_CTL_SOFTRST            (1 << 30)
0031 #define  IPU_PRG_CTL_SHADOW_EN          (1 << 31)
0032 
0033 #define IPU_PRG_STATUS              0x04
0034 #define  IPU_PRG_STATUS_BUFFER0_READY(i)    (1 << (0 + i * 2))
0035 #define  IPU_PRG_STATUS_BUFFER1_READY(i)    (1 << (1 + i * 2))
0036 
0037 #define IPU_PRG_QOS             0x08
0038 #define  IPU_PRG_QOS_ARID_MASK          0xf
0039 #define  IPU_PRG_QOS_ARID_SHIFT(i)      (0 + i * 4)
0040 
0041 #define IPU_PRG_REG_UPDATE          0x0c
0042 #define  IPU_PRG_REG_UPDATE_REG_UPDATE      (1 << 0)
0043 
0044 #define IPU_PRG_STRIDE(i)           (0x10 + i * 0x4)
0045 #define  IPU_PRG_STRIDE_STRIDE_MASK     0x3fff
0046 
0047 #define IPU_PRG_CROP_LINE           0x1c
0048 
0049 #define IPU_PRG_THD             0x20
0050 
0051 #define IPU_PRG_BADDR(i)            (0x24 + i * 0x4)
0052 
0053 #define IPU_PRG_OFFSET(i)           (0x30 + i * 0x4)
0054 
0055 #define IPU_PRG_ILO(i)              (0x3c + i * 0x4)
0056 
0057 #define IPU_PRG_HEIGHT(i)           (0x48 + i * 0x4)
0058 #define  IPU_PRG_HEIGHT_PRE_HEIGHT_MASK     0xfff
0059 #define  IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT    0
0060 #define  IPU_PRG_HEIGHT_IPU_HEIGHT_MASK     0xfff
0061 #define  IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT    16
0062 
0063 struct ipu_prg_channel {
0064     bool            enabled;
0065     int         used_pre;
0066 };
0067 
0068 struct ipu_prg {
0069     struct list_head    list;
0070     struct device       *dev;
0071     int         id;
0072 
0073     void __iomem        *regs;
0074     struct clk      *clk_ipg, *clk_axi;
0075     struct regmap       *iomuxc_gpr;
0076     struct ipu_pre      *pres[3];
0077 
0078     struct ipu_prg_channel  chan[3];
0079 };
0080 
0081 static DEFINE_MUTEX(ipu_prg_list_mutex);
0082 static LIST_HEAD(ipu_prg_list);
0083 
0084 struct ipu_prg *
0085 ipu_prg_lookup_by_phandle(struct device *dev, const char *name, int ipu_id)
0086 {
0087     struct device_node *prg_node = of_parse_phandle(dev->of_node,
0088                             name, 0);
0089     struct ipu_prg *prg;
0090 
0091     mutex_lock(&ipu_prg_list_mutex);
0092     list_for_each_entry(prg, &ipu_prg_list, list) {
0093         if (prg_node == prg->dev->of_node) {
0094             mutex_unlock(&ipu_prg_list_mutex);
0095             device_link_add(dev, prg->dev,
0096                     DL_FLAG_AUTOREMOVE_CONSUMER);
0097             prg->id = ipu_id;
0098             of_node_put(prg_node);
0099             return prg;
0100         }
0101     }
0102     mutex_unlock(&ipu_prg_list_mutex);
0103 
0104     of_node_put(prg_node);
0105 
0106     return NULL;
0107 }
0108 
0109 int ipu_prg_max_active_channels(void)
0110 {
0111     return ipu_pre_get_available_count();
0112 }
0113 EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels);
0114 
0115 bool ipu_prg_present(struct ipu_soc *ipu)
0116 {
0117     if (ipu->prg_priv)
0118         return true;
0119 
0120     return false;
0121 }
0122 EXPORT_SYMBOL_GPL(ipu_prg_present);
0123 
0124 bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format,
0125                   uint64_t modifier)
0126 {
0127     const struct drm_format_info *info = drm_format_info(format);
0128 
0129     if (info->num_planes != 1)
0130         return false;
0131 
0132     switch (modifier) {
0133     case DRM_FORMAT_MOD_LINEAR:
0134     case DRM_FORMAT_MOD_VIVANTE_TILED:
0135     case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
0136         return true;
0137     default:
0138         return false;
0139     }
0140 }
0141 EXPORT_SYMBOL_GPL(ipu_prg_format_supported);
0142 
0143 int ipu_prg_enable(struct ipu_soc *ipu)
0144 {
0145     struct ipu_prg *prg = ipu->prg_priv;
0146 
0147     if (!prg)
0148         return 0;
0149 
0150     return pm_runtime_get_sync(prg->dev);
0151 }
0152 EXPORT_SYMBOL_GPL(ipu_prg_enable);
0153 
0154 void ipu_prg_disable(struct ipu_soc *ipu)
0155 {
0156     struct ipu_prg *prg = ipu->prg_priv;
0157 
0158     if (!prg)
0159         return;
0160 
0161     pm_runtime_put(prg->dev);
0162 }
0163 EXPORT_SYMBOL_GPL(ipu_prg_disable);
0164 
0165 /*
0166  * The channel configuartion functions below are not thread safe, as they
0167  * must be only called from the atomic commit path in the DRM driver, which
0168  * is properly serialized.
0169  */
0170 static int ipu_prg_ipu_to_prg_chan(int ipu_chan)
0171 {
0172     /*
0173      * This isn't clearly documented in the RM, but IPU to PRG channel
0174      * assignment is fixed, as only with this mapping the control signals
0175      * match up.
0176      */
0177     switch (ipu_chan) {
0178     case IPUV3_CHANNEL_MEM_BG_SYNC:
0179         return 0;
0180     case IPUV3_CHANNEL_MEM_FG_SYNC:
0181         return 1;
0182     case IPUV3_CHANNEL_MEM_DC_SYNC:
0183         return 2;
0184     default:
0185         return -EINVAL;
0186     }
0187 }
0188 
0189 static int ipu_prg_get_pre(struct ipu_prg *prg, int prg_chan)
0190 {
0191     int i, ret;
0192 
0193     /* channel 0 is special as it is hardwired to one of the PREs */
0194     if (prg_chan == 0) {
0195         ret = ipu_pre_get(prg->pres[0]);
0196         if (ret)
0197             goto fail;
0198         prg->chan[prg_chan].used_pre = 0;
0199         return 0;
0200     }
0201 
0202     for (i = 1; i < 3; i++) {
0203         ret = ipu_pre_get(prg->pres[i]);
0204         if (!ret) {
0205             u32 val, mux;
0206             int shift;
0207 
0208             prg->chan[prg_chan].used_pre = i;
0209 
0210             /* configure the PRE to PRG channel mux */
0211             shift = (i == 1) ? 12 : 14;
0212             mux = (prg->id << 1) | (prg_chan - 1);
0213             regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
0214                        0x3 << shift, mux << shift);
0215 
0216             /* check other mux, must not point to same channel */
0217             shift = (i == 1) ? 14 : 12;
0218             regmap_read(prg->iomuxc_gpr, IOMUXC_GPR5, &val);
0219             if (((val >> shift) & 0x3) == mux) {
0220                 regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
0221                            0x3 << shift,
0222                            (mux ^ 0x1) << shift);
0223             }
0224 
0225             return 0;
0226         }
0227     }
0228 
0229 fail:
0230     dev_err(prg->dev, "could not get PRE for PRG chan %d", prg_chan);
0231     return ret;
0232 }
0233 
0234 static void ipu_prg_put_pre(struct ipu_prg *prg, int prg_chan)
0235 {
0236     struct ipu_prg_channel *chan = &prg->chan[prg_chan];
0237 
0238     ipu_pre_put(prg->pres[chan->used_pre]);
0239     chan->used_pre = -1;
0240 }
0241 
0242 void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan)
0243 {
0244     int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
0245     struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
0246     struct ipu_prg_channel *chan;
0247     u32 val;
0248 
0249     if (prg_chan < 0)
0250         return;
0251 
0252     chan = &prg->chan[prg_chan];
0253     if (!chan->enabled)
0254         return;
0255 
0256     pm_runtime_get_sync(prg->dev);
0257 
0258     val = readl(prg->regs + IPU_PRG_CTL);
0259     val |= IPU_PRG_CTL_BYPASS(prg_chan);
0260     writel(val, prg->regs + IPU_PRG_CTL);
0261 
0262     val = IPU_PRG_REG_UPDATE_REG_UPDATE;
0263     writel(val, prg->regs + IPU_PRG_REG_UPDATE);
0264 
0265     pm_runtime_put(prg->dev);
0266 
0267     ipu_prg_put_pre(prg, prg_chan);
0268 
0269     chan->enabled = false;
0270 }
0271 EXPORT_SYMBOL_GPL(ipu_prg_channel_disable);
0272 
0273 int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
0274                   unsigned int axi_id, unsigned int width,
0275                   unsigned int height, unsigned int stride,
0276                   u32 format, uint64_t modifier, unsigned long *eba)
0277 {
0278     int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
0279     struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
0280     struct ipu_prg_channel *chan;
0281     u32 val;
0282     int ret;
0283 
0284     if (prg_chan < 0)
0285         return prg_chan;
0286 
0287     chan = &prg->chan[prg_chan];
0288 
0289     if (chan->enabled) {
0290         ipu_pre_update(prg->pres[chan->used_pre], *eba);
0291         return 0;
0292     }
0293 
0294     ret = ipu_prg_get_pre(prg, prg_chan);
0295     if (ret)
0296         return ret;
0297 
0298     ipu_pre_configure(prg->pres[chan->used_pre],
0299               width, height, stride, format, modifier, *eba);
0300 
0301 
0302     pm_runtime_get_sync(prg->dev);
0303 
0304     val = (stride - 1) & IPU_PRG_STRIDE_STRIDE_MASK;
0305     writel(val, prg->regs + IPU_PRG_STRIDE(prg_chan));
0306 
0307     val = ((height & IPU_PRG_HEIGHT_PRE_HEIGHT_MASK) <<
0308            IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT) |
0309           ((height & IPU_PRG_HEIGHT_IPU_HEIGHT_MASK) <<
0310            IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT);
0311     writel(val, prg->regs + IPU_PRG_HEIGHT(prg_chan));
0312 
0313     val = ipu_pre_get_baddr(prg->pres[chan->used_pre]);
0314     *eba = val;
0315     writel(val, prg->regs + IPU_PRG_BADDR(prg_chan));
0316 
0317     val = readl(prg->regs + IPU_PRG_CTL);
0318     /* config AXI ID */
0319     val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK <<
0320          IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan));
0321     val |= IPU_PRG_CTL_SOFT_ARID(prg_chan, axi_id);
0322     /* enable channel */
0323     val &= ~IPU_PRG_CTL_BYPASS(prg_chan);
0324     writel(val, prg->regs + IPU_PRG_CTL);
0325 
0326     val = IPU_PRG_REG_UPDATE_REG_UPDATE;
0327     writel(val, prg->regs + IPU_PRG_REG_UPDATE);
0328 
0329     /* wait for both double buffers to be filled */
0330     readl_poll_timeout(prg->regs + IPU_PRG_STATUS, val,
0331                (val & IPU_PRG_STATUS_BUFFER0_READY(prg_chan)) &&
0332                (val & IPU_PRG_STATUS_BUFFER1_READY(prg_chan)),
0333                5, 1000);
0334 
0335     pm_runtime_put(prg->dev);
0336 
0337     chan->enabled = true;
0338     return 0;
0339 }
0340 EXPORT_SYMBOL_GPL(ipu_prg_channel_configure);
0341 
0342 bool ipu_prg_channel_configure_pending(struct ipuv3_channel *ipu_chan)
0343 {
0344     int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
0345     struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
0346     struct ipu_prg_channel *chan;
0347 
0348     if (prg_chan < 0)
0349         return false;
0350 
0351     chan = &prg->chan[prg_chan];
0352     WARN_ON(!chan->enabled);
0353 
0354     return ipu_pre_update_pending(prg->pres[chan->used_pre]);
0355 }
0356 EXPORT_SYMBOL_GPL(ipu_prg_channel_configure_pending);
0357 
0358 static int ipu_prg_probe(struct platform_device *pdev)
0359 {
0360     struct device *dev = &pdev->dev;
0361     struct resource *res;
0362     struct ipu_prg *prg;
0363     u32 val;
0364     int i, ret;
0365 
0366     prg = devm_kzalloc(dev, sizeof(*prg), GFP_KERNEL);
0367     if (!prg)
0368         return -ENOMEM;
0369 
0370     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0371     prg->regs = devm_ioremap_resource(&pdev->dev, res);
0372     if (IS_ERR(prg->regs))
0373         return PTR_ERR(prg->regs);
0374 
0375 
0376     prg->clk_ipg = devm_clk_get(dev, "ipg");
0377     if (IS_ERR(prg->clk_ipg))
0378         return PTR_ERR(prg->clk_ipg);
0379 
0380     prg->clk_axi = devm_clk_get(dev, "axi");
0381     if (IS_ERR(prg->clk_axi))
0382         return PTR_ERR(prg->clk_axi);
0383 
0384     prg->iomuxc_gpr =
0385         syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
0386     if (IS_ERR(prg->iomuxc_gpr))
0387         return PTR_ERR(prg->iomuxc_gpr);
0388 
0389     for (i = 0; i < 3; i++) {
0390         prg->pres[i] = ipu_pre_lookup_by_phandle(dev, "fsl,pres", i);
0391         if (!prg->pres[i])
0392             return -EPROBE_DEFER;
0393     }
0394 
0395     ret = clk_prepare_enable(prg->clk_ipg);
0396     if (ret)
0397         return ret;
0398 
0399     ret = clk_prepare_enable(prg->clk_axi);
0400     if (ret) {
0401         clk_disable_unprepare(prg->clk_ipg);
0402         return ret;
0403     }
0404 
0405     /* init to free running mode */
0406     val = readl(prg->regs + IPU_PRG_CTL);
0407     val |= IPU_PRG_CTL_SHADOW_EN;
0408     writel(val, prg->regs + IPU_PRG_CTL);
0409 
0410     /* disable address threshold */
0411     writel(0xffffffff, prg->regs + IPU_PRG_THD);
0412 
0413     pm_runtime_set_active(dev);
0414     pm_runtime_enable(dev);
0415 
0416     prg->dev = dev;
0417     platform_set_drvdata(pdev, prg);
0418     mutex_lock(&ipu_prg_list_mutex);
0419     list_add(&prg->list, &ipu_prg_list);
0420     mutex_unlock(&ipu_prg_list_mutex);
0421 
0422     return 0;
0423 }
0424 
0425 static int ipu_prg_remove(struct platform_device *pdev)
0426 {
0427     struct ipu_prg *prg = platform_get_drvdata(pdev);
0428 
0429     mutex_lock(&ipu_prg_list_mutex);
0430     list_del(&prg->list);
0431     mutex_unlock(&ipu_prg_list_mutex);
0432 
0433     return 0;
0434 }
0435 
0436 #ifdef CONFIG_PM
0437 static int prg_suspend(struct device *dev)
0438 {
0439     struct ipu_prg *prg = dev_get_drvdata(dev);
0440 
0441     clk_disable_unprepare(prg->clk_axi);
0442     clk_disable_unprepare(prg->clk_ipg);
0443 
0444     return 0;
0445 }
0446 
0447 static int prg_resume(struct device *dev)
0448 {
0449     struct ipu_prg *prg = dev_get_drvdata(dev);
0450     int ret;
0451 
0452     ret = clk_prepare_enable(prg->clk_ipg);
0453     if (ret)
0454         return ret;
0455 
0456     ret = clk_prepare_enable(prg->clk_axi);
0457     if (ret) {
0458         clk_disable_unprepare(prg->clk_ipg);
0459         return ret;
0460     }
0461 
0462     return 0;
0463 }
0464 #endif
0465 
0466 static const struct dev_pm_ops prg_pm_ops = {
0467     SET_RUNTIME_PM_OPS(prg_suspend, prg_resume, NULL)
0468 };
0469 
0470 static const struct of_device_id ipu_prg_dt_ids[] = {
0471     { .compatible = "fsl,imx6qp-prg", },
0472     { /* sentinel */ },
0473 };
0474 
0475 struct platform_driver ipu_prg_drv = {
0476     .probe      = ipu_prg_probe,
0477     .remove     = ipu_prg_remove,
0478     .driver     = {
0479         .name   = "imx-ipu-prg",
0480         .pm = &prg_pm_ops,
0481         .of_match_table = ipu_prg_dt_ids,
0482     },
0483 };