2 * Copyright (c) 2016-2017 Lucas Stach, Pengutronix
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 #include <drm/drm_fourcc.h>
15 #include <linux/clk.h>
16 #include <linux/err.h>
17 #include <linux/iopoll.h>
18 #include <linux/mfd/syscon.h>
19 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
20 #include <linux/module.h>
22 #include <linux/platform_device.h>
23 #include <linux/pm_runtime.h>
24 #include <linux/regmap.h>
25 #include <video/imx-ipu-v3.h>
29 #define IPU_PRG_CTL 0x00
30 #define IPU_PRG_CTL_BYPASS(i) (1 << (0 + i))
31 #define IPU_PRG_CTL_SOFT_ARID_MASK 0x3
32 #define IPU_PRG_CTL_SOFT_ARID_SHIFT(i) (8 + i * 2)
33 #define IPU_PRG_CTL_SOFT_ARID(i, v) ((v & 0x3) << (8 + 2 * i))
34 #define IPU_PRG_CTL_SO(i) (1 << (16 + i))
35 #define IPU_PRG_CTL_VFLIP(i) (1 << (19 + i))
36 #define IPU_PRG_CTL_BLOCK_MODE(i) (1 << (22 + i))
37 #define IPU_PRG_CTL_CNT_LOAD_EN(i) (1 << (25 + i))
38 #define IPU_PRG_CTL_SOFTRST (1 << 30)
39 #define IPU_PRG_CTL_SHADOW_EN (1 << 31)
41 #define IPU_PRG_STATUS 0x04
42 #define IPU_PRG_STATUS_BUFFER0_READY(i) (1 << (0 + i * 2))
43 #define IPU_PRG_STATUS_BUFFER1_READY(i) (1 << (1 + i * 2))
45 #define IPU_PRG_QOS 0x08
46 #define IPU_PRG_QOS_ARID_MASK 0xf
47 #define IPU_PRG_QOS_ARID_SHIFT(i) (0 + i * 4)
49 #define IPU_PRG_REG_UPDATE 0x0c
50 #define IPU_PRG_REG_UPDATE_REG_UPDATE (1 << 0)
52 #define IPU_PRG_STRIDE(i) (0x10 + i * 0x4)
53 #define IPU_PRG_STRIDE_STRIDE_MASK 0x3fff
55 #define IPU_PRG_CROP_LINE 0x1c
57 #define IPU_PRG_THD 0x20
59 #define IPU_PRG_BADDR(i) (0x24 + i * 0x4)
61 #define IPU_PRG_OFFSET(i) (0x30 + i * 0x4)
63 #define IPU_PRG_ILO(i) (0x3c + i * 0x4)
65 #define IPU_PRG_HEIGHT(i) (0x48 + i * 0x4)
66 #define IPU_PRG_HEIGHT_PRE_HEIGHT_MASK 0xfff
67 #define IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT 0
68 #define IPU_PRG_HEIGHT_IPU_HEIGHT_MASK 0xfff
69 #define IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT 16
71 struct ipu_prg_channel
{
77 struct list_head list
;
82 struct clk
*clk_ipg
, *clk_axi
;
83 struct regmap
*iomuxc_gpr
;
84 struct ipu_pre
*pres
[3];
86 struct ipu_prg_channel chan
[3];
89 static DEFINE_MUTEX(ipu_prg_list_mutex
);
90 static LIST_HEAD(ipu_prg_list
);
93 ipu_prg_lookup_by_phandle(struct device
*dev
, const char *name
, int ipu_id
)
95 struct device_node
*prg_node
= of_parse_phandle(dev
->of_node
,
99 mutex_lock(&ipu_prg_list_mutex
);
100 list_for_each_entry(prg
, &ipu_prg_list
, list
) {
101 if (prg_node
== prg
->dev
->of_node
) {
102 mutex_unlock(&ipu_prg_list_mutex
);
103 device_link_add(dev
, prg
->dev
,
104 DL_FLAG_AUTOREMOVE_CONSUMER
);
106 of_node_put(prg_node
);
110 mutex_unlock(&ipu_prg_list_mutex
);
112 of_node_put(prg_node
);
117 int ipu_prg_max_active_channels(void)
119 return ipu_pre_get_available_count();
121 EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels
);
123 bool ipu_prg_present(struct ipu_soc
*ipu
)
130 EXPORT_SYMBOL_GPL(ipu_prg_present
);
132 bool ipu_prg_format_supported(struct ipu_soc
*ipu
, uint32_t format
,
135 const struct drm_format_info
*info
= drm_format_info(format
);
137 if (info
->num_planes
!= 1)
141 case DRM_FORMAT_MOD_LINEAR
:
142 case DRM_FORMAT_MOD_VIVANTE_TILED
:
143 case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED
:
149 EXPORT_SYMBOL_GPL(ipu_prg_format_supported
);
151 int ipu_prg_enable(struct ipu_soc
*ipu
)
153 struct ipu_prg
*prg
= ipu
->prg_priv
;
158 return pm_runtime_get_sync(prg
->dev
);
160 EXPORT_SYMBOL_GPL(ipu_prg_enable
);
162 void ipu_prg_disable(struct ipu_soc
*ipu
)
164 struct ipu_prg
*prg
= ipu
->prg_priv
;
169 pm_runtime_put(prg
->dev
);
171 EXPORT_SYMBOL_GPL(ipu_prg_disable
);
174 * The channel configuartion functions below are not thread safe, as they
175 * must be only called from the atomic commit path in the DRM driver, which
176 * is properly serialized.
178 static int ipu_prg_ipu_to_prg_chan(int ipu_chan
)
181 * This isn't clearly documented in the RM, but IPU to PRG channel
182 * assignment is fixed, as only with this mapping the control signals
186 case IPUV3_CHANNEL_MEM_BG_SYNC
:
188 case IPUV3_CHANNEL_MEM_FG_SYNC
:
190 case IPUV3_CHANNEL_MEM_DC_SYNC
:
197 static int ipu_prg_get_pre(struct ipu_prg
*prg
, int prg_chan
)
201 /* channel 0 is special as it is hardwired to one of the PREs */
203 ret
= ipu_pre_get(prg
->pres
[0]);
206 prg
->chan
[prg_chan
].used_pre
= 0;
210 for (i
= 1; i
< 3; i
++) {
211 ret
= ipu_pre_get(prg
->pres
[i
]);
216 prg
->chan
[prg_chan
].used_pre
= i
;
218 /* configure the PRE to PRG channel mux */
219 shift
= (i
== 1) ? 12 : 14;
220 mux
= (prg
->id
<< 1) | (prg_chan
- 1);
221 regmap_update_bits(prg
->iomuxc_gpr
, IOMUXC_GPR5
,
222 0x3 << shift
, mux
<< shift
);
224 /* check other mux, must not point to same channel */
225 shift
= (i
== 1) ? 14 : 12;
226 regmap_read(prg
->iomuxc_gpr
, IOMUXC_GPR5
, &val
);
227 if (((val
>> shift
) & 0x3) == mux
) {
228 regmap_update_bits(prg
->iomuxc_gpr
, IOMUXC_GPR5
,
230 (mux
^ 0x1) << shift
);
238 dev_err(prg
->dev
, "could not get PRE for PRG chan %d", prg_chan
);
242 static void ipu_prg_put_pre(struct ipu_prg
*prg
, int prg_chan
)
244 struct ipu_prg_channel
*chan
= &prg
->chan
[prg_chan
];
246 ipu_pre_put(prg
->pres
[chan
->used_pre
]);
250 void ipu_prg_channel_disable(struct ipuv3_channel
*ipu_chan
)
252 int prg_chan
= ipu_prg_ipu_to_prg_chan(ipu_chan
->num
);
253 struct ipu_prg
*prg
= ipu_chan
->ipu
->prg_priv
;
254 struct ipu_prg_channel
*chan
;
260 chan
= &prg
->chan
[prg_chan
];
264 pm_runtime_get_sync(prg
->dev
);
266 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
267 val
|= IPU_PRG_CTL_BYPASS(prg_chan
);
268 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
270 val
= IPU_PRG_REG_UPDATE_REG_UPDATE
;
271 writel(val
, prg
->regs
+ IPU_PRG_REG_UPDATE
);
273 pm_runtime_put(prg
->dev
);
275 ipu_prg_put_pre(prg
, prg_chan
);
277 chan
->enabled
= false;
279 EXPORT_SYMBOL_GPL(ipu_prg_channel_disable
);
281 int ipu_prg_channel_configure(struct ipuv3_channel
*ipu_chan
,
282 unsigned int axi_id
, unsigned int width
,
283 unsigned int height
, unsigned int stride
,
284 u32 format
, uint64_t modifier
, unsigned long *eba
)
286 int prg_chan
= ipu_prg_ipu_to_prg_chan(ipu_chan
->num
);
287 struct ipu_prg
*prg
= ipu_chan
->ipu
->prg_priv
;
288 struct ipu_prg_channel
*chan
;
295 chan
= &prg
->chan
[prg_chan
];
298 ipu_pre_update(prg
->pres
[chan
->used_pre
], *eba
);
302 ret
= ipu_prg_get_pre(prg
, prg_chan
);
306 ipu_pre_configure(prg
->pres
[chan
->used_pre
],
307 width
, height
, stride
, format
, modifier
, *eba
);
310 pm_runtime_get_sync(prg
->dev
);
312 val
= (stride
- 1) & IPU_PRG_STRIDE_STRIDE_MASK
;
313 writel(val
, prg
->regs
+ IPU_PRG_STRIDE(prg_chan
));
315 val
= ((height
& IPU_PRG_HEIGHT_PRE_HEIGHT_MASK
) <<
316 IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT
) |
317 ((height
& IPU_PRG_HEIGHT_IPU_HEIGHT_MASK
) <<
318 IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT
);
319 writel(val
, prg
->regs
+ IPU_PRG_HEIGHT(prg_chan
));
321 val
= ipu_pre_get_baddr(prg
->pres
[chan
->used_pre
]);
323 writel(val
, prg
->regs
+ IPU_PRG_BADDR(prg_chan
));
325 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
327 val
&= ~(IPU_PRG_CTL_SOFT_ARID_MASK
<<
328 IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan
));
329 val
|= IPU_PRG_CTL_SOFT_ARID(prg_chan
, axi_id
);
331 val
&= ~IPU_PRG_CTL_BYPASS(prg_chan
);
332 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
334 val
= IPU_PRG_REG_UPDATE_REG_UPDATE
;
335 writel(val
, prg
->regs
+ IPU_PRG_REG_UPDATE
);
337 /* wait for both double buffers to be filled */
338 readl_poll_timeout(prg
->regs
+ IPU_PRG_STATUS
, val
,
339 (val
& IPU_PRG_STATUS_BUFFER0_READY(prg_chan
)) &&
340 (val
& IPU_PRG_STATUS_BUFFER1_READY(prg_chan
)),
343 pm_runtime_put(prg
->dev
);
345 chan
->enabled
= true;
348 EXPORT_SYMBOL_GPL(ipu_prg_channel_configure
);
350 static int ipu_prg_probe(struct platform_device
*pdev
)
352 struct device
*dev
= &pdev
->dev
;
353 struct resource
*res
;
358 prg
= devm_kzalloc(dev
, sizeof(*prg
), GFP_KERNEL
);
362 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
363 prg
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
364 if (IS_ERR(prg
->regs
))
365 return PTR_ERR(prg
->regs
);
368 prg
->clk_ipg
= devm_clk_get(dev
, "ipg");
369 if (IS_ERR(prg
->clk_ipg
))
370 return PTR_ERR(prg
->clk_ipg
);
372 prg
->clk_axi
= devm_clk_get(dev
, "axi");
373 if (IS_ERR(prg
->clk_axi
))
374 return PTR_ERR(prg
->clk_axi
);
377 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
378 if (IS_ERR(prg
->iomuxc_gpr
))
379 return PTR_ERR(prg
->iomuxc_gpr
);
381 for (i
= 0; i
< 3; i
++) {
382 prg
->pres
[i
] = ipu_pre_lookup_by_phandle(dev
, "fsl,pres", i
);
384 return -EPROBE_DEFER
;
387 ret
= clk_prepare_enable(prg
->clk_ipg
);
391 ret
= clk_prepare_enable(prg
->clk_axi
);
393 clk_disable_unprepare(prg
->clk_ipg
);
397 /* init to free running mode */
398 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
399 val
|= IPU_PRG_CTL_SHADOW_EN
;
400 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
402 /* disable address threshold */
403 writel(0xffffffff, prg
->regs
+ IPU_PRG_THD
);
405 pm_runtime_set_active(dev
);
406 pm_runtime_enable(dev
);
409 platform_set_drvdata(pdev
, prg
);
410 mutex_lock(&ipu_prg_list_mutex
);
411 list_add(&prg
->list
, &ipu_prg_list
);
412 mutex_unlock(&ipu_prg_list_mutex
);
417 static int ipu_prg_remove(struct platform_device
*pdev
)
419 struct ipu_prg
*prg
= platform_get_drvdata(pdev
);
421 mutex_lock(&ipu_prg_list_mutex
);
422 list_del(&prg
->list
);
423 mutex_unlock(&ipu_prg_list_mutex
);
429 static int prg_suspend(struct device
*dev
)
431 struct ipu_prg
*prg
= dev_get_drvdata(dev
);
433 clk_disable_unprepare(prg
->clk_axi
);
434 clk_disable_unprepare(prg
->clk_ipg
);
439 static int prg_resume(struct device
*dev
)
441 struct ipu_prg
*prg
= dev_get_drvdata(dev
);
444 ret
= clk_prepare_enable(prg
->clk_ipg
);
448 ret
= clk_prepare_enable(prg
->clk_axi
);
450 clk_disable_unprepare(prg
->clk_ipg
);
458 static const struct dev_pm_ops prg_pm_ops
= {
459 SET_RUNTIME_PM_OPS(prg_suspend
, prg_resume
, NULL
)
462 static const struct of_device_id ipu_prg_dt_ids
[] = {
463 { .compatible
= "fsl,imx6qp-prg", },
467 struct platform_driver ipu_prg_drv
= {
468 .probe
= ipu_prg_probe
,
469 .remove
= ipu_prg_remove
,
471 .name
= "imx-ipu-prg",
473 .of_match_table
= ipu_prg_dt_ids
,