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
);
108 mutex_unlock(&ipu_prg_list_mutex
);
113 int ipu_prg_max_active_channels(void)
115 return ipu_pre_get_available_count();
117 EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels
);
119 bool ipu_prg_present(struct ipu_soc
*ipu
)
126 EXPORT_SYMBOL_GPL(ipu_prg_present
);
128 bool ipu_prg_format_supported(struct ipu_soc
*ipu
, uint32_t format
,
131 const struct drm_format_info
*info
= drm_format_info(format
);
133 if (info
->num_planes
!= 1)
137 case DRM_FORMAT_MOD_LINEAR
:
138 case DRM_FORMAT_MOD_VIVANTE_TILED
:
139 case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED
:
145 EXPORT_SYMBOL_GPL(ipu_prg_format_supported
);
147 int ipu_prg_enable(struct ipu_soc
*ipu
)
149 struct ipu_prg
*prg
= ipu
->prg_priv
;
154 return pm_runtime_get_sync(prg
->dev
);
156 EXPORT_SYMBOL_GPL(ipu_prg_enable
);
158 void ipu_prg_disable(struct ipu_soc
*ipu
)
160 struct ipu_prg
*prg
= ipu
->prg_priv
;
165 pm_runtime_put(prg
->dev
);
167 EXPORT_SYMBOL_GPL(ipu_prg_disable
);
170 * The channel configuartion functions below are not thread safe, as they
171 * must be only called from the atomic commit path in the DRM driver, which
172 * is properly serialized.
174 static int ipu_prg_ipu_to_prg_chan(int ipu_chan
)
177 * This isn't clearly documented in the RM, but IPU to PRG channel
178 * assignment is fixed, as only with this mapping the control signals
182 case IPUV3_CHANNEL_MEM_BG_SYNC
:
184 case IPUV3_CHANNEL_MEM_FG_SYNC
:
186 case IPUV3_CHANNEL_MEM_DC_SYNC
:
193 static int ipu_prg_get_pre(struct ipu_prg
*prg
, int prg_chan
)
197 /* channel 0 is special as it is hardwired to one of the PREs */
199 ret
= ipu_pre_get(prg
->pres
[0]);
202 prg
->chan
[prg_chan
].used_pre
= 0;
206 for (i
= 1; i
< 3; i
++) {
207 ret
= ipu_pre_get(prg
->pres
[i
]);
212 prg
->chan
[prg_chan
].used_pre
= i
;
214 /* configure the PRE to PRG channel mux */
215 shift
= (i
== 1) ? 12 : 14;
216 mux
= (prg
->id
<< 1) | (prg_chan
- 1);
217 regmap_update_bits(prg
->iomuxc_gpr
, IOMUXC_GPR5
,
218 0x3 << shift
, mux
<< shift
);
220 /* check other mux, must not point to same channel */
221 shift
= (i
== 1) ? 14 : 12;
222 regmap_read(prg
->iomuxc_gpr
, IOMUXC_GPR5
, &val
);
223 if (((val
>> shift
) & 0x3) == mux
) {
224 regmap_update_bits(prg
->iomuxc_gpr
, IOMUXC_GPR5
,
226 (mux
^ 0x1) << shift
);
234 dev_err(prg
->dev
, "could not get PRE for PRG chan %d", prg_chan
);
238 static void ipu_prg_put_pre(struct ipu_prg
*prg
, int prg_chan
)
240 struct ipu_prg_channel
*chan
= &prg
->chan
[prg_chan
];
242 ipu_pre_put(prg
->pres
[chan
->used_pre
]);
246 void ipu_prg_channel_disable(struct ipuv3_channel
*ipu_chan
)
248 int prg_chan
= ipu_prg_ipu_to_prg_chan(ipu_chan
->num
);
249 struct ipu_prg
*prg
= ipu_chan
->ipu
->prg_priv
;
250 struct ipu_prg_channel
*chan
= &prg
->chan
[prg_chan
];
253 if (!chan
->enabled
|| prg_chan
< 0)
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
= &prg
->chan
[prg_chan
];
288 ipu_pre_update(prg
->pres
[chan
->used_pre
], *eba
);
292 ret
= ipu_prg_get_pre(prg
, prg_chan
);
296 ipu_pre_configure(prg
->pres
[chan
->used_pre
],
297 width
, height
, stride
, format
, modifier
, *eba
);
300 pm_runtime_get_sync(prg
->dev
);
302 val
= (stride
- 1) & IPU_PRG_STRIDE_STRIDE_MASK
;
303 writel(val
, prg
->regs
+ IPU_PRG_STRIDE(prg_chan
));
305 val
= ((height
& IPU_PRG_HEIGHT_PRE_HEIGHT_MASK
) <<
306 IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT
) |
307 ((height
& IPU_PRG_HEIGHT_IPU_HEIGHT_MASK
) <<
308 IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT
);
309 writel(val
, prg
->regs
+ IPU_PRG_HEIGHT(prg_chan
));
311 val
= ipu_pre_get_baddr(prg
->pres
[chan
->used_pre
]);
313 writel(val
, prg
->regs
+ IPU_PRG_BADDR(prg_chan
));
315 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
317 val
&= ~(IPU_PRG_CTL_SOFT_ARID_MASK
<<
318 IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan
));
319 val
|= IPU_PRG_CTL_SOFT_ARID(prg_chan
, axi_id
);
321 val
&= ~IPU_PRG_CTL_BYPASS(prg_chan
);
322 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
324 val
= IPU_PRG_REG_UPDATE_REG_UPDATE
;
325 writel(val
, prg
->regs
+ IPU_PRG_REG_UPDATE
);
327 /* wait for both double buffers to be filled */
328 readl_poll_timeout(prg
->regs
+ IPU_PRG_STATUS
, val
,
329 (val
& IPU_PRG_STATUS_BUFFER0_READY(prg_chan
)) &&
330 (val
& IPU_PRG_STATUS_BUFFER1_READY(prg_chan
)),
333 pm_runtime_put(prg
->dev
);
335 chan
->enabled
= true;
338 EXPORT_SYMBOL_GPL(ipu_prg_channel_configure
);
340 static int ipu_prg_probe(struct platform_device
*pdev
)
342 struct device
*dev
= &pdev
->dev
;
343 struct resource
*res
;
348 prg
= devm_kzalloc(dev
, sizeof(*prg
), GFP_KERNEL
);
352 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
353 prg
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
354 if (IS_ERR(prg
->regs
))
355 return PTR_ERR(prg
->regs
);
358 prg
->clk_ipg
= devm_clk_get(dev
, "ipg");
359 if (IS_ERR(prg
->clk_ipg
))
360 return PTR_ERR(prg
->clk_ipg
);
362 prg
->clk_axi
= devm_clk_get(dev
, "axi");
363 if (IS_ERR(prg
->clk_axi
))
364 return PTR_ERR(prg
->clk_axi
);
367 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
368 if (IS_ERR(prg
->iomuxc_gpr
))
369 return PTR_ERR(prg
->iomuxc_gpr
);
371 for (i
= 0; i
< 3; i
++) {
372 prg
->pres
[i
] = ipu_pre_lookup_by_phandle(dev
, "fsl,pres", i
);
374 return -EPROBE_DEFER
;
377 ret
= clk_prepare_enable(prg
->clk_ipg
);
381 ret
= clk_prepare_enable(prg
->clk_axi
);
383 clk_disable_unprepare(prg
->clk_ipg
);
387 /* init to free running mode */
388 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
389 val
|= IPU_PRG_CTL_SHADOW_EN
;
390 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
392 /* disable address threshold */
393 writel(0xffffffff, prg
->regs
+ IPU_PRG_THD
);
395 pm_runtime_set_active(dev
);
396 pm_runtime_enable(dev
);
399 platform_set_drvdata(pdev
, prg
);
400 mutex_lock(&ipu_prg_list_mutex
);
401 list_add(&prg
->list
, &ipu_prg_list
);
402 mutex_unlock(&ipu_prg_list_mutex
);
407 static int ipu_prg_remove(struct platform_device
*pdev
)
409 struct ipu_prg
*prg
= platform_get_drvdata(pdev
);
411 mutex_lock(&ipu_prg_list_mutex
);
412 list_del(&prg
->list
);
413 mutex_unlock(&ipu_prg_list_mutex
);
419 static int prg_suspend(struct device
*dev
)
421 struct ipu_prg
*prg
= dev_get_drvdata(dev
);
423 clk_disable_unprepare(prg
->clk_axi
);
424 clk_disable_unprepare(prg
->clk_ipg
);
429 static int prg_resume(struct device
*dev
)
431 struct ipu_prg
*prg
= dev_get_drvdata(dev
);
434 ret
= clk_prepare_enable(prg
->clk_ipg
);
438 ret
= clk_prepare_enable(prg
->clk_axi
);
440 clk_disable_unprepare(prg
->clk_ipg
);
448 static const struct dev_pm_ops prg_pm_ops
= {
449 SET_RUNTIME_PM_OPS(prg_suspend
, prg_resume
, NULL
)
452 static const struct of_device_id ipu_prg_dt_ids
[] = {
453 { .compatible
= "fsl,imx6qp-prg", },
457 struct platform_driver ipu_prg_drv
= {
458 .probe
= ipu_prg_probe
,
459 .remove
= ipu_prg_remove
,
461 .name
= "imx-ipu-prg",
463 .of_match_table
= ipu_prg_dt_ids
,