static void mdp4_lcdc_encoder_destroy(struct drm_encoder *encoder) { struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); bs_fini(mdp4_lcdc_encoder); drm_encoder_cleanup(encoder); kfree(mdp4_lcdc_encoder); }
static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); unsigned long pc = mdp4_lcdc_encoder->pixclock; struct mdp4_kms *mdp4_kms = get_kms(encoder); struct drm_panel *panel; uint32_t config; int i, ret; if (WARN_ON(mdp4_lcdc_encoder->enabled)) return; /* TODO: hard-coded for 18bpp: */ config = MDP4_DMA_CONFIG_R_BPC(BPC6) | MDP4_DMA_CONFIG_G_BPC(BPC6) | MDP4_DMA_CONFIG_B_BPC(BPC6) | MDP4_DMA_CONFIG_PACK(0x21) | MDP4_DMA_CONFIG_DEFLKR_EN | MDP4_DMA_CONFIG_DITHER_EN; if (!of_property_read_bool(dev->dev->of_node, "qcom,lcdc-align-lsb")) config |= MDP4_DMA_CONFIG_PACK_ALIGN_MSB; mdp4_crtc_set_config(encoder->crtc, config); mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0); bs_set(mdp4_lcdc_encoder, 1); for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { ret = regulator_enable(mdp4_lcdc_encoder->regs[i]); if (ret) DRM_DEV_ERROR(dev->dev, "failed to enable regulator: %d\n", ret); } DBG("setting lcdc_clk=%lu", pc); ret = clk_set_rate(mdp4_lcdc_encoder->lcdc_clk, pc); if (ret) DRM_DEV_ERROR(dev->dev, "failed to configure lcdc_clk: %d\n", ret); ret = clk_prepare_enable(mdp4_lcdc_encoder->lcdc_clk); if (ret) DRM_DEV_ERROR(dev->dev, "failed to enable lcdc_clk: %d\n", ret); panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node); if (!IS_ERR(panel)) { drm_panel_prepare(panel); drm_panel_enable(panel); } setup_phy(encoder); mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1); mdp4_lcdc_encoder->enabled = true; }
static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); unsigned long pc = mdp4_lcdc_encoder->pixclock; struct mdp4_kms *mdp4_kms = get_kms(encoder); struct drm_panel *panel = mdp4_lcdc_encoder->panel; int i, ret; if (WARN_ON(mdp4_lcdc_encoder->enabled)) return; /* TODO: hard-coded for 18bpp: */ mdp4_crtc_set_config(encoder->crtc, MDP4_DMA_CONFIG_R_BPC(BPC6) | MDP4_DMA_CONFIG_G_BPC(BPC6) | MDP4_DMA_CONFIG_B_BPC(BPC6) | MDP4_DMA_CONFIG_PACK_ALIGN_MSB | MDP4_DMA_CONFIG_PACK(0x21) | MDP4_DMA_CONFIG_DEFLKR_EN | MDP4_DMA_CONFIG_DITHER_EN); mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0); bs_set(mdp4_lcdc_encoder, 1); for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { ret = regulator_enable(mdp4_lcdc_encoder->regs[i]); if (ret) dev_err(dev->dev, "failed to enable regulator: %d\n", ret); } DBG("setting lcdc_clk=%lu", pc); ret = clk_set_rate(mdp4_lcdc_encoder->lcdc_clk, pc); if (ret) dev_err(dev->dev, "failed to configure lcdc_clk: %d\n", ret); ret = clk_prepare_enable(mdp4_lcdc_encoder->lcdc_clk); if (ret) dev_err(dev->dev, "failed to enable lcdc_clk: %d\n", ret); if (panel) { drm_panel_prepare(panel); drm_panel_enable(panel); } setup_phy(encoder); mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1); mdp4_lcdc_encoder->enabled = true; }
static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); struct mdp4_kms *mdp4_kms = get_kms(encoder); struct drm_panel *panel; int i, ret; if (WARN_ON(!mdp4_lcdc_encoder->enabled)) return; mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0); panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node); if (!IS_ERR(panel)) { drm_panel_disable(panel); drm_panel_unprepare(panel); } /* * Wait for a vsync so we know the ENABLE=0 latched before * the (connector) source of the vsync's gets disabled, * otherwise we end up in a funny state if we re-enable * before the disable latches, which results that some of * the settings changes for the new modeset (like new * scanout buffer) don't latch properly.. */ mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_PRIMARY_VSYNC); clk_disable_unprepare(mdp4_lcdc_encoder->lcdc_clk); for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { ret = regulator_disable(mdp4_lcdc_encoder->regs[i]); if (ret) DRM_DEV_ERROR(dev->dev, "failed to disable regulator: %d\n", ret); } bs_set(mdp4_lcdc_encoder, 0); mdp4_lcdc_encoder->enabled = false; }
long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate) { struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); return clk_round_rate(mdp4_lcdc_encoder->lcdc_clk, rate); }
static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); struct mdp4_kms *mdp4_kms = get_kms(encoder); uint32_t lcdc_hsync_skew, vsync_period, vsync_len, ctrl_pol; uint32_t display_v_start, display_v_end; uint32_t hsync_start_x, hsync_end_x; 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); mdp4_lcdc_encoder->pixclock = mode->clock * 1000; DBG("pixclock=%lu", mdp4_lcdc_encoder->pixclock); ctrl_pol = 0; if (mode->flags & DRM_MODE_FLAG_NHSYNC) ctrl_pol |= MDP4_LCDC_CTRL_POLARITY_HSYNC_LOW; if (mode->flags & DRM_MODE_FLAG_NVSYNC) ctrl_pol |= MDP4_LCDC_CTRL_POLARITY_VSYNC_LOW; /* probably need to get DATA_EN polarity from panel.. */ lcdc_hsync_skew = 0; /* 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 + lcdc_hsync_skew; display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + lcdc_hsync_skew - 1; mdp4_write(mdp4_kms, REG_MDP4_LCDC_HSYNC_CTRL, MDP4_LCDC_HSYNC_CTRL_PULSEW(mode->hsync_end - mode->hsync_start) | MDP4_LCDC_HSYNC_CTRL_PERIOD(mode->htotal)); mdp4_write(mdp4_kms, REG_MDP4_LCDC_VSYNC_PERIOD, vsync_period); mdp4_write(mdp4_kms, REG_MDP4_LCDC_VSYNC_LEN, vsync_len); mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_HCTRL, MDP4_LCDC_DISPLAY_HCTRL_START(hsync_start_x) | MDP4_LCDC_DISPLAY_HCTRL_END(hsync_end_x)); mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_VSTART, display_v_start); mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_VEND, display_v_end); mdp4_write(mdp4_kms, REG_MDP4_LCDC_BORDER_CLR, 0); mdp4_write(mdp4_kms, REG_MDP4_LCDC_UNDERFLOW_CLR, MDP4_LCDC_UNDERFLOW_CLR_ENABLE_RECOVERY | MDP4_LCDC_UNDERFLOW_CLR_COLOR(0xff)); mdp4_write(mdp4_kms, REG_MDP4_LCDC_HSYNC_SKEW, lcdc_hsync_skew); mdp4_write(mdp4_kms, REG_MDP4_LCDC_CTRL_POLARITY, ctrl_pol); mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_HCTL, MDP4_LCDC_ACTIVE_HCTL_START(0) | MDP4_LCDC_ACTIVE_HCTL_END(0)); mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VSTART, 0); mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VEND, 0); }