File Index
Files and directories
Sign in
FILE

mtk_disp_ccorr.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c C
  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.h>
 10#include <linux/platform_device.h>
 11#include <linux/soc/mediatek/mtk-cmdq.h>
 12
 13#include "mtk_crtc.h"
 14#include "mtk_ddp_comp.h"
 15#include "mtk_disp_drv.h"
 16#include "mtk_drm_drv.h"
 17
 18#define DISP_CCORR_EN				0x0000
 19#define CCORR_EN					BIT(0)
 20#define DISP_CCORR_CFG				0x0020
 21#define CCORR_RELAY_MODE				BIT(0)
 22#define CCORR_ENGINE_EN					BIT(1)
 23#define CCORR_GAMMA_OFF					BIT(2)
 24#define CCORR_WGAMUT_SRC_CLIP				BIT(3)
 25#define DISP_CCORR_SIZE				0x0030
 26#define DISP_CCORR_COEF_0			0x0080
 27#define DISP_CCORR_COEF_1			0x0084
 28#define DISP_CCORR_COEF_2			0x0088
 29#define DISP_CCORR_COEF_3			0x008C
 30#define DISP_CCORR_COEF_4			0x0090
 31
 32struct mtk_disp_ccorr_data {
 33	u32 matrix_bits;
 34};
 35
 36struct mtk_disp_ccorr {
 37	struct clk *clk;
 38	void __iomem *regs;
 39	struct cmdq_client_reg cmdq_reg;
 40	const struct mtk_disp_ccorr_data	*data;
 41};
 42
 43int mtk_ccorr_clk_enable(struct device *dev)
 44{
 45	struct mtk_disp_ccorr *ccorr = dev_get_drvdata(dev);
 46
 47	return clk_prepare_enable(ccorr->clk);
 48}
 49
 50void mtk_ccorr_clk_disable(struct device *dev)
 51{
 52	struct mtk_disp_ccorr *ccorr = dev_get_drvdata(dev);
 53
 54	clk_disable_unprepare(ccorr->clk);
 55}
 56
 57void mtk_ccorr_config(struct device *dev, unsigned int w,
 58			     unsigned int h, unsigned int vrefresh,
 59			     unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
 60{
 61	struct mtk_disp_ccorr *ccorr = dev_get_drvdata(dev);
 62
 63	mtk_ddp_write(cmdq_pkt, w << 16 | h, &ccorr->cmdq_reg, ccorr->regs,
 64		      DISP_CCORR_SIZE);
 65	mtk_ddp_write(cmdq_pkt, CCORR_ENGINE_EN, &ccorr->cmdq_reg, ccorr->regs,
 66		      DISP_CCORR_CFG);
 67}
 68
 69void mtk_ccorr_start(struct device *dev)
 70{
 71	struct mtk_disp_ccorr *ccorr = dev_get_drvdata(dev);
 72
 73	writel(CCORR_EN, ccorr->regs + DISP_CCORR_EN);
 74}
 75
 76void mtk_ccorr_stop(struct device *dev)
 77{
 78	struct mtk_disp_ccorr *ccorr = dev_get_drvdata(dev);
 79
 80	writel_relaxed(0x0, ccorr->regs + DISP_CCORR_EN);
 81}
 82
 83void mtk_ccorr_ctm_set(struct device *dev, struct drm_crtc_state *state)
 84{
 85	struct mtk_disp_ccorr *ccorr = dev_get_drvdata(dev);
 86	struct drm_property_blob *blob = state->ctm;
 87	struct drm_color_ctm *ctm;
 88	const u64 *input;
 89	uint16_t coeffs[9] = { 0 };
 90	int i;
 91	struct cmdq_pkt *cmdq_pkt = NULL;
 92	u32 matrix_bits = ccorr->data->matrix_bits;
 93
 94	if (!blob)
 95		return;
 96
 97	ctm = (struct drm_color_ctm *)blob->data;
 98	input = ctm->matrix;
 99
100	for (i = 0; i < ARRAY_SIZE(coeffs); i++)
101		coeffs[i] = drm_color_ctm_s31_32_to_qm_n(input[i], 2, matrix_bits);
102
103	mtk_ddp_write(cmdq_pkt, coeffs[0] << 16 | coeffs[1],
104		      &ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_0);
105	mtk_ddp_write(cmdq_pkt, coeffs[2] << 16 | coeffs[3],
106		      &ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_1);
107	mtk_ddp_write(cmdq_pkt, coeffs[4] << 16 | coeffs[5],
108		      &ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_2);
109	mtk_ddp_write(cmdq_pkt, coeffs[6] << 16 | coeffs[7],
110		      &ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_3);
111	mtk_ddp_write(cmdq_pkt, coeffs[8] << 16,
112		      &ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_4);
113}
114
115static int mtk_disp_ccorr_bind(struct device *dev, struct device *master,
116			       void *data)
117{
118	return 0;
119}
120
121static void mtk_disp_ccorr_unbind(struct device *dev, struct device *master,
122				  void *data)
123{
124}
125
126static const struct component_ops mtk_disp_ccorr_component_ops = {
127	.bind	= mtk_disp_ccorr_bind,
128	.unbind	= mtk_disp_ccorr_unbind,
129};
130
131static int mtk_disp_ccorr_probe(struct platform_device *pdev)
132{
133	struct device *dev = &pdev->dev;
134	struct mtk_disp_ccorr *priv;
135	int ret;
136
137	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
138	if (!priv)
139		return -ENOMEM;
140
141	priv->clk = devm_clk_get(dev, NULL);
142	if (IS_ERR(priv->clk))
143		return dev_err_probe(dev, PTR_ERR(priv->clk),
144				     "failed to get ccorr clk\n");
145
146	priv->regs = devm_platform_ioremap_resource(pdev, 0);
147	if (IS_ERR(priv->regs))
148		return dev_err_probe(dev, PTR_ERR(priv->regs),
149				     "failed to ioremap ccorr\n");
150
151#if IS_REACHABLE(CONFIG_MTK_CMDQ)
152	ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
153	if (ret)
154		dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
155#endif
156
157	priv->data = of_device_get_match_data(dev);
158	platform_set_drvdata(pdev, priv);
159
160	ret = component_add(dev, &mtk_disp_ccorr_component_ops);
161	if (ret)
162		return dev_err_probe(dev, ret, "Failed to add component\n");
163
164	return 0;
165}
166
167static void mtk_disp_ccorr_remove(struct platform_device *pdev)
168{
169	component_del(&pdev->dev, &mtk_disp_ccorr_component_ops);
170}
171
172static const struct mtk_disp_ccorr_data mt8183_ccorr_driver_data = {
173	.matrix_bits = 10,
174};
175
176static const struct mtk_disp_ccorr_data mt8192_ccorr_driver_data = {
177	.matrix_bits = 11,
178};
179
180static const struct of_device_id mtk_disp_ccorr_driver_dt_match[] = {
181	{ .compatible = "mediatek,mt8183-disp-ccorr",
182	  .data = &mt8183_ccorr_driver_data},
183	{ .compatible = "mediatek,mt8192-disp-ccorr",
184	  .data = &mt8192_ccorr_driver_data},
185	{},
186};
187MODULE_DEVICE_TABLE(of, mtk_disp_ccorr_driver_dt_match);
188
189struct platform_driver mtk_disp_ccorr_driver = {
190	.probe		= mtk_disp_ccorr_probe,
191	.remove		= mtk_disp_ccorr_remove,
192	.driver		= {
193		.name	= "mediatek-disp-ccorr",
194		.of_match_table = mtk_disp_ccorr_driver_dt_match,
195	},
196};
~/ Read-only file preview.