1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2015, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2014, Inforce Computing. All rights reserved. 5 * 6 * Author: Vinay Simha <vinaysimha@inforcecomputing.com> 7 */ 8 9 #include <drm/drm_crtc.h> 10 #include <drm/drm_probe_helper.h> 11 12 #include "mdp4_kms.h" 13 14 struct mdp4_dsi_encoder { 15 struct drm_encoder base; 16 struct drm_panel *panel; 17 bool enabled; 18 }; 19 #define to_mdp4_dsi_encoder(x) container_of(x, struct mdp4_dsi_encoder, base) 20 21 static struct mdp4_kms *get_kms(struct drm_encoder *encoder) 22 { 23 struct msm_drm_private *priv = encoder->dev->dev_private; 24 return to_mdp4_kms(to_mdp_kms(priv->kms)); 25 } 26 27 static void mdp4_dsi_encoder_destroy(struct drm_encoder *encoder) 28 { 29 struct mdp4_dsi_encoder *mdp4_dsi_encoder = to_mdp4_dsi_encoder(encoder); 30 31 drm_encoder_cleanup(encoder); 32 kfree(mdp4_dsi_encoder); 33 } 34 35 static const struct drm_encoder_funcs mdp4_dsi_encoder_funcs = { 36 .destroy = mdp4_dsi_encoder_destroy, 37 }; 38 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) 42 { 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; 47 48 mode = adjusted_mode; 49 50 DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode)); 51 52 ctrl_pol = 0; 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.. */ 58 59 dsi_hsync_skew = 0; /* get this from panel? */ 60 61 hsync_start_x = (mode->htotal - mode->hsync_start); 62 hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1; 63 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; 68 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); 79 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); 91 } 92 93 static void mdp4_dsi_encoder_disable(struct drm_encoder *encoder) 94 { 95 struct mdp4_dsi_encoder *mdp4_dsi_encoder = to_mdp4_dsi_encoder(encoder); 96 struct mdp4_kms *mdp4_kms = get_kms(encoder); 97 98 if (!mdp4_dsi_encoder->enabled) 99 return; 100 101 mdp4_write(mdp4_kms, REG_MDP4_DSI_ENABLE, 0); 102 103 /* 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.. 110 */ 111 mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_PRIMARY_VSYNC); 112 113 mdp4_dsi_encoder->enabled = false; 114 } 115 116 static void mdp4_dsi_encoder_enable(struct drm_encoder *encoder) 117 { 118 struct mdp4_dsi_encoder *mdp4_dsi_encoder = to_mdp4_dsi_encoder(encoder); 119 struct mdp4_kms *mdp4_kms = get_kms(encoder); 120 121 if (mdp4_dsi_encoder->enabled) 122 return; 123 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)); 132 133 mdp4_crtc_set_intf(encoder->crtc, INTF_DSI_VIDEO, 0); 134 135 mdp4_write(mdp4_kms, REG_MDP4_DSI_ENABLE, 1); 136 137 mdp4_dsi_encoder->enabled = true; 138 } 139 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, 144 }; 145 146 /* initialize encoder */ 147 struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev) 148 { 149 struct drm_encoder *encoder = NULL; 150 struct mdp4_dsi_encoder *mdp4_dsi_encoder; 151 int ret; 152 153 mdp4_dsi_encoder = kzalloc(sizeof(*mdp4_dsi_encoder), GFP_KERNEL); 154 if (!mdp4_dsi_encoder) { 155 ret = -ENOMEM; 156 goto fail; 157 } 158 159 encoder = &mdp4_dsi_encoder->base; 160 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); 164 165 return encoder; 166 167 fail: 168 if (encoder) 169 mdp4_dsi_encoder_destroy(encoder); 170 171 return ERR_PTR(ret); 172 } 173