1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright 2015 Freescale Semiconductor, Inc.
5 * Freescale DCU drm device driver
8 #include <linux/regmap.h>
10 #include <drm/drm_atomic_helper.h>
11 #include <drm/drm_crtc.h>
12 #include <drm/drm_fb_cma_helper.h>
13 #include <drm/drm_fourcc.h>
14 #include <drm/drm_gem_cma_helper.h>
15 #include <drm/drm_plane_helper.h>
16 #include <drm/drm_probe_helper.h>
18 #include "fsl_dcu_drm_drv.h"
19 #include "fsl_dcu_drm_plane.h"
21 static int fsl_dcu_drm_plane_index(struct drm_plane
*plane
)
23 struct fsl_dcu_drm_device
*fsl_dev
= plane
->dev
->dev_private
;
24 unsigned int total_layer
= fsl_dev
->soc
->total_layer
;
27 index
= drm_plane_index(plane
);
28 if (index
< total_layer
)
29 return total_layer
- index
- 1;
31 dev_err(fsl_dev
->dev
, "No more layer left\n");
35 static int fsl_dcu_drm_plane_atomic_check(struct drm_plane
*plane
,
36 struct drm_plane_state
*state
)
38 struct drm_framebuffer
*fb
= state
->fb
;
40 if (!state
->fb
|| !state
->crtc
)
43 switch (fb
->format
->format
) {
44 case DRM_FORMAT_RGB565
:
45 case DRM_FORMAT_RGB888
:
46 case DRM_FORMAT_XRGB8888
:
47 case DRM_FORMAT_ARGB8888
:
48 case DRM_FORMAT_XRGB4444
:
49 case DRM_FORMAT_ARGB4444
:
50 case DRM_FORMAT_XRGB1555
:
51 case DRM_FORMAT_ARGB1555
:
52 case DRM_FORMAT_YUV422
:
59 static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane
*plane
,
60 struct drm_plane_state
*old_state
)
62 struct fsl_dcu_drm_device
*fsl_dev
= plane
->dev
->dev_private
;
66 index
= fsl_dcu_drm_plane_index(plane
);
70 regmap_read(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 4), &value
);
71 value
&= ~DCU_LAYER_EN
;
72 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 4), value
);
75 static void fsl_dcu_drm_plane_atomic_update(struct drm_plane
*plane
,
76 struct drm_plane_state
*old_state
)
79 struct fsl_dcu_drm_device
*fsl_dev
= plane
->dev
->dev_private
;
80 struct drm_plane_state
*state
= plane
->state
;
81 struct drm_framebuffer
*fb
= plane
->state
->fb
;
82 struct drm_gem_cma_object
*gem
;
83 unsigned int alpha
= DCU_LAYER_AB_NONE
, bpp
;
89 index
= fsl_dcu_drm_plane_index(plane
);
93 gem
= drm_fb_cma_get_gem_obj(fb
, 0);
95 switch (fb
->format
->format
) {
96 case DRM_FORMAT_RGB565
:
99 case DRM_FORMAT_RGB888
:
100 bpp
= FSL_DCU_RGB888
;
102 case DRM_FORMAT_ARGB8888
:
103 alpha
= DCU_LAYER_AB_WHOLE_FRAME
;
105 case DRM_FORMAT_XRGB8888
:
106 bpp
= FSL_DCU_ARGB8888
;
108 case DRM_FORMAT_ARGB4444
:
109 alpha
= DCU_LAYER_AB_WHOLE_FRAME
;
111 case DRM_FORMAT_XRGB4444
:
112 bpp
= FSL_DCU_ARGB4444
;
114 case DRM_FORMAT_ARGB1555
:
115 alpha
= DCU_LAYER_AB_WHOLE_FRAME
;
117 case DRM_FORMAT_XRGB1555
:
118 bpp
= FSL_DCU_ARGB1555
;
120 case DRM_FORMAT_YUV422
:
121 bpp
= FSL_DCU_YUV422
;
127 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 1),
128 DCU_LAYER_HEIGHT(state
->crtc_h
) |
129 DCU_LAYER_WIDTH(state
->crtc_w
));
130 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 2),
131 DCU_LAYER_POSY(state
->crtc_y
) |
132 DCU_LAYER_POSX(state
->crtc_x
));
133 regmap_write(fsl_dev
->regmap
,
134 DCU_CTRLDESCLN(index
, 3), gem
->paddr
);
135 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 4),
137 DCU_LAYER_TRANS(0xff) |
140 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 5),
141 DCU_LAYER_CKMAX_R(0xFF) |
142 DCU_LAYER_CKMAX_G(0xFF) |
143 DCU_LAYER_CKMAX_B(0xFF));
144 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 6),
145 DCU_LAYER_CKMIN_R(0) |
146 DCU_LAYER_CKMIN_G(0) |
147 DCU_LAYER_CKMIN_B(0));
148 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 7), 0);
149 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 8),
150 DCU_LAYER_FG_FCOLOR(0));
151 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 9),
152 DCU_LAYER_BG_BCOLOR(0));
154 if (!strcmp(fsl_dev
->soc
->name
, "ls1021a")) {
155 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 10),
156 DCU_LAYER_POST_SKIP(0) |
157 DCU_LAYER_PRE_SKIP(0));
163 static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs
= {
164 .atomic_check
= fsl_dcu_drm_plane_atomic_check
,
165 .atomic_disable
= fsl_dcu_drm_plane_atomic_disable
,
166 .atomic_update
= fsl_dcu_drm_plane_atomic_update
,
169 static void fsl_dcu_drm_plane_destroy(struct drm_plane
*plane
)
171 drm_plane_cleanup(plane
);
175 static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs
= {
176 .atomic_duplicate_state
= drm_atomic_helper_plane_duplicate_state
,
177 .atomic_destroy_state
= drm_atomic_helper_plane_destroy_state
,
178 .destroy
= fsl_dcu_drm_plane_destroy
,
179 .disable_plane
= drm_atomic_helper_disable_plane
,
180 .reset
= drm_atomic_helper_plane_reset
,
181 .update_plane
= drm_atomic_helper_update_plane
,
184 static const u32 fsl_dcu_drm_plane_formats
[] = {
196 void fsl_dcu_drm_init_planes(struct drm_device
*dev
)
198 struct fsl_dcu_drm_device
*fsl_dev
= dev
->dev_private
;
201 for (i
= 0; i
< fsl_dev
->soc
->total_layer
; i
++) {
202 for (j
= 1; j
<= fsl_dev
->soc
->layer_regs
; j
++)
203 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(i
, j
), 0);
207 struct drm_plane
*fsl_dcu_drm_primary_create_plane(struct drm_device
*dev
)
209 struct drm_plane
*primary
;
212 primary
= kzalloc(sizeof(*primary
), GFP_KERNEL
);
214 DRM_DEBUG_KMS("Failed to allocate primary plane\n");
218 /* possible_crtc's will be filled in later by crtc_init */
219 ret
= drm_universal_plane_init(dev
, primary
, 0,
220 &fsl_dcu_drm_plane_funcs
,
221 fsl_dcu_drm_plane_formats
,
222 ARRAY_SIZE(fsl_dcu_drm_plane_formats
),
223 NULL
, DRM_PLANE_TYPE_PRIMARY
, NULL
);
228 drm_plane_helper_add(primary
, &fsl_dcu_drm_plane_helper_funcs
);