1 // SPDX-License-Identifier: GPL-2.0+
2
3 /*
4 * Copyright 2020 NXP
5 */
6
7 #include <linux/bitfield.h>
8 #include <linux/clk.h>
9 #include <linux/delay.h>
10 #include <linux/io.h>
11 #include <linux/media-bus-format.h>
12 #include <linux/module.h>
13 #include <linux/of.h>
14 #include <linux/of_graph.h>
15 #include <linux/platform_device.h>
16 #include <linux/pm_runtime.h>
17
18 #include <drm/drm_atomic_state_helper.h>
19 #include <drm/drm_bridge.h>
20 #include <drm/drm_print.h>
21
22 #define PC_CTRL_REG 0x0
23 #define PC_COMBINE_ENABLE BIT(0)
24 #define PC_DISP_BYPASS(n) BIT(1 + 21 * (n))
25 #define PC_DISP_HSYNC_POLARITY(n) BIT(2 + 11 * (n))
26 #define PC_DISP_HSYNC_POLARITY_POS(n) DISP_HSYNC_POLARITY(n)
27 #define PC_DISP_VSYNC_POLARITY(n) BIT(3 + 11 * (n))
28 #define PC_DISP_VSYNC_POLARITY_POS(n) DISP_VSYNC_POLARITY(n)
29 #define PC_DISP_DVALID_POLARITY(n) BIT(4 + 11 * (n))
30 #define PC_DISP_DVALID_POLARITY_POS(n) DISP_DVALID_POLARITY(n)
31 #define PC_VSYNC_MASK_ENABLE BIT(5)
32 #define PC_SKIP_MODE BIT(6)
33 #define PC_SKIP_NUMBER_MASK GENMASK(12, 7)
34 #define PC_SKIP_NUMBER(n) FIELD_PREP(PC_SKIP_NUMBER_MASK, (n))
35 #define PC_DISP0_PIX_DATA_FORMAT_MASK GENMASK(18, 16)
36 #define PC_DISP0_PIX_DATA_FORMAT(fmt) \
37 FIELD_PREP(PC_DISP0_PIX_DATA_FORMAT_MASK, (fmt))
38 #define PC_DISP1_PIX_DATA_FORMAT_MASK GENMASK(21, 19)
39 #define PC_DISP1_PIX_DATA_FORMAT(fmt) \
40 FIELD_PREP(PC_DISP1_PIX_DATA_FORMAT_MASK, (fmt))
41
42 #define PC_SW_RESET_REG 0x20
43 #define PC_SW_RESET_N BIT(0)
44 #define PC_DISP_SW_RESET_N(n) BIT(1 + (n))
45 #define PC_FULL_RESET_N (PC_SW_RESET_N | \
46 PC_DISP_SW_RESET_N(0) | \
47 PC_DISP_SW_RESET_N(1))
48
49 #define PC_REG_SET 0x4
50 #define PC_REG_CLR 0x8
51
52 #define DRIVER_NAME "imx8qxp-pixel-combiner"
53
54 enum imx8qxp_pc_pix_data_format {
55 RGB,
56 YUV444,
57 YUV422,
58 SPLIT_RGB,
59 };
60
61 struct imx8qxp_pc_channel {
62 struct drm_bridge bridge;
63 struct imx8qxp_pc *pc;
64 unsigned int stream_id;
65 };
66
67 struct imx8qxp_pc {
68 struct device *dev;
69 struct imx8qxp_pc_channel *ch[2];
70 struct clk *clk_apb;
71 void __iomem *base;
72 };
73
imx8qxp_pc_read(struct imx8qxp_pc * pc,unsigned int offset)74 static inline u32 imx8qxp_pc_read(struct imx8qxp_pc *pc, unsigned int offset)
75 {
76 return readl(pc->base + offset);
77 }
78
79 static inline void
imx8qxp_pc_write(struct imx8qxp_pc * pc,unsigned int offset,u32 value)80 imx8qxp_pc_write(struct imx8qxp_pc *pc, unsigned int offset, u32 value)
81 {
82 writel(value, pc->base + offset);
83 }
84
85 static inline void
imx8qxp_pc_write_set(struct imx8qxp_pc * pc,unsigned int offset,u32 value)86 imx8qxp_pc_write_set(struct imx8qxp_pc *pc, unsigned int offset, u32 value)
87 {
88 imx8qxp_pc_write(pc, offset + PC_REG_SET, value);
89 }
90
91 static inline void
imx8qxp_pc_write_clr(struct imx8qxp_pc * pc,unsigned int offset,u32 value)92 imx8qxp_pc_write_clr(struct imx8qxp_pc *pc, unsigned int offset, u32 value)
93 {
94 imx8qxp_pc_write(pc, offset + PC_REG_CLR, value);
95 }
96
97 static enum drm_mode_status
imx8qxp_pc_bridge_mode_valid(struct drm_bridge * bridge,const struct drm_display_info * info,const struct drm_display_mode * mode)98 imx8qxp_pc_bridge_mode_valid(struct drm_bridge *bridge,
99 const struct drm_display_info *info,
100 const struct drm_display_mode *mode)
101 {
102 if (mode->hdisplay > 2560)
103 return MODE_BAD_HVALUE;
104
105 return MODE_OK;
106 }
107
imx8qxp_pc_bridge_attach(struct drm_bridge * bridge,struct drm_encoder * encoder,enum drm_bridge_attach_flags flags)108 static int imx8qxp_pc_bridge_attach(struct drm_bridge *bridge,
109 struct drm_encoder *encoder,
110 enum drm_bridge_attach_flags flags)
111 {
112 struct imx8qxp_pc_channel *ch = bridge->driver_private;
113 struct imx8qxp_pc *pc = ch->pc;
114
115 if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) {
116 DRM_DEV_ERROR(pc->dev,
117 "do not support creating a drm_connector\n");
118 return -EINVAL;
119 }
120
121 return drm_bridge_attach(encoder,
122 ch->bridge.next_bridge, bridge,
123 DRM_BRIDGE_ATTACH_NO_CONNECTOR);
124 }
125
126 static void
imx8qxp_pc_bridge_mode_set(struct drm_bridge * bridge,const struct drm_display_mode * mode,const struct drm_display_mode * adjusted_mode)127 imx8qxp_pc_bridge_mode_set(struct drm_bridge *bridge,
128 const struct drm_display_mode *mode,
129 const struct drm_display_mode *adjusted_mode)
130 {
131 struct imx8qxp_pc_channel *ch = bridge->driver_private;
132 struct imx8qxp_pc *pc = ch->pc;
133 u32 val;
134 int ret;
135
136 ret = pm_runtime_get_sync(pc->dev);
137 if (ret < 0)
138 DRM_DEV_ERROR(pc->dev,
139 "failed to get runtime PM sync: %d\n", ret);
140
141 ret = clk_prepare_enable(pc->clk_apb);
142 if (ret)
143 DRM_DEV_ERROR(pc->dev, "%s: failed to enable apb clock: %d\n",
144 __func__, ret);
145
146 /* HSYNC to pixel link is active low. */
147 imx8qxp_pc_write_clr(pc, PC_CTRL_REG,
148 PC_DISP_HSYNC_POLARITY(ch->stream_id));
149
150 /* VSYNC to pixel link is active low. */
151 imx8qxp_pc_write_clr(pc, PC_CTRL_REG,
152 PC_DISP_VSYNC_POLARITY(ch->stream_id));
153
154 /* Data enable to pixel link is active high. */
155 imx8qxp_pc_write_set(pc, PC_CTRL_REG,
156 PC_DISP_DVALID_POLARITY(ch->stream_id));
157
158 /* Mask the first frame output which may be incomplete. */
159 imx8qxp_pc_write_set(pc, PC_CTRL_REG, PC_VSYNC_MASK_ENABLE);
160
161 /* Only support RGB currently. */
162 val = imx8qxp_pc_read(pc, PC_CTRL_REG);
163 if (ch->stream_id == 0) {
164 val &= ~PC_DISP0_PIX_DATA_FORMAT_MASK;
165 val |= PC_DISP0_PIX_DATA_FORMAT(RGB);
166 } else {
167 val &= ~PC_DISP1_PIX_DATA_FORMAT_MASK;
168 val |= PC_DISP1_PIX_DATA_FORMAT(RGB);
169 }
170 imx8qxp_pc_write(pc, PC_CTRL_REG, val);
171
172 /* Only support bypass mode currently. */
173 imx8qxp_pc_write_set(pc, PC_CTRL_REG, PC_DISP_BYPASS(ch->stream_id));
174
175 clk_disable_unprepare(pc->clk_apb);
176 }
177
imx8qxp_pc_bridge_atomic_disable(struct drm_bridge * bridge,struct drm_atomic_state * state)178 static void imx8qxp_pc_bridge_atomic_disable(struct drm_bridge *bridge,
179 struct drm_atomic_state *state)
180 {
181 struct imx8qxp_pc_channel *ch = bridge->driver_private;
182 struct imx8qxp_pc *pc = ch->pc;
183
184 pm_runtime_put(pc->dev);
185 }
186
187 static const u32 imx8qxp_pc_bus_output_fmts[] = {
188 MEDIA_BUS_FMT_RGB888_1X36_CPADLO,
189 MEDIA_BUS_FMT_RGB666_1X36_CPADLO,
190 };
191
imx8qxp_pc_bus_output_fmt_supported(u32 fmt)192 static bool imx8qxp_pc_bus_output_fmt_supported(u32 fmt)
193 {
194 int i;
195
196 for (i = 0; i < ARRAY_SIZE(imx8qxp_pc_bus_output_fmts); i++) {
197 if (imx8qxp_pc_bus_output_fmts[i] == fmt)
198 return true;
199 }
200
201 return false;
202 }
203
204 static u32 *
imx8qxp_pc_bridge_atomic_get_input_bus_fmts(struct drm_bridge * bridge,struct drm_bridge_state * bridge_state,struct drm_crtc_state * crtc_state,struct drm_connector_state * conn_state,u32 output_fmt,unsigned int * num_input_fmts)205 imx8qxp_pc_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
206 struct drm_bridge_state *bridge_state,
207 struct drm_crtc_state *crtc_state,
208 struct drm_connector_state *conn_state,
209 u32 output_fmt,
210 unsigned int *num_input_fmts)
211 {
212 u32 *input_fmts;
213
214 if (!imx8qxp_pc_bus_output_fmt_supported(output_fmt))
215 return NULL;
216
217 *num_input_fmts = 1;
218
219 input_fmts = kmalloc_obj(*input_fmts);
220 if (!input_fmts)
221 return NULL;
222
223 switch (output_fmt) {
224 case MEDIA_BUS_FMT_RGB888_1X36_CPADLO:
225 input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X30_CPADLO;
226 break;
227 case MEDIA_BUS_FMT_RGB666_1X36_CPADLO:
228 input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X30_CPADLO;
229 break;
230 default:
231 kfree(input_fmts);
232 input_fmts = NULL;
233 break;
234 }
235
236 return input_fmts;
237 }
238
239 static u32 *
imx8qxp_pc_bridge_atomic_get_output_bus_fmts(struct drm_bridge * bridge,struct drm_bridge_state * bridge_state,struct drm_crtc_state * crtc_state,struct drm_connector_state * conn_state,unsigned int * num_output_fmts)240 imx8qxp_pc_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
241 struct drm_bridge_state *bridge_state,
242 struct drm_crtc_state *crtc_state,
243 struct drm_connector_state *conn_state,
244 unsigned int *num_output_fmts)
245 {
246 *num_output_fmts = ARRAY_SIZE(imx8qxp_pc_bus_output_fmts);
247 return kmemdup(imx8qxp_pc_bus_output_fmts,
248 sizeof(imx8qxp_pc_bus_output_fmts), GFP_KERNEL);
249 }
250
251 static const struct drm_bridge_funcs imx8qxp_pc_bridge_funcs = {
252 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
253 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
254 .atomic_reset = drm_atomic_helper_bridge_reset,
255 .mode_valid = imx8qxp_pc_bridge_mode_valid,
256 .attach = imx8qxp_pc_bridge_attach,
257 .mode_set = imx8qxp_pc_bridge_mode_set,
258 .atomic_disable = imx8qxp_pc_bridge_atomic_disable,
259 .atomic_get_input_bus_fmts =
260 imx8qxp_pc_bridge_atomic_get_input_bus_fmts,
261 .atomic_get_output_bus_fmts =
262 imx8qxp_pc_bridge_atomic_get_output_bus_fmts,
263 };
264
imx8qxp_pc_bridge_probe(struct platform_device * pdev)265 static int imx8qxp_pc_bridge_probe(struct platform_device *pdev)
266 {
267 struct imx8qxp_pc *pc;
268 struct imx8qxp_pc_channel *ch;
269 struct device *dev = &pdev->dev;
270 struct device_node *np = dev->of_node;
271 struct device_node *child, *remote;
272 u32 i;
273 int ret;
274
275 pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
276 if (!pc)
277 return -ENOMEM;
278
279 pc->base = devm_platform_ioremap_resource(pdev, 0);
280 if (IS_ERR(pc->base))
281 return PTR_ERR(pc->base);
282
283 pc->dev = dev;
284
285 pc->clk_apb = devm_clk_get(dev, "apb");
286 if (IS_ERR(pc->clk_apb)) {
287 ret = PTR_ERR(pc->clk_apb);
288 if (ret != -EPROBE_DEFER)
289 DRM_DEV_ERROR(dev, "failed to get apb clock: %d\n", ret);
290 return ret;
291 }
292
293 platform_set_drvdata(pdev, pc);
294 pm_runtime_enable(dev);
295
296 for_each_available_child_of_node(np, child) {
297 ret = of_property_read_u32(child, "reg", &i);
298 if (ret || i > 1) {
299 ret = -EINVAL;
300 DRM_DEV_ERROR(dev,
301 "invalid channel(%u) node address\n", i);
302 goto free_child;
303 }
304
305 ch = devm_drm_bridge_alloc(dev, struct imx8qxp_pc_channel, bridge,
306 &imx8qxp_pc_bridge_funcs);
307 if (IS_ERR(ch)) {
308 ret = PTR_ERR(ch);
309 goto free_child;
310 }
311
312 pc->ch[i] = ch;
313 ch->pc = pc;
314 ch->stream_id = i;
315
316 remote = of_graph_get_remote_node(child, 1, 0);
317 if (!remote) {
318 ret = -ENODEV;
319 DRM_DEV_ERROR(dev,
320 "channel%u failed to get port1's remote node: %d\n",
321 i, ret);
322 goto free_child;
323 }
324
325 ch->bridge.next_bridge = of_drm_find_and_get_bridge(remote);
326 if (!ch->bridge.next_bridge) {
327 of_node_put(remote);
328 ret = -EPROBE_DEFER;
329 DRM_DEV_DEBUG_DRIVER(dev,
330 "channel%u failed to find next bridge: %d\n",
331 i, ret);
332 goto free_child;
333 }
334
335 of_node_put(remote);
336
337 ch->bridge.driver_private = ch;
338 ch->bridge.of_node = child;
339
340 drm_bridge_add(&ch->bridge);
341 }
342
343 return 0;
344
345 free_child:
346 of_node_put(child);
347
348 if (i == 1 && pc->ch[0] && pc->ch[0]->bridge.next_bridge)
349 drm_bridge_remove(&pc->ch[0]->bridge);
350
351 pm_runtime_disable(dev);
352 return ret;
353 }
354
imx8qxp_pc_bridge_remove(struct platform_device * pdev)355 static void imx8qxp_pc_bridge_remove(struct platform_device *pdev)
356 {
357 struct imx8qxp_pc *pc = platform_get_drvdata(pdev);
358 struct imx8qxp_pc_channel *ch;
359 int i;
360
361 for (i = 0; i < 2; i++) {
362 ch = pc->ch[i];
363
364 if (ch)
365 drm_bridge_remove(&ch->bridge);
366 }
367
368 pm_runtime_disable(&pdev->dev);
369 }
370
imx8qxp_pc_runtime_suspend(struct device * dev)371 static int imx8qxp_pc_runtime_suspend(struct device *dev)
372 {
373 struct platform_device *pdev = to_platform_device(dev);
374 struct imx8qxp_pc *pc = platform_get_drvdata(pdev);
375 int ret;
376
377 ret = clk_prepare_enable(pc->clk_apb);
378 if (ret)
379 DRM_DEV_ERROR(pc->dev, "%s: failed to enable apb clock: %d\n",
380 __func__, ret);
381
382 /* Disable pixel combiner by full reset. */
383 imx8qxp_pc_write_clr(pc, PC_SW_RESET_REG, PC_FULL_RESET_N);
384
385 clk_disable_unprepare(pc->clk_apb);
386
387 /* Ensure the reset takes effect. */
388 usleep_range(10, 20);
389
390 return ret;
391 }
392
imx8qxp_pc_runtime_resume(struct device * dev)393 static int imx8qxp_pc_runtime_resume(struct device *dev)
394 {
395 struct platform_device *pdev = to_platform_device(dev);
396 struct imx8qxp_pc *pc = platform_get_drvdata(pdev);
397 int ret;
398
399 ret = clk_prepare_enable(pc->clk_apb);
400 if (ret) {
401 DRM_DEV_ERROR(pc->dev, "%s: failed to enable apb clock: %d\n",
402 __func__, ret);
403 return ret;
404 }
405
406 /* out of reset */
407 imx8qxp_pc_write_set(pc, PC_SW_RESET_REG, PC_FULL_RESET_N);
408
409 clk_disable_unprepare(pc->clk_apb);
410
411 return ret;
412 }
413
414 static const struct dev_pm_ops imx8qxp_pc_pm_ops = {
415 RUNTIME_PM_OPS(imx8qxp_pc_runtime_suspend, imx8qxp_pc_runtime_resume, NULL)
416 };
417
418 static const struct of_device_id imx8qxp_pc_dt_ids[] = {
419 { .compatible = "fsl,imx8qm-pixel-combiner", },
420 { .compatible = "fsl,imx8qxp-pixel-combiner", },
421 { /* sentinel */ }
422 };
423 MODULE_DEVICE_TABLE(of, imx8qxp_pc_dt_ids);
424
425 static struct platform_driver imx8qxp_pc_bridge_driver = {
426 .probe = imx8qxp_pc_bridge_probe,
427 .remove = imx8qxp_pc_bridge_remove,
428 .driver = {
429 .pm = pm_ptr(&imx8qxp_pc_pm_ops),
430 .name = DRIVER_NAME,
431 .of_match_table = imx8qxp_pc_dt_ids,
432 },
433 };
434 module_platform_driver(imx8qxp_pc_bridge_driver);
435
436 MODULE_DESCRIPTION("i.MX8QM/QXP pixel combiner bridge driver");
437 MODULE_AUTHOR("Liu Ying <victor.liu@nxp.com>");
438 MODULE_LICENSE("GPL v2");
439 MODULE_ALIAS("platform:" DRIVER_NAME);
440