1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
4 * Copyright (c) 2014, Inforce Computing. All rights reserved.
6 * Author: Vinay Simha <vinaysimha@inforcecomputing.com>
9 #include <drm/drm_crtc.h>
10 #include <drm/drm_probe_helper.h>
14 struct mdp4_dsi_encoder
{
15 struct drm_encoder base
;
16 struct drm_panel
*panel
;
19 #define to_mdp4_dsi_encoder(x) container_of(x, struct mdp4_dsi_encoder, base)
21 static struct mdp4_kms
*get_kms(struct drm_encoder
*encoder
)
23 struct msm_drm_private
*priv
= encoder
->dev
->dev_private
;
24 return to_mdp4_kms(to_mdp_kms(priv
->kms
));
27 static void mdp4_dsi_encoder_destroy(struct drm_encoder
*encoder
)
29 struct mdp4_dsi_encoder
*mdp4_dsi_encoder
= to_mdp4_dsi_encoder(encoder
);
31 drm_encoder_cleanup(encoder
);
32 kfree(mdp4_dsi_encoder
);
35 static const struct drm_encoder_funcs mdp4_dsi_encoder_funcs
= {
36 .destroy
= mdp4_dsi_encoder_destroy
,
39 static void mdp4_dsi_encoder_mode_set(struct drm_encoder
*encoder
,
40 struct drm_display_mode
*mode
,
41 struct drm_display_mode
*adjusted_mode
)
43 struct mdp4_kms
*mdp4_kms
= get_kms(encoder
);
44 uint32_t dsi_hsync_skew
, vsync_period
, vsync_len
, ctrl_pol
;
45 uint32_t display_v_start
, display_v_end
;
46 uint32_t hsync_start_x
, hsync_end_x
;
50 DBG("set mode: " DRM_MODE_FMT
, DRM_MODE_ARG(mode
));
53 if (mode
->flags
& DRM_MODE_FLAG_NHSYNC
)
54 ctrl_pol
|= MDP4_DSI_CTRL_POLARITY_HSYNC_LOW
;
55 if (mode
->flags
& DRM_MODE_FLAG_NVSYNC
)
56 ctrl_pol
|= MDP4_DSI_CTRL_POLARITY_VSYNC_LOW
;
57 /* probably need to get DATA_EN polarity from panel.. */
59 dsi_hsync_skew
= 0; /* get this from panel? */
61 hsync_start_x
= (mode
->htotal
- mode
->hsync_start
);
62 hsync_end_x
= mode
->htotal
- (mode
->hsync_start
- mode
->hdisplay
) - 1;
64 vsync_period
= mode
->vtotal
* mode
->htotal
;
65 vsync_len
= (mode
->vsync_end
- mode
->vsync_start
) * mode
->htotal
;
66 display_v_start
= (mode
->vtotal
- mode
->vsync_start
) * mode
->htotal
+ dsi_hsync_skew
;
67 display_v_end
= vsync_period
- ((mode
->vsync_start
- mode
->vdisplay
) * mode
->htotal
) + dsi_hsync_skew
- 1;
69 mdp4_write(mdp4_kms
, REG_MDP4_DSI_HSYNC_CTRL
,
70 MDP4_DSI_HSYNC_CTRL_PULSEW(mode
->hsync_end
- mode
->hsync_start
) |
71 MDP4_DSI_HSYNC_CTRL_PERIOD(mode
->htotal
));
72 mdp4_write(mdp4_kms
, REG_MDP4_DSI_VSYNC_PERIOD
, vsync_period
);
73 mdp4_write(mdp4_kms
, REG_MDP4_DSI_VSYNC_LEN
, vsync_len
);
74 mdp4_write(mdp4_kms
, REG_MDP4_DSI_DISPLAY_HCTRL
,
75 MDP4_DSI_DISPLAY_HCTRL_START(hsync_start_x
) |
76 MDP4_DSI_DISPLAY_HCTRL_END(hsync_end_x
));
77 mdp4_write(mdp4_kms
, REG_MDP4_DSI_DISPLAY_VSTART
, display_v_start
);
78 mdp4_write(mdp4_kms
, REG_MDP4_DSI_DISPLAY_VEND
, display_v_end
);
80 mdp4_write(mdp4_kms
, REG_MDP4_DSI_CTRL_POLARITY
, ctrl_pol
);
81 mdp4_write(mdp4_kms
, REG_MDP4_DSI_UNDERFLOW_CLR
,
82 MDP4_DSI_UNDERFLOW_CLR_ENABLE_RECOVERY
|
83 MDP4_DSI_UNDERFLOW_CLR_COLOR(0xff));
84 mdp4_write(mdp4_kms
, REG_MDP4_DSI_ACTIVE_HCTL
,
85 MDP4_DSI_ACTIVE_HCTL_START(0) |
86 MDP4_DSI_ACTIVE_HCTL_END(0));
87 mdp4_write(mdp4_kms
, REG_MDP4_DSI_HSYNC_SKEW
, dsi_hsync_skew
);
88 mdp4_write(mdp4_kms
, REG_MDP4_DSI_BORDER_CLR
, 0);
89 mdp4_write(mdp4_kms
, REG_MDP4_DSI_ACTIVE_VSTART
, 0);
90 mdp4_write(mdp4_kms
, REG_MDP4_DSI_ACTIVE_VEND
, 0);
93 static void mdp4_dsi_encoder_disable(struct drm_encoder
*encoder
)
95 struct mdp4_dsi_encoder
*mdp4_dsi_encoder
= to_mdp4_dsi_encoder(encoder
);
96 struct mdp4_kms
*mdp4_kms
= get_kms(encoder
);
98 if (!mdp4_dsi_encoder
->enabled
)
101 mdp4_write(mdp4_kms
, REG_MDP4_DSI_ENABLE
, 0);
104 * Wait for a vsync so we know the ENABLE=0 latched before
105 * the (connector) source of the vsync's gets disabled,
106 * otherwise we end up in a funny state if we re-enable
107 * before the disable latches, which results that some of
108 * the settings changes for the new modeset (like new
109 * scanout buffer) don't latch properly..
111 mdp_irq_wait(&mdp4_kms
->base
, MDP4_IRQ_PRIMARY_VSYNC
);
113 mdp4_dsi_encoder
->enabled
= false;
116 static void mdp4_dsi_encoder_enable(struct drm_encoder
*encoder
)
118 struct mdp4_dsi_encoder
*mdp4_dsi_encoder
= to_mdp4_dsi_encoder(encoder
);
119 struct mdp4_kms
*mdp4_kms
= get_kms(encoder
);
121 if (mdp4_dsi_encoder
->enabled
)
124 mdp4_crtc_set_config(encoder
->crtc
,
125 MDP4_DMA_CONFIG_PACK_ALIGN_MSB
|
126 MDP4_DMA_CONFIG_DEFLKR_EN
|
127 MDP4_DMA_CONFIG_DITHER_EN
|
128 MDP4_DMA_CONFIG_R_BPC(BPC8
) |
129 MDP4_DMA_CONFIG_G_BPC(BPC8
) |
130 MDP4_DMA_CONFIG_B_BPC(BPC8
) |
131 MDP4_DMA_CONFIG_PACK(0x21));
133 mdp4_crtc_set_intf(encoder
->crtc
, INTF_DSI_VIDEO
, 0);
135 mdp4_write(mdp4_kms
, REG_MDP4_DSI_ENABLE
, 1);
137 mdp4_dsi_encoder
->enabled
= true;
140 static const struct drm_encoder_helper_funcs mdp4_dsi_encoder_helper_funcs
= {
141 .mode_set
= mdp4_dsi_encoder_mode_set
,
142 .disable
= mdp4_dsi_encoder_disable
,
143 .enable
= mdp4_dsi_encoder_enable
,
146 /* initialize encoder */
147 struct drm_encoder
*mdp4_dsi_encoder_init(struct drm_device
*dev
)
149 struct drm_encoder
*encoder
= NULL
;
150 struct mdp4_dsi_encoder
*mdp4_dsi_encoder
;
153 mdp4_dsi_encoder
= kzalloc(sizeof(*mdp4_dsi_encoder
), GFP_KERNEL
);
154 if (!mdp4_dsi_encoder
) {
159 encoder
= &mdp4_dsi_encoder
->base
;
161 drm_encoder_init(dev
, encoder
, &mdp4_dsi_encoder_funcs
,
162 DRM_MODE_ENCODER_DSI
, NULL
);
163 drm_encoder_helper_add(encoder
, &mdp4_dsi_encoder_helper_funcs
);
169 mdp4_dsi_encoder_destroy(encoder
);