Merge tag 'fixes-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[linux-2.6-microblaze.git] / drivers / gpu / drm / ingenic / ingenic-drm-drv.c
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Ingenic JZ47xx KMS driver
4 //
5 // Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net>
6
7 #include "ingenic-drm.h"
8
9 #include <linux/component.h>
10 #include <linux/clk.h>
11 #include <linux/dma-mapping.h>
12 #include <linux/module.h>
13 #include <linux/mutex.h>
14 #include <linux/of_device.h>
15 #include <linux/of_reserved_mem.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm.h>
18 #include <linux/regmap.h>
19
20 #include <drm/drm_atomic.h>
21 #include <drm/drm_atomic_helper.h>
22 #include <drm/drm_bridge.h>
23 #include <drm/drm_color_mgmt.h>
24 #include <drm/drm_crtc.h>
25 #include <drm/drm_crtc_helper.h>
26 #include <drm/drm_drv.h>
27 #include <drm/drm_gem_cma_helper.h>
28 #include <drm/drm_fb_cma_helper.h>
29 #include <drm/drm_fb_helper.h>
30 #include <drm/drm_fourcc.h>
31 #include <drm/drm_gem_framebuffer_helper.h>
32 #include <drm/drm_irq.h>
33 #include <drm/drm_managed.h>
34 #include <drm/drm_of.h>
35 #include <drm/drm_panel.h>
36 #include <drm/drm_plane.h>
37 #include <drm/drm_plane_helper.h>
38 #include <drm/drm_probe_helper.h>
39 #include <drm/drm_simple_kms_helper.h>
40 #include <drm/drm_vblank.h>
41
42 struct ingenic_dma_hwdesc {
43         u32 next;
44         u32 addr;
45         u32 id;
46         u32 cmd;
47 } __aligned(16);
48
49 struct ingenic_dma_hwdescs {
50         struct ingenic_dma_hwdesc hwdesc_f0;
51         struct ingenic_dma_hwdesc hwdesc_f1;
52         struct ingenic_dma_hwdesc hwdesc_pal;
53         u16 palette[256] __aligned(16);
54 };
55
56 struct jz_soc_info {
57         bool needs_dev_clk;
58         bool has_osd;
59         unsigned int max_width, max_height;
60         const u32 *formats_f0, *formats_f1;
61         unsigned int num_formats_f0, num_formats_f1;
62 };
63
64 struct ingenic_drm {
65         struct drm_device drm;
66         /*
67          * f1 (aka. foreground1) is our primary plane, on top of which
68          * f0 (aka. foreground0) can be overlayed. Z-order is fixed in
69          * hardware and cannot be changed.
70          */
71         struct drm_plane f0, f1, *ipu_plane;
72         struct drm_crtc crtc;
73
74         struct device *dev;
75         struct regmap *map;
76         struct clk *lcd_clk, *pix_clk;
77         const struct jz_soc_info *soc_info;
78
79         struct ingenic_dma_hwdescs *dma_hwdescs;
80         dma_addr_t dma_hwdescs_phys;
81
82         bool panel_is_sharp;
83         bool no_vblank;
84
85         /*
86          * clk_mutex is used to synchronize the pixel clock rate update with
87          * the VBLANK. When the pixel clock's parent clock needs to be updated,
88          * clock_nb's notifier function will lock the mutex, then wait until the
89          * next VBLANK. At that point, the parent clock's rate can be updated,
90          * and the mutex is then unlocked. If an atomic commit happens in the
91          * meantime, it will lock on the mutex, effectively waiting until the
92          * clock update process finishes. Finally, the pixel clock's rate will
93          * be recomputed when the mutex has been released, in the pending atomic
94          * commit, or a future one.
95          */
96         struct mutex clk_mutex;
97         bool update_clk_rate;
98         struct notifier_block clock_nb;
99 };
100
101 static bool ingenic_drm_writeable_reg(struct device *dev, unsigned int reg)
102 {
103         switch (reg) {
104         case JZ_REG_LCD_IID:
105         case JZ_REG_LCD_SA0:
106         case JZ_REG_LCD_FID0:
107         case JZ_REG_LCD_CMD0:
108         case JZ_REG_LCD_SA1:
109         case JZ_REG_LCD_FID1:
110         case JZ_REG_LCD_CMD1:
111                 return false;
112         default:
113                 return true;
114         }
115 }
116
117 static const struct regmap_config ingenic_drm_regmap_config = {
118         .reg_bits = 32,
119         .val_bits = 32,
120         .reg_stride = 4,
121
122         .max_register = JZ_REG_LCD_SIZE1,
123         .writeable_reg = ingenic_drm_writeable_reg,
124 };
125
126 static inline struct ingenic_drm *drm_device_get_priv(struct drm_device *drm)
127 {
128         return container_of(drm, struct ingenic_drm, drm);
129 }
130
131 static inline struct ingenic_drm *drm_crtc_get_priv(struct drm_crtc *crtc)
132 {
133         return container_of(crtc, struct ingenic_drm, crtc);
134 }
135
136 static inline struct ingenic_drm *drm_nb_get_priv(struct notifier_block *nb)
137 {
138         return container_of(nb, struct ingenic_drm, clock_nb);
139 }
140
141 static int ingenic_drm_update_pixclk(struct notifier_block *nb,
142                                      unsigned long action,
143                                      void *data)
144 {
145         struct ingenic_drm *priv = drm_nb_get_priv(nb);
146
147         switch (action) {
148         case PRE_RATE_CHANGE:
149                 mutex_lock(&priv->clk_mutex);
150                 priv->update_clk_rate = true;
151                 drm_crtc_wait_one_vblank(&priv->crtc);
152                 return NOTIFY_OK;
153         default:
154                 mutex_unlock(&priv->clk_mutex);
155                 return NOTIFY_OK;
156         }
157 }
158
159 static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc,
160                                            struct drm_atomic_state *state)
161 {
162         struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
163
164         regmap_write(priv->map, JZ_REG_LCD_STATE, 0);
165
166         regmap_update_bits(priv->map, JZ_REG_LCD_CTRL,
167                            JZ_LCD_CTRL_ENABLE | JZ_LCD_CTRL_DISABLE,
168                            JZ_LCD_CTRL_ENABLE);
169
170         drm_crtc_vblank_on(crtc);
171 }
172
173 static void ingenic_drm_crtc_atomic_disable(struct drm_crtc *crtc,
174                                             struct drm_atomic_state *state)
175 {
176         struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
177         unsigned int var;
178
179         drm_crtc_vblank_off(crtc);
180
181         regmap_update_bits(priv->map, JZ_REG_LCD_CTRL,
182                            JZ_LCD_CTRL_DISABLE, JZ_LCD_CTRL_DISABLE);
183
184         regmap_read_poll_timeout(priv->map, JZ_REG_LCD_STATE, var,
185                                  var & JZ_LCD_STATE_DISABLED,
186                                  1000, 0);
187 }
188
189 static void ingenic_drm_crtc_update_timings(struct ingenic_drm *priv,
190                                             struct drm_display_mode *mode)
191 {
192         unsigned int vpe, vds, vde, vt, hpe, hds, hde, ht;
193
194         vpe = mode->crtc_vsync_end - mode->crtc_vsync_start;
195         vds = mode->crtc_vtotal - mode->crtc_vsync_start;
196         vde = vds + mode->crtc_vdisplay;
197         vt = vde + mode->crtc_vsync_start - mode->crtc_vdisplay;
198
199         hpe = mode->crtc_hsync_end - mode->crtc_hsync_start;
200         hds = mode->crtc_htotal - mode->crtc_hsync_start;
201         hde = hds + mode->crtc_hdisplay;
202         ht = hde + mode->crtc_hsync_start - mode->crtc_hdisplay;
203
204         regmap_write(priv->map, JZ_REG_LCD_VSYNC,
205                      0 << JZ_LCD_VSYNC_VPS_OFFSET |
206                      vpe << JZ_LCD_VSYNC_VPE_OFFSET);
207
208         regmap_write(priv->map, JZ_REG_LCD_HSYNC,
209                      0 << JZ_LCD_HSYNC_HPS_OFFSET |
210                      hpe << JZ_LCD_HSYNC_HPE_OFFSET);
211
212         regmap_write(priv->map, JZ_REG_LCD_VAT,
213                      ht << JZ_LCD_VAT_HT_OFFSET |
214                      vt << JZ_LCD_VAT_VT_OFFSET);
215
216         regmap_write(priv->map, JZ_REG_LCD_DAH,
217                      hds << JZ_LCD_DAH_HDS_OFFSET |
218                      hde << JZ_LCD_DAH_HDE_OFFSET);
219         regmap_write(priv->map, JZ_REG_LCD_DAV,
220                      vds << JZ_LCD_DAV_VDS_OFFSET |
221                      vde << JZ_LCD_DAV_VDE_OFFSET);
222
223         if (priv->panel_is_sharp) {
224                 regmap_write(priv->map, JZ_REG_LCD_PS, hde << 16 | (hde + 1));
225                 regmap_write(priv->map, JZ_REG_LCD_CLS, hde << 16 | (hde + 1));
226                 regmap_write(priv->map, JZ_REG_LCD_SPL, hpe << 16 | (hpe + 1));
227                 regmap_write(priv->map, JZ_REG_LCD_REV, mode->htotal << 16);
228         }
229
230         regmap_set_bits(priv->map, JZ_REG_LCD_CTRL,
231                         JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16);
232
233         /*
234          * IPU restart - specify how much time the LCDC will wait before
235          * transferring a new frame from the IPU. The value is the one
236          * suggested in the programming manual.
237          */
238         regmap_write(priv->map, JZ_REG_LCD_IPUR, JZ_LCD_IPUR_IPUREN |
239                      (ht * vpe / 3) << JZ_LCD_IPUR_IPUR_LSB);
240 }
241
242 static int ingenic_drm_crtc_atomic_check(struct drm_crtc *crtc,
243                                          struct drm_atomic_state *state)
244 {
245         struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
246                                                                           crtc);
247         struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
248         struct drm_plane_state *f1_state, *f0_state, *ipu_state = NULL;
249
250         if (crtc_state->gamma_lut &&
251             drm_color_lut_size(crtc_state->gamma_lut) != ARRAY_SIZE(priv->dma_hwdescs->palette)) {
252                 dev_dbg(priv->dev, "Invalid palette size\n");
253                 return -EINVAL;
254         }
255
256         if (drm_atomic_crtc_needs_modeset(crtc_state) && priv->soc_info->has_osd) {
257                 f1_state = drm_atomic_get_plane_state(crtc_state->state,
258                                                       &priv->f1);
259                 if (IS_ERR(f1_state))
260                         return PTR_ERR(f1_state);
261
262                 f0_state = drm_atomic_get_plane_state(crtc_state->state,
263                                                       &priv->f0);
264                 if (IS_ERR(f0_state))
265                         return PTR_ERR(f0_state);
266
267                 if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU) && priv->ipu_plane) {
268                         ipu_state = drm_atomic_get_plane_state(crtc_state->state,
269                                                                priv->ipu_plane);
270                         if (IS_ERR(ipu_state))
271                                 return PTR_ERR(ipu_state);
272
273                         /* IPU and F1 planes cannot be enabled at the same time. */
274                         if (f1_state->fb && ipu_state->fb) {
275                                 dev_dbg(priv->dev, "Cannot enable both F1 and IPU\n");
276                                 return -EINVAL;
277                         }
278                 }
279
280                 /* If all the planes are disabled, we won't get a VBLANK IRQ */
281                 priv->no_vblank = !f1_state->fb && !f0_state->fb &&
282                                   !(ipu_state && ipu_state->fb);
283         }
284
285         return 0;
286 }
287
288 static enum drm_mode_status
289 ingenic_drm_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
290 {
291         struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
292         long rate;
293
294         if (mode->hdisplay > priv->soc_info->max_width)
295                 return MODE_BAD_HVALUE;
296         if (mode->vdisplay > priv->soc_info->max_height)
297                 return MODE_BAD_VVALUE;
298
299         rate = clk_round_rate(priv->pix_clk, mode->clock * 1000);
300         if (rate < 0)
301                 return MODE_CLOCK_RANGE;
302
303         return MODE_OK;
304 }
305
306 static void ingenic_drm_crtc_atomic_begin(struct drm_crtc *crtc,
307                                           struct drm_atomic_state *state)
308 {
309         struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
310                                                                           crtc);
311         struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
312         u32 ctrl = 0;
313
314         if (priv->soc_info->has_osd &&
315             drm_atomic_crtc_needs_modeset(crtc_state)) {
316                 /*
317                  * If IPU plane is enabled, enable IPU as source for the F1
318                  * plane; otherwise use regular DMA.
319                  */
320                 if (priv->ipu_plane && priv->ipu_plane->state->fb)
321                         ctrl |= JZ_LCD_OSDCTRL_IPU;
322
323                 regmap_update_bits(priv->map, JZ_REG_LCD_OSDCTRL,
324                                    JZ_LCD_OSDCTRL_IPU, ctrl);
325         }
326 }
327
328 static void ingenic_drm_crtc_atomic_flush(struct drm_crtc *crtc,
329                                           struct drm_atomic_state *state)
330 {
331         struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
332         struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
333                                                                           crtc);
334         struct drm_pending_vblank_event *event = crtc_state->event;
335
336         if (drm_atomic_crtc_needs_modeset(crtc_state)) {
337                 ingenic_drm_crtc_update_timings(priv, &crtc_state->adjusted_mode);
338                 priv->update_clk_rate = true;
339         }
340
341         if (priv->update_clk_rate) {
342                 mutex_lock(&priv->clk_mutex);
343                 clk_set_rate(priv->pix_clk,
344                              crtc_state->adjusted_mode.clock * 1000);
345                 priv->update_clk_rate = false;
346                 mutex_unlock(&priv->clk_mutex);
347         }
348
349         if (event) {
350                 crtc_state->event = NULL;
351
352                 spin_lock_irq(&crtc->dev->event_lock);
353                 if (drm_crtc_vblank_get(crtc) == 0)
354                         drm_crtc_arm_vblank_event(crtc, event);
355                 else
356                         drm_crtc_send_vblank_event(crtc, event);
357                 spin_unlock_irq(&crtc->dev->event_lock);
358         }
359 }
360
361 static int ingenic_drm_plane_atomic_check(struct drm_plane *plane,
362                                           struct drm_plane_state *state)
363 {
364         struct ingenic_drm *priv = drm_device_get_priv(plane->dev);
365         struct drm_crtc_state *crtc_state;
366         struct drm_crtc *crtc = state->crtc ?: plane->state->crtc;
367         int ret;
368
369         if (!crtc)
370                 return 0;
371
372         crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
373         if (WARN_ON(!crtc_state))
374                 return -EINVAL;
375
376         ret = drm_atomic_helper_check_plane_state(state, crtc_state,
377                                                   DRM_PLANE_HELPER_NO_SCALING,
378                                                   DRM_PLANE_HELPER_NO_SCALING,
379                                                   priv->soc_info->has_osd,
380                                                   true);
381         if (ret)
382                 return ret;
383
384         /*
385          * If OSD is not available, check that the width/height match.
386          * Note that state->src_* are in 16.16 fixed-point format.
387          */
388         if (!priv->soc_info->has_osd &&
389             (state->src_x != 0 ||
390              (state->src_w >> 16) != state->crtc_w ||
391              (state->src_h >> 16) != state->crtc_h))
392                 return -EINVAL;
393
394         /*
395          * Require full modeset if enabling or disabling a plane, or changing
396          * its position, size or depth.
397          */
398         if (priv->soc_info->has_osd &&
399             (!plane->state->fb || !state->fb ||
400              plane->state->crtc_x != state->crtc_x ||
401              plane->state->crtc_y != state->crtc_y ||
402              plane->state->crtc_w != state->crtc_w ||
403              plane->state->crtc_h != state->crtc_h ||
404              plane->state->fb->format->format != state->fb->format->format))
405                 crtc_state->mode_changed = true;
406
407         return 0;
408 }
409
410 static void ingenic_drm_plane_enable(struct ingenic_drm *priv,
411                                      struct drm_plane *plane)
412 {
413         unsigned int en_bit;
414
415         if (priv->soc_info->has_osd) {
416                 if (plane->type == DRM_PLANE_TYPE_PRIMARY)
417                         en_bit = JZ_LCD_OSDC_F1EN;
418                 else
419                         en_bit = JZ_LCD_OSDC_F0EN;
420
421                 regmap_set_bits(priv->map, JZ_REG_LCD_OSDC, en_bit);
422         }
423 }
424
425 void ingenic_drm_plane_disable(struct device *dev, struct drm_plane *plane)
426 {
427         struct ingenic_drm *priv = dev_get_drvdata(dev);
428         unsigned int en_bit;
429
430         if (priv->soc_info->has_osd) {
431                 if (plane->type == DRM_PLANE_TYPE_PRIMARY)
432                         en_bit = JZ_LCD_OSDC_F1EN;
433                 else
434                         en_bit = JZ_LCD_OSDC_F0EN;
435
436                 regmap_clear_bits(priv->map, JZ_REG_LCD_OSDC, en_bit);
437         }
438 }
439
440 static void ingenic_drm_plane_atomic_disable(struct drm_plane *plane,
441                                              struct drm_plane_state *old_state)
442 {
443         struct ingenic_drm *priv = drm_device_get_priv(plane->dev);
444
445         ingenic_drm_plane_disable(priv->dev, plane);
446 }
447
448 void ingenic_drm_plane_config(struct device *dev,
449                               struct drm_plane *plane, u32 fourcc)
450 {
451         struct ingenic_drm *priv = dev_get_drvdata(dev);
452         struct drm_plane_state *state = plane->state;
453         unsigned int xy_reg, size_reg;
454         unsigned int ctrl = 0;
455
456         ingenic_drm_plane_enable(priv, plane);
457
458         if (priv->soc_info->has_osd &&
459             plane->type == DRM_PLANE_TYPE_PRIMARY) {
460                 switch (fourcc) {
461                 case DRM_FORMAT_XRGB1555:
462                         ctrl |= JZ_LCD_OSDCTRL_RGB555;
463                         fallthrough;
464                 case DRM_FORMAT_RGB565:
465                         ctrl |= JZ_LCD_OSDCTRL_BPP_15_16;
466                         break;
467                 case DRM_FORMAT_RGB888:
468                         ctrl |= JZ_LCD_OSDCTRL_BPP_24_COMP;
469                         break;
470                 case DRM_FORMAT_XRGB8888:
471                         ctrl |= JZ_LCD_OSDCTRL_BPP_18_24;
472                         break;
473                 case DRM_FORMAT_XRGB2101010:
474                         ctrl |= JZ_LCD_OSDCTRL_BPP_30;
475                         break;
476                 }
477
478                 regmap_update_bits(priv->map, JZ_REG_LCD_OSDCTRL,
479                                    JZ_LCD_OSDCTRL_BPP_MASK, ctrl);
480         } else {
481                 switch (fourcc) {
482                 case DRM_FORMAT_C8:
483                         ctrl |= JZ_LCD_CTRL_BPP_8;
484                         break;
485                 case DRM_FORMAT_XRGB1555:
486                         ctrl |= JZ_LCD_CTRL_RGB555;
487                         fallthrough;
488                 case DRM_FORMAT_RGB565:
489                         ctrl |= JZ_LCD_CTRL_BPP_15_16;
490                         break;
491                 case DRM_FORMAT_RGB888:
492                         ctrl |= JZ_LCD_CTRL_BPP_24_COMP;
493                         break;
494                 case DRM_FORMAT_XRGB8888:
495                         ctrl |= JZ_LCD_CTRL_BPP_18_24;
496                         break;
497                 case DRM_FORMAT_XRGB2101010:
498                         ctrl |= JZ_LCD_CTRL_BPP_30;
499                         break;
500                 }
501
502                 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL,
503                                    JZ_LCD_CTRL_BPP_MASK, ctrl);
504         }
505
506         if (priv->soc_info->has_osd) {
507                 if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
508                         xy_reg = JZ_REG_LCD_XYP1;
509                         size_reg = JZ_REG_LCD_SIZE1;
510                 } else {
511                         xy_reg = JZ_REG_LCD_XYP0;
512                         size_reg = JZ_REG_LCD_SIZE0;
513                 }
514
515                 regmap_write(priv->map, xy_reg,
516                              state->crtc_x << JZ_LCD_XYP01_XPOS_LSB |
517                              state->crtc_y << JZ_LCD_XYP01_YPOS_LSB);
518                 regmap_write(priv->map, size_reg,
519                              state->crtc_w << JZ_LCD_SIZE01_WIDTH_LSB |
520                              state->crtc_h << JZ_LCD_SIZE01_HEIGHT_LSB);
521         }
522 }
523
524 static void ingenic_drm_update_palette(struct ingenic_drm *priv,
525                                        const struct drm_color_lut *lut)
526 {
527         unsigned int i;
528
529         for (i = 0; i < ARRAY_SIZE(priv->dma_hwdescs->palette); i++) {
530                 u16 color = drm_color_lut_extract(lut[i].red, 5) << 11
531                         | drm_color_lut_extract(lut[i].green, 6) << 5
532                         | drm_color_lut_extract(lut[i].blue, 5);
533
534                 priv->dma_hwdescs->palette[i] = color;
535         }
536 }
537
538 static void ingenic_drm_plane_atomic_update(struct drm_plane *plane,
539                                             struct drm_plane_state *oldstate)
540 {
541         struct ingenic_drm *priv = drm_device_get_priv(plane->dev);
542         struct drm_plane_state *state = plane->state;
543         struct drm_crtc_state *crtc_state;
544         struct ingenic_dma_hwdesc *hwdesc;
545         unsigned int width, height, cpp, offset;
546         dma_addr_t addr;
547         u32 fourcc;
548
549         if (state && state->fb) {
550                 crtc_state = state->crtc->state;
551
552                 addr = drm_fb_cma_get_gem_addr(state->fb, state, 0);
553                 width = state->src_w >> 16;
554                 height = state->src_h >> 16;
555                 cpp = state->fb->format->cpp[0];
556
557                 if (priv->soc_info->has_osd && plane->type == DRM_PLANE_TYPE_OVERLAY)
558                         hwdesc = &priv->dma_hwdescs->hwdesc_f0;
559                 else
560                         hwdesc = &priv->dma_hwdescs->hwdesc_f1;
561
562                 hwdesc->addr = addr;
563                 hwdesc->cmd = JZ_LCD_CMD_EOF_IRQ | (width * height * cpp / 4);
564
565                 if (drm_atomic_crtc_needs_modeset(crtc_state)) {
566                         fourcc = state->fb->format->format;
567
568                         ingenic_drm_plane_config(priv->dev, plane, fourcc);
569
570                         if (fourcc == DRM_FORMAT_C8)
571                                 offset = offsetof(struct ingenic_dma_hwdescs, hwdesc_pal);
572                         else
573                                 offset = offsetof(struct ingenic_dma_hwdescs, hwdesc_f0);
574
575                         priv->dma_hwdescs->hwdesc_f0.next = priv->dma_hwdescs_phys + offset;
576
577                         crtc_state->color_mgmt_changed = fourcc == DRM_FORMAT_C8;
578                 }
579
580                 if (crtc_state->color_mgmt_changed)
581                         ingenic_drm_update_palette(priv, crtc_state->gamma_lut->data);
582         }
583 }
584
585 static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
586                                                 struct drm_crtc_state *crtc_state,
587                                                 struct drm_connector_state *conn_state)
588 {
589         struct ingenic_drm *priv = drm_device_get_priv(encoder->dev);
590         struct drm_display_mode *mode = &crtc_state->adjusted_mode;
591         struct drm_connector *conn = conn_state->connector;
592         struct drm_display_info *info = &conn->display_info;
593         unsigned int cfg, rgbcfg = 0;
594
595         priv->panel_is_sharp = info->bus_flags & DRM_BUS_FLAG_SHARP_SIGNALS;
596
597         if (priv->panel_is_sharp) {
598                 cfg = JZ_LCD_CFG_MODE_SPECIAL_TFT_1 | JZ_LCD_CFG_REV_POLARITY;
599         } else {
600                 cfg = JZ_LCD_CFG_PS_DISABLE | JZ_LCD_CFG_CLS_DISABLE
601                     | JZ_LCD_CFG_SPL_DISABLE | JZ_LCD_CFG_REV_DISABLE;
602         }
603
604         if (mode->flags & DRM_MODE_FLAG_NHSYNC)
605                 cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
606         if (mode->flags & DRM_MODE_FLAG_NVSYNC)
607                 cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
608         if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
609                 cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
610         if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
611                 cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
612
613         if (!priv->panel_is_sharp) {
614                 if (conn->connector_type == DRM_MODE_CONNECTOR_TV) {
615                         if (mode->flags & DRM_MODE_FLAG_INTERLACE)
616                                 cfg |= JZ_LCD_CFG_MODE_TV_OUT_I;
617                         else
618                                 cfg |= JZ_LCD_CFG_MODE_TV_OUT_P;
619                 } else {
620                         switch (*info->bus_formats) {
621                         case MEDIA_BUS_FMT_RGB565_1X16:
622                                 cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT;
623                                 break;
624                         case MEDIA_BUS_FMT_RGB666_1X18:
625                                 cfg |= JZ_LCD_CFG_MODE_GENERIC_18BIT;
626                                 break;
627                         case MEDIA_BUS_FMT_RGB888_1X24:
628                                 cfg |= JZ_LCD_CFG_MODE_GENERIC_24BIT;
629                                 break;
630                         case MEDIA_BUS_FMT_RGB888_3X8_DELTA:
631                                 rgbcfg = JZ_LCD_RGBC_EVEN_GBR | JZ_LCD_RGBC_ODD_RGB;
632                                 fallthrough;
633                         case MEDIA_BUS_FMT_RGB888_3X8:
634                                 cfg |= JZ_LCD_CFG_MODE_8BIT_SERIAL;
635                                 break;
636                         default:
637                                 break;
638                         }
639                 }
640         }
641
642         regmap_write(priv->map, JZ_REG_LCD_CFG, cfg);
643         regmap_write(priv->map, JZ_REG_LCD_RGBC, rgbcfg);
644 }
645
646 static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder,
647                                             struct drm_crtc_state *crtc_state,
648                                             struct drm_connector_state *conn_state)
649 {
650         struct drm_display_info *info = &conn_state->connector->display_info;
651         struct drm_display_mode *mode = &crtc_state->adjusted_mode;
652
653         if (info->num_bus_formats != 1)
654                 return -EINVAL;
655
656         if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV)
657                 return 0;
658
659         switch (*info->bus_formats) {
660         case MEDIA_BUS_FMT_RGB888_3X8:
661         case MEDIA_BUS_FMT_RGB888_3X8_DELTA:
662                 /*
663                  * The LCD controller expects timing values in dot-clock ticks,
664                  * which is 3x the timing values in pixels when using a 3x8-bit
665                  * display; but it will count the display area size in pixels
666                  * either way. Go figure.
667                  */
668                 mode->crtc_clock = mode->clock * 3;
669                 mode->crtc_hsync_start = mode->hsync_start * 3 - mode->hdisplay * 2;
670                 mode->crtc_hsync_end = mode->hsync_end * 3 - mode->hdisplay * 2;
671                 mode->crtc_hdisplay = mode->hdisplay;
672                 mode->crtc_htotal = mode->htotal * 3 - mode->hdisplay * 2;
673                 return 0;
674         case MEDIA_BUS_FMT_RGB565_1X16:
675         case MEDIA_BUS_FMT_RGB666_1X18:
676         case MEDIA_BUS_FMT_RGB888_1X24:
677                 return 0;
678         default:
679                 return -EINVAL;
680         }
681 }
682
683 static void ingenic_drm_atomic_helper_commit_tail(struct drm_atomic_state *old_state)
684 {
685         /*
686          * Just your regular drm_atomic_helper_commit_tail(), but only calls
687          * drm_atomic_helper_wait_for_vblanks() if priv->no_vblank.
688          */
689         struct drm_device *dev = old_state->dev;
690         struct ingenic_drm *priv = drm_device_get_priv(dev);
691
692         drm_atomic_helper_commit_modeset_disables(dev, old_state);
693
694         drm_atomic_helper_commit_planes(dev, old_state, 0);
695
696         drm_atomic_helper_commit_modeset_enables(dev, old_state);
697
698         drm_atomic_helper_commit_hw_done(old_state);
699
700         if (!priv->no_vblank)
701                 drm_atomic_helper_wait_for_vblanks(dev, old_state);
702
703         drm_atomic_helper_cleanup_planes(dev, old_state);
704 }
705
706 static irqreturn_t ingenic_drm_irq_handler(int irq, void *arg)
707 {
708         struct ingenic_drm *priv = drm_device_get_priv(arg);
709         unsigned int state;
710
711         regmap_read(priv->map, JZ_REG_LCD_STATE, &state);
712
713         regmap_update_bits(priv->map, JZ_REG_LCD_STATE,
714                            JZ_LCD_STATE_EOF_IRQ, 0);
715
716         if (state & JZ_LCD_STATE_EOF_IRQ)
717                 drm_crtc_handle_vblank(&priv->crtc);
718
719         return IRQ_HANDLED;
720 }
721
722 static int ingenic_drm_enable_vblank(struct drm_crtc *crtc)
723 {
724         struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
725
726         regmap_update_bits(priv->map, JZ_REG_LCD_CTRL,
727                            JZ_LCD_CTRL_EOF_IRQ, JZ_LCD_CTRL_EOF_IRQ);
728
729         return 0;
730 }
731
732 static void ingenic_drm_disable_vblank(struct drm_crtc *crtc)
733 {
734         struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
735
736         regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, JZ_LCD_CTRL_EOF_IRQ, 0);
737 }
738
739 DEFINE_DRM_GEM_CMA_FOPS(ingenic_drm_fops);
740
741 static const struct drm_driver ingenic_drm_driver_data = {
742         .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
743         .name                   = "ingenic-drm",
744         .desc                   = "DRM module for Ingenic SoCs",
745         .date                   = "20200716",
746         .major                  = 1,
747         .minor                  = 1,
748         .patchlevel             = 0,
749
750         .fops                   = &ingenic_drm_fops,
751         DRM_GEM_CMA_DRIVER_OPS,
752
753         .irq_handler            = ingenic_drm_irq_handler,
754 };
755
756 static const struct drm_plane_funcs ingenic_drm_primary_plane_funcs = {
757         .update_plane           = drm_atomic_helper_update_plane,
758         .disable_plane          = drm_atomic_helper_disable_plane,
759         .reset                  = drm_atomic_helper_plane_reset,
760         .destroy                = drm_plane_cleanup,
761
762         .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
763         .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
764 };
765
766 static const struct drm_crtc_funcs ingenic_drm_crtc_funcs = {
767         .set_config             = drm_atomic_helper_set_config,
768         .page_flip              = drm_atomic_helper_page_flip,
769         .reset                  = drm_atomic_helper_crtc_reset,
770         .destroy                = drm_crtc_cleanup,
771
772         .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
773         .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
774
775         .enable_vblank          = ingenic_drm_enable_vblank,
776         .disable_vblank         = ingenic_drm_disable_vblank,
777 };
778
779 static const struct drm_plane_helper_funcs ingenic_drm_plane_helper_funcs = {
780         .atomic_update          = ingenic_drm_plane_atomic_update,
781         .atomic_check           = ingenic_drm_plane_atomic_check,
782         .atomic_disable         = ingenic_drm_plane_atomic_disable,
783         .prepare_fb             = drm_gem_fb_prepare_fb,
784 };
785
786 static const struct drm_crtc_helper_funcs ingenic_drm_crtc_helper_funcs = {
787         .atomic_enable          = ingenic_drm_crtc_atomic_enable,
788         .atomic_disable         = ingenic_drm_crtc_atomic_disable,
789         .atomic_begin           = ingenic_drm_crtc_atomic_begin,
790         .atomic_flush           = ingenic_drm_crtc_atomic_flush,
791         .atomic_check           = ingenic_drm_crtc_atomic_check,
792         .mode_valid             = ingenic_drm_crtc_mode_valid,
793 };
794
795 static const struct drm_encoder_helper_funcs ingenic_drm_encoder_helper_funcs = {
796         .atomic_mode_set        = ingenic_drm_encoder_atomic_mode_set,
797         .atomic_check           = ingenic_drm_encoder_atomic_check,
798 };
799
800 static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = {
801         .fb_create              = drm_gem_fb_create,
802         .output_poll_changed    = drm_fb_helper_output_poll_changed,
803         .atomic_check           = drm_atomic_helper_check,
804         .atomic_commit          = drm_atomic_helper_commit,
805 };
806
807 static struct drm_mode_config_helper_funcs ingenic_drm_mode_config_helpers = {
808         .atomic_commit_tail = ingenic_drm_atomic_helper_commit_tail,
809 };
810
811 static void ingenic_drm_unbind_all(void *d)
812 {
813         struct ingenic_drm *priv = d;
814
815         component_unbind_all(priv->dev, &priv->drm);
816 }
817
818 static void __maybe_unused ingenic_drm_release_rmem(void *d)
819 {
820         of_reserved_mem_device_release(d);
821 }
822
823 static int ingenic_drm_bind(struct device *dev, bool has_components)
824 {
825         struct platform_device *pdev = to_platform_device(dev);
826         const struct jz_soc_info *soc_info;
827         struct ingenic_drm *priv;
828         struct clk *parent_clk;
829         struct drm_bridge *bridge;
830         struct drm_panel *panel;
831         struct drm_encoder *encoder;
832         struct drm_device *drm;
833         void __iomem *base;
834         long parent_rate;
835         unsigned int i, clone_mask = 0;
836         dma_addr_t dma_hwdesc_phys_f0, dma_hwdesc_phys_f1;
837         int ret, irq;
838
839         soc_info = of_device_get_match_data(dev);
840         if (!soc_info) {
841                 dev_err(dev, "Missing platform data\n");
842                 return -EINVAL;
843         }
844
845         if (IS_ENABLED(CONFIG_OF_RESERVED_MEM)) {
846                 ret = of_reserved_mem_device_init(dev);
847
848                 if (ret && ret != -ENODEV)
849                         dev_warn(dev, "Failed to get reserved memory: %d\n", ret);
850
851                 if (!ret) {
852                         ret = devm_add_action_or_reset(dev, ingenic_drm_release_rmem, dev);
853                         if (ret)
854                                 return ret;
855                 }
856         }
857
858         priv = devm_drm_dev_alloc(dev, &ingenic_drm_driver_data,
859                                   struct ingenic_drm, drm);
860         if (IS_ERR(priv))
861                 return PTR_ERR(priv);
862
863         priv->soc_info = soc_info;
864         priv->dev = dev;
865         drm = &priv->drm;
866
867         platform_set_drvdata(pdev, priv);
868
869         ret = drmm_mode_config_init(drm);
870         if (ret)
871                 return ret;
872
873         drm->mode_config.min_width = 0;
874         drm->mode_config.min_height = 0;
875         drm->mode_config.max_width = soc_info->max_width;
876         drm->mode_config.max_height = 4095;
877         drm->mode_config.funcs = &ingenic_drm_mode_config_funcs;
878         drm->mode_config.helper_private = &ingenic_drm_mode_config_helpers;
879
880         base = devm_platform_ioremap_resource(pdev, 0);
881         if (IS_ERR(base)) {
882                 dev_err(dev, "Failed to get memory resource\n");
883                 return PTR_ERR(base);
884         }
885
886         priv->map = devm_regmap_init_mmio(dev, base,
887                                           &ingenic_drm_regmap_config);
888         if (IS_ERR(priv->map)) {
889                 dev_err(dev, "Failed to create regmap\n");
890                 return PTR_ERR(priv->map);
891         }
892
893         irq = platform_get_irq(pdev, 0);
894         if (irq < 0)
895                 return irq;
896
897         if (soc_info->needs_dev_clk) {
898                 priv->lcd_clk = devm_clk_get(dev, "lcd");
899                 if (IS_ERR(priv->lcd_clk)) {
900                         dev_err(dev, "Failed to get lcd clock\n");
901                         return PTR_ERR(priv->lcd_clk);
902                 }
903         }
904
905         priv->pix_clk = devm_clk_get(dev, "lcd_pclk");
906         if (IS_ERR(priv->pix_clk)) {
907                 dev_err(dev, "Failed to get pixel clock\n");
908                 return PTR_ERR(priv->pix_clk);
909         }
910
911         priv->dma_hwdescs = dmam_alloc_coherent(dev,
912                                                 sizeof(*priv->dma_hwdescs),
913                                                 &priv->dma_hwdescs_phys,
914                                                 GFP_KERNEL);
915         if (!priv->dma_hwdescs)
916                 return -ENOMEM;
917
918
919         /* Configure DMA hwdesc for foreground0 plane */
920         dma_hwdesc_phys_f0 = priv->dma_hwdescs_phys
921                 + offsetof(struct ingenic_dma_hwdescs, hwdesc_f0);
922         priv->dma_hwdescs->hwdesc_f0.next = dma_hwdesc_phys_f0;
923         priv->dma_hwdescs->hwdesc_f0.id = 0xf0;
924
925         /* Configure DMA hwdesc for foreground1 plane */
926         dma_hwdesc_phys_f1 = priv->dma_hwdescs_phys
927                 + offsetof(struct ingenic_dma_hwdescs, hwdesc_f1);
928         priv->dma_hwdescs->hwdesc_f1.next = dma_hwdesc_phys_f1;
929         priv->dma_hwdescs->hwdesc_f1.id = 0xf1;
930
931         /* Configure DMA hwdesc for palette */
932         priv->dma_hwdescs->hwdesc_pal.next = priv->dma_hwdescs_phys
933                 + offsetof(struct ingenic_dma_hwdescs, hwdesc_f0);
934         priv->dma_hwdescs->hwdesc_pal.id = 0xc0;
935         priv->dma_hwdescs->hwdesc_pal.addr = priv->dma_hwdescs_phys
936                 + offsetof(struct ingenic_dma_hwdescs, palette);
937         priv->dma_hwdescs->hwdesc_pal.cmd = JZ_LCD_CMD_ENABLE_PAL
938                 | (sizeof(priv->dma_hwdescs->palette) / 4);
939
940         if (soc_info->has_osd)
941                 priv->ipu_plane = drm_plane_from_index(drm, 0);
942
943         drm_plane_helper_add(&priv->f1, &ingenic_drm_plane_helper_funcs);
944
945         ret = drm_universal_plane_init(drm, &priv->f1, 1,
946                                        &ingenic_drm_primary_plane_funcs,
947                                        priv->soc_info->formats_f1,
948                                        priv->soc_info->num_formats_f1,
949                                        NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
950         if (ret) {
951                 dev_err(dev, "Failed to register plane: %i\n", ret);
952                 return ret;
953         }
954
955         drm_crtc_helper_add(&priv->crtc, &ingenic_drm_crtc_helper_funcs);
956
957         ret = drm_crtc_init_with_planes(drm, &priv->crtc, &priv->f1,
958                                         NULL, &ingenic_drm_crtc_funcs, NULL);
959         if (ret) {
960                 dev_err(dev, "Failed to init CRTC: %i\n", ret);
961                 return ret;
962         }
963
964         drm_crtc_enable_color_mgmt(&priv->crtc, 0, false,
965                                    ARRAY_SIZE(priv->dma_hwdescs->palette));
966
967         if (soc_info->has_osd) {
968                 drm_plane_helper_add(&priv->f0,
969                                      &ingenic_drm_plane_helper_funcs);
970
971                 ret = drm_universal_plane_init(drm, &priv->f0, 1,
972                                                &ingenic_drm_primary_plane_funcs,
973                                                priv->soc_info->formats_f0,
974                                                priv->soc_info->num_formats_f0,
975                                                NULL, DRM_PLANE_TYPE_OVERLAY,
976                                                NULL);
977                 if (ret) {
978                         dev_err(dev, "Failed to register overlay plane: %i\n",
979                                 ret);
980                         return ret;
981                 }
982
983                 if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU) && has_components) {
984                         ret = component_bind_all(dev, drm);
985                         if (ret) {
986                                 if (ret != -EPROBE_DEFER)
987                                         dev_err(dev, "Failed to bind components: %i\n", ret);
988                                 return ret;
989                         }
990
991                         ret = devm_add_action_or_reset(dev, ingenic_drm_unbind_all, priv);
992                         if (ret)
993                                 return ret;
994
995                         priv->ipu_plane = drm_plane_from_index(drm, 2);
996                         if (!priv->ipu_plane) {
997                                 dev_err(dev, "Failed to retrieve IPU plane\n");
998                                 return -EINVAL;
999                         }
1000                 }
1001         }
1002
1003         for (i = 0; ; i++) {
1004                 ret = drm_of_find_panel_or_bridge(dev->of_node, 0, i, &panel, &bridge);
1005                 if (ret) {
1006                         if (ret == -ENODEV)
1007                                 break; /* we're done */
1008                         if (ret != -EPROBE_DEFER)
1009                                 dev_err(dev, "Failed to get bridge handle\n");
1010                         return ret;
1011                 }
1012
1013                 if (panel)
1014                         bridge = devm_drm_panel_bridge_add_typed(dev, panel,
1015                                                                  DRM_MODE_CONNECTOR_DPI);
1016
1017                 encoder = devm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL);
1018                 if (!encoder)
1019                         return -ENOMEM;
1020
1021                 encoder->possible_crtcs = 1;
1022
1023                 drm_encoder_helper_add(encoder, &ingenic_drm_encoder_helper_funcs);
1024
1025                 ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_DPI);
1026                 if (ret) {
1027                         dev_err(dev, "Failed to init encoder: %d\n", ret);
1028                         return ret;
1029                 }
1030
1031                 ret = drm_bridge_attach(encoder, bridge, NULL, 0);
1032                 if (ret) {
1033                         dev_err(dev, "Unable to attach bridge\n");
1034                         return ret;
1035                 }
1036         }
1037
1038         drm_for_each_encoder(encoder, drm) {
1039                 clone_mask |= BIT(drm_encoder_index(encoder));
1040         }
1041
1042         drm_for_each_encoder(encoder, drm) {
1043                 encoder->possible_clones = clone_mask;
1044         }
1045
1046         ret = drm_irq_install(drm, irq);
1047         if (ret) {
1048                 dev_err(dev, "Unable to install IRQ handler\n");
1049                 return ret;
1050         }
1051
1052         ret = drm_vblank_init(drm, 1);
1053         if (ret) {
1054                 dev_err(dev, "Failed calling drm_vblank_init()\n");
1055                 return ret;
1056         }
1057
1058         drm_mode_config_reset(drm);
1059
1060         ret = clk_prepare_enable(priv->pix_clk);
1061         if (ret) {
1062                 dev_err(dev, "Unable to start pixel clock\n");
1063                 return ret;
1064         }
1065
1066         if (priv->lcd_clk) {
1067                 parent_clk = clk_get_parent(priv->lcd_clk);
1068                 parent_rate = clk_get_rate(parent_clk);
1069
1070                 /* LCD Device clock must be 3x the pixel clock for STN panels,
1071                  * or 1.5x the pixel clock for TFT panels. To avoid having to
1072                  * check for the LCD device clock everytime we do a mode change,
1073                  * we set the LCD device clock to the highest rate possible.
1074                  */
1075                 ret = clk_set_rate(priv->lcd_clk, parent_rate);
1076                 if (ret) {
1077                         dev_err(dev, "Unable to set LCD clock rate\n");
1078                         goto err_pixclk_disable;
1079                 }
1080
1081                 ret = clk_prepare_enable(priv->lcd_clk);
1082                 if (ret) {
1083                         dev_err(dev, "Unable to start lcd clock\n");
1084                         goto err_pixclk_disable;
1085                 }
1086         }
1087
1088         /* Set address of our DMA descriptor chain */
1089         regmap_write(priv->map, JZ_REG_LCD_DA0, dma_hwdesc_phys_f0);
1090         regmap_write(priv->map, JZ_REG_LCD_DA1, dma_hwdesc_phys_f1);
1091
1092         /* Enable OSD if available */
1093         if (soc_info->has_osd)
1094                 regmap_write(priv->map, JZ_REG_LCD_OSDC, JZ_LCD_OSDC_OSDEN);
1095
1096         mutex_init(&priv->clk_mutex);
1097         priv->clock_nb.notifier_call = ingenic_drm_update_pixclk;
1098
1099         parent_clk = clk_get_parent(priv->pix_clk);
1100         ret = clk_notifier_register(parent_clk, &priv->clock_nb);
1101         if (ret) {
1102                 dev_err(dev, "Unable to register clock notifier\n");
1103                 goto err_devclk_disable;
1104         }
1105
1106         ret = drm_dev_register(drm, 0);
1107         if (ret) {
1108                 dev_err(dev, "Failed to register DRM driver\n");
1109                 goto err_clk_notifier_unregister;
1110         }
1111
1112         drm_fbdev_generic_setup(drm, 32);
1113
1114         return 0;
1115
1116 err_clk_notifier_unregister:
1117         clk_notifier_unregister(parent_clk, &priv->clock_nb);
1118 err_devclk_disable:
1119         if (priv->lcd_clk)
1120                 clk_disable_unprepare(priv->lcd_clk);
1121 err_pixclk_disable:
1122         clk_disable_unprepare(priv->pix_clk);
1123         return ret;
1124 }
1125
1126 static int ingenic_drm_bind_with_components(struct device *dev)
1127 {
1128         return ingenic_drm_bind(dev, true);
1129 }
1130
1131 static int compare_of(struct device *dev, void *data)
1132 {
1133         return dev->of_node == data;
1134 }
1135
1136 static void ingenic_drm_unbind(struct device *dev)
1137 {
1138         struct ingenic_drm *priv = dev_get_drvdata(dev);
1139         struct clk *parent_clk = clk_get_parent(priv->pix_clk);
1140
1141         clk_notifier_unregister(parent_clk, &priv->clock_nb);
1142         if (priv->lcd_clk)
1143                 clk_disable_unprepare(priv->lcd_clk);
1144         clk_disable_unprepare(priv->pix_clk);
1145
1146         drm_dev_unregister(&priv->drm);
1147         drm_atomic_helper_shutdown(&priv->drm);
1148 }
1149
1150 static const struct component_master_ops ingenic_master_ops = {
1151         .bind = ingenic_drm_bind_with_components,
1152         .unbind = ingenic_drm_unbind,
1153 };
1154
1155 static int ingenic_drm_probe(struct platform_device *pdev)
1156 {
1157         struct device *dev = &pdev->dev;
1158         struct component_match *match = NULL;
1159         struct device_node *np;
1160
1161         if (!IS_ENABLED(CONFIG_DRM_INGENIC_IPU))
1162                 return ingenic_drm_bind(dev, false);
1163
1164         /* IPU is at port address 8 */
1165         np = of_graph_get_remote_node(dev->of_node, 8, 0);
1166         if (!np)
1167                 return ingenic_drm_bind(dev, false);
1168
1169         drm_of_component_match_add(dev, &match, compare_of, np);
1170         of_node_put(np);
1171
1172         return component_master_add_with_match(dev, &ingenic_master_ops, match);
1173 }
1174
1175 static int ingenic_drm_remove(struct platform_device *pdev)
1176 {
1177         struct device *dev = &pdev->dev;
1178
1179         if (!IS_ENABLED(CONFIG_DRM_INGENIC_IPU))
1180                 ingenic_drm_unbind(dev);
1181         else
1182                 component_master_del(dev, &ingenic_master_ops);
1183
1184         return 0;
1185 }
1186
1187 static int __maybe_unused ingenic_drm_suspend(struct device *dev)
1188 {
1189         struct ingenic_drm *priv = dev_get_drvdata(dev);
1190
1191         return drm_mode_config_helper_suspend(&priv->drm);
1192 }
1193
1194 static int __maybe_unused ingenic_drm_resume(struct device *dev)
1195 {
1196         struct ingenic_drm *priv = dev_get_drvdata(dev);
1197
1198         return drm_mode_config_helper_resume(&priv->drm);
1199 }
1200
1201 static SIMPLE_DEV_PM_OPS(ingenic_drm_pm_ops, ingenic_drm_suspend, ingenic_drm_resume);
1202
1203 static const u32 jz4740_formats[] = {
1204         DRM_FORMAT_XRGB1555,
1205         DRM_FORMAT_RGB565,
1206         DRM_FORMAT_XRGB8888,
1207 };
1208
1209 static const u32 jz4725b_formats_f1[] = {
1210         DRM_FORMAT_XRGB1555,
1211         DRM_FORMAT_RGB565,
1212         DRM_FORMAT_XRGB8888,
1213 };
1214
1215 static const u32 jz4725b_formats_f0[] = {
1216         DRM_FORMAT_C8,
1217         DRM_FORMAT_XRGB1555,
1218         DRM_FORMAT_RGB565,
1219         DRM_FORMAT_XRGB8888,
1220 };
1221
1222 static const u32 jz4770_formats_f1[] = {
1223         DRM_FORMAT_XRGB1555,
1224         DRM_FORMAT_RGB565,
1225         DRM_FORMAT_RGB888,
1226         DRM_FORMAT_XRGB8888,
1227         DRM_FORMAT_XRGB2101010,
1228 };
1229
1230 static const u32 jz4770_formats_f0[] = {
1231         DRM_FORMAT_C8,
1232         DRM_FORMAT_XRGB1555,
1233         DRM_FORMAT_RGB565,
1234         DRM_FORMAT_RGB888,
1235         DRM_FORMAT_XRGB8888,
1236         DRM_FORMAT_XRGB2101010,
1237 };
1238
1239 static const struct jz_soc_info jz4740_soc_info = {
1240         .needs_dev_clk = true,
1241         .has_osd = false,
1242         .max_width = 800,
1243         .max_height = 600,
1244         .formats_f1 = jz4740_formats,
1245         .num_formats_f1 = ARRAY_SIZE(jz4740_formats),
1246         /* JZ4740 has only one plane */
1247 };
1248
1249 static const struct jz_soc_info jz4725b_soc_info = {
1250         .needs_dev_clk = false,
1251         .has_osd = true,
1252         .max_width = 800,
1253         .max_height = 600,
1254         .formats_f1 = jz4725b_formats_f1,
1255         .num_formats_f1 = ARRAY_SIZE(jz4725b_formats_f1),
1256         .formats_f0 = jz4725b_formats_f0,
1257         .num_formats_f0 = ARRAY_SIZE(jz4725b_formats_f0),
1258 };
1259
1260 static const struct jz_soc_info jz4770_soc_info = {
1261         .needs_dev_clk = false,
1262         .has_osd = true,
1263         .max_width = 1280,
1264         .max_height = 720,
1265         .formats_f1 = jz4770_formats_f1,
1266         .num_formats_f1 = ARRAY_SIZE(jz4770_formats_f1),
1267         .formats_f0 = jz4770_formats_f0,
1268         .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0),
1269 };
1270
1271 static const struct of_device_id ingenic_drm_of_match[] = {
1272         { .compatible = "ingenic,jz4740-lcd", .data = &jz4740_soc_info },
1273         { .compatible = "ingenic,jz4725b-lcd", .data = &jz4725b_soc_info },
1274         { .compatible = "ingenic,jz4770-lcd", .data = &jz4770_soc_info },
1275         { /* sentinel */ },
1276 };
1277 MODULE_DEVICE_TABLE(of, ingenic_drm_of_match);
1278
1279 static struct platform_driver ingenic_drm_driver = {
1280         .driver = {
1281                 .name = "ingenic-drm",
1282                 .pm = pm_ptr(&ingenic_drm_pm_ops),
1283                 .of_match_table = of_match_ptr(ingenic_drm_of_match),
1284         },
1285         .probe = ingenic_drm_probe,
1286         .remove = ingenic_drm_remove,
1287 };
1288
1289 static int ingenic_drm_init(void)
1290 {
1291         int err;
1292
1293         if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU)) {
1294                 err = platform_driver_register(ingenic_ipu_driver_ptr);
1295                 if (err)
1296                         return err;
1297         }
1298
1299         return platform_driver_register(&ingenic_drm_driver);
1300 }
1301 module_init(ingenic_drm_init);
1302
1303 static void ingenic_drm_exit(void)
1304 {
1305         platform_driver_unregister(&ingenic_drm_driver);
1306
1307         if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU))
1308                 platform_driver_unregister(ingenic_ipu_driver_ptr);
1309 }
1310 module_exit(ingenic_drm_exit);
1311
1312 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
1313 MODULE_DESCRIPTION("DRM driver for the Ingenic SoCs\n");
1314 MODULE_LICENSE("GPL v2");