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
= &prg
->chan
[prg_chan
];
256 if (!chan
->enabled
|| prg_chan
< 0)
259 pm_runtime_get_sync(prg
->dev
);
261 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
262 val
|= IPU_PRG_CTL_BYPASS(prg_chan
);
263 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
265 val
= IPU_PRG_REG_UPDATE_REG_UPDATE
;
266 writel(val
, prg
->regs
+ IPU_PRG_REG_UPDATE
);
268 pm_runtime_put(prg
->dev
);
270 ipu_prg_put_pre(prg
, prg_chan
);
272 chan
->enabled
= false;
274 EXPORT_SYMBOL_GPL(ipu_prg_channel_disable
);
276 int ipu_prg_channel_configure(struct ipuv3_channel
*ipu_chan
,
277 unsigned int axi_id
, unsigned int width
,
278 unsigned int height
, unsigned int stride
,
279 u32 format
, uint64_t modifier
, unsigned long *eba
)
281 int prg_chan
= ipu_prg_ipu_to_prg_chan(ipu_chan
->num
);
282 struct ipu_prg
*prg
= ipu_chan
->ipu
->prg_priv
;
283 struct ipu_prg_channel
*chan
= &prg
->chan
[prg_chan
];
291 ipu_pre_update(prg
->pres
[chan
->used_pre
], *eba
);
295 ret
= ipu_prg_get_pre(prg
, prg_chan
);
299 ipu_pre_configure(prg
->pres
[chan
->used_pre
],
300 width
, height
, stride
, format
, modifier
, *eba
);
303 pm_runtime_get_sync(prg
->dev
);
305 val
= (stride
- 1) & IPU_PRG_STRIDE_STRIDE_MASK
;
306 writel(val
, prg
->regs
+ IPU_PRG_STRIDE(prg_chan
));
308 val
= ((height
& IPU_PRG_HEIGHT_PRE_HEIGHT_MASK
) <<
309 IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT
) |
310 ((height
& IPU_PRG_HEIGHT_IPU_HEIGHT_MASK
) <<
311 IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT
);
312 writel(val
, prg
->regs
+ IPU_PRG_HEIGHT(prg_chan
));
314 val
= ipu_pre_get_baddr(prg
->pres
[chan
->used_pre
]);
316 writel(val
, prg
->regs
+ IPU_PRG_BADDR(prg_chan
));
318 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
320 val
&= ~(IPU_PRG_CTL_SOFT_ARID_MASK
<<
321 IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan
));
322 val
|= IPU_PRG_CTL_SOFT_ARID(prg_chan
, axi_id
);
324 val
&= ~IPU_PRG_CTL_BYPASS(prg_chan
);
325 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
327 val
= IPU_PRG_REG_UPDATE_REG_UPDATE
;
328 writel(val
, prg
->regs
+ IPU_PRG_REG_UPDATE
);
330 /* wait for both double buffers to be filled */
331 readl_poll_timeout(prg
->regs
+ IPU_PRG_STATUS
, val
,
332 (val
& IPU_PRG_STATUS_BUFFER0_READY(prg_chan
)) &&
333 (val
& IPU_PRG_STATUS_BUFFER1_READY(prg_chan
)),
336 pm_runtime_put(prg
->dev
);
338 chan
->enabled
= true;
341 EXPORT_SYMBOL_GPL(ipu_prg_channel_configure
);
343 static int ipu_prg_probe(struct platform_device
*pdev
)
345 struct device
*dev
= &pdev
->dev
;
346 struct resource
*res
;
351 prg
= devm_kzalloc(dev
, sizeof(*prg
), GFP_KERNEL
);
355 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
356 prg
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
357 if (IS_ERR(prg
->regs
))
358 return PTR_ERR(prg
->regs
);
361 prg
->clk_ipg
= devm_clk_get(dev
, "ipg");
362 if (IS_ERR(prg
->clk_ipg
))
363 return PTR_ERR(prg
->clk_ipg
);
365 prg
->clk_axi
= devm_clk_get(dev
, "axi");
366 if (IS_ERR(prg
->clk_axi
))
367 return PTR_ERR(prg
->clk_axi
);
370 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
371 if (IS_ERR(prg
->iomuxc_gpr
))
372 return PTR_ERR(prg
->iomuxc_gpr
);
374 for (i
= 0; i
< 3; i
++) {
375 prg
->pres
[i
] = ipu_pre_lookup_by_phandle(dev
, "fsl,pres", i
);
377 return -EPROBE_DEFER
;
380 ret
= clk_prepare_enable(prg
->clk_ipg
);
384 ret
= clk_prepare_enable(prg
->clk_axi
);
386 clk_disable_unprepare(prg
->clk_ipg
);
390 /* init to free running mode */
391 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
392 val
|= IPU_PRG_CTL_SHADOW_EN
;
393 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
395 /* disable address threshold */
396 writel(0xffffffff, prg
->regs
+ IPU_PRG_THD
);
398 pm_runtime_set_active(dev
);
399 pm_runtime_enable(dev
);
402 platform_set_drvdata(pdev
, prg
);
403 mutex_lock(&ipu_prg_list_mutex
);
404 list_add(&prg
->list
, &ipu_prg_list
);
405 mutex_unlock(&ipu_prg_list_mutex
);
410 static int ipu_prg_remove(struct platform_device
*pdev
)
412 struct ipu_prg
*prg
= platform_get_drvdata(pdev
);
414 mutex_lock(&ipu_prg_list_mutex
);
415 list_del(&prg
->list
);
416 mutex_unlock(&ipu_prg_list_mutex
);
422 static int prg_suspend(struct device
*dev
)
424 struct ipu_prg
*prg
= dev_get_drvdata(dev
);
426 clk_disable_unprepare(prg
->clk_axi
);
427 clk_disable_unprepare(prg
->clk_ipg
);
432 static int prg_resume(struct device
*dev
)
434 struct ipu_prg
*prg
= dev_get_drvdata(dev
);
437 ret
= clk_prepare_enable(prg
->clk_ipg
);
441 ret
= clk_prepare_enable(prg
->clk_axi
);
443 clk_disable_unprepare(prg
->clk_ipg
);
451 static const struct dev_pm_ops prg_pm_ops
= {
452 SET_RUNTIME_PM_OPS(prg_suspend
, prg_resume
, NULL
)
455 static const struct of_device_id ipu_prg_dt_ids
[] = {
456 { .compatible
= "fsl,imx6qp-prg", },
460 struct platform_driver ipu_prg_drv
= {
461 .probe
= ipu_prg_probe
,
462 .remove
= ipu_prg_remove
,
464 .name
= "imx-ipu-prg",
466 .of_match_table
= ipu_prg_dt_ids
,