xref: /openbmc/linux/drivers/gpu/drm/mediatek/mtk_disp_aal.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
178d1783cSYongqiang Niu // SPDX-License-Identifier: GPL-2.0-only
278d1783cSYongqiang Niu /*
378d1783cSYongqiang Niu  * Copyright (c) 2021 MediaTek Inc.
478d1783cSYongqiang Niu  */
578d1783cSYongqiang Niu 
678d1783cSYongqiang Niu #include <linux/clk.h>
778d1783cSYongqiang Niu #include <linux/component.h>
878d1783cSYongqiang Niu #include <linux/module.h>
9722d4f06SRob Herring #include <linux/of.h>
1078d1783cSYongqiang Niu #include <linux/platform_device.h>
1178d1783cSYongqiang Niu #include <linux/soc/mediatek/mtk-cmdq.h>
1278d1783cSYongqiang Niu 
1378d1783cSYongqiang Niu #include "mtk_disp_drv.h"
1478d1783cSYongqiang Niu #include "mtk_drm_crtc.h"
1578d1783cSYongqiang Niu #include "mtk_drm_ddp_comp.h"
16807e2f3fSMiles Chen #include "mtk_drm_drv.h"
1778d1783cSYongqiang Niu 
1878d1783cSYongqiang Niu #define DISP_AAL_EN				0x0000
1978d1783cSYongqiang Niu #define AAL_EN						BIT(0)
2078d1783cSYongqiang Niu #define DISP_AAL_SIZE				0x0030
21477f70cdSLinus Torvalds #define DISP_AAL_OUTPUT_SIZE			0x04d8
2278d1783cSYongqiang Niu 
2378d1783cSYongqiang Niu 
2478d1783cSYongqiang Niu struct mtk_disp_aal_data {
2578d1783cSYongqiang Niu 	bool has_gamma;
2678d1783cSYongqiang Niu };
2778d1783cSYongqiang Niu 
2878d1783cSYongqiang Niu struct mtk_disp_aal {
2978d1783cSYongqiang Niu 	struct clk *clk;
3078d1783cSYongqiang Niu 	void __iomem *regs;
3178d1783cSYongqiang Niu 	struct cmdq_client_reg cmdq_reg;
3278d1783cSYongqiang Niu 	const struct mtk_disp_aal_data *data;
3378d1783cSYongqiang Niu };
3478d1783cSYongqiang Niu 
mtk_aal_clk_enable(struct device * dev)3578d1783cSYongqiang Niu int mtk_aal_clk_enable(struct device *dev)
3678d1783cSYongqiang Niu {
3778d1783cSYongqiang Niu 	struct mtk_disp_aal *aal = dev_get_drvdata(dev);
3878d1783cSYongqiang Niu 
3978d1783cSYongqiang Niu 	return clk_prepare_enable(aal->clk);
4078d1783cSYongqiang Niu }
4178d1783cSYongqiang Niu 
mtk_aal_clk_disable(struct device * dev)4278d1783cSYongqiang Niu void mtk_aal_clk_disable(struct device *dev)
4378d1783cSYongqiang Niu {
4478d1783cSYongqiang Niu 	struct mtk_disp_aal *aal = dev_get_drvdata(dev);
4578d1783cSYongqiang Niu 
4678d1783cSYongqiang Niu 	clk_disable_unprepare(aal->clk);
4778d1783cSYongqiang Niu }
4878d1783cSYongqiang Niu 
mtk_aal_config(struct device * dev,unsigned int w,unsigned int h,unsigned int vrefresh,unsigned int bpc,struct cmdq_pkt * cmdq_pkt)4978d1783cSYongqiang Niu void mtk_aal_config(struct device *dev, unsigned int w,
5078d1783cSYongqiang Niu 			   unsigned int h, unsigned int vrefresh,
5178d1783cSYongqiang Niu 			   unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
5278d1783cSYongqiang Niu {
5378d1783cSYongqiang Niu 	struct mtk_disp_aal *aal = dev_get_drvdata(dev);
5478d1783cSYongqiang Niu 
5578d1783cSYongqiang Niu 	mtk_ddp_write(cmdq_pkt, w << 16 | h, &aal->cmdq_reg, aal->regs, DISP_AAL_SIZE);
56477f70cdSLinus Torvalds 	mtk_ddp_write(cmdq_pkt, w << 16 | h, &aal->cmdq_reg, aal->regs, DISP_AAL_OUTPUT_SIZE);
5778d1783cSYongqiang Niu }
5878d1783cSYongqiang Niu 
mtk_aal_gamma_set(struct device * dev,struct drm_crtc_state * state)5978d1783cSYongqiang Niu void mtk_aal_gamma_set(struct device *dev, struct drm_crtc_state *state)
6078d1783cSYongqiang Niu {
6178d1783cSYongqiang Niu 	struct mtk_disp_aal *aal = dev_get_drvdata(dev);
6278d1783cSYongqiang Niu 
6378d1783cSYongqiang Niu 	if (aal->data && aal->data->has_gamma)
64ba99d08dSYongqiang Niu 		mtk_gamma_set_common(aal->regs, state, false);
6578d1783cSYongqiang Niu }
6678d1783cSYongqiang Niu 
mtk_aal_start(struct device * dev)6778d1783cSYongqiang Niu void mtk_aal_start(struct device *dev)
6878d1783cSYongqiang Niu {
6978d1783cSYongqiang Niu 	struct mtk_disp_aal *aal = dev_get_drvdata(dev);
7078d1783cSYongqiang Niu 
7178d1783cSYongqiang Niu 	writel(AAL_EN, aal->regs + DISP_AAL_EN);
7278d1783cSYongqiang Niu }
7378d1783cSYongqiang Niu 
mtk_aal_stop(struct device * dev)7478d1783cSYongqiang Niu void mtk_aal_stop(struct device *dev)
7578d1783cSYongqiang Niu {
7678d1783cSYongqiang Niu 	struct mtk_disp_aal *aal = dev_get_drvdata(dev);
7778d1783cSYongqiang Niu 
7878d1783cSYongqiang Niu 	writel_relaxed(0x0, aal->regs + DISP_AAL_EN);
7978d1783cSYongqiang Niu }
8078d1783cSYongqiang Niu 
mtk_disp_aal_bind(struct device * dev,struct device * master,void * data)8178d1783cSYongqiang Niu static int mtk_disp_aal_bind(struct device *dev, struct device *master,
8278d1783cSYongqiang Niu 			       void *data)
8378d1783cSYongqiang Niu {
8478d1783cSYongqiang Niu 	return 0;
8578d1783cSYongqiang Niu }
8678d1783cSYongqiang Niu 
mtk_disp_aal_unbind(struct device * dev,struct device * master,void * data)8778d1783cSYongqiang Niu static void mtk_disp_aal_unbind(struct device *dev, struct device *master,
8878d1783cSYongqiang Niu 				  void *data)
8978d1783cSYongqiang Niu {
9078d1783cSYongqiang Niu }
9178d1783cSYongqiang Niu 
9278d1783cSYongqiang Niu static const struct component_ops mtk_disp_aal_component_ops = {
9378d1783cSYongqiang Niu 	.bind	= mtk_disp_aal_bind,
9478d1783cSYongqiang Niu 	.unbind = mtk_disp_aal_unbind,
9578d1783cSYongqiang Niu };
9678d1783cSYongqiang Niu 
mtk_disp_aal_probe(struct platform_device * pdev)9778d1783cSYongqiang Niu static int mtk_disp_aal_probe(struct platform_device *pdev)
9878d1783cSYongqiang Niu {
9978d1783cSYongqiang Niu 	struct device *dev = &pdev->dev;
10078d1783cSYongqiang Niu 	struct mtk_disp_aal *priv;
10178d1783cSYongqiang Niu 	struct resource *res;
10278d1783cSYongqiang Niu 	int ret;
10378d1783cSYongqiang Niu 
10478d1783cSYongqiang Niu 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
10578d1783cSYongqiang Niu 	if (!priv)
10678d1783cSYongqiang Niu 		return -ENOMEM;
10778d1783cSYongqiang Niu 
10878d1783cSYongqiang Niu 	priv->clk = devm_clk_get(dev, NULL);
10978d1783cSYongqiang Niu 	if (IS_ERR(priv->clk)) {
11078d1783cSYongqiang Niu 		dev_err(dev, "failed to get aal clk\n");
11178d1783cSYongqiang Niu 		return PTR_ERR(priv->clk);
11278d1783cSYongqiang Niu 	}
11378d1783cSYongqiang Niu 
11478d1783cSYongqiang Niu 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
11578d1783cSYongqiang Niu 	priv->regs = devm_ioremap_resource(dev, res);
11678d1783cSYongqiang Niu 	if (IS_ERR(priv->regs)) {
11778d1783cSYongqiang Niu 		dev_err(dev, "failed to ioremap aal\n");
11878d1783cSYongqiang Niu 		return PTR_ERR(priv->regs);
11978d1783cSYongqiang Niu 	}
12078d1783cSYongqiang Niu 
12178d1783cSYongqiang Niu #if IS_REACHABLE(CONFIG_MTK_CMDQ)
12278d1783cSYongqiang Niu 	ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
12378d1783cSYongqiang Niu 	if (ret)
12478d1783cSYongqiang Niu 		dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
12578d1783cSYongqiang Niu #endif
12678d1783cSYongqiang Niu 
12778d1783cSYongqiang Niu 	priv->data = of_device_get_match_data(dev);
12878d1783cSYongqiang Niu 	platform_set_drvdata(pdev, priv);
12978d1783cSYongqiang Niu 
13078d1783cSYongqiang Niu 	ret = component_add(dev, &mtk_disp_aal_component_ops);
13178d1783cSYongqiang Niu 	if (ret)
13278d1783cSYongqiang Niu 		dev_err(dev, "Failed to add component: %d\n", ret);
13378d1783cSYongqiang Niu 
13478d1783cSYongqiang Niu 	return ret;
13578d1783cSYongqiang Niu }
13678d1783cSYongqiang Niu 
mtk_disp_aal_remove(struct platform_device * pdev)137*b3af12a0SUwe Kleine-König static void mtk_disp_aal_remove(struct platform_device *pdev)
13878d1783cSYongqiang Niu {
13978d1783cSYongqiang Niu 	component_del(&pdev->dev, &mtk_disp_aal_component_ops);
14078d1783cSYongqiang Niu }
14178d1783cSYongqiang Niu 
14278d1783cSYongqiang Niu static const struct mtk_disp_aal_data mt8173_aal_driver_data = {
14378d1783cSYongqiang Niu 	.has_gamma = true,
14478d1783cSYongqiang Niu };
14578d1783cSYongqiang Niu 
14678d1783cSYongqiang Niu static const struct of_device_id mtk_disp_aal_driver_dt_match[] = {
14778d1783cSYongqiang Niu 	{ .compatible = "mediatek,mt8173-disp-aal",
14878d1783cSYongqiang Niu 	  .data = &mt8173_aal_driver_data},
149c7ef8f35SYongqiang Niu 	{ .compatible = "mediatek,mt8183-disp-aal"},
15078d1783cSYongqiang Niu 	{},
15178d1783cSYongqiang Niu };
15278d1783cSYongqiang Niu MODULE_DEVICE_TABLE(of, mtk_disp_aal_driver_dt_match);
15378d1783cSYongqiang Niu 
15478d1783cSYongqiang Niu struct platform_driver mtk_disp_aal_driver = {
15578d1783cSYongqiang Niu 	.probe		= mtk_disp_aal_probe,
156*b3af12a0SUwe Kleine-König 	.remove_new	= mtk_disp_aal_remove,
15778d1783cSYongqiang Niu 	.driver		= {
15878d1783cSYongqiang Niu 		.name	= "mediatek-disp-aal",
15978d1783cSYongqiang Niu 		.owner	= THIS_MODULE,
16078d1783cSYongqiang Niu 		.of_match_table = mtk_disp_aal_driver_dt_match,
16178d1783cSYongqiang Niu 	},
16278d1783cSYongqiang Niu };
163