static void mdp5_encoder_destroy(struct drm_encoder *encoder) { struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); bs_fini(mdp5_encoder); drm_encoder_cleanup(encoder); kfree(mdp5_encoder); }
static void mdp5_encoder_commit(struct drm_encoder *encoder) { struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); mdp5_crtc_set_intf(encoder->crtc, mdp5_encoder->intf, mdp5_encoder->intf_id); mdp5_encoder_dpms(encoder, DRM_MODE_DPMS_ON); }
void mdp5_cmd_encoder_disable(struct drm_encoder *encoder) { struct mdp5_encoder *mdp5_cmd_enc = to_mdp5_encoder(encoder); struct mdp5_ctl *ctl = mdp5_cmd_enc->ctl; struct mdp5_interface *intf = mdp5_cmd_enc->intf; struct mdp5_pipeline *pipeline = mdp5_crtc_get_pipeline(encoder->crtc); if (WARN_ON(!mdp5_cmd_enc->enabled)) return; pingpong_tearcheck_disable(encoder); mdp5_ctl_set_encoder_state(ctl, pipeline, false); mdp5_ctl_commit(ctl, pipeline, mdp_ctl_flush_mask_encoder(intf), true); bs_set(mdp5_cmd_enc, 0); mdp5_cmd_enc->enabled = false; }
int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder, struct drm_encoder *slave_encoder) { struct mdp5_encoder *mdp5_cmd_enc = to_mdp5_encoder(encoder); struct mdp5_kms *mdp5_kms; struct device *dev; int intf_num; u32 data = 0; if (!encoder || !slave_encoder) return -EINVAL; mdp5_kms = get_kms(encoder); intf_num = mdp5_cmd_enc->intf->num; /* Switch slave encoder's trigger MUX, to use the master's * start signal for the slave encoder */ if (intf_num == 1) data |= MDP5_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX; else if (intf_num == 2) data |= MDP5_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX; else return -EINVAL; /* Smart Panel, Sync mode */ data |= MDP5_SPLIT_DPL_UPPER_SMART_PANEL; dev = &mdp5_kms->pdev->dev; /* Make sure clocks are on when connectors calling this function. */ pm_runtime_get_sync(dev); mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, data); mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER, MDP5_SPLIT_DPL_LOWER_SMART_PANEL); mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1); pm_runtime_put_sync(dev); return 0; }
static void mdp5_encoder_dpms(struct drm_encoder *encoder, int mode) { struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); struct mdp5_kms *mdp5_kms = get_kms(encoder); int intf = mdp5_encoder->intf; bool enabled = (mode == DRM_MODE_DPMS_ON); DBG("mode=%d", mode); if (enabled == mdp5_encoder->enabled) return; if (enabled) { bs_set(mdp5_encoder, 1); mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 1); } else { mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 0); bs_set(mdp5_encoder, 0); } mdp5_encoder->enabled = enabled; }
static void mdp5_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); struct mdp5_kms *mdp5_kms = get_kms(encoder); int intf = mdp5_encoder->intf; 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; uint32_t format; mode = adjusted_mode; DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", mode->base.id, mode->name, mode->vrefresh, mode->clock, mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal, mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal, mode->type, mode->flags); ctrl_pol = 0; if (mode->flags & DRM_MODE_FLAG_NHSYNC) ctrl_pol |= MDP5_INTF_POLARITY_CTL_HSYNC_LOW; if (mode->flags & DRM_MODE_FLAG_NVSYNC) ctrl_pol |= MDP5_INTF_POLARITY_CTL_VSYNC_LOW; /* probably need to get DATA_EN polarity from panel.. */ dtv_hsync_skew = 0; /* get this from panel? */ format = 0x213f; /* get this from panel? */ hsync_start_x = (mode->htotal - mode->hsync_start); hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1; vsync_period = mode->vtotal * mode->htotal; vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal; display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + dtv_hsync_skew; display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + dtv_hsync_skew - 1; mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_CTL(intf), MDP5_INTF_HSYNC_CTL_PULSEW(mode->hsync_end - mode->hsync_start) | MDP5_INTF_HSYNC_CTL_PERIOD(mode->htotal)); mdp5_write(mdp5_kms, REG_MDP5_INTF_VSYNC_PERIOD_F0(intf), vsync_period); mdp5_write(mdp5_kms, REG_MDP5_INTF_VSYNC_LEN_F0(intf), vsync_len); mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_HCTL(intf), MDP5_INTF_DISPLAY_HCTL_START(hsync_start_x) | MDP5_INTF_DISPLAY_HCTL_END(hsync_end_x)); mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_VSTART_F0(intf), display_v_start); mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_VEND_F0(intf), display_v_end); mdp5_write(mdp5_kms, REG_MDP5_INTF_BORDER_COLOR(intf), 0); mdp5_write(mdp5_kms, REG_MDP5_INTF_UNDERFLOW_COLOR(intf), 0xff); mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_SKEW(intf), dtv_hsync_skew); mdp5_write(mdp5_kms, REG_MDP5_INTF_POLARITY_CTL(intf), ctrl_pol); mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_HCTL(intf), MDP5_INTF_ACTIVE_HCTL_START(0) | MDP5_INTF_ACTIVE_HCTL_END(0)); mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_VSTART_F0(intf), 0); mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_VEND_F0(intf), 0); mdp5_write(mdp5_kms, REG_MDP5_INTF_PANEL_FORMAT(intf), format); mdp5_write(mdp5_kms, REG_MDP5_INTF_FRAME_LINE_COUNT_EN(intf), 0x3); /* frame+line? */ }