Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2015, The Linux Foundation. All rights reserved.
0004  * Copyright (c) 2014, Inforce Computing. All rights reserved.
0005  *
0006  * Author: Vinay Simha <vinaysimha@inforcecomputing.com>
0007  */
0008 
0009 #include <drm/drm_crtc.h>
0010 #include <drm/drm_probe_helper.h>
0011 
0012 #include "mdp4_kms.h"
0013 
0014 #ifdef CONFIG_DRM_MSM_DSI
0015 
0016 struct mdp4_dsi_encoder {
0017     struct drm_encoder base;
0018     struct drm_panel *panel;
0019     bool enabled;
0020 };
0021 #define to_mdp4_dsi_encoder(x) container_of(x, struct mdp4_dsi_encoder, base)
0022 
0023 static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
0024 {
0025     struct msm_drm_private *priv = encoder->dev->dev_private;
0026     return to_mdp4_kms(to_mdp_kms(priv->kms));
0027 }
0028 
0029 static void mdp4_dsi_encoder_destroy(struct drm_encoder *encoder)
0030 {
0031     struct mdp4_dsi_encoder *mdp4_dsi_encoder = to_mdp4_dsi_encoder(encoder);
0032 
0033     drm_encoder_cleanup(encoder);
0034     kfree(mdp4_dsi_encoder);
0035 }
0036 
0037 static const struct drm_encoder_funcs mdp4_dsi_encoder_funcs = {
0038     .destroy = mdp4_dsi_encoder_destroy,
0039 };
0040 
0041 static void mdp4_dsi_encoder_mode_set(struct drm_encoder *encoder,
0042                       struct drm_display_mode *mode,
0043                       struct drm_display_mode *adjusted_mode)
0044 {
0045     struct mdp4_kms *mdp4_kms = get_kms(encoder);
0046     uint32_t dsi_hsync_skew, vsync_period, vsync_len, ctrl_pol;
0047     uint32_t display_v_start, display_v_end;
0048     uint32_t hsync_start_x, hsync_end_x;
0049 
0050     mode = adjusted_mode;
0051 
0052     DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
0053 
0054     ctrl_pol = 0;
0055     if (mode->flags & DRM_MODE_FLAG_NHSYNC)
0056         ctrl_pol |= MDP4_DSI_CTRL_POLARITY_HSYNC_LOW;
0057     if (mode->flags & DRM_MODE_FLAG_NVSYNC)
0058         ctrl_pol |= MDP4_DSI_CTRL_POLARITY_VSYNC_LOW;
0059     /* probably need to get DATA_EN polarity from panel.. */
0060 
0061     dsi_hsync_skew = 0;  /* get this from panel? */
0062 
0063     hsync_start_x = (mode->htotal - mode->hsync_start);
0064     hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
0065 
0066     vsync_period = mode->vtotal * mode->htotal;
0067     vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal;
0068     display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + dsi_hsync_skew;
0069     display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + dsi_hsync_skew - 1;
0070 
0071     mdp4_write(mdp4_kms, REG_MDP4_DSI_HSYNC_CTRL,
0072             MDP4_DSI_HSYNC_CTRL_PULSEW(mode->hsync_end - mode->hsync_start) |
0073             MDP4_DSI_HSYNC_CTRL_PERIOD(mode->htotal));
0074     mdp4_write(mdp4_kms, REG_MDP4_DSI_VSYNC_PERIOD, vsync_period);
0075     mdp4_write(mdp4_kms, REG_MDP4_DSI_VSYNC_LEN, vsync_len);
0076     mdp4_write(mdp4_kms, REG_MDP4_DSI_DISPLAY_HCTRL,
0077             MDP4_DSI_DISPLAY_HCTRL_START(hsync_start_x) |
0078             MDP4_DSI_DISPLAY_HCTRL_END(hsync_end_x));
0079     mdp4_write(mdp4_kms, REG_MDP4_DSI_DISPLAY_VSTART, display_v_start);
0080     mdp4_write(mdp4_kms, REG_MDP4_DSI_DISPLAY_VEND, display_v_end);
0081 
0082     mdp4_write(mdp4_kms, REG_MDP4_DSI_CTRL_POLARITY, ctrl_pol);
0083     mdp4_write(mdp4_kms, REG_MDP4_DSI_UNDERFLOW_CLR,
0084             MDP4_DSI_UNDERFLOW_CLR_ENABLE_RECOVERY |
0085             MDP4_DSI_UNDERFLOW_CLR_COLOR(0xff));
0086     mdp4_write(mdp4_kms, REG_MDP4_DSI_ACTIVE_HCTL,
0087             MDP4_DSI_ACTIVE_HCTL_START(0) |
0088             MDP4_DSI_ACTIVE_HCTL_END(0));
0089     mdp4_write(mdp4_kms, REG_MDP4_DSI_HSYNC_SKEW, dsi_hsync_skew);
0090     mdp4_write(mdp4_kms, REG_MDP4_DSI_BORDER_CLR, 0);
0091     mdp4_write(mdp4_kms, REG_MDP4_DSI_ACTIVE_VSTART, 0);
0092     mdp4_write(mdp4_kms, REG_MDP4_DSI_ACTIVE_VEND, 0);
0093 }
0094 
0095 static void mdp4_dsi_encoder_disable(struct drm_encoder *encoder)
0096 {
0097     struct mdp4_dsi_encoder *mdp4_dsi_encoder = to_mdp4_dsi_encoder(encoder);
0098     struct mdp4_kms *mdp4_kms = get_kms(encoder);
0099 
0100     if (!mdp4_dsi_encoder->enabled)
0101         return;
0102 
0103     mdp4_write(mdp4_kms, REG_MDP4_DSI_ENABLE, 0);
0104 
0105     /*
0106      * Wait for a vsync so we know the ENABLE=0 latched before
0107      * the (connector) source of the vsync's gets disabled,
0108      * otherwise we end up in a funny state if we re-enable
0109      * before the disable latches, which results that some of
0110      * the settings changes for the new modeset (like new
0111      * scanout buffer) don't latch properly..
0112      */
0113     mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_PRIMARY_VSYNC);
0114 
0115     mdp4_dsi_encoder->enabled = false;
0116 }
0117 
0118 static void mdp4_dsi_encoder_enable(struct drm_encoder *encoder)
0119 {
0120     struct mdp4_dsi_encoder *mdp4_dsi_encoder = to_mdp4_dsi_encoder(encoder);
0121     struct mdp4_kms *mdp4_kms = get_kms(encoder);
0122 
0123     if (mdp4_dsi_encoder->enabled)
0124         return;
0125 
0126     mdp4_crtc_set_config(encoder->crtc,
0127             MDP4_DMA_CONFIG_PACK_ALIGN_MSB |
0128             MDP4_DMA_CONFIG_DEFLKR_EN |
0129             MDP4_DMA_CONFIG_DITHER_EN |
0130             MDP4_DMA_CONFIG_R_BPC(BPC8) |
0131             MDP4_DMA_CONFIG_G_BPC(BPC8) |
0132             MDP4_DMA_CONFIG_B_BPC(BPC8) |
0133             MDP4_DMA_CONFIG_PACK(0x21));
0134 
0135     mdp4_crtc_set_intf(encoder->crtc, INTF_DSI_VIDEO, 0);
0136 
0137     mdp4_write(mdp4_kms, REG_MDP4_DSI_ENABLE, 1);
0138 
0139     mdp4_dsi_encoder->enabled = true;
0140 }
0141 
0142 static const struct drm_encoder_helper_funcs mdp4_dsi_encoder_helper_funcs = {
0143     .mode_set = mdp4_dsi_encoder_mode_set,
0144     .disable = mdp4_dsi_encoder_disable,
0145     .enable = mdp4_dsi_encoder_enable,
0146 };
0147 
0148 /* initialize encoder */
0149 struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev)
0150 {
0151     struct drm_encoder *encoder = NULL;
0152     struct mdp4_dsi_encoder *mdp4_dsi_encoder;
0153     int ret;
0154 
0155     mdp4_dsi_encoder = kzalloc(sizeof(*mdp4_dsi_encoder), GFP_KERNEL);
0156     if (!mdp4_dsi_encoder) {
0157         ret = -ENOMEM;
0158         goto fail;
0159     }
0160 
0161     encoder = &mdp4_dsi_encoder->base;
0162 
0163     drm_encoder_init(dev, encoder, &mdp4_dsi_encoder_funcs,
0164              DRM_MODE_ENCODER_DSI, NULL);
0165     drm_encoder_helper_add(encoder, &mdp4_dsi_encoder_helper_funcs);
0166 
0167     return encoder;
0168 
0169 fail:
0170     if (encoder)
0171         mdp4_dsi_encoder_destroy(encoder);
0172 
0173     return ERR_PTR(ret);
0174 }
0175 #endif /* CONFIG_DRM_MSM_DSI */