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/mfd/syscon.h>
18 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
19 #include <linux/module.h>
21 #include <linux/platform_device.h>
22 #include <linux/regmap.h>
23 #include <video/imx-ipu-v3.h>
27 #define IPU_PRG_CTL 0x00
28 #define IPU_PRG_CTL_BYPASS(i) (1 << (0 + i))
29 #define IPU_PRG_CTL_SOFT_ARID_MASK 0x3
30 #define IPU_PRG_CTL_SOFT_ARID_SHIFT(i) (8 + i * 2)
31 #define IPU_PRG_CTL_SOFT_ARID(i, v) ((v & 0x3) << (8 + 2 * i))
32 #define IPU_PRG_CTL_SO(i) (1 << (16 + i))
33 #define IPU_PRG_CTL_VFLIP(i) (1 << (19 + i))
34 #define IPU_PRG_CTL_BLOCK_MODE(i) (1 << (22 + i))
35 #define IPU_PRG_CTL_CNT_LOAD_EN(i) (1 << (25 + i))
36 #define IPU_PRG_CTL_SOFTRST (1 << 30)
37 #define IPU_PRG_CTL_SHADOW_EN (1 << 31)
39 #define IPU_PRG_STATUS 0x04
40 #define IPU_PRG_STATUS_BUFFER0_READY(i) (1 << (0 + i * 2))
41 #define IPU_PRG_STATUS_BUFFER1_READY(i) (1 << (1 + i * 2))
43 #define IPU_PRG_QOS 0x08
44 #define IPU_PRG_QOS_ARID_MASK 0xf
45 #define IPU_PRG_QOS_ARID_SHIFT(i) (0 + i * 4)
47 #define IPU_PRG_REG_UPDATE 0x0c
48 #define IPU_PRG_REG_UPDATE_REG_UPDATE (1 << 0)
50 #define IPU_PRG_STRIDE(i) (0x10 + i * 0x4)
51 #define IPU_PRG_STRIDE_STRIDE_MASK 0x3fff
53 #define IPU_PRG_CROP_LINE 0x1c
55 #define IPU_PRG_THD 0x20
57 #define IPU_PRG_BADDR(i) (0x24 + i * 0x4)
59 #define IPU_PRG_OFFSET(i) (0x30 + i * 0x4)
61 #define IPU_PRG_ILO(i) (0x3c + i * 0x4)
63 #define IPU_PRG_HEIGHT(i) (0x48 + i * 0x4)
64 #define IPU_PRG_HEIGHT_PRE_HEIGHT_MASK 0xfff
65 #define IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT 0
66 #define IPU_PRG_HEIGHT_IPU_HEIGHT_MASK 0xfff
67 #define IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT 16
69 struct ipu_prg_channel
{
75 struct list_head list
;
80 struct clk
*clk_ipg
, *clk_axi
;
81 struct regmap
*iomuxc_gpr
;
82 struct ipu_pre
*pres
[3];
84 struct ipu_prg_channel chan
[3];
87 static DEFINE_MUTEX(ipu_prg_list_mutex
);
88 static LIST_HEAD(ipu_prg_list
);
91 ipu_prg_lookup_by_phandle(struct device
*dev
, const char *name
, int ipu_id
)
93 struct device_node
*prg_node
= of_parse_phandle(dev
->of_node
,
97 mutex_lock(&ipu_prg_list_mutex
);
98 list_for_each_entry(prg
, &ipu_prg_list
, list
) {
99 if (prg_node
== prg
->dev
->of_node
) {
100 mutex_unlock(&ipu_prg_list_mutex
);
101 device_link_add(dev
, prg
->dev
, DL_FLAG_AUTOREMOVE
);
106 mutex_unlock(&ipu_prg_list_mutex
);
111 int ipu_prg_max_active_channels(void)
113 return ipu_pre_get_available_count();
115 EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels
);
117 bool ipu_prg_present(struct ipu_soc
*ipu
)
124 EXPORT_SYMBOL_GPL(ipu_prg_present
);
126 bool ipu_prg_format_supported(struct ipu_soc
*ipu
, uint32_t format
,
129 const struct drm_format_info
*info
= drm_format_info(format
);
131 if (info
->num_planes
!= 1)
136 EXPORT_SYMBOL_GPL(ipu_prg_format_supported
);
138 int ipu_prg_enable(struct ipu_soc
*ipu
)
140 struct ipu_prg
*prg
= ipu
->prg_priv
;
146 ret
= clk_prepare_enable(prg
->clk_axi
);
148 goto fail_disable_ipg
;
153 clk_disable_unprepare(prg
->clk_ipg
);
157 EXPORT_SYMBOL_GPL(ipu_prg_enable
);
159 void ipu_prg_disable(struct ipu_soc
*ipu
)
161 struct ipu_prg
*prg
= ipu
->prg_priv
;
166 clk_disable_unprepare(prg
->clk_axi
);
168 EXPORT_SYMBOL_GPL(ipu_prg_disable
);
171 * The channel configuartion functions below are not thread safe, as they
172 * must be only called from the atomic commit path in the DRM driver, which
173 * is properly serialized.
175 static int ipu_prg_ipu_to_prg_chan(int ipu_chan
)
178 * This isn't clearly documented in the RM, but IPU to PRG channel
179 * assignment is fixed, as only with this mapping the control signals
183 case IPUV3_CHANNEL_MEM_BG_SYNC
:
185 case IPUV3_CHANNEL_MEM_FG_SYNC
:
187 case IPUV3_CHANNEL_MEM_DC_SYNC
:
194 static int ipu_prg_get_pre(struct ipu_prg
*prg
, int prg_chan
)
198 /* channel 0 is special as it is hardwired to one of the PREs */
200 ret
= ipu_pre_get(prg
->pres
[0]);
203 prg
->chan
[prg_chan
].used_pre
= 0;
207 for (i
= 1; i
< 3; i
++) {
208 ret
= ipu_pre_get(prg
->pres
[i
]);
213 prg
->chan
[prg_chan
].used_pre
= i
;
215 /* configure the PRE to PRG channel mux */
216 shift
= (i
== 1) ? 12 : 14;
217 mux
= (prg
->id
<< 1) | (prg_chan
- 1);
218 regmap_update_bits(prg
->iomuxc_gpr
, IOMUXC_GPR5
,
219 0x3 << shift
, mux
<< shift
);
221 /* check other mux, must not point to same channel */
222 shift
= (i
== 1) ? 14 : 12;
223 regmap_read(prg
->iomuxc_gpr
, IOMUXC_GPR5
, &val
);
224 if (((val
>> shift
) & 0x3) == mux
) {
225 regmap_update_bits(prg
->iomuxc_gpr
, IOMUXC_GPR5
,
227 (mux
^ 0x1) << shift
);
235 dev_err(prg
->dev
, "could not get PRE for PRG chan %d", prg_chan
);
239 static void ipu_prg_put_pre(struct ipu_prg
*prg
, int prg_chan
)
241 struct ipu_prg_channel
*chan
= &prg
->chan
[prg_chan
];
243 ipu_pre_put(prg
->pres
[chan
->used_pre
]);
247 void ipu_prg_channel_disable(struct ipuv3_channel
*ipu_chan
)
249 int prg_chan
= ipu_prg_ipu_to_prg_chan(ipu_chan
->num
);
250 struct ipu_prg
*prg
= ipu_chan
->ipu
->prg_priv
;
251 struct ipu_prg_channel
*chan
= &prg
->chan
[prg_chan
];
254 if (!chan
->enabled
|| prg_chan
< 0)
257 clk_prepare_enable(prg
->clk_ipg
);
259 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
260 val
|= IPU_PRG_CTL_BYPASS(prg_chan
);
261 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
263 val
= IPU_PRG_REG_UPDATE_REG_UPDATE
;
264 writel(val
, prg
->regs
+ IPU_PRG_REG_UPDATE
);
266 clk_disable_unprepare(prg
->clk_ipg
);
268 ipu_prg_put_pre(prg
, prg_chan
);
270 chan
->enabled
= false;
272 EXPORT_SYMBOL_GPL(ipu_prg_channel_disable
);
274 int ipu_prg_channel_configure(struct ipuv3_channel
*ipu_chan
,
275 unsigned int axi_id
, unsigned int width
,
276 unsigned int height
, unsigned int stride
,
277 u32 format
, unsigned long *eba
)
279 int prg_chan
= ipu_prg_ipu_to_prg_chan(ipu_chan
->num
);
280 struct ipu_prg
*prg
= ipu_chan
->ipu
->prg_priv
;
281 struct ipu_prg_channel
*chan
= &prg
->chan
[prg_chan
];
289 ipu_pre_update(prg
->pres
[chan
->used_pre
], *eba
);
293 ret
= ipu_prg_get_pre(prg
, prg_chan
);
297 ipu_pre_configure(prg
->pres
[chan
->used_pre
],
298 width
, height
, stride
, format
, *eba
);
301 ret
= clk_prepare_enable(prg
->clk_ipg
);
303 ipu_prg_put_pre(prg
, prg_chan
);
307 val
= (stride
- 1) & IPU_PRG_STRIDE_STRIDE_MASK
;
308 writel(val
, prg
->regs
+ IPU_PRG_STRIDE(prg_chan
));
310 val
= ((height
& IPU_PRG_HEIGHT_PRE_HEIGHT_MASK
) <<
311 IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT
) |
312 ((height
& IPU_PRG_HEIGHT_IPU_HEIGHT_MASK
) <<
313 IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT
);
314 writel(val
, prg
->regs
+ IPU_PRG_HEIGHT(prg_chan
));
316 val
= ipu_pre_get_baddr(prg
->pres
[chan
->used_pre
]);
318 writel(val
, prg
->regs
+ IPU_PRG_BADDR(prg_chan
));
320 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
321 /* counter load enable */
322 val
|= IPU_PRG_CTL_CNT_LOAD_EN(prg_chan
);
324 val
&= ~(IPU_PRG_CTL_SOFT_ARID_MASK
<<
325 IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan
));
326 val
|= IPU_PRG_CTL_SOFT_ARID(prg_chan
, axi_id
);
328 val
&= ~IPU_PRG_CTL_BYPASS(prg_chan
);
329 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
331 val
= IPU_PRG_REG_UPDATE_REG_UPDATE
;
332 writel(val
, prg
->regs
+ IPU_PRG_REG_UPDATE
);
334 clk_disable_unprepare(prg
->clk_ipg
);
336 chan
->enabled
= true;
339 EXPORT_SYMBOL_GPL(ipu_prg_channel_configure
);
341 static int ipu_prg_probe(struct platform_device
*pdev
)
343 struct device
*dev
= &pdev
->dev
;
344 struct resource
*res
;
349 prg
= devm_kzalloc(dev
, sizeof(*prg
), GFP_KERNEL
);
353 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
354 prg
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
355 if (IS_ERR(prg
->regs
))
356 return PTR_ERR(prg
->regs
);
359 prg
->clk_ipg
= devm_clk_get(dev
, "ipg");
360 if (IS_ERR(prg
->clk_ipg
))
361 return PTR_ERR(prg
->clk_ipg
);
363 prg
->clk_axi
= devm_clk_get(dev
, "axi");
364 if (IS_ERR(prg
->clk_axi
))
365 return PTR_ERR(prg
->clk_axi
);
368 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
369 if (IS_ERR(prg
->iomuxc_gpr
))
370 return PTR_ERR(prg
->iomuxc_gpr
);
372 for (i
= 0; i
< 3; i
++) {
373 prg
->pres
[i
] = ipu_pre_lookup_by_phandle(dev
, "fsl,pres", i
);
375 return -EPROBE_DEFER
;
378 ret
= clk_prepare_enable(prg
->clk_ipg
);
382 /* init to free running mode */
383 val
= readl(prg
->regs
+ IPU_PRG_CTL
);
384 val
|= IPU_PRG_CTL_SHADOW_EN
;
385 writel(val
, prg
->regs
+ IPU_PRG_CTL
);
387 /* disable address threshold */
388 writel(0xffffffff, prg
->regs
+ IPU_PRG_THD
);
390 clk_disable_unprepare(prg
->clk_ipg
);
393 platform_set_drvdata(pdev
, prg
);
394 mutex_lock(&ipu_prg_list_mutex
);
395 list_add(&prg
->list
, &ipu_prg_list
);
396 mutex_unlock(&ipu_prg_list_mutex
);
401 static int ipu_prg_remove(struct platform_device
*pdev
)
403 struct ipu_prg
*prg
= platform_get_drvdata(pdev
);
405 mutex_lock(&ipu_prg_list_mutex
);
406 list_del(&prg
->list
);
407 mutex_unlock(&ipu_prg_list_mutex
);
412 static const struct of_device_id ipu_prg_dt_ids
[] = {
413 { .compatible
= "fsl,imx6qp-prg", },
417 struct platform_driver ipu_prg_drv
= {
418 .probe
= ipu_prg_probe
,
419 .remove
= ipu_prg_remove
,
421 .name
= "imx-ipu-prg",
422 .of_match_table
= ipu_prg_dt_ids
,