2 * Copyright 2015 Freescale Semiconductor, Inc.
4 * Freescale DCU drm device driver
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
12 #include <linux/regmap.h>
15 #include <drm/drm_atomic_helper.h>
16 #include <drm/drm_crtc.h>
17 #include <drm/drm_crtc_helper.h>
18 #include <drm/drm_fb_cma_helper.h>
19 #include <drm/drm_gem_cma_helper.h>
20 #include <drm/drm_plane_helper.h>
22 #include "fsl_dcu_drm_drv.h"
23 #include "fsl_dcu_drm_plane.h"
25 static int fsl_dcu_drm_plane_index(struct drm_plane
*plane
)
27 struct fsl_dcu_drm_device
*fsl_dev
= plane
->dev
->dev_private
;
28 unsigned int total_layer
= fsl_dev
->soc
->total_layer
;
31 index
= drm_plane_index(plane
);
32 if (index
< total_layer
)
33 return total_layer
- index
- 1;
35 dev_err(fsl_dev
->dev
, "No more layer left\n");
39 static int fsl_dcu_drm_plane_atomic_check(struct drm_plane
*plane
,
40 struct drm_plane_state
*state
)
42 struct drm_framebuffer
*fb
= state
->fb
;
44 if (!state
->fb
|| !state
->crtc
)
47 switch (fb
->pixel_format
) {
48 case DRM_FORMAT_RGB565
:
49 case DRM_FORMAT_RGB888
:
50 case DRM_FORMAT_XRGB8888
:
51 case DRM_FORMAT_ARGB8888
:
52 case DRM_FORMAT_XRGB4444
:
53 case DRM_FORMAT_ARGB4444
:
54 case DRM_FORMAT_XRGB1555
:
55 case DRM_FORMAT_ARGB1555
:
56 case DRM_FORMAT_YUV422
:
63 static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane
*plane
,
64 struct drm_plane_state
*old_state
)
66 struct fsl_dcu_drm_device
*fsl_dev
= plane
->dev
->dev_private
;
70 index
= fsl_dcu_drm_plane_index(plane
);
74 regmap_read(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 4), &value
);
75 value
&= ~DCU_LAYER_EN
;
76 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 4), value
);
79 static void fsl_dcu_drm_plane_atomic_update(struct drm_plane
*plane
,
80 struct drm_plane_state
*old_state
)
83 struct fsl_dcu_drm_device
*fsl_dev
= plane
->dev
->dev_private
;
84 struct drm_plane_state
*state
= plane
->state
;
85 struct drm_framebuffer
*fb
= plane
->state
->fb
;
86 struct drm_gem_cma_object
*gem
;
87 unsigned int alpha
= DCU_LAYER_AB_NONE
, bpp
;
93 index
= fsl_dcu_drm_plane_index(plane
);
97 gem
= drm_fb_cma_get_gem_obj(fb
, 0);
99 switch (fb
->pixel_format
) {
100 case DRM_FORMAT_RGB565
:
101 bpp
= FSL_DCU_RGB565
;
103 case DRM_FORMAT_RGB888
:
104 bpp
= FSL_DCU_RGB888
;
106 case DRM_FORMAT_ARGB8888
:
107 alpha
= DCU_LAYER_AB_WHOLE_FRAME
;
109 case DRM_FORMAT_XRGB8888
:
110 bpp
= FSL_DCU_ARGB8888
;
112 case DRM_FORMAT_ARGB4444
:
113 alpha
= DCU_LAYER_AB_WHOLE_FRAME
;
115 case DRM_FORMAT_XRGB4444
:
116 bpp
= FSL_DCU_ARGB4444
;
118 case DRM_FORMAT_ARGB1555
:
119 alpha
= DCU_LAYER_AB_WHOLE_FRAME
;
121 case DRM_FORMAT_XRGB1555
:
122 bpp
= FSL_DCU_ARGB1555
;
124 case DRM_FORMAT_YUV422
:
125 bpp
= FSL_DCU_YUV422
;
131 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 1),
132 DCU_LAYER_HEIGHT(state
->crtc_h
) |
133 DCU_LAYER_WIDTH(state
->crtc_w
));
134 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 2),
135 DCU_LAYER_POSY(state
->crtc_y
) |
136 DCU_LAYER_POSX(state
->crtc_x
));
137 regmap_write(fsl_dev
->regmap
,
138 DCU_CTRLDESCLN(index
, 3), gem
->paddr
);
139 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 4),
141 DCU_LAYER_TRANS(0xff) |
144 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 5),
145 DCU_LAYER_CKMAX_R(0xFF) |
146 DCU_LAYER_CKMAX_G(0xFF) |
147 DCU_LAYER_CKMAX_B(0xFF));
148 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 6),
149 DCU_LAYER_CKMIN_R(0) |
150 DCU_LAYER_CKMIN_G(0) |
151 DCU_LAYER_CKMIN_B(0));
152 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 7), 0);
153 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 8),
154 DCU_LAYER_FG_FCOLOR(0));
155 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 9),
156 DCU_LAYER_BG_BCOLOR(0));
158 if (!strcmp(fsl_dev
->soc
->name
, "ls1021a")) {
159 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(index
, 10),
160 DCU_LAYER_POST_SKIP(0) |
161 DCU_LAYER_PRE_SKIP(0));
163 regmap_update_bits(fsl_dev
->regmap
, DCU_DCU_MODE
,
164 DCU_MODE_DCU_MODE_MASK
,
165 DCU_MODE_DCU_MODE(DCU_MODE_NORMAL
));
166 regmap_write(fsl_dev
->regmap
,
167 DCU_UPDATE_MODE
, DCU_UPDATE_MODE_READREG
);
173 fsl_dcu_drm_plane_cleanup_fb(struct drm_plane
*plane
,
174 const struct drm_plane_state
*new_state
)
179 fsl_dcu_drm_plane_prepare_fb(struct drm_plane
*plane
,
180 const struct drm_plane_state
*new_state
)
185 static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs
= {
186 .atomic_check
= fsl_dcu_drm_plane_atomic_check
,
187 .atomic_disable
= fsl_dcu_drm_plane_atomic_disable
,
188 .atomic_update
= fsl_dcu_drm_plane_atomic_update
,
189 .cleanup_fb
= fsl_dcu_drm_plane_cleanup_fb
,
190 .prepare_fb
= fsl_dcu_drm_plane_prepare_fb
,
193 static void fsl_dcu_drm_plane_destroy(struct drm_plane
*plane
)
195 drm_plane_cleanup(plane
);
199 static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs
= {
200 .atomic_duplicate_state
= drm_atomic_helper_plane_duplicate_state
,
201 .atomic_destroy_state
= drm_atomic_helper_plane_destroy_state
,
202 .destroy
= fsl_dcu_drm_plane_destroy
,
203 .disable_plane
= drm_atomic_helper_disable_plane
,
204 .reset
= drm_atomic_helper_plane_reset
,
205 .update_plane
= drm_atomic_helper_update_plane
,
208 static const u32 fsl_dcu_drm_plane_formats
[] = {
220 struct drm_plane
*fsl_dcu_drm_primary_create_plane(struct drm_device
*dev
)
222 struct drm_plane
*primary
;
225 primary
= kzalloc(sizeof(*primary
), GFP_KERNEL
);
227 DRM_DEBUG_KMS("Failed to allocate primary plane\n");
231 /* possible_crtc's will be filled in later by crtc_init */
232 ret
= drm_universal_plane_init(dev
, primary
, 0,
233 &fsl_dcu_drm_plane_funcs
,
234 fsl_dcu_drm_plane_formats
,
235 ARRAY_SIZE(fsl_dcu_drm_plane_formats
),
236 DRM_PLANE_TYPE_PRIMARY
, NULL
);
241 drm_plane_helper_add(primary
, &fsl_dcu_drm_plane_helper_funcs
);