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_gamma.c (5458B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2021 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/soc/mediatek/mtk-cmdq.h>
     13
     14#include "mtk_disp_drv.h"
     15#include "mtk_drm_crtc.h"
     16#include "mtk_drm_ddp_comp.h"
     17
     18#define DISP_GAMMA_EN				0x0000
     19#define GAMMA_EN					BIT(0)
     20#define DISP_GAMMA_CFG				0x0020
     21#define GAMMA_LUT_EN					BIT(1)
     22#define GAMMA_DITHERING					BIT(2)
     23#define DISP_GAMMA_SIZE				0x0030
     24#define DISP_GAMMA_LUT				0x0700
     25
     26#define LUT_10BIT_MASK				0x03ff
     27
     28struct mtk_disp_gamma_data {
     29	bool has_dither;
     30	bool lut_diff;
     31};
     32
     33/*
     34 * struct mtk_disp_gamma - DISP_GAMMA driver structure
     35 */
     36struct mtk_disp_gamma {
     37	struct clk *clk;
     38	void __iomem *regs;
     39	struct cmdq_client_reg cmdq_reg;
     40	const struct mtk_disp_gamma_data *data;
     41};
     42
     43int mtk_gamma_clk_enable(struct device *dev)
     44{
     45	struct mtk_disp_gamma *gamma = dev_get_drvdata(dev);
     46
     47	return clk_prepare_enable(gamma->clk);
     48}
     49
     50void mtk_gamma_clk_disable(struct device *dev)
     51{
     52	struct mtk_disp_gamma *gamma = dev_get_drvdata(dev);
     53
     54	clk_disable_unprepare(gamma->clk);
     55}
     56
     57void mtk_gamma_set_common(void __iomem *regs, struct drm_crtc_state *state, bool lut_diff)
     58{
     59	unsigned int i, reg;
     60	struct drm_color_lut *lut;
     61	void __iomem *lut_base;
     62	u32 word;
     63	u32 diff[3] = {0};
     64
     65	if (state->gamma_lut) {
     66		reg = readl(regs + DISP_GAMMA_CFG);
     67		reg = reg | GAMMA_LUT_EN;
     68		writel(reg, regs + DISP_GAMMA_CFG);
     69		lut_base = regs + DISP_GAMMA_LUT;
     70		lut = (struct drm_color_lut *)state->gamma_lut->data;
     71		for (i = 0; i < MTK_LUT_SIZE; i++) {
     72
     73			if (!lut_diff || (i % 2 == 0)) {
     74				word = (((lut[i].red >> 6) & LUT_10BIT_MASK) << 20) +
     75					(((lut[i].green >> 6) & LUT_10BIT_MASK) << 10) +
     76					((lut[i].blue >> 6) & LUT_10BIT_MASK);
     77			} else {
     78				diff[0] = (lut[i].red >> 6) - (lut[i - 1].red >> 6);
     79				diff[1] = (lut[i].green >> 6) - (lut[i - 1].green >> 6);
     80				diff[2] = (lut[i].blue >> 6) - (lut[i - 1].blue >> 6);
     81
     82				word = ((diff[0] & LUT_10BIT_MASK) << 20) +
     83					((diff[1] & LUT_10BIT_MASK) << 10) +
     84					(diff[2] & LUT_10BIT_MASK);
     85			}
     86			writel(word, (lut_base + i * 4));
     87		}
     88	}
     89}
     90
     91void mtk_gamma_set(struct device *dev, struct drm_crtc_state *state)
     92{
     93	struct mtk_disp_gamma *gamma = dev_get_drvdata(dev);
     94	bool lut_diff = false;
     95
     96	if (gamma->data)
     97		lut_diff = gamma->data->lut_diff;
     98
     99	mtk_gamma_set_common(gamma->regs, state, lut_diff);
    100}
    101
    102void mtk_gamma_config(struct device *dev, unsigned int w,
    103		      unsigned int h, unsigned int vrefresh,
    104		      unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
    105{
    106	struct mtk_disp_gamma *gamma = dev_get_drvdata(dev);
    107
    108	mtk_ddp_write(cmdq_pkt, h << 16 | w, &gamma->cmdq_reg, gamma->regs,
    109		      DISP_GAMMA_SIZE);
    110	if (gamma->data && gamma->data->has_dither)
    111		mtk_dither_set_common(gamma->regs, &gamma->cmdq_reg, bpc,
    112				      DISP_GAMMA_CFG, GAMMA_DITHERING, cmdq_pkt);
    113}
    114
    115void mtk_gamma_start(struct device *dev)
    116{
    117	struct mtk_disp_gamma *gamma = dev_get_drvdata(dev);
    118
    119	writel(GAMMA_EN, gamma->regs + DISP_GAMMA_EN);
    120}
    121
    122void mtk_gamma_stop(struct device *dev)
    123{
    124	struct mtk_disp_gamma *gamma = dev_get_drvdata(dev);
    125
    126	writel_relaxed(0x0, gamma->regs + DISP_GAMMA_EN);
    127}
    128
    129static int mtk_disp_gamma_bind(struct device *dev, struct device *master,
    130			       void *data)
    131{
    132	return 0;
    133}
    134
    135static void mtk_disp_gamma_unbind(struct device *dev, struct device *master,
    136				  void *data)
    137{
    138}
    139
    140static const struct component_ops mtk_disp_gamma_component_ops = {
    141	.bind	= mtk_disp_gamma_bind,
    142	.unbind = mtk_disp_gamma_unbind,
    143};
    144
    145static int mtk_disp_gamma_probe(struct platform_device *pdev)
    146{
    147	struct device *dev = &pdev->dev;
    148	struct mtk_disp_gamma *priv;
    149	struct resource *res;
    150	int ret;
    151
    152	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    153	if (!priv)
    154		return -ENOMEM;
    155
    156	priv->clk = devm_clk_get(dev, NULL);
    157	if (IS_ERR(priv->clk)) {
    158		dev_err(dev, "failed to get gamma clk\n");
    159		return PTR_ERR(priv->clk);
    160	}
    161
    162	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    163	priv->regs = devm_ioremap_resource(dev, res);
    164	if (IS_ERR(priv->regs)) {
    165		dev_err(dev, "failed to ioremap gamma\n");
    166		return PTR_ERR(priv->regs);
    167	}
    168
    169#if IS_REACHABLE(CONFIG_MTK_CMDQ)
    170	ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
    171	if (ret)
    172		dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
    173#endif
    174
    175	priv->data = of_device_get_match_data(dev);
    176	platform_set_drvdata(pdev, priv);
    177
    178	ret = component_add(dev, &mtk_disp_gamma_component_ops);
    179	if (ret)
    180		dev_err(dev, "Failed to add component: %d\n", ret);
    181
    182	return ret;
    183}
    184
    185static int mtk_disp_gamma_remove(struct platform_device *pdev)
    186{
    187	component_del(&pdev->dev, &mtk_disp_gamma_component_ops);
    188
    189	return 0;
    190}
    191
    192static const struct mtk_disp_gamma_data mt8173_gamma_driver_data = {
    193	.has_dither = true,
    194};
    195
    196static const struct mtk_disp_gamma_data mt8183_gamma_driver_data = {
    197	.lut_diff = true,
    198};
    199
    200static const struct of_device_id mtk_disp_gamma_driver_dt_match[] = {
    201	{ .compatible = "mediatek,mt8173-disp-gamma",
    202	  .data = &mt8173_gamma_driver_data},
    203	{ .compatible = "mediatek,mt8183-disp-gamma",
    204	  .data = &mt8183_gamma_driver_data},
    205	{},
    206};
    207MODULE_DEVICE_TABLE(of, mtk_disp_gamma_driver_dt_match);
    208
    209struct platform_driver mtk_disp_gamma_driver = {
    210	.probe		= mtk_disp_gamma_probe,
    211	.remove		= mtk_disp_gamma_remove,
    212	.driver		= {
    213		.name	= "mediatek-disp-gamma",
    214		.owner	= THIS_MODULE,
    215		.of_match_table = mtk_disp_gamma_driver_dt_match,
    216	},
    217};