cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mtk_disp_rdma.c (11177B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2015 MediaTek Inc.
      4 */
      5
      6#include <linux/clk.h>
      7#include <linux/component.h>
      8#include <linux/module.h>
      9#include <linux/of_device.h>
     10#include <linux/of_irq.h>
     11#include <linux/platform_device.h>
     12#include <linux/pm_runtime.h>
     13#include <linux/soc/mediatek/mtk-cmdq.h>
     14
     15#include "mtk_disp_drv.h"
     16#include "mtk_drm_crtc.h"
     17#include "mtk_drm_ddp_comp.h"
     18
     19#define DISP_REG_RDMA_INT_ENABLE		0x0000
     20#define DISP_REG_RDMA_INT_STATUS		0x0004
     21#define RDMA_TARGET_LINE_INT				BIT(5)
     22#define RDMA_FIFO_UNDERFLOW_INT				BIT(4)
     23#define RDMA_EOF_ABNORMAL_INT				BIT(3)
     24#define RDMA_FRAME_END_INT				BIT(2)
     25#define RDMA_FRAME_START_INT				BIT(1)
     26#define RDMA_REG_UPDATE_INT				BIT(0)
     27#define DISP_REG_RDMA_GLOBAL_CON		0x0010
     28#define RDMA_ENGINE_EN					BIT(0)
     29#define RDMA_MODE_MEMORY				BIT(1)
     30#define DISP_REG_RDMA_SIZE_CON_0		0x0014
     31#define RDMA_MATRIX_ENABLE				BIT(17)
     32#define RDMA_MATRIX_INT_MTX_SEL				GENMASK(23, 20)
     33#define RDMA_MATRIX_INT_MTX_BT601_to_RGB		(6 << 20)
     34#define DISP_REG_RDMA_SIZE_CON_1		0x0018
     35#define DISP_REG_RDMA_TARGET_LINE		0x001c
     36#define DISP_RDMA_MEM_CON			0x0024
     37#define MEM_MODE_INPUT_FORMAT_RGB565			(0x000 << 4)
     38#define MEM_MODE_INPUT_FORMAT_RGB888			(0x001 << 4)
     39#define MEM_MODE_INPUT_FORMAT_RGBA8888			(0x002 << 4)
     40#define MEM_MODE_INPUT_FORMAT_ARGB8888			(0x003 << 4)
     41#define MEM_MODE_INPUT_FORMAT_UYVY			(0x004 << 4)
     42#define MEM_MODE_INPUT_FORMAT_YUYV			(0x005 << 4)
     43#define MEM_MODE_INPUT_SWAP				BIT(8)
     44#define DISP_RDMA_MEM_SRC_PITCH			0x002c
     45#define DISP_RDMA_MEM_GMC_SETTING_0		0x0030
     46#define DISP_REG_RDMA_FIFO_CON			0x0040
     47#define RDMA_FIFO_UNDERFLOW_EN				BIT(31)
     48#define RDMA_FIFO_PSEUDO_SIZE(bytes)			(((bytes) / 16) << 16)
     49#define RDMA_OUTPUT_VALID_FIFO_THRESHOLD(bytes)		((bytes) / 16)
     50#define RDMA_FIFO_SIZE(rdma)			((rdma)->data->fifo_size)
     51#define DISP_RDMA_MEM_START_ADDR		0x0f00
     52
     53#define RDMA_MEM_GMC				0x40402020
     54
     55struct mtk_disp_rdma_data {
     56	unsigned int fifo_size;
     57};
     58
     59/*
     60 * struct mtk_disp_rdma - DISP_RDMA driver structure
     61 * @data: local driver data
     62 */
     63struct mtk_disp_rdma {
     64	struct clk			*clk;
     65	void __iomem			*regs;
     66	struct cmdq_client_reg		cmdq_reg;
     67	const struct mtk_disp_rdma_data	*data;
     68	void				(*vblank_cb)(void *data);
     69	void				*vblank_cb_data;
     70	u32				fifo_size;
     71};
     72
     73static irqreturn_t mtk_disp_rdma_irq_handler(int irq, void *dev_id)
     74{
     75	struct mtk_disp_rdma *priv = dev_id;
     76
     77	/* Clear frame completion interrupt */
     78	writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);
     79
     80	if (!priv->vblank_cb)
     81		return IRQ_NONE;
     82
     83	priv->vblank_cb(priv->vblank_cb_data);
     84
     85	return IRQ_HANDLED;
     86}
     87
     88static void rdma_update_bits(struct device *dev, unsigned int reg,
     89			     unsigned int mask, unsigned int val)
     90{
     91	struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
     92	unsigned int tmp = readl(rdma->regs + reg);
     93
     94	tmp = (tmp & ~mask) | (val & mask);
     95	writel(tmp, rdma->regs + reg);
     96}
     97
     98void mtk_rdma_register_vblank_cb(struct device *dev,
     99				 void (*vblank_cb)(void *),
    100				 void *vblank_cb_data)
    101{
    102	struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
    103
    104	rdma->vblank_cb = vblank_cb;
    105	rdma->vblank_cb_data = vblank_cb_data;
    106}
    107
    108void mtk_rdma_unregister_vblank_cb(struct device *dev)
    109{
    110	struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
    111
    112	rdma->vblank_cb = NULL;
    113	rdma->vblank_cb_data = NULL;
    114}
    115
    116void mtk_rdma_enable_vblank(struct device *dev)
    117{
    118	rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT,
    119			 RDMA_FRAME_END_INT);
    120}
    121
    122void mtk_rdma_disable_vblank(struct device *dev)
    123{
    124	rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0);
    125}
    126
    127int mtk_rdma_clk_enable(struct device *dev)
    128{
    129	struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
    130
    131	return clk_prepare_enable(rdma->clk);
    132}
    133
    134void mtk_rdma_clk_disable(struct device *dev)
    135{
    136	struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
    137
    138	clk_disable_unprepare(rdma->clk);
    139}
    140
    141void mtk_rdma_start(struct device *dev)
    142{
    143	rdma_update_bits(dev, DISP_REG_RDMA_GLOBAL_CON, RDMA_ENGINE_EN,
    144			 RDMA_ENGINE_EN);
    145}
    146
    147void mtk_rdma_stop(struct device *dev)
    148{
    149	rdma_update_bits(dev, DISP_REG_RDMA_GLOBAL_CON, RDMA_ENGINE_EN, 0);
    150}
    151
    152void mtk_rdma_config(struct device *dev, unsigned int width,
    153		     unsigned int height, unsigned int vrefresh,
    154		     unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
    155{
    156	unsigned int threshold;
    157	unsigned int reg;
    158	struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
    159	u32 rdma_fifo_size;
    160
    161	mtk_ddp_write_mask(cmdq_pkt, width, &rdma->cmdq_reg, rdma->regs,
    162			   DISP_REG_RDMA_SIZE_CON_0, 0xfff);
    163	mtk_ddp_write_mask(cmdq_pkt, height, &rdma->cmdq_reg, rdma->regs,
    164			   DISP_REG_RDMA_SIZE_CON_1, 0xfffff);
    165
    166	if (rdma->fifo_size)
    167		rdma_fifo_size = rdma->fifo_size;
    168	else
    169		rdma_fifo_size = RDMA_FIFO_SIZE(rdma);
    170
    171	/*
    172	 * Enable FIFO underflow since DSI and DPI can't be blocked.
    173	 * Keep the FIFO pseudo size reset default of 8 KiB. Set the
    174	 * output threshold to 70% of max fifo size to make sure the
    175	 * threhold will not overflow
    176	 */
    177	threshold = rdma_fifo_size * 7 / 10;
    178	reg = RDMA_FIFO_UNDERFLOW_EN |
    179	      RDMA_FIFO_PSEUDO_SIZE(rdma_fifo_size) |
    180	      RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold);
    181	mtk_ddp_write(cmdq_pkt, reg, &rdma->cmdq_reg, rdma->regs, DISP_REG_RDMA_FIFO_CON);
    182}
    183
    184static unsigned int rdma_fmt_convert(struct mtk_disp_rdma *rdma,
    185				     unsigned int fmt)
    186{
    187	/* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX"
    188	 * is defined in mediatek HW data sheet.
    189	 * The alphabet order in XXX is no relation to data
    190	 * arrangement in memory.
    191	 */
    192	switch (fmt) {
    193	default:
    194	case DRM_FORMAT_RGB565:
    195		return MEM_MODE_INPUT_FORMAT_RGB565;
    196	case DRM_FORMAT_BGR565:
    197		return MEM_MODE_INPUT_FORMAT_RGB565 | MEM_MODE_INPUT_SWAP;
    198	case DRM_FORMAT_RGB888:
    199		return MEM_MODE_INPUT_FORMAT_RGB888;
    200	case DRM_FORMAT_BGR888:
    201		return MEM_MODE_INPUT_FORMAT_RGB888 | MEM_MODE_INPUT_SWAP;
    202	case DRM_FORMAT_RGBX8888:
    203	case DRM_FORMAT_RGBA8888:
    204		return MEM_MODE_INPUT_FORMAT_ARGB8888;
    205	case DRM_FORMAT_BGRX8888:
    206	case DRM_FORMAT_BGRA8888:
    207		return MEM_MODE_INPUT_FORMAT_ARGB8888 | MEM_MODE_INPUT_SWAP;
    208	case DRM_FORMAT_XRGB8888:
    209	case DRM_FORMAT_ARGB8888:
    210		return MEM_MODE_INPUT_FORMAT_RGBA8888;
    211	case DRM_FORMAT_XBGR8888:
    212	case DRM_FORMAT_ABGR8888:
    213		return MEM_MODE_INPUT_FORMAT_RGBA8888 | MEM_MODE_INPUT_SWAP;
    214	case DRM_FORMAT_UYVY:
    215		return MEM_MODE_INPUT_FORMAT_UYVY;
    216	case DRM_FORMAT_YUYV:
    217		return MEM_MODE_INPUT_FORMAT_YUYV;
    218	}
    219}
    220
    221unsigned int mtk_rdma_layer_nr(struct device *dev)
    222{
    223	return 1;
    224}
    225
    226void mtk_rdma_layer_config(struct device *dev, unsigned int idx,
    227			   struct mtk_plane_state *state,
    228			   struct cmdq_pkt *cmdq_pkt)
    229{
    230	struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
    231	struct mtk_plane_pending_state *pending = &state->pending;
    232	unsigned int addr = pending->addr;
    233	unsigned int pitch = pending->pitch & 0xffff;
    234	unsigned int fmt = pending->format;
    235	unsigned int con;
    236
    237	con = rdma_fmt_convert(rdma, fmt);
    238	mtk_ddp_write_relaxed(cmdq_pkt, con, &rdma->cmdq_reg, rdma->regs, DISP_RDMA_MEM_CON);
    239
    240	if (fmt == DRM_FORMAT_UYVY || fmt == DRM_FORMAT_YUYV) {
    241		mtk_ddp_write_mask(cmdq_pkt, RDMA_MATRIX_ENABLE, &rdma->cmdq_reg, rdma->regs,
    242				   DISP_REG_RDMA_SIZE_CON_0,
    243				   RDMA_MATRIX_ENABLE);
    244		mtk_ddp_write_mask(cmdq_pkt, RDMA_MATRIX_INT_MTX_BT601_to_RGB,
    245				   &rdma->cmdq_reg, rdma->regs, DISP_REG_RDMA_SIZE_CON_0,
    246				   RDMA_MATRIX_INT_MTX_SEL);
    247	} else {
    248		mtk_ddp_write_mask(cmdq_pkt, 0, &rdma->cmdq_reg, rdma->regs,
    249				   DISP_REG_RDMA_SIZE_CON_0,
    250				   RDMA_MATRIX_ENABLE);
    251	}
    252	mtk_ddp_write_relaxed(cmdq_pkt, addr, &rdma->cmdq_reg, rdma->regs,
    253			      DISP_RDMA_MEM_START_ADDR);
    254	mtk_ddp_write_relaxed(cmdq_pkt, pitch, &rdma->cmdq_reg, rdma->regs,
    255			      DISP_RDMA_MEM_SRC_PITCH);
    256	mtk_ddp_write(cmdq_pkt, RDMA_MEM_GMC, &rdma->cmdq_reg, rdma->regs,
    257		      DISP_RDMA_MEM_GMC_SETTING_0);
    258	mtk_ddp_write_mask(cmdq_pkt, RDMA_MODE_MEMORY, &rdma->cmdq_reg, rdma->regs,
    259			   DISP_REG_RDMA_GLOBAL_CON, RDMA_MODE_MEMORY);
    260
    261}
    262
    263static int mtk_disp_rdma_bind(struct device *dev, struct device *master,
    264			      void *data)
    265{
    266	return 0;
    267
    268}
    269
    270static void mtk_disp_rdma_unbind(struct device *dev, struct device *master,
    271				 void *data)
    272{
    273}
    274
    275static const struct component_ops mtk_disp_rdma_component_ops = {
    276	.bind	= mtk_disp_rdma_bind,
    277	.unbind = mtk_disp_rdma_unbind,
    278};
    279
    280static int mtk_disp_rdma_probe(struct platform_device *pdev)
    281{
    282	struct device *dev = &pdev->dev;
    283	struct mtk_disp_rdma *priv;
    284	struct resource *res;
    285	int irq;
    286	int ret;
    287
    288	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    289	if (!priv)
    290		return -ENOMEM;
    291
    292	irq = platform_get_irq(pdev, 0);
    293	if (irq < 0)
    294		return irq;
    295
    296	priv->clk = devm_clk_get(dev, NULL);
    297	if (IS_ERR(priv->clk)) {
    298		dev_err(dev, "failed to get rdma clk\n");
    299		return PTR_ERR(priv->clk);
    300	}
    301
    302	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    303	priv->regs = devm_ioremap_resource(dev, res);
    304	if (IS_ERR(priv->regs)) {
    305		dev_err(dev, "failed to ioremap rdma\n");
    306		return PTR_ERR(priv->regs);
    307	}
    308#if IS_REACHABLE(CONFIG_MTK_CMDQ)
    309	ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
    310	if (ret)
    311		dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
    312#endif
    313
    314	if (of_find_property(dev->of_node, "mediatek,rdma-fifo-size", &ret)) {
    315		ret = of_property_read_u32(dev->of_node,
    316					   "mediatek,rdma-fifo-size",
    317					   &priv->fifo_size);
    318		if (ret) {
    319			dev_err(dev, "Failed to get rdma fifo size\n");
    320			return ret;
    321		}
    322	}
    323
    324	/* Disable and clear pending interrupts */
    325	writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE);
    326	writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);
    327
    328	ret = devm_request_irq(dev, irq, mtk_disp_rdma_irq_handler,
    329			       IRQF_TRIGGER_NONE, dev_name(dev), priv);
    330	if (ret < 0) {
    331		dev_err(dev, "Failed to request irq %d: %d\n", irq, ret);
    332		return ret;
    333	}
    334
    335	priv->data = of_device_get_match_data(dev);
    336
    337	platform_set_drvdata(pdev, priv);
    338
    339	pm_runtime_enable(dev);
    340
    341	ret = component_add(dev, &mtk_disp_rdma_component_ops);
    342	if (ret) {
    343		pm_runtime_disable(dev);
    344		dev_err(dev, "Failed to add component: %d\n", ret);
    345	}
    346
    347	return ret;
    348}
    349
    350static int mtk_disp_rdma_remove(struct platform_device *pdev)
    351{
    352	component_del(&pdev->dev, &mtk_disp_rdma_component_ops);
    353
    354	pm_runtime_disable(&pdev->dev);
    355
    356	return 0;
    357}
    358
    359static const struct mtk_disp_rdma_data mt2701_rdma_driver_data = {
    360	.fifo_size = SZ_4K,
    361};
    362
    363static const struct mtk_disp_rdma_data mt8173_rdma_driver_data = {
    364	.fifo_size = SZ_8K,
    365};
    366
    367static const struct mtk_disp_rdma_data mt8183_rdma_driver_data = {
    368	.fifo_size = 5 * SZ_1K,
    369};
    370
    371static const struct mtk_disp_rdma_data mt8192_rdma_driver_data = {
    372	.fifo_size = 5 * SZ_1K,
    373};
    374
    375static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
    376	{ .compatible = "mediatek,mt2701-disp-rdma",
    377	  .data = &mt2701_rdma_driver_data},
    378	{ .compatible = "mediatek,mt8173-disp-rdma",
    379	  .data = &mt8173_rdma_driver_data},
    380	{ .compatible = "mediatek,mt8183-disp-rdma",
    381	  .data = &mt8183_rdma_driver_data},
    382	{ .compatible = "mediatek,mt8192-disp-rdma",
    383	  .data = &mt8192_rdma_driver_data},
    384	{},
    385};
    386MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
    387
    388struct platform_driver mtk_disp_rdma_driver = {
    389	.probe		= mtk_disp_rdma_probe,
    390	.remove		= mtk_disp_rdma_remove,
    391	.driver		= {
    392		.name	= "mediatek-disp-rdma",
    393		.owner	= THIS_MODULE,
    394		.of_match_table = mtk_disp_rdma_driver_dt_match,
    395	},
    396};