Merge branch 'turbostat' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
[linux-2.6-microblaze.git] / drivers / gpu / drm / msm / disp / mdp4 / mdp4_dsi_encoder.c
1 /*
2  * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2014, Inforce Computing. All rights reserved.
4  *
5  * Author: Vinay Simha <vinaysimha@inforcecomputing.com>
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License version 2 as published by
9  * the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <drm/drm_crtc.h>
21 #include <drm/drm_probe_helper.h>
22
23 #include "mdp4_kms.h"
24
25 struct mdp4_dsi_encoder {
26         struct drm_encoder base;
27         struct drm_panel *panel;
28         bool enabled;
29 };
30 #define to_mdp4_dsi_encoder(x) container_of(x, struct mdp4_dsi_encoder, base)
31
32 static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
33 {
34         struct msm_drm_private *priv = encoder->dev->dev_private;
35         return to_mdp4_kms(to_mdp_kms(priv->kms));
36 }
37
38 static void mdp4_dsi_encoder_destroy(struct drm_encoder *encoder)
39 {
40         struct mdp4_dsi_encoder *mdp4_dsi_encoder = to_mdp4_dsi_encoder(encoder);
41
42         drm_encoder_cleanup(encoder);
43         kfree(mdp4_dsi_encoder);
44 }
45
46 static const struct drm_encoder_funcs mdp4_dsi_encoder_funcs = {
47         .destroy = mdp4_dsi_encoder_destroy,
48 };
49
50 static void mdp4_dsi_encoder_mode_set(struct drm_encoder *encoder,
51                                       struct drm_display_mode *mode,
52                                       struct drm_display_mode *adjusted_mode)
53 {
54         struct mdp4_kms *mdp4_kms = get_kms(encoder);
55         uint32_t dsi_hsync_skew, vsync_period, vsync_len, ctrl_pol;
56         uint32_t display_v_start, display_v_end;
57         uint32_t hsync_start_x, hsync_end_x;
58
59         mode = adjusted_mode;
60
61         DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
62
63         ctrl_pol = 0;
64         if (mode->flags & DRM_MODE_FLAG_NHSYNC)
65                 ctrl_pol |= MDP4_DSI_CTRL_POLARITY_HSYNC_LOW;
66         if (mode->flags & DRM_MODE_FLAG_NVSYNC)
67                 ctrl_pol |= MDP4_DSI_CTRL_POLARITY_VSYNC_LOW;
68         /* probably need to get DATA_EN polarity from panel.. */
69
70         dsi_hsync_skew = 0;  /* get this from panel? */
71
72         hsync_start_x = (mode->htotal - mode->hsync_start);
73         hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
74
75         vsync_period = mode->vtotal * mode->htotal;
76         vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal;
77         display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + dsi_hsync_skew;
78         display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + dsi_hsync_skew - 1;
79
80         mdp4_write(mdp4_kms, REG_MDP4_DSI_HSYNC_CTRL,
81                         MDP4_DSI_HSYNC_CTRL_PULSEW(mode->hsync_end - mode->hsync_start) |
82                         MDP4_DSI_HSYNC_CTRL_PERIOD(mode->htotal));
83         mdp4_write(mdp4_kms, REG_MDP4_DSI_VSYNC_PERIOD, vsync_period);
84         mdp4_write(mdp4_kms, REG_MDP4_DSI_VSYNC_LEN, vsync_len);
85         mdp4_write(mdp4_kms, REG_MDP4_DSI_DISPLAY_HCTRL,
86                         MDP4_DSI_DISPLAY_HCTRL_START(hsync_start_x) |
87                         MDP4_DSI_DISPLAY_HCTRL_END(hsync_end_x));
88         mdp4_write(mdp4_kms, REG_MDP4_DSI_DISPLAY_VSTART, display_v_start);
89         mdp4_write(mdp4_kms, REG_MDP4_DSI_DISPLAY_VEND, display_v_end);
90
91         mdp4_write(mdp4_kms, REG_MDP4_DSI_CTRL_POLARITY, ctrl_pol);
92         mdp4_write(mdp4_kms, REG_MDP4_DSI_UNDERFLOW_CLR,
93                         MDP4_DSI_UNDERFLOW_CLR_ENABLE_RECOVERY |
94                         MDP4_DSI_UNDERFLOW_CLR_COLOR(0xff));
95         mdp4_write(mdp4_kms, REG_MDP4_DSI_ACTIVE_HCTL,
96                         MDP4_DSI_ACTIVE_HCTL_START(0) |
97                         MDP4_DSI_ACTIVE_HCTL_END(0));
98         mdp4_write(mdp4_kms, REG_MDP4_DSI_HSYNC_SKEW, dsi_hsync_skew);
99         mdp4_write(mdp4_kms, REG_MDP4_DSI_BORDER_CLR, 0);
100         mdp4_write(mdp4_kms, REG_MDP4_DSI_ACTIVE_VSTART, 0);
101         mdp4_write(mdp4_kms, REG_MDP4_DSI_ACTIVE_VEND, 0);
102 }
103
104 static void mdp4_dsi_encoder_disable(struct drm_encoder *encoder)
105 {
106         struct mdp4_dsi_encoder *mdp4_dsi_encoder = to_mdp4_dsi_encoder(encoder);
107         struct mdp4_kms *mdp4_kms = get_kms(encoder);
108
109         if (!mdp4_dsi_encoder->enabled)
110                 return;
111
112         mdp4_write(mdp4_kms, REG_MDP4_DSI_ENABLE, 0);
113
114         /*
115          * Wait for a vsync so we know the ENABLE=0 latched before
116          * the (connector) source of the vsync's gets disabled,
117          * otherwise we end up in a funny state if we re-enable
118          * before the disable latches, which results that some of
119          * the settings changes for the new modeset (like new
120          * scanout buffer) don't latch properly..
121          */
122         mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_PRIMARY_VSYNC);
123
124         mdp4_dsi_encoder->enabled = false;
125 }
126
127 static void mdp4_dsi_encoder_enable(struct drm_encoder *encoder)
128 {
129         struct mdp4_dsi_encoder *mdp4_dsi_encoder = to_mdp4_dsi_encoder(encoder);
130         struct mdp4_kms *mdp4_kms = get_kms(encoder);
131
132         if (mdp4_dsi_encoder->enabled)
133                 return;
134
135          mdp4_crtc_set_config(encoder->crtc,
136                         MDP4_DMA_CONFIG_PACK_ALIGN_MSB |
137                         MDP4_DMA_CONFIG_DEFLKR_EN |
138                         MDP4_DMA_CONFIG_DITHER_EN |
139                         MDP4_DMA_CONFIG_R_BPC(BPC8) |
140                         MDP4_DMA_CONFIG_G_BPC(BPC8) |
141                         MDP4_DMA_CONFIG_B_BPC(BPC8) |
142                         MDP4_DMA_CONFIG_PACK(0x21));
143
144         mdp4_crtc_set_intf(encoder->crtc, INTF_DSI_VIDEO, 0);
145
146         mdp4_write(mdp4_kms, REG_MDP4_DSI_ENABLE, 1);
147
148         mdp4_dsi_encoder->enabled = true;
149 }
150
151 static const struct drm_encoder_helper_funcs mdp4_dsi_encoder_helper_funcs = {
152         .mode_set = mdp4_dsi_encoder_mode_set,
153         .disable = mdp4_dsi_encoder_disable,
154         .enable = mdp4_dsi_encoder_enable,
155 };
156
157 /* initialize encoder */
158 struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev)
159 {
160         struct drm_encoder *encoder = NULL;
161         struct mdp4_dsi_encoder *mdp4_dsi_encoder;
162         int ret;
163
164         mdp4_dsi_encoder = kzalloc(sizeof(*mdp4_dsi_encoder), GFP_KERNEL);
165         if (!mdp4_dsi_encoder) {
166                 ret = -ENOMEM;
167                 goto fail;
168         }
169
170         encoder = &mdp4_dsi_encoder->base;
171
172         drm_encoder_init(dev, encoder, &mdp4_dsi_encoder_funcs,
173                          DRM_MODE_ENCODER_DSI, NULL);
174         drm_encoder_helper_add(encoder, &mdp4_dsi_encoder_helper_funcs);
175
176         return encoder;
177
178 fail:
179         if (encoder)
180                 mdp4_dsi_encoder_destroy(encoder);
181
182         return ERR_PTR(ret);
183 }