diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2015-06-19 22:07:07 +0800 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2015-06-19 22:07:07 +0800 |
commit | c0b59fafe31bf91f589736be304d739b13952fdd (patch) | |
tree | 0088a41c6b68132739294643be06734e3af67677 /drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | |
parent | 28bceeaaf81140d69647acd0eb7dc9312f27844a (diff) | |
parent | bfa1ce5f38938cc9e6c7f2d1011f88eba2b9e2b2 (diff) | |
download | blackbird-obmc-linux-c0b59fafe31bf91f589736be304d739b13952fdd.tar.gz blackbird-obmc-linux-c0b59fafe31bf91f589736be304d739b13952fdd.zip |
Merge branch 'mvebu/drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Merge the mvebu/drivers branch of the arm-soc tree which contains
just a single patch bfa1ce5f38938cc9e6c7f2d1011f88eba2b9e2b2 ("bus:
mvebu-mbus: add mv_mbus_dram_info_nooverlap()") that happens to be
a prerequisite of the new marvell/cesa crypto driver.
Diffstat (limited to 'drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c')
-rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | 83 |
1 files changed, 65 insertions, 18 deletions
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c index af0e02fa4f48..1188f4bf1e60 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c @@ -23,8 +23,7 @@ struct mdp5_encoder { struct drm_encoder base; - int intf; - enum mdp5_intf intf_id; + struct mdp5_interface intf; spinlock_t intf_lock; /* protect REG_MDP5_INTF_* registers */ bool enabled; uint32_t bsc; @@ -126,7 +125,7 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder, struct mdp5_kms *mdp5_kms = get_kms(encoder); struct drm_device *dev = encoder->dev; struct drm_connector *connector; - int intf = mdp5_encoder->intf; + int intf = mdp5_encoder->intf.num; uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol; uint32_t display_v_start, display_v_end; uint32_t hsync_start_x, hsync_end_x; @@ -188,7 +187,7 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder, * DISPLAY_V_START = (VBP * HCYCLE) + HBP * DISPLAY_V_END = (VBP + VACTIVE) * HCYCLE - 1 - HFP */ - if (mdp5_encoder->intf_id == INTF_eDP) { + if (mdp5_encoder->intf.type == INTF_eDP) { display_v_start += mode->htotal - mode->hsync_start; display_v_end -= mode->hsync_start - mode->hdisplay; } @@ -218,21 +217,29 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder, mdp5_write(mdp5_kms, REG_MDP5_INTF_FRAME_LINE_COUNT_EN(intf), 0x3); /* frame+line? */ spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); + + mdp5_crtc_set_intf(encoder->crtc, &mdp5_encoder->intf); } static void mdp5_encoder_disable(struct drm_encoder *encoder) { struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); struct mdp5_kms *mdp5_kms = get_kms(encoder); - int intf = mdp5_encoder->intf; + struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc); + int lm = mdp5_crtc_get_lm(encoder->crtc); + struct mdp5_interface *intf = &mdp5_encoder->intf; + int intfn = mdp5_encoder->intf.num; unsigned long flags; if (WARN_ON(!mdp5_encoder->enabled)) return; + mdp5_ctl_set_encoder_state(ctl, false); + spin_lock_irqsave(&mdp5_encoder->intf_lock, flags); - mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 0); + mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 0); spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); + mdp5_ctl_commit(ctl, mdp_ctl_flush_mask_encoder(intf)); /* * Wait for a vsync so we know the ENABLE=0 latched before @@ -242,7 +249,7 @@ static void mdp5_encoder_disable(struct drm_encoder *encoder) * the settings changes for the new modeset (like new * scanout buffer) don't latch properly.. */ - mdp_irq_wait(&mdp5_kms->base, intf2vblank(intf)); + mdp_irq_wait(&mdp5_kms->base, intf2vblank(lm, intf)); bs_set(mdp5_encoder, 0); @@ -253,19 +260,21 @@ static void mdp5_encoder_enable(struct drm_encoder *encoder) { struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); struct mdp5_kms *mdp5_kms = get_kms(encoder); - int intf = mdp5_encoder->intf; + struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc); + struct mdp5_interface *intf = &mdp5_encoder->intf; + int intfn = mdp5_encoder->intf.num; unsigned long flags; if (WARN_ON(mdp5_encoder->enabled)) return; - mdp5_crtc_set_intf(encoder->crtc, mdp5_encoder->intf, - mdp5_encoder->intf_id); - bs_set(mdp5_encoder, 1); spin_lock_irqsave(&mdp5_encoder->intf_lock, flags); - mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 1); + mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 1); spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); + mdp5_ctl_commit(ctl, mdp_ctl_flush_mask_encoder(intf)); + + mdp5_ctl_set_encoder_state(ctl, true); mdp5_encoder->enabled = true; } @@ -277,12 +286,51 @@ static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = { .enable = mdp5_encoder_enable, }; +int mdp5_encoder_set_split_display(struct drm_encoder *encoder, + struct drm_encoder *slave_encoder) +{ + struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); + struct mdp5_kms *mdp5_kms; + int intf_num; + u32 data = 0; + + if (!encoder || !slave_encoder) + return -EINVAL; + + mdp5_kms = get_kms(encoder); + intf_num = mdp5_encoder->intf.num; + + /* Switch slave encoder's TimingGen Sync mode, + * to use the master's enable signal for the slave encoder. + */ + if (intf_num == 1) + data |= MDP5_SPLIT_DPL_LOWER_INTF2_TG_SYNC; + else if (intf_num == 2) + data |= MDP5_SPLIT_DPL_LOWER_INTF1_TG_SYNC; + else + return -EINVAL; + + /* Make sure clocks are on when connectors calling this function. */ + mdp5_enable(mdp5_kms); + mdp5_write(mdp5_kms, REG_MDP5_MDP_SPARE_0(0), + MDP5_MDP_SPARE_0_SPLIT_DPL_SINGLE_FLUSH_EN); + /* Dumb Panel, Sync mode */ + mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, 0); + mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER, data); + mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1); + mdp5_disable(mdp5_kms); + + return 0; +} + /* initialize encoder */ -struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, int intf, - enum mdp5_intf intf_id) +struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, + struct mdp5_interface *intf) { struct drm_encoder *encoder = NULL; struct mdp5_encoder *mdp5_encoder; + int enc_type = (intf->type == INTF_DSI) ? + DRM_MODE_ENCODER_DSI : DRM_MODE_ENCODER_TMDS; int ret; mdp5_encoder = kzalloc(sizeof(*mdp5_encoder), GFP_KERNEL); @@ -291,14 +339,13 @@ struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, int intf, goto fail; } - mdp5_encoder->intf = intf; - mdp5_encoder->intf_id = intf_id; + memcpy(&mdp5_encoder->intf, intf, sizeof(mdp5_encoder->intf)); encoder = &mdp5_encoder->base; spin_lock_init(&mdp5_encoder->intf_lock); - drm_encoder_init(dev, encoder, &mdp5_encoder_funcs, - DRM_MODE_ENCODER_TMDS); + drm_encoder_init(dev, encoder, &mdp5_encoder_funcs, enc_type); + drm_encoder_helper_add(encoder, &mdp5_encoder_helper_funcs); bs_init(mdp5_encoder); |