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
, DL_FLAG_AUTOREMOVE
);
105 of_node_put(prg_node
);
109 mutex_unlock(&ipu_prg_list_mutex
);
111 of_node_put(prg_node
);
116 int ipu_prg_max_active_channels(void)
118 return ipu_pre_get_available_count();
120 EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels
);
122 bool ipu_prg_present(struct ipu_soc
*ipu
)
129 EXPORT_SYMBOL_GPL(ipu_prg_present
);
131 bool ipu_prg_format_supported(struct ipu_soc
*ipu
, uint32_t format
,
134 const struct drm_format_info
*info
= drm_format_info(format
);
136 if (info
->num_planes
!= 1)
140 case DRM_FORMAT_MOD_LINEAR
:
141 case DRM_FORMAT_MOD_VIVANTE_TILED
:
142 case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED
:
148 EXPORT_SYMBOL_GPL(ipu_prg_format_supported
);
150 int ipu_prg_enable(struct ipu_soc
*ipu
)
152 struct ipu_prg
*prg
= ipu
->prg_priv
;
157 return pm_runtime_get_sync(prg
->dev
);
159 EXPORT_SYMBOL_GPL(ipu_prg_enable
);
161 void ipu_prg_disable(struct ipu_soc
*ipu
)
163 struct ipu_prg
*prg
= ipu
->prg_priv
;
168 pm_runtime_put(prg
->dev
);
170 EXPORT_SYMBOL_GPL(ipu_prg_disable
);
173 * The channel configuartion functions below are not thread safe, as they
174 * must be only called from the atomic commit path in the DRM driver, which
175 * is properly serialized.
177 static int ipu_prg_ipu_to_prg_chan(int ipu_chan
)
180 * This isn't clearly documented in the RM, but IPU to PRG channel
181 * assignment is fixed, as only with this mapping the control signals
185 case IPUV3_CHANNEL_MEM_BG_SYNC
:
187 case IPUV3_CHANNEL_MEM_FG_SYNC
:
189 case IPUV3_CHANNEL_MEM_DC_SYNC
:
196 static int ipu_prg_get_pre(struct ipu_prg
*prg
, int prg_chan
)
200 /* channel 0 is special as it is hardwired to one of the PREs */
202 ret
= ipu_pre_get(prg
->pres
[0]);
205 prg
->chan
[prg_chan
].used_pre
= 0;
209 for (i
= 1; i
< 3; i
++) {
210 ret
= ipu_pre_get(prg
->pres
[i
]);
215 prg
->chan
[prg_chan
].used_pre
= i
;
217 /* configure the PRE to PRG channel mux */
218 shift
= (i
== 1) ? 12 : 14;
219 mux
= (prg
->id
<< 1) | (prg_chan
- 1);
220 regmap_update_bits(prg
->iomuxc_gpr
, IOMUXC_GPR5
,
221 0x3 << shift
, mux
<< shift
);
223 /* check other mux, must not point to same channel */
224 shift
= (i
== 1) ? 14 : 12;
225 regmap_read(prg
->iomuxc_gpr
, IOMUXC_GPR5
, &val
);
226 if (((val
>> shift
) & 0x3) == mux
) {
227 regmap_update_bits(prg
->iomuxc_gpr
, IOMUXC_GPR5
,
229 (mux
^ 0x1) << shift
);
237 dev_err(prg
->dev
, "could not get PRE for PRG chan %d", prg_chan
);
241 static void ipu_prg_put_pre(struct ipu_prg
*prg
, int prg_chan
)
243 struct ipu_prg_channel
*chan
= &prg
->chan
[prg_chan
];
245 ipu_pre_put(prg
->pres
[chan
->used_pre
]);
249 void ipu_prg_channel_disable(struct ipuv3_channel
*ipu_chan
)
251 int prg_chan
= ipu_prg_ipu_to_prg_chan(ipu_chan
->num
);
252 struct ipu_prg
*prg
= ipu_chan
->ipu
->prg_priv
;
253 struct ipu_prg_channel
*chan
;
259 chan
= &prg
->chan
[prg_chan
];
263 pm_runtime_get_sync(prg
->dev
);
265 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
266 val
|= IPU_PRG_CTL_BYPASS(prg_chan
);
267 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
269 val
= IPU_PRG_REG_UPDATE_REG_UPDATE
;
270 writel(val
, prg
->regs
+ IPU_PRG_REG_UPDATE
);
272 pm_runtime_put(prg
->dev
);
274 ipu_prg_put_pre(prg
, prg_chan
);
276 chan
->enabled
= false;
278 EXPORT_SYMBOL_GPL(ipu_prg_channel_disable
);
280 int ipu_prg_channel_configure(struct ipuv3_channel
*ipu_chan
,
281 unsigned int axi_id
, unsigned int width
,
282 unsigned int height
, unsigned int stride
,
283 u32 format
, uint64_t modifier
, unsigned long *eba
)
285 int prg_chan
= ipu_prg_ipu_to_prg_chan(ipu_chan
->num
);
286 struct ipu_prg
*prg
= ipu_chan
->ipu
->prg_priv
;
287 struct ipu_prg_channel
*chan
;
294 chan
= &prg
->chan
[prg_chan
];
297 ipu_pre_update(prg
->pres
[chan
->used_pre
], *eba
);
301 ret
= ipu_prg_get_pre(prg
, prg_chan
);
305 ipu_pre_configure(prg
->pres
[chan
->used_pre
],
306 width
, height
, stride
, format
, modifier
, *eba
);
309 pm_runtime_get_sync(prg
->dev
);
311 val
= (stride
- 1) & IPU_PRG_STRIDE_STRIDE_MASK
;
312 writel(val
, prg
->regs
+ IPU_PRG_STRIDE(prg_chan
));
314 val
= ((height
& IPU_PRG_HEIGHT_PRE_HEIGHT_MASK
) <<
315 IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT
) |
316 ((height
& IPU_PRG_HEIGHT_IPU_HEIGHT_MASK
) <<
317 IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT
);
318 writel(val
, prg
->regs
+ IPU_PRG_HEIGHT(prg_chan
));
320 val
= ipu_pre_get_baddr(prg
->pres
[chan
->used_pre
]);
322 writel(val
, prg
->regs
+ IPU_PRG_BADDR(prg_chan
));
324 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
326 val
&= ~(IPU_PRG_CTL_SOFT_ARID_MASK
<<
327 IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan
));
328 val
|= IPU_PRG_CTL_SOFT_ARID(prg_chan
, axi_id
);
330 val
&= ~IPU_PRG_CTL_BYPASS(prg_chan
);
331 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
333 val
= IPU_PRG_REG_UPDATE_REG_UPDATE
;
334 writel(val
, prg
->regs
+ IPU_PRG_REG_UPDATE
);
336 /* wait for both double buffers to be filled */
337 readl_poll_timeout(prg
->regs
+ IPU_PRG_STATUS
, val
,
338 (val
& IPU_PRG_STATUS_BUFFER0_READY(prg_chan
)) &&
339 (val
& IPU_PRG_STATUS_BUFFER1_READY(prg_chan
)),
342 pm_runtime_put(prg
->dev
);
344 chan
->enabled
= true;
347 EXPORT_SYMBOL_GPL(ipu_prg_channel_configure
);
349 static int ipu_prg_probe(struct platform_device
*pdev
)
351 struct device
*dev
= &pdev
->dev
;
352 struct resource
*res
;
357 prg
= devm_kzalloc(dev
, sizeof(*prg
), GFP_KERNEL
);
361 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
362 prg
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
363 if (IS_ERR(prg
->regs
))
364 return PTR_ERR(prg
->regs
);
367 prg
->clk_ipg
= devm_clk_get(dev
, "ipg");
368 if (IS_ERR(prg
->clk_ipg
))
369 return PTR_ERR(prg
->clk_ipg
);
371 prg
->clk_axi
= devm_clk_get(dev
, "axi");
372 if (IS_ERR(prg
->clk_axi
))
373 return PTR_ERR(prg
->clk_axi
);
376 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
377 if (IS_ERR(prg
->iomuxc_gpr
))
378 return PTR_ERR(prg
->iomuxc_gpr
);
380 for (i
= 0; i
< 3; i
++) {
381 prg
->pres
[i
] = ipu_pre_lookup_by_phandle(dev
, "fsl,pres", i
);
383 return -EPROBE_DEFER
;
386 ret
= clk_prepare_enable(prg
->clk_ipg
);
390 ret
= clk_prepare_enable(prg
->clk_axi
);
392 clk_disable_unprepare(prg
->clk_ipg
);
396 /* init to free running mode */
397 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
398 val
|= IPU_PRG_CTL_SHADOW_EN
;
399 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
401 /* disable address threshold */
402 writel(0xffffffff, prg
->regs
+ IPU_PRG_THD
);
404 pm_runtime_set_active(dev
);
405 pm_runtime_enable(dev
);
408 platform_set_drvdata(pdev
, prg
);
409 mutex_lock(&ipu_prg_list_mutex
);
410 list_add(&prg
->list
, &ipu_prg_list
);
411 mutex_unlock(&ipu_prg_list_mutex
);
416 static int ipu_prg_remove(struct platform_device
*pdev
)
418 struct ipu_prg
*prg
= platform_get_drvdata(pdev
);
420 mutex_lock(&ipu_prg_list_mutex
);
421 list_del(&prg
->list
);
422 mutex_unlock(&ipu_prg_list_mutex
);
428 static int prg_suspend(struct device
*dev
)
430 struct ipu_prg
*prg
= dev_get_drvdata(dev
);
432 clk_disable_unprepare(prg
->clk_axi
);
433 clk_disable_unprepare(prg
->clk_ipg
);
438 static int prg_resume(struct device
*dev
)
440 struct ipu_prg
*prg
= dev_get_drvdata(dev
);
443 ret
= clk_prepare_enable(prg
->clk_ipg
);
447 ret
= clk_prepare_enable(prg
->clk_axi
);
449 clk_disable_unprepare(prg
->clk_ipg
);
457 static const struct dev_pm_ops prg_pm_ops
= {
458 SET_RUNTIME_PM_OPS(prg_suspend
, prg_resume
, NULL
)
461 static const struct of_device_id ipu_prg_dt_ids
[] = {
462 { .compatible
= "fsl,imx6qp-prg", },
466 struct platform_driver ipu_prg_drv
= {
467 .probe
= ipu_prg_probe
,
468 .remove
= ipu_prg_remove
,
470 .name
= "imx-ipu-prg",
472 .of_match_table
= ipu_prg_dt_ids
,