1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2016-2017 Lucas Stach, Pengutronix
4 */
5
6#include <drm/drm_fourcc.h>
7#include <linux/clk.h>
8#include <linux/err.h>
9#include <linux/iopoll.h>
10#include <linux/mfd/syscon.h>
11#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/platform_device.h>
15#include <linux/pm_runtime.h>
16#include <linux/regmap.h>
17#include <video/imx-ipu-v3.h>
18
19#include "ipu-prv.h"
20
21#define IPU_PRG_CTL				0x00
22#define  IPU_PRG_CTL_BYPASS(i)			(1 << (0 + i))
23#define  IPU_PRG_CTL_SOFT_ARID_MASK		0x3
24#define  IPU_PRG_CTL_SOFT_ARID_SHIFT(i)		(8 + i * 2)
25#define  IPU_PRG_CTL_SOFT_ARID(i, v)		((v & 0x3) << (8 + 2 * i))
26#define  IPU_PRG_CTL_SO(i)			(1 << (16 + i))
27#define  IPU_PRG_CTL_VFLIP(i)			(1 << (19 + i))
28#define  IPU_PRG_CTL_BLOCK_MODE(i)		(1 << (22 + i))
29#define  IPU_PRG_CTL_CNT_LOAD_EN(i)		(1 << (25 + i))
30#define  IPU_PRG_CTL_SOFTRST			(1 << 30)
31#define  IPU_PRG_CTL_SHADOW_EN			(1 << 31)
32
33#define IPU_PRG_STATUS				0x04
34#define  IPU_PRG_STATUS_BUFFER0_READY(i)	(1 << (0 + i * 2))
35#define  IPU_PRG_STATUS_BUFFER1_READY(i)	(1 << (1 + i * 2))
36
37#define IPU_PRG_QOS				0x08
38#define  IPU_PRG_QOS_ARID_MASK			0xf
39#define  IPU_PRG_QOS_ARID_SHIFT(i)		(0 + i * 4)
40
41#define IPU_PRG_REG_UPDATE			0x0c
42#define  IPU_PRG_REG_UPDATE_REG_UPDATE		(1 << 0)
43
44#define IPU_PRG_STRIDE(i)			(0x10 + i * 0x4)
45#define  IPU_PRG_STRIDE_STRIDE_MASK		0x3fff
46
47#define IPU_PRG_CROP_LINE			0x1c
48
49#define IPU_PRG_THD				0x20
50
51#define IPU_PRG_BADDR(i)			(0x24 + i * 0x4)
52
53#define IPU_PRG_OFFSET(i)			(0x30 + i * 0x4)
54
55#define IPU_PRG_ILO(i)				(0x3c + i * 0x4)
56
57#define IPU_PRG_HEIGHT(i)			(0x48 + i * 0x4)
58#define  IPU_PRG_HEIGHT_PRE_HEIGHT_MASK		0xfff
59#define  IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT	0
60#define  IPU_PRG_HEIGHT_IPU_HEIGHT_MASK		0xfff
61#define  IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT	16
62
63struct ipu_prg_channel {
64	bool			enabled;
65	int			used_pre;
66};
67
68struct ipu_prg {
69	struct list_head	list;
70	struct device		*dev;
71	int			id;
72
73	void __iomem		*regs;
74	struct clk		*clk_ipg, *clk_axi;
75	struct regmap		*iomuxc_gpr;
76	struct ipu_pre		*pres[3];
77
78	struct ipu_prg_channel	chan[3];
79};
80
81static DEFINE_MUTEX(ipu_prg_list_mutex);
82static LIST_HEAD(ipu_prg_list);
83
84struct ipu_prg *
85ipu_prg_lookup_by_phandle(struct device *dev, const char *name, int ipu_id)
86{
87	struct device_node *prg_node = of_parse_phandle(dev->of_node,
88							name, 0);
89	struct ipu_prg *prg;
90
91	mutex_lock(&ipu_prg_list_mutex);
92	list_for_each_entry(prg, &ipu_prg_list, list) {
93		if (prg_node == prg->dev->of_node) {
94			mutex_unlock(&ipu_prg_list_mutex);
95			device_link_add(dev, prg->dev,
96					DL_FLAG_AUTOREMOVE_CONSUMER);
97			prg->id = ipu_id;
98			of_node_put(prg_node);
99			return prg;
100		}
101	}
102	mutex_unlock(&ipu_prg_list_mutex);
103
104	of_node_put(prg_node);
105
106	return NULL;
107}
108
109int ipu_prg_max_active_channels(void)
110{
111	return ipu_pre_get_available_count();
112}
113EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels);
114
115bool ipu_prg_present(struct ipu_soc *ipu)
116{
117	if (ipu->prg_priv)
118		return true;
119
120	return false;
121}
122EXPORT_SYMBOL_GPL(ipu_prg_present);
123
124bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format,
125			      uint64_t modifier)
126{
127	const struct drm_format_info *info = drm_format_info(format);
128
129	if (info->num_planes != 1)
130		return false;
131
132	switch (modifier) {
133	case DRM_FORMAT_MOD_LINEAR:
134	case DRM_FORMAT_MOD_VIVANTE_TILED:
135	case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
136		return true;
137	default:
138		return false;
139	}
140}
141EXPORT_SYMBOL_GPL(ipu_prg_format_supported);
142
143int ipu_prg_enable(struct ipu_soc *ipu)
144{
145	struct ipu_prg *prg = ipu->prg_priv;
146
147	if (!prg)
148		return 0;
149
150	return pm_runtime_get_sync(prg->dev);
151}
152EXPORT_SYMBOL_GPL(ipu_prg_enable);
153
154void ipu_prg_disable(struct ipu_soc *ipu)
155{
156	struct ipu_prg *prg = ipu->prg_priv;
157
158	if (!prg)
159		return;
160
161	pm_runtime_put(prg->dev);
162}
163EXPORT_SYMBOL_GPL(ipu_prg_disable);
164
165/*
166 * The channel configuartion functions below are not thread safe, as they
167 * must be only called from the atomic commit path in the DRM driver, which
168 * is properly serialized.
169 */
170static int ipu_prg_ipu_to_prg_chan(int ipu_chan)
171{
172	/*
173	 * This isn't clearly documented in the RM, but IPU to PRG channel
174	 * assignment is fixed, as only with this mapping the control signals
175	 * match up.
176	 */
177	switch (ipu_chan) {
178	case IPUV3_CHANNEL_MEM_BG_SYNC:
179		return 0;
180	case IPUV3_CHANNEL_MEM_FG_SYNC:
181		return 1;
182	case IPUV3_CHANNEL_MEM_DC_SYNC:
183		return 2;
184	default:
185		return -EINVAL;
186	}
187}
188
189static int ipu_prg_get_pre(struct ipu_prg *prg, int prg_chan)
190{
191	int i, ret;
192
193	/* channel 0 is special as it is hardwired to one of the PREs */
194	if (prg_chan == 0) {
195		ret = ipu_pre_get(prg->pres[0]);
196		if (ret)
197			goto fail;
198		prg->chan[prg_chan].used_pre = 0;
199		return 0;
200	}
201
202	for (i = 1; i < 3; i++) {
203		ret = ipu_pre_get(prg->pres[i]);
204		if (!ret) {
205			u32 val, mux;
206			int shift;
207
208			prg->chan[prg_chan].used_pre = i;
209
210			/* configure the PRE to PRG channel mux */
211			shift = (i == 1) ? 12 : 14;
212			mux = (prg->id << 1) | (prg_chan - 1);
213			regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
214					   0x3 << shift, mux << shift);
215
216			/* check other mux, must not point to same channel */
217			shift = (i == 1) ? 14 : 12;
218			regmap_read(prg->iomuxc_gpr, IOMUXC_GPR5, &val);
219			if (((val >> shift) & 0x3) == mux) {
220				regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
221						   0x3 << shift,
222						   (mux ^ 0x1) << shift);
223			}
224
225			return 0;
226		}
227	}
228
229fail:
230	dev_err(prg->dev, "could not get PRE for PRG chan %d", prg_chan);
231	return ret;
232}
233
234static void ipu_prg_put_pre(struct ipu_prg *prg, int prg_chan)
235{
236	struct ipu_prg_channel *chan = &prg->chan[prg_chan];
237
238	ipu_pre_put(prg->pres[chan->used_pre]);
239	chan->used_pre = -1;
240}
241
242void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan)
243{
244	int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
245	struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
246	struct ipu_prg_channel *chan;
247	u32 val;
248
249	if (prg_chan < 0)
250		return;
251
252	chan = &prg->chan[prg_chan];
253	if (!chan->enabled)
254		return;
255
256	pm_runtime_get_sync(prg->dev);
257
258	val = readl(prg->regs + IPU_PRG_CTL);
259	val |= IPU_PRG_CTL_BYPASS(prg_chan);
260	writel(val, prg->regs + IPU_PRG_CTL);
261
262	val = IPU_PRG_REG_UPDATE_REG_UPDATE;
263	writel(val, prg->regs + IPU_PRG_REG_UPDATE);
264
265	pm_runtime_put(prg->dev);
266
267	ipu_prg_put_pre(prg, prg_chan);
268
269	chan->enabled = false;
270}
271EXPORT_SYMBOL_GPL(ipu_prg_channel_disable);
272
273int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
274			      unsigned int axi_id, unsigned int width,
275			      unsigned int height, unsigned int stride,
276			      u32 format, uint64_t modifier, unsigned long *eba)
277{
278	int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
279	struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
280	struct ipu_prg_channel *chan;
281	u32 val;
282	int ret;
283
284	if (prg_chan < 0)
285		return prg_chan;
286
287	chan = &prg->chan[prg_chan];
288
289	if (chan->enabled) {
290		ipu_pre_update(prg->pres[chan->used_pre], *eba);
291		return 0;
292	}
293
294	ret = ipu_prg_get_pre(prg, prg_chan);
295	if (ret)
296		return ret;
297
298	ipu_pre_configure(prg->pres[chan->used_pre],
299			  width, height, stride, format, modifier, *eba);
300
301
302	pm_runtime_get_sync(prg->dev);
303
304	val = (stride - 1) & IPU_PRG_STRIDE_STRIDE_MASK;
305	writel(val, prg->regs + IPU_PRG_STRIDE(prg_chan));
306
307	val = ((height & IPU_PRG_HEIGHT_PRE_HEIGHT_MASK) <<
308	       IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT) |
309	      ((height & IPU_PRG_HEIGHT_IPU_HEIGHT_MASK) <<
310	       IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT);
311	writel(val, prg->regs + IPU_PRG_HEIGHT(prg_chan));
312
313	val = ipu_pre_get_baddr(prg->pres[chan->used_pre]);
314	*eba = val;
315	writel(val, prg->regs + IPU_PRG_BADDR(prg_chan));
316
317	val = readl(prg->regs + IPU_PRG_CTL);
318	/* config AXI ID */
319	val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK <<
320		 IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan));
321	val |= IPU_PRG_CTL_SOFT_ARID(prg_chan, axi_id);
322	/* enable channel */
323	val &= ~IPU_PRG_CTL_BYPASS(prg_chan);
324	writel(val, prg->regs + IPU_PRG_CTL);
325
326	val = IPU_PRG_REG_UPDATE_REG_UPDATE;
327	writel(val, prg->regs + IPU_PRG_REG_UPDATE);
328
329	/* wait for both double buffers to be filled */
330	readl_poll_timeout(prg->regs + IPU_PRG_STATUS, val,
331			   (val & IPU_PRG_STATUS_BUFFER0_READY(prg_chan)) &&
332			   (val & IPU_PRG_STATUS_BUFFER1_READY(prg_chan)),
333			   5, 1000);
334
335	pm_runtime_put(prg->dev);
336
337	chan->enabled = true;
338	return 0;
339}
340EXPORT_SYMBOL_GPL(ipu_prg_channel_configure);
341
342bool ipu_prg_channel_configure_pending(struct ipuv3_channel *ipu_chan)
343{
344	int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
345	struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
346	struct ipu_prg_channel *chan;
347
348	if (prg_chan < 0)
349		return false;
350
351	chan = &prg->chan[prg_chan];
352	WARN_ON(!chan->enabled);
353
354	return ipu_pre_update_pending(prg->pres[chan->used_pre]);
355}
356EXPORT_SYMBOL_GPL(ipu_prg_channel_configure_pending);
357
358static int ipu_prg_probe(struct platform_device *pdev)
359{
360	struct device *dev = &pdev->dev;
361	struct ipu_prg *prg;
362	u32 val;
363	int i, ret;
364
365	prg = devm_kzalloc(dev, sizeof(*prg), GFP_KERNEL);
366	if (!prg)
367		return -ENOMEM;
368
369	prg->regs = devm_platform_ioremap_resource(pdev, 0);
370	if (IS_ERR(prg->regs))
371		return PTR_ERR(prg->regs);
372
373	prg->clk_ipg = devm_clk_get(dev, "ipg");
374	if (IS_ERR(prg->clk_ipg))
375		return PTR_ERR(prg->clk_ipg);
376
377	prg->clk_axi = devm_clk_get(dev, "axi");
378	if (IS_ERR(prg->clk_axi))
379		return PTR_ERR(prg->clk_axi);
380
381	prg->iomuxc_gpr =
382		syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
383	if (IS_ERR(prg->iomuxc_gpr))
384		return PTR_ERR(prg->iomuxc_gpr);
385
386	for (i = 0; i < 3; i++) {
387		prg->pres[i] = ipu_pre_lookup_by_phandle(dev, "fsl,pres", i);
388		if (!prg->pres[i])
389			return -EPROBE_DEFER;
390	}
391
392	ret = clk_prepare_enable(prg->clk_ipg);
393	if (ret)
394		return ret;
395
396	ret = clk_prepare_enable(prg->clk_axi);
397	if (ret) {
398		clk_disable_unprepare(prg->clk_ipg);
399		return ret;
400	}
401
402	/* init to free running mode */
403	val = readl(prg->regs + IPU_PRG_CTL);
404	val |= IPU_PRG_CTL_SHADOW_EN;
405	writel(val, prg->regs + IPU_PRG_CTL);
406
407	/* disable address threshold */
408	writel(0xffffffff, prg->regs + IPU_PRG_THD);
409
410	pm_runtime_set_active(dev);
411	pm_runtime_enable(dev);
412
413	prg->dev = dev;
414	platform_set_drvdata(pdev, prg);
415	mutex_lock(&ipu_prg_list_mutex);
416	list_add(&prg->list, &ipu_prg_list);
417	mutex_unlock(&ipu_prg_list_mutex);
418
419	return 0;
420}
421
422static int ipu_prg_remove(struct platform_device *pdev)
423{
424	struct ipu_prg *prg = platform_get_drvdata(pdev);
425
426	mutex_lock(&ipu_prg_list_mutex);
427	list_del(&prg->list);
428	mutex_unlock(&ipu_prg_list_mutex);
429
430	return 0;
431}
432
433#ifdef CONFIG_PM
434static int prg_suspend(struct device *dev)
435{
436	struct ipu_prg *prg = dev_get_drvdata(dev);
437
438	clk_disable_unprepare(prg->clk_axi);
439	clk_disable_unprepare(prg->clk_ipg);
440
441	return 0;
442}
443
444static int prg_resume(struct device *dev)
445{
446	struct ipu_prg *prg = dev_get_drvdata(dev);
447	int ret;
448
449	ret = clk_prepare_enable(prg->clk_ipg);
450	if (ret)
451		return ret;
452
453	ret = clk_prepare_enable(prg->clk_axi);
454	if (ret) {
455		clk_disable_unprepare(prg->clk_ipg);
456		return ret;
457	}
458
459	return 0;
460}
461#endif
462
463static const struct dev_pm_ops prg_pm_ops = {
464	SET_RUNTIME_PM_OPS(prg_suspend, prg_resume, NULL)
465};
466
467static const struct of_device_id ipu_prg_dt_ids[] = {
468	{ .compatible = "fsl,imx6qp-prg", },
469	{ /* sentinel */ },
470};
471
472struct platform_driver ipu_prg_drv = {
473	.probe		= ipu_prg_probe,
474	.remove		= ipu_prg_remove,
475	.driver		= {
476		.name	= "imx-ipu-prg",
477		.pm	= &prg_pm_ops,
478		.of_match_table = ipu_prg_dt_ids,
479	},
480};
481