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