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/clk.h>
13 #include <linux/regmap.h>
16 #include <drm/drm_atomic.h>
17 #include <drm/drm_atomic_helper.h>
18 #include <drm/drm_crtc.h>
19 #include <drm/drm_crtc_helper.h>
21 #include "fsl_dcu_drm_crtc.h"
22 #include "fsl_dcu_drm_drv.h"
23 #include "fsl_dcu_drm_plane.h"
25 static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc
*crtc
,
26 struct drm_crtc_state
*old_crtc_state
)
30 static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc
*crtc
,
31 struct drm_crtc_state
*state
)
36 static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc
*crtc
,
37 struct drm_crtc_state
*old_crtc_state
)
41 static void fsl_dcu_drm_disable_crtc(struct drm_crtc
*crtc
)
43 struct drm_device
*dev
= crtc
->dev
;
44 struct fsl_dcu_drm_device
*fsl_dev
= dev
->dev_private
;
46 regmap_update_bits(fsl_dev
->regmap
, DCU_DCU_MODE
,
47 DCU_MODE_DCU_MODE_MASK
,
48 DCU_MODE_DCU_MODE(DCU_MODE_OFF
));
49 regmap_write(fsl_dev
->regmap
, DCU_UPDATE_MODE
,
50 DCU_UPDATE_MODE_READREG
);
53 static void fsl_dcu_drm_crtc_enable(struct drm_crtc
*crtc
)
55 struct drm_device
*dev
= crtc
->dev
;
56 struct fsl_dcu_drm_device
*fsl_dev
= dev
->dev_private
;
58 regmap_update_bits(fsl_dev
->regmap
, DCU_DCU_MODE
,
59 DCU_MODE_DCU_MODE_MASK
,
60 DCU_MODE_DCU_MODE(DCU_MODE_NORMAL
));
61 regmap_write(fsl_dev
->regmap
, DCU_UPDATE_MODE
,
62 DCU_UPDATE_MODE_READREG
);
65 static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc
*crtc
)
67 struct drm_device
*dev
= crtc
->dev
;
68 struct fsl_dcu_drm_device
*fsl_dev
= dev
->dev_private
;
69 struct drm_display_mode
*mode
= &crtc
->state
->mode
;
70 unsigned int hbp
, hfp
, hsw
, vbp
, vfp
, vsw
, div
, index
, pol
= 0;
73 index
= drm_crtc_index(crtc
);
74 dcuclk
= clk_get_rate(fsl_dev
->clk
);
75 div
= dcuclk
/ mode
->clock
/ 1000;
77 /* Configure timings: */
78 hbp
= mode
->htotal
- mode
->hsync_end
;
79 hfp
= mode
->hsync_start
- mode
->hdisplay
;
80 hsw
= mode
->hsync_end
- mode
->hsync_start
;
81 vbp
= mode
->vtotal
- mode
->vsync_end
;
82 vfp
= mode
->vsync_start
- mode
->vdisplay
;
83 vsw
= mode
->vsync_end
- mode
->vsync_start
;
85 if (mode
->flags
& DRM_MODE_FLAG_NHSYNC
)
86 pol
|= DCU_SYN_POL_INV_HS_LOW
;
88 if (mode
->flags
& DRM_MODE_FLAG_NVSYNC
)
89 pol
|= DCU_SYN_POL_INV_VS_LOW
;
91 regmap_write(fsl_dev
->regmap
, DCU_HSYN_PARA
,
92 DCU_HSYN_PARA_BP(hbp
) |
93 DCU_HSYN_PARA_PW(hsw
) |
94 DCU_HSYN_PARA_FP(hfp
));
95 regmap_write(fsl_dev
->regmap
, DCU_VSYN_PARA
,
96 DCU_VSYN_PARA_BP(vbp
) |
97 DCU_VSYN_PARA_PW(vsw
) |
98 DCU_VSYN_PARA_FP(vfp
));
99 regmap_write(fsl_dev
->regmap
, DCU_DISP_SIZE
,
100 DCU_DISP_SIZE_DELTA_Y(mode
->vdisplay
) |
101 DCU_DISP_SIZE_DELTA_X(mode
->hdisplay
));
102 regmap_write(fsl_dev
->regmap
, DCU_DIV_RATIO
, div
);
103 regmap_write(fsl_dev
->regmap
, DCU_SYN_POL
, pol
);
104 regmap_write(fsl_dev
->regmap
, DCU_BGND
, DCU_BGND_R(0) |
105 DCU_BGND_G(0) | DCU_BGND_B(0));
106 regmap_write(fsl_dev
->regmap
, DCU_DCU_MODE
,
107 DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN
);
108 regmap_write(fsl_dev
->regmap
, DCU_THRESHOLD
,
109 DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL
) |
110 DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL
) |
111 DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL
));
112 regmap_write(fsl_dev
->regmap
, DCU_UPDATE_MODE
,
113 DCU_UPDATE_MODE_READREG
);
117 static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs
= {
118 .atomic_begin
= fsl_dcu_drm_crtc_atomic_begin
,
119 .atomic_check
= fsl_dcu_drm_crtc_atomic_check
,
120 .atomic_flush
= fsl_dcu_drm_crtc_atomic_flush
,
121 .disable
= fsl_dcu_drm_disable_crtc
,
122 .enable
= fsl_dcu_drm_crtc_enable
,
123 .mode_set_nofb
= fsl_dcu_drm_crtc_mode_set_nofb
,
126 static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs
= {
127 .atomic_duplicate_state
= drm_atomic_helper_crtc_duplicate_state
,
128 .atomic_destroy_state
= drm_atomic_helper_crtc_destroy_state
,
129 .destroy
= drm_crtc_cleanup
,
130 .page_flip
= drm_atomic_helper_page_flip
,
131 .reset
= drm_atomic_helper_crtc_reset
,
132 .set_config
= drm_atomic_helper_set_config
,
135 int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device
*fsl_dev
)
137 struct drm_plane
*primary
;
138 struct drm_crtc
*crtc
= &fsl_dev
->crtc
;
139 unsigned int i
, j
, reg_num
;
142 primary
= fsl_dcu_drm_primary_create_plane(fsl_dev
->drm
);
146 ret
= drm_crtc_init_with_planes(fsl_dev
->drm
, crtc
, primary
, NULL
,
147 &fsl_dcu_drm_crtc_funcs
, NULL
);
149 primary
->funcs
->destroy(primary
);
153 drm_crtc_helper_add(crtc
, &fsl_dcu_drm_crtc_helper_funcs
);
155 if (!strcmp(fsl_dev
->soc
->name
, "ls1021a"))
156 reg_num
= LS1021A_LAYER_REG_NUM
;
158 reg_num
= VF610_LAYER_REG_NUM
;
159 for (i
= 0; i
< fsl_dev
->soc
->total_layer
; i
++) {
160 for (j
= 1; j
<= reg_num
; j
++)
161 regmap_write(fsl_dev
->regmap
, DCU_CTRLDESCLN(i
, j
), 0);
163 regmap_update_bits(fsl_dev
->regmap
, DCU_DCU_MODE
,
164 DCU_MODE_DCU_MODE_MASK
,
165 DCU_MODE_DCU_MODE(DCU_MODE_OFF
));
166 regmap_write(fsl_dev
->regmap
, DCU_UPDATE_MODE
,
167 DCU_UPDATE_MODE_READREG
);