1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2016-2017 Lucas Stach, Pengutronix
6 #include <drm/drm_fourcc.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>
14 #include <linux/platform_device.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/regmap.h>
17 #include <video/imx-ipu-v3.h>
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)
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))
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)
41 #define IPU_PRG_REG_UPDATE 0x0c
42 #define IPU_PRG_REG_UPDATE_REG_UPDATE (1 << 0)
44 #define IPU_PRG_STRIDE(i) (0x10 + i * 0x4)
45 #define IPU_PRG_STRIDE_STRIDE_MASK 0x3fff
47 #define IPU_PRG_CROP_LINE 0x1c
49 #define IPU_PRG_THD 0x20
51 #define IPU_PRG_BADDR(i) (0x24 + i * 0x4)
53 #define IPU_PRG_OFFSET(i) (0x30 + i * 0x4)
55 #define IPU_PRG_ILO(i) (0x3c + i * 0x4)
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
63 struct ipu_prg_channel
{
69 struct list_head list
;
74 struct clk
*clk_ipg
, *clk_axi
;
75 struct regmap
*iomuxc_gpr
;
76 struct ipu_pre
*pres
[3];
78 struct ipu_prg_channel chan
[3];
81 static DEFINE_MUTEX(ipu_prg_list_mutex
);
82 static LIST_HEAD(ipu_prg_list
);
85 ipu_prg_lookup_by_phandle(struct device
*dev
, const char *name
, int ipu_id
)
87 struct device_node
*prg_node
= of_parse_phandle(dev
->of_node
,
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
);
98 of_node_put(prg_node
);
102 mutex_unlock(&ipu_prg_list_mutex
);
104 of_node_put(prg_node
);
109 int ipu_prg_max_active_channels(void)
111 return ipu_pre_get_available_count();
113 EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels
);
115 bool ipu_prg_present(struct ipu_soc
*ipu
)
122 EXPORT_SYMBOL_GPL(ipu_prg_present
);
124 bool ipu_prg_format_supported(struct ipu_soc
*ipu
, uint32_t format
,
127 const struct drm_format_info
*info
= drm_format_info(format
);
129 if (info
->num_planes
!= 1)
133 case DRM_FORMAT_MOD_LINEAR
:
134 case DRM_FORMAT_MOD_VIVANTE_TILED
:
135 case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED
:
141 EXPORT_SYMBOL_GPL(ipu_prg_format_supported
);
143 int ipu_prg_enable(struct ipu_soc
*ipu
)
145 struct ipu_prg
*prg
= ipu
->prg_priv
;
150 return pm_runtime_get_sync(prg
->dev
);
152 EXPORT_SYMBOL_GPL(ipu_prg_enable
);
154 void ipu_prg_disable(struct ipu_soc
*ipu
)
156 struct ipu_prg
*prg
= ipu
->prg_priv
;
161 pm_runtime_put(prg
->dev
);
163 EXPORT_SYMBOL_GPL(ipu_prg_disable
);
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.
170 static int ipu_prg_ipu_to_prg_chan(int ipu_chan
)
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
178 case IPUV3_CHANNEL_MEM_BG_SYNC
:
180 case IPUV3_CHANNEL_MEM_FG_SYNC
:
182 case IPUV3_CHANNEL_MEM_DC_SYNC
:
189 static int ipu_prg_get_pre(struct ipu_prg
*prg
, int prg_chan
)
193 /* channel 0 is special as it is hardwired to one of the PREs */
195 ret
= ipu_pre_get(prg
->pres
[0]);
198 prg
->chan
[prg_chan
].used_pre
= 0;
202 for (i
= 1; i
< 3; i
++) {
203 ret
= ipu_pre_get(prg
->pres
[i
]);
208 prg
->chan
[prg_chan
].used_pre
= i
;
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
);
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
,
222 (mux
^ 0x1) << shift
);
230 dev_err(prg
->dev
, "could not get PRE for PRG chan %d", prg_chan
);
234 static void ipu_prg_put_pre(struct ipu_prg
*prg
, int prg_chan
)
236 struct ipu_prg_channel
*chan
= &prg
->chan
[prg_chan
];
238 ipu_pre_put(prg
->pres
[chan
->used_pre
]);
242 void ipu_prg_channel_disable(struct ipuv3_channel
*ipu_chan
)
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
;
252 chan
= &prg
->chan
[prg_chan
];
256 pm_runtime_get_sync(prg
->dev
);
258 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
259 val
|= IPU_PRG_CTL_BYPASS(prg_chan
);
260 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
262 val
= IPU_PRG_REG_UPDATE_REG_UPDATE
;
263 writel(val
, prg
->regs
+ IPU_PRG_REG_UPDATE
);
265 pm_runtime_put(prg
->dev
);
267 ipu_prg_put_pre(prg
, prg_chan
);
269 chan
->enabled
= false;
271 EXPORT_SYMBOL_GPL(ipu_prg_channel_disable
);
273 int 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
)
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
;
287 chan
= &prg
->chan
[prg_chan
];
290 ipu_pre_update(prg
->pres
[chan
->used_pre
], *eba
);
294 ret
= ipu_prg_get_pre(prg
, prg_chan
);
298 ipu_pre_configure(prg
->pres
[chan
->used_pre
],
299 width
, height
, stride
, format
, modifier
, *eba
);
302 pm_runtime_get_sync(prg
->dev
);
304 val
= (stride
- 1) & IPU_PRG_STRIDE_STRIDE_MASK
;
305 writel(val
, prg
->regs
+ IPU_PRG_STRIDE(prg_chan
));
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
));
313 val
= ipu_pre_get_baddr(prg
->pres
[chan
->used_pre
]);
315 writel(val
, prg
->regs
+ IPU_PRG_BADDR(prg_chan
));
317 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
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
);
323 val
&= ~IPU_PRG_CTL_BYPASS(prg_chan
);
324 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
326 val
= IPU_PRG_REG_UPDATE_REG_UPDATE
;
327 writel(val
, prg
->regs
+ IPU_PRG_REG_UPDATE
);
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
)),
335 pm_runtime_put(prg
->dev
);
337 chan
->enabled
= true;
340 EXPORT_SYMBOL_GPL(ipu_prg_channel_configure
);
342 bool ipu_prg_channel_configure_pending(struct ipuv3_channel
*ipu_chan
)
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
;
351 chan
= &prg
->chan
[prg_chan
];
352 WARN_ON(!chan
->enabled
);
354 return ipu_pre_update_pending(prg
->pres
[chan
->used_pre
]);
356 EXPORT_SYMBOL_GPL(ipu_prg_channel_configure_pending
);
358 static int ipu_prg_probe(struct platform_device
*pdev
)
360 struct device
*dev
= &pdev
->dev
;
361 struct resource
*res
;
366 prg
= devm_kzalloc(dev
, sizeof(*prg
), GFP_KERNEL
);
370 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
371 prg
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
372 if (IS_ERR(prg
->regs
))
373 return PTR_ERR(prg
->regs
);
376 prg
->clk_ipg
= devm_clk_get(dev
, "ipg");
377 if (IS_ERR(prg
->clk_ipg
))
378 return PTR_ERR(prg
->clk_ipg
);
380 prg
->clk_axi
= devm_clk_get(dev
, "axi");
381 if (IS_ERR(prg
->clk_axi
))
382 return PTR_ERR(prg
->clk_axi
);
385 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
386 if (IS_ERR(prg
->iomuxc_gpr
))
387 return PTR_ERR(prg
->iomuxc_gpr
);
389 for (i
= 0; i
< 3; i
++) {
390 prg
->pres
[i
] = ipu_pre_lookup_by_phandle(dev
, "fsl,pres", i
);
392 return -EPROBE_DEFER
;
395 ret
= clk_prepare_enable(prg
->clk_ipg
);
399 ret
= clk_prepare_enable(prg
->clk_axi
);
401 clk_disable_unprepare(prg
->clk_ipg
);
405 /* init to free running mode */
406 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
407 val
|= IPU_PRG_CTL_SHADOW_EN
;
408 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
410 /* disable address threshold */
411 writel(0xffffffff, prg
->regs
+ IPU_PRG_THD
);
413 pm_runtime_set_active(dev
);
414 pm_runtime_enable(dev
);
417 platform_set_drvdata(pdev
, prg
);
418 mutex_lock(&ipu_prg_list_mutex
);
419 list_add(&prg
->list
, &ipu_prg_list
);
420 mutex_unlock(&ipu_prg_list_mutex
);
425 static int ipu_prg_remove(struct platform_device
*pdev
)
427 struct ipu_prg
*prg
= platform_get_drvdata(pdev
);
429 mutex_lock(&ipu_prg_list_mutex
);
430 list_del(&prg
->list
);
431 mutex_unlock(&ipu_prg_list_mutex
);
437 static int prg_suspend(struct device
*dev
)
439 struct ipu_prg
*prg
= dev_get_drvdata(dev
);
441 clk_disable_unprepare(prg
->clk_axi
);
442 clk_disable_unprepare(prg
->clk_ipg
);
447 static int prg_resume(struct device
*dev
)
449 struct ipu_prg
*prg
= dev_get_drvdata(dev
);
452 ret
= clk_prepare_enable(prg
->clk_ipg
);
456 ret
= clk_prepare_enable(prg
->clk_axi
);
458 clk_disable_unprepare(prg
->clk_ipg
);
466 static const struct dev_pm_ops prg_pm_ops
= {
467 SET_RUNTIME_PM_OPS(prg_suspend
, prg_resume
, NULL
)
470 static const struct of_device_id ipu_prg_dt_ids
[] = {
471 { .compatible
= "fsl,imx6qp-prg", },
475 struct platform_driver ipu_prg_drv
= {
476 .probe
= ipu_prg_probe
,
477 .remove
= ipu_prg_remove
,
479 .name
= "imx-ipu-prg",
481 .of_match_table
= ipu_prg_dt_ids
,