0001
0002
0003
0004
0005
0006
0007
0008 #include <drm/drm_crtc.h>
0009 #include <drm/drm_probe_helper.h>
0010
0011 #include "mdp5_kms.h"
0012
0013 static struct mdp5_kms *get_kms(struct drm_encoder *encoder)
0014 {
0015 struct msm_drm_private *priv = encoder->dev->dev_private;
0016 return to_mdp5_kms(to_mdp_kms(priv->kms));
0017 }
0018
0019 static void mdp5_encoder_destroy(struct drm_encoder *encoder)
0020 {
0021 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
0022 drm_encoder_cleanup(encoder);
0023 kfree(mdp5_encoder);
0024 }
0025
0026 static const struct drm_encoder_funcs mdp5_encoder_funcs = {
0027 .destroy = mdp5_encoder_destroy,
0028 };
0029
0030 static void mdp5_vid_encoder_mode_set(struct drm_encoder *encoder,
0031 struct drm_display_mode *mode,
0032 struct drm_display_mode *adjusted_mode)
0033 {
0034 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
0035 struct mdp5_kms *mdp5_kms = get_kms(encoder);
0036 struct drm_device *dev = encoder->dev;
0037 struct drm_connector *connector;
0038 int intf = mdp5_encoder->intf->num;
0039 uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
0040 uint32_t display_v_start, display_v_end;
0041 uint32_t hsync_start_x, hsync_end_x;
0042 uint32_t format = 0x2100;
0043 unsigned long flags;
0044
0045 mode = adjusted_mode;
0046
0047 DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
0048
0049 ctrl_pol = 0;
0050
0051
0052 if (mdp5_encoder->intf->type != INTF_DSI) {
0053 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
0054 ctrl_pol |= MDP5_INTF_POLARITY_CTL_HSYNC_LOW;
0055 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
0056 ctrl_pol |= MDP5_INTF_POLARITY_CTL_VSYNC_LOW;
0057 }
0058
0059
0060 dtv_hsync_skew = 0;
0061
0062
0063 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
0064 if (connector->encoder == encoder) {
0065 switch (connector->display_info.bpc) {
0066 case 4:
0067 format |= 0;
0068 break;
0069 case 5:
0070 format |= 0x15;
0071 break;
0072 case 6:
0073 format |= 0x2A;
0074 break;
0075 case 8:
0076 default:
0077 format |= 0x3F;
0078 break;
0079 }
0080 break;
0081 }
0082 }
0083
0084 hsync_start_x = (mode->htotal - mode->hsync_start);
0085 hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
0086
0087 vsync_period = mode->vtotal * mode->htotal;
0088 vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal;
0089 display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + dtv_hsync_skew;
0090 display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + dtv_hsync_skew - 1;
0091
0092
0093
0094
0095
0096
0097 if (mdp5_encoder->intf->type == INTF_eDP) {
0098 display_v_start += mode->htotal - mode->hsync_start;
0099 display_v_end -= mode->hsync_start - mode->hdisplay;
0100 }
0101
0102 spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
0103
0104 mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_CTL(intf),
0105 MDP5_INTF_HSYNC_CTL_PULSEW(mode->hsync_end - mode->hsync_start) |
0106 MDP5_INTF_HSYNC_CTL_PERIOD(mode->htotal));
0107 mdp5_write(mdp5_kms, REG_MDP5_INTF_VSYNC_PERIOD_F0(intf), vsync_period);
0108 mdp5_write(mdp5_kms, REG_MDP5_INTF_VSYNC_LEN_F0(intf), vsync_len);
0109 mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_HCTL(intf),
0110 MDP5_INTF_DISPLAY_HCTL_START(hsync_start_x) |
0111 MDP5_INTF_DISPLAY_HCTL_END(hsync_end_x));
0112 mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_VSTART_F0(intf), display_v_start);
0113 mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_VEND_F0(intf), display_v_end);
0114 mdp5_write(mdp5_kms, REG_MDP5_INTF_BORDER_COLOR(intf), 0);
0115 mdp5_write(mdp5_kms, REG_MDP5_INTF_UNDERFLOW_COLOR(intf), 0xff);
0116 mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_SKEW(intf), dtv_hsync_skew);
0117 mdp5_write(mdp5_kms, REG_MDP5_INTF_POLARITY_CTL(intf), ctrl_pol);
0118 mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_HCTL(intf),
0119 MDP5_INTF_ACTIVE_HCTL_START(0) |
0120 MDP5_INTF_ACTIVE_HCTL_END(0));
0121 mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_VSTART_F0(intf), 0);
0122 mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_VEND_F0(intf), 0);
0123 mdp5_write(mdp5_kms, REG_MDP5_INTF_PANEL_FORMAT(intf), format);
0124 mdp5_write(mdp5_kms, REG_MDP5_INTF_FRAME_LINE_COUNT_EN(intf), 0x3);
0125
0126 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
0127
0128 mdp5_crtc_set_pipeline(encoder->crtc);
0129 }
0130
0131 static void mdp5_vid_encoder_disable(struct drm_encoder *encoder)
0132 {
0133 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
0134 struct mdp5_kms *mdp5_kms = get_kms(encoder);
0135 struct mdp5_ctl *ctl = mdp5_encoder->ctl;
0136 struct mdp5_pipeline *pipeline = mdp5_crtc_get_pipeline(encoder->crtc);
0137 struct mdp5_hw_mixer *mixer = mdp5_crtc_get_mixer(encoder->crtc);
0138 struct mdp5_interface *intf = mdp5_encoder->intf;
0139 int intfn = mdp5_encoder->intf->num;
0140 unsigned long flags;
0141
0142 if (WARN_ON(!mdp5_encoder->enabled))
0143 return;
0144
0145 mdp5_ctl_set_encoder_state(ctl, pipeline, false);
0146
0147 spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
0148 mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 0);
0149 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
0150 mdp5_ctl_commit(ctl, pipeline, mdp_ctl_flush_mask_encoder(intf), true);
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160 mdp_irq_wait(&mdp5_kms->base, intf2vblank(mixer, intf));
0161
0162 mdp5_encoder->enabled = false;
0163 }
0164
0165 static void mdp5_vid_encoder_enable(struct drm_encoder *encoder)
0166 {
0167 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
0168 struct mdp5_kms *mdp5_kms = get_kms(encoder);
0169 struct mdp5_ctl *ctl = mdp5_encoder->ctl;
0170 struct mdp5_interface *intf = mdp5_encoder->intf;
0171 struct mdp5_pipeline *pipeline = mdp5_crtc_get_pipeline(encoder->crtc);
0172 int intfn = intf->num;
0173 unsigned long flags;
0174
0175 if (WARN_ON(mdp5_encoder->enabled))
0176 return;
0177
0178 spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
0179 mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 1);
0180 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
0181 mdp5_ctl_commit(ctl, pipeline, mdp_ctl_flush_mask_encoder(intf), true);
0182
0183 mdp5_ctl_set_encoder_state(ctl, pipeline, true);
0184
0185 mdp5_encoder->enabled = true;
0186 }
0187
0188 static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
0189 struct drm_display_mode *mode,
0190 struct drm_display_mode *adjusted_mode)
0191 {
0192 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
0193 struct mdp5_interface *intf = mdp5_encoder->intf;
0194
0195 if (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)
0196 mdp5_cmd_encoder_mode_set(encoder, mode, adjusted_mode);
0197 else
0198 mdp5_vid_encoder_mode_set(encoder, mode, adjusted_mode);
0199 }
0200
0201 static void mdp5_encoder_disable(struct drm_encoder *encoder)
0202 {
0203 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
0204 struct mdp5_interface *intf = mdp5_encoder->intf;
0205
0206 if (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)
0207 mdp5_cmd_encoder_disable(encoder);
0208 else
0209 mdp5_vid_encoder_disable(encoder);
0210 }
0211
0212 static void mdp5_encoder_enable(struct drm_encoder *encoder)
0213 {
0214 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
0215 struct mdp5_interface *intf = mdp5_encoder->intf;
0216
0217 struct drm_crtc_state *cstate = encoder->crtc->state;
0218
0219 mdp5_encoder_mode_set(encoder, &cstate->mode, &cstate->adjusted_mode);
0220
0221 if (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)
0222 mdp5_cmd_encoder_enable(encoder);
0223 else
0224 mdp5_vid_encoder_enable(encoder);
0225 }
0226
0227 static int mdp5_encoder_atomic_check(struct drm_encoder *encoder,
0228 struct drm_crtc_state *crtc_state,
0229 struct drm_connector_state *conn_state)
0230 {
0231 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
0232 struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc_state);
0233 struct mdp5_interface *intf = mdp5_encoder->intf;
0234 struct mdp5_ctl *ctl = mdp5_encoder->ctl;
0235
0236 mdp5_cstate->ctl = ctl;
0237 mdp5_cstate->pipeline.intf = intf;
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247 if (drm_atomic_crtc_needs_modeset(crtc_state))
0248 mdp5_cstate->defer_start = true;
0249
0250 return 0;
0251 }
0252
0253 static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = {
0254 .disable = mdp5_encoder_disable,
0255 .enable = mdp5_encoder_enable,
0256 .atomic_check = mdp5_encoder_atomic_check,
0257 };
0258
0259 int mdp5_encoder_get_linecount(struct drm_encoder *encoder)
0260 {
0261 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
0262 struct mdp5_kms *mdp5_kms = get_kms(encoder);
0263 int intf = mdp5_encoder->intf->num;
0264
0265 return mdp5_read(mdp5_kms, REG_MDP5_INTF_LINE_COUNT(intf));
0266 }
0267
0268 u32 mdp5_encoder_get_framecount(struct drm_encoder *encoder)
0269 {
0270 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
0271 struct mdp5_kms *mdp5_kms = get_kms(encoder);
0272 int intf = mdp5_encoder->intf->num;
0273
0274 return mdp5_read(mdp5_kms, REG_MDP5_INTF_FRAME_COUNT(intf));
0275 }
0276
0277 int mdp5_vid_encoder_set_split_display(struct drm_encoder *encoder,
0278 struct drm_encoder *slave_encoder)
0279 {
0280 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
0281 struct mdp5_encoder *mdp5_slave_enc = to_mdp5_encoder(slave_encoder);
0282 struct mdp5_kms *mdp5_kms;
0283 struct device *dev;
0284 int intf_num;
0285 u32 data = 0;
0286
0287 if (!encoder || !slave_encoder)
0288 return -EINVAL;
0289
0290 mdp5_kms = get_kms(encoder);
0291 intf_num = mdp5_encoder->intf->num;
0292
0293
0294
0295
0296 if (intf_num == 1)
0297 data |= MDP5_SPLIT_DPL_LOWER_INTF2_TG_SYNC;
0298 else if (intf_num == 2)
0299 data |= MDP5_SPLIT_DPL_LOWER_INTF1_TG_SYNC;
0300 else
0301 return -EINVAL;
0302
0303 dev = &mdp5_kms->pdev->dev;
0304
0305 pm_runtime_get_sync(dev);
0306
0307
0308 mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, 0);
0309 mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER, data);
0310 mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1);
0311
0312 mdp5_ctl_pair(mdp5_encoder->ctl, mdp5_slave_enc->ctl, true);
0313
0314 pm_runtime_put_sync(dev);
0315
0316 return 0;
0317 }
0318
0319 void mdp5_encoder_set_intf_mode(struct drm_encoder *encoder, bool cmd_mode)
0320 {
0321 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
0322 struct mdp5_interface *intf = mdp5_encoder->intf;
0323
0324
0325 if (cmd_mode) {
0326 WARN_ON(intf->type != INTF_DSI);
0327 intf->mode = MDP5_INTF_DSI_MODE_COMMAND;
0328 } else {
0329 if (intf->type == INTF_DSI)
0330 intf->mode = MDP5_INTF_DSI_MODE_VIDEO;
0331 else
0332 intf->mode = MDP5_INTF_MODE_NONE;
0333 }
0334 }
0335
0336
0337 struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
0338 struct mdp5_interface *intf,
0339 struct mdp5_ctl *ctl)
0340 {
0341 struct drm_encoder *encoder = NULL;
0342 struct mdp5_encoder *mdp5_encoder;
0343 int enc_type = (intf->type == INTF_DSI) ?
0344 DRM_MODE_ENCODER_DSI : DRM_MODE_ENCODER_TMDS;
0345 int ret;
0346
0347 mdp5_encoder = kzalloc(sizeof(*mdp5_encoder), GFP_KERNEL);
0348 if (!mdp5_encoder) {
0349 ret = -ENOMEM;
0350 goto fail;
0351 }
0352
0353 encoder = &mdp5_encoder->base;
0354 mdp5_encoder->ctl = ctl;
0355 mdp5_encoder->intf = intf;
0356
0357 spin_lock_init(&mdp5_encoder->intf_lock);
0358
0359 drm_encoder_init(dev, encoder, &mdp5_encoder_funcs, enc_type, NULL);
0360
0361 drm_encoder_helper_add(encoder, &mdp5_encoder_helper_funcs);
0362
0363 return encoder;
0364
0365 fail:
0366 if (encoder)
0367 mdp5_encoder_destroy(encoder);
0368
0369 return ERR_PTR(ret);
0370 }