From ab0bad483d3ae16fedf44bc4f2a64a64b7088c3d Mon Sep 17 00:00:00 2001 From: Narendra Muppalla Date: Wed, 25 Jan 2017 11:26:03 -0800 Subject: [PATCH] Revert "drm/msm/sde: sde encoder virtualization" This reverts 'commit a142ec80cac0 ("drm/msm/sde: sde encoder virtualization")' This is partial change for display drm driver, that will break drm/sde merge commit. Change-Id: Ida1e127788961e1c9484b0a69695d0ad5391cf88 Signed-off-by: Narendra Muppalla --- drivers/gpu/drm/msm/Makefile | 2 - drivers/gpu/drm/msm/sde/sde_encoder.c | 520 ++++++++++-------- drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 80 --- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 25 - .../gpu/drm/msm/sde/sde_encoder_phys_vid.c | 280 ---------- 5 files changed, 285 insertions(+), 622 deletions(-) delete mode 100644 drivers/gpu/drm/msm/sde/sde_encoder_phys.h delete mode 100644 drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c delete mode 100644 drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 61163578c06c..549b534a3f4d 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -40,8 +40,6 @@ msm-y := \ mdp/mdp5/mdp5_smp.o \ sde/sde_crtc.o \ sde/sde_encoder.o \ - sde/sde_encoder_phys_vid.o \ - sde/sde_encoder_phys_cmd.o \ sde/sde_irq.o \ sde/sde_kms.o \ sde/sde_plane.o \ diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 08abe700844b..db3c57681675 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -10,7 +10,6 @@ * GNU General Public License for more details. */ -#include "msm_drv.h" #include "sde_kms.h" #include "drm_crtc.h" #include "drm_crtc_helper.h" @@ -21,11 +20,32 @@ #include "sde_hw_mdp_ctl.h" #include "sde_mdp_formats.h" -#include "sde_encoder_phys.h" - #include "../dsi-staging/dsi_display.h" -#define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base) +#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) + +struct sde_encoder { + struct drm_encoder base; + spinlock_t intf_lock; + bool enabled; + uint32_t bus_scaling_client; + struct sde_hw_intf *hw_intf; + struct sde_hw_ctl *hw_ctl; + int drm_mode_enc; + + void (*vblank_callback)(void *); + void *vblank_callback_data; + + struct mdp_irq vblank_irq; +}; +#define to_sde_encoder(x) container_of(x, struct sde_encoder, base) + +static struct sde_kms *get_kms(struct drm_encoder *drm_enc) +{ + struct msm_drm_private *priv = drm_enc->dev->dev_private; + + return to_sde_kms(to_mdp_kms(priv->kms)); +} #ifdef CONFIG_QCOM_BUS_SCALING #include @@ -42,7 +62,6 @@ static struct msm_bus_vectors mdp_bus_vectors[] = { MDP_BUS_VECTOR_ENTRY(0, 0), MDP_BUS_VECTOR_ENTRY(2000000000, 2000000000), }; - static struct msm_bus_paths mdp_bus_usecases[] = { { .num_paths = 1, .vectors = @@ -60,14 +79,14 @@ static struct msm_bus_scale_pdata mdp_bus_scale_table = { .name = "mdss_mdp", }; -static void bs_init(struct sde_encoder_virt *sde_enc) +static void bs_init(struct sde_encoder *sde_enc) { sde_enc->bus_scaling_client = msm_bus_scale_register_client(&mdp_bus_scale_table); DBG("bus scale client: %08x", sde_enc->bus_scaling_client); } -static void bs_fini(struct sde_encoder_virt *sde_enc) +static void bs_fini(struct sde_encoder *sde_enc) { if (sde_enc->bus_scaling_client) { msm_bus_scale_unregister_client(sde_enc->bus_scaling_client); @@ -75,7 +94,7 @@ static void bs_fini(struct sde_encoder_virt *sde_enc) } } -static void bs_set(struct sde_encoder_virt *sde_enc, int idx) +static void bs_set(struct sde_encoder *sde_enc, int idx) { if (sde_enc->bus_scaling_client) { DBG("set bus scaling: %d", idx); @@ -85,189 +104,242 @@ static void bs_set(struct sde_encoder_virt *sde_enc, int idx) } } #else -static void bs_init(struct sde_encoder_virt *sde_enc) +static void bs_init(struct sde_encoder *sde_enc) { } -static void bs_fini(struct sde_encoder_virt *sde_enc) +static void bs_fini(struct sde_encoder *sde_enc) { } -static void bs_set(struct sde_encoder_virt *sde_enc, int idx) +static void bs_set(struct sde_encoder *sde_enc, int idx) { } #endif -void sde_encoder_get_hw_resources(struct drm_encoder *drm_enc, - struct sde_encoder_hw_resources *hw_res) +static bool sde_encoder_mode_fixup(struct drm_encoder *drm_enc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { - struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); - int i = 0; - DBG(""); - - if (!hw_res) { - DRM_ERROR("Invalid pointer"); - return; - } - - /* Query resources used by phys encs, expected to be without overlap */ - memset(hw_res, 0, sizeof(*hw_res)); - for (i = 0; i < sde_enc->num_phys_encs; i++) { - struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; - - if (phys) - phys->phys_ops.get_hw_resources(phys, hw_res); - } -} - -static void sde_encoder_destroy(struct drm_encoder *drm_enc) -{ - struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); - int i = 0; - - DBG(""); - - for (i = 0; i < ARRAY_SIZE(sde_enc->phys_encs); i++) { - struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; - - if (phys) { - phys->phys_ops.destroy(phys); - --sde_enc->num_phys_encs; - sde_enc->phys_encs[i] = NULL; - } - } - - if (sde_enc->num_phys_encs) { - DRM_ERROR("Expected num_phys_encs to be 0 not %d\n", - sde_enc->num_phys_encs); - } - - drm_encoder_cleanup(drm_enc); - bs_fini(sde_enc); - kfree(sde_enc); -} - -static bool sde_encoder_virt_mode_fixup(struct drm_encoder *drm_enc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); - int i = 0; - - DBG(""); - - for (i = 0; i < sde_enc->num_phys_encs; i++) { - struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; - - if (phys) { - phys->phys_ops.mode_fixup(phys, mode, adjusted_mode); - if (memcmp(mode, adjusted_mode, sizeof(*mode)) != 0) { - DRM_ERROR("adjusted modes not supported\n"); - return false; - } - } - } - return true; } -static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +static void sde_encoder_mode_set(struct drm_encoder *drm_enc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { - struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); - int i = 0; - DBG(""); + struct sde_encoder *sde_enc = to_sde_encoder(drm_enc); + struct intf_timing_params p = {0}; + uint32_t hsync_polarity = 0, vsync_polarity = 0; + struct sde_mdp_format_params *sde_fmt_params = NULL; + u32 fmt_fourcc = DRM_FORMAT_RGB888, fmt_mod = 0; + unsigned long lock_flags; + struct sde_hw_intf_cfg intf_cfg = {0}; - for (i = 0; i < sde_enc->num_phys_encs; i++) { - struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; + mode = adjusted_mode; - if (phys) { - phys->phys_ops.mode_set(phys, mode, adjusted_mode); - if (memcmp(mode, adjusted_mode, sizeof(*mode)) != 0) - DRM_ERROR("adjusted modes not supported\n"); - } - } -} + 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); -static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) -{ - struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); - int i = 0; - - DBG(""); - - bs_set(sde_enc, 1); - - for (i = 0; i < sde_enc->num_phys_encs; i++) { - struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; - - if (phys) - phys->phys_ops.enable(phys); - } -} - -static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) -{ - struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); - int i = 0; - - DBG(""); - - for (i = 0; i < sde_enc->num_phys_encs; i++) { - struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; - - if (phys && phys->phys_ops.disable) - phys->phys_ops.disable(phys); + /* DSI controller cannot handle active-low sync signals. */ + if (sde_enc->hw_intf->cap->type != INTF_DSI) { + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + hsync_polarity = 1; + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + vsync_polarity = 1; } - bs_set(sde_enc, 0); + /* + * For edp only: + * DISPLAY_V_START = (VBP * HCYCLE) + HBP + * DISPLAY_V_END = (VBP + VACTIVE) * HCYCLE - 1 - HFP + */ + /* + * if (sde_enc->hw->cap->type == INTF_EDP) { + * display_v_start += mode->htotal - mode->hsync_start; + * display_v_end -= mode->hsync_start - mode->hdisplay; + * } + */ + + /* + * https://www.kernel.org/doc/htmldocs/drm/ch02s05.html + * Active Region Front Porch Sync Back Porch + * <---------------------><----------------><---------><--------------> + * <--- [hv]display -----> + * <----------- [hv]sync_start ------------> + * <------------------- [hv]sync_end -----------------> + * <------------------------------ [hv]total -------------------------> + */ + + sde_fmt_params = sde_mdp_get_format_params(fmt_fourcc, fmt_mod); + + p.width = mode->hdisplay; /* active width */ + p.height = mode->vdisplay; /* active height */ + p.xres = p.width; /* Display panel width */ + p.yres = p.height; /* Display panel height */ + p.h_back_porch = mode->htotal - mode->hsync_end; + p.h_front_porch = mode->hsync_start - mode->hdisplay; + p.v_back_porch = mode->vtotal - mode->vsync_end; + p.v_front_porch = mode->vsync_start - mode->vdisplay; + p.hsync_pulse_width = mode->hsync_end - mode->hsync_start; + p.vsync_pulse_width = mode->vsync_end - mode->vsync_start; + p.hsync_polarity = hsync_polarity; + p.vsync_polarity = vsync_polarity; + p.border_clr = 0; + p.underflow_clr = 0xff; + p.hsync_skew = mode->hskew; + + intf_cfg.intf = sde_enc->hw_intf->idx; + intf_cfg.wb = SDE_NONE; + + spin_lock_irqsave(&sde_enc->intf_lock, lock_flags); + sde_enc->hw_intf->ops.setup_timing_gen(sde_enc->hw_intf, &p, + sde_fmt_params); + sde_enc->hw_ctl->ops.setup_intf_cfg(sde_enc->hw_ctl, &intf_cfg); + spin_unlock_irqrestore(&sde_enc->intf_lock, lock_flags); } -static const struct drm_encoder_helper_funcs sde_encoder_helper_funcs = { - .mode_fixup = sde_encoder_virt_mode_fixup, - .mode_set = sde_encoder_virt_mode_set, - .disable = sde_encoder_virt_disable, - .enable = sde_encoder_virt_enable, -}; - -static const struct drm_encoder_funcs sde_encoder_funcs = { - .destroy = sde_encoder_destroy, -}; - -static enum sde_intf sde_encoder_get_intf(struct sde_mdss_cfg *catalog, - enum sde_intf_type type, u32 instance) +static void sde_encoder_wait_for_vblank(struct sde_encoder *sde_enc) { - int i = 0; + struct sde_kms *sde_kms = get_kms(&sde_enc->base); + struct mdp_kms *mdp_kms = &sde_kms->base; DBG(""); - - for (i = 0; i < catalog->intf_count; i++) { - if (catalog->intf[i].type == type - && catalog->intf[i].controller_id == instance) { - return catalog->intf[i].id; - } - } - - return INTF_MAX; + mdp_irq_wait(mdp_kms, sde_enc->vblank_irq.irqmask); } -static void sde_encoder_vblank_callback(struct drm_encoder *drm_enc) +static void sde_encoder_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus) { - struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); + struct sde_encoder *sde_enc = container_of(irq, struct sde_encoder, + vblank_irq); + struct intf_status status = { 0 }; + unsigned long lock_flags; + + spin_lock_irqsave(&sde_enc->intf_lock, lock_flags); + if (sde_enc->vblank_callback) + sde_enc->vblank_callback(sde_enc->vblank_callback_data); + spin_unlock_irqrestore(&sde_enc->intf_lock, lock_flags); + + sde_enc->hw_intf->ops.get_status(sde_enc->hw_intf, &status); +} + +static void sde_encoder_disable(struct drm_encoder *drm_enc) +{ + struct sde_encoder *sde_enc = to_sde_encoder(drm_enc); + struct sde_kms *sde_kms = get_kms(drm_enc); + struct mdp_kms *mdp_kms = &(sde_kms->base); unsigned long lock_flags; DBG(""); - spin_lock_irqsave(&sde_enc->spin_lock, lock_flags); - if (sde_enc->kms_vblank_callback) - sde_enc->kms_vblank_callback(sde_enc->kms_vblank_callback_data); - spin_unlock_irqrestore(&sde_enc->spin_lock, lock_flags); + if (WARN_ON(!sde_enc->enabled)) + return; + + spin_lock_irqsave(&sde_enc->intf_lock, lock_flags); + sde_enc->hw_intf->ops.enable_timing(sde_enc->hw_intf, 0); + spin_unlock_irqrestore(&sde_enc->intf_lock, lock_flags); + + /* + * 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.. + */ + sde_encoder_wait_for_vblank(sde_enc); + + mdp_irq_unregister(mdp_kms, &sde_enc->vblank_irq); + bs_set(sde_enc, 0); + sde_enc->enabled = false; } -static int sde_encoder_virt_add_phys_vid_enc(struct sde_encoder_virt *sde_enc, +static void sde_encoder_enable(struct drm_encoder *drm_enc) +{ + struct sde_encoder *sde_enc = to_sde_encoder(drm_enc); + struct mdp_kms *mdp_kms = &(get_kms(drm_enc)->base); + unsigned long lock_flags; + + DBG(""); + + if (WARN_ON(sde_enc->enabled)) + return; + + bs_set(sde_enc, 1); + spin_lock_irqsave(&sde_enc->intf_lock, lock_flags); + sde_enc->hw_intf->ops.enable_timing(sde_enc->hw_intf, 1); + spin_unlock_irqrestore(&sde_enc->intf_lock, lock_flags); + sde_enc->enabled = true; + + mdp_irq_register(mdp_kms, &sde_enc->vblank_irq); + DBG("Registered IRQ for intf %d mask 0x%X", sde_enc->hw_intf->idx, + sde_enc->vblank_irq.irqmask); +} + +void sde_encoder_get_hw_resources(struct drm_encoder *drm_enc, + struct sde_encoder_hw_resources *hw_res) +{ + struct sde_encoder *sde_enc = to_sde_encoder(drm_enc); + + DBG(""); + + if (WARN_ON(!hw_res)) + return; + + memset(hw_res, 0, sizeof(*hw_res)); + hw_res->intfs[sde_enc->hw_intf->idx] = true; +} + +static void sde_encoder_destroy(struct drm_encoder *drm_enc) +{ + struct sde_encoder *sde_enc = to_sde_encoder(drm_enc); + + DBG(""); + drm_encoder_cleanup(drm_enc); + bs_fini(sde_enc); + kfree(sde_enc->hw_intf); + kfree(sde_enc); +} + +static const struct drm_encoder_helper_funcs sde_encoder_helper_funcs = { + .mode_fixup = sde_encoder_mode_fixup, + .mode_set = sde_encoder_mode_set, + .disable = sde_encoder_disable, + .enable = sde_encoder_enable, +}; + +static const struct drm_encoder_funcs sde_encoder_funcs = {.destroy = + sde_encoder_destroy, +}; + +static int sde_encoder_setup_hw(struct sde_encoder *sde_enc, + struct sde_kms *sde_kms, + enum sde_intf intf_idx, + enum sde_ctl ctl_idx) +{ + int ret = 0; + + DBG(""); + + sde_enc->hw_intf = sde_hw_intf_init(intf_idx, sde_kms->mmio, + sde_kms->catalog); + if (!sde_enc->hw_intf) + return -EINVAL; + + sde_enc->hw_ctl = sde_hw_ctl_init(ctl_idx, sde_kms->mmio, + sde_kms->catalog); + if (!sde_enc->hw_ctl) + return -EINVAL; + + return ret; +} + +static int sde_encoder_virt_add_phys_vid_enc(struct sde_encoder *sde_enc, struct sde_kms *sde_kms, enum sde_intf intf_idx, enum sde_ctl ctl_idx) @@ -276,30 +348,15 @@ static int sde_encoder_virt_add_phys_vid_enc(struct sde_encoder_virt *sde_enc, DBG(""); - if (sde_enc->num_phys_encs >= ARRAY_SIZE(sde_enc->phys_encs)) { - DRM_ERROR("Too many video encoders %d, unable to add\n", - sde_enc->num_phys_encs); - ret = -EINVAL; - } else { - struct sde_encoder_virt_ops parent_ops = { - sde_encoder_vblank_callback - }; - struct sde_encoder_phys *enc = - sde_encoder_phys_vid_init(sde_kms, intf_idx, ctl_idx, - &sde_enc->base, parent_ops); - if (IS_ERR(enc)) - ret = PTR_ERR(enc); - - if (!ret) { - sde_enc->phys_encs[sde_enc->num_phys_encs] = enc; - ++sde_enc->num_phys_encs; - } + ret = sde_encoder_setup_hw(sde_enc, sde_kms, intf_idx, ctl_idx); + if (!ret) { + sde_enc->vblank_irq.irq = sde_encoder_vblank_irq; + sde_enc->vblank_irq.irqmask = 0x8000000; } - return ret; } -static int sde_encoder_setup_hdmi(struct sde_encoder_virt *sde_enc, +static int sde_encoder_setup_hdmi(struct sde_encoder *sde_enc, struct sde_kms *sde_kms, int *hdmi_info) { int ret = 0; @@ -307,7 +364,9 @@ static int sde_encoder_setup_hdmi(struct sde_encoder_virt *sde_enc, DBG(""); - intf_idx = sde_encoder_get_intf(sde_kms->catalog, INTF_HDMI, 0); + sde_enc->drm_mode_enc = DRM_MODE_ENCODER_TMDS; + + intf_idx = INTF_3; if (intf_idx == INTF_MAX) ret = -EINVAL; @@ -320,7 +379,7 @@ static int sde_encoder_setup_hdmi(struct sde_encoder_virt *sde_enc, return ret; } -static int sde_encoder_setup_dsi(struct sde_encoder_virt *sde_enc, +static int sde_encoder_setup_dsi(struct sde_encoder *sde_enc, struct sde_kms *sde_kms, struct dsi_display_info *dsi_info) { @@ -329,27 +388,30 @@ static int sde_encoder_setup_dsi(struct sde_encoder_virt *sde_enc, DBG(""); - WARN_ON(dsi_info->num_of_h_tiles < 1); + sde_enc->drm_mode_enc = DRM_MODE_ENCODER_DSI; - if (dsi_info->num_of_h_tiles == 0) - dsi_info->num_of_h_tiles = 1; + if (WARN_ON(dsi_info->num_of_h_tiles > 1)) { + DBG("Dual DSI mode not yet supported"); + ret = -EINVAL; + } + + WARN_ON(dsi_info->num_of_h_tiles != 1); + dsi_info->num_of_h_tiles = 1; DBG("dsi_info->num_of_h_tiles %d h_tiled %d dsi_info->h_tile_ids %d ", - dsi_info->num_of_h_tiles, dsi_info->h_tiled, - dsi_info->h_tile_ids[0]); + dsi_info->num_of_h_tiles, dsi_info->h_tiled, + dsi_info->h_tile_ids[0]); - for (i = 0; i < dsi_info->num_of_h_tiles && !ret; i++) { - enum sde_intf intf_idx = INTF_MAX; + for (i = 0; i < !ret && dsi_info->num_of_h_tiles; i++) { + enum sde_intf intf_idx = INTF_1; enum sde_ctl ctl_idx = CTL_0; - intf_idx = sde_encoder_get_intf(sde_kms->catalog, - INTF_DSI, dsi_info->h_tile_ids[i]); if (intf_idx == INTF_MAX) { DBG("Error: could not get the interface id"); ret = -EINVAL; } - /* Create both VID and CMD Phys Encoders here */ + /* Get DSI modes, create both VID & CMD Phys Encoders */ if (!ret) ret = sde_encoder_virt_add_phys_vid_enc(sde_enc, sde_kms, @@ -367,13 +429,13 @@ struct display_probe_info { }; static struct drm_encoder *sde_encoder_virt_init(struct drm_device *dev, - struct display_probe_info *display) + struct display_probe_info + *display) { struct msm_drm_private *priv = dev->dev_private; struct sde_kms *sde_kms = to_sde_kms(to_mdp_kms(priv->kms)); struct drm_encoder *drm_enc = NULL; - struct sde_encoder_virt *sde_enc = NULL; - int drm_encoder_mode = DRM_MODE_ENCODER_NONE; + struct sde_encoder *sde_enc = NULL; int ret = 0; DBG(""); @@ -385,35 +447,31 @@ static struct drm_encoder *sde_encoder_virt_init(struct drm_device *dev, } if (display->type == INTF_DSI) { - drm_encoder_mode = DRM_MODE_ENCODER_DSI; ret = sde_encoder_setup_dsi(sde_enc, sde_kms, &display->dsi_info); - } else if (display->type == INTF_HDMI) { - drm_encoder_mode = DRM_MODE_ENCODER_TMDS; ret = sde_encoder_setup_hdmi(sde_enc, sde_kms, &display->hdmi_info); } else { - DRM_ERROR("No valid displays found\n"); + DBG("No valid displays found"); ret = -EINVAL; } - if (ret) goto fail; - spin_lock_init(&sde_enc->spin_lock); + spin_lock_init(&sde_enc->intf_lock); drm_enc = &sde_enc->base; - drm_encoder_init(dev, drm_enc, &sde_encoder_funcs, drm_encoder_mode); + drm_encoder_init(dev, drm_enc, &sde_encoder_funcs, + sde_enc->drm_mode_enc); drm_encoder_helper_add(drm_enc, &sde_encoder_helper_funcs); bs_init(sde_enc); - DBG("Created encoder"); + DBG("Created sde_encoder for intf %d", sde_enc->hw_intf->idx); return drm_enc; fail: - DRM_ERROR("Failed to create encoder\n"); if (drm_enc) sde_encoder_destroy(drm_enc); @@ -434,12 +492,10 @@ static int sde_encoder_probe_hdmi(struct drm_device *dev) enc = sde_encoder_virt_init(dev, &probe_info); if (IS_ERR(enc)) ret = PTR_ERR(enc); - - if (!ret) { - /* Register new encoder with the upper layer */ + else { + /* Register new encoder with the upper layer */ priv->encoders[priv->num_encoders++] = enc; } - return ret; } @@ -454,56 +510,50 @@ static int sde_encoder_probe_dsi(struct drm_device *dev) num_displays = dsi_display_get_num_of_displays(); DBG("num_displays %d", num_displays); - - if (priv->num_encoders + num_displays > ARRAY_SIZE(priv->encoders)) { - DBG("Too many displays found in probe"); - return -EINVAL; - } - for (i = 0; i < num_displays; i++) { - struct dsi_display *dsi = dsi_display_get_display_by_index(i); if (dsi_display_is_active(dsi)) { - struct drm_encoder *enc = NULL; struct display_probe_info probe_info = { 0 }; + DBG("display %d/%d is active", i, num_displays); probe_info.type = INTF_DSI; - DBG("display %d is active", i); - ret = dsi_display_get_info(dsi, &probe_info.dsi_info); - if (ret) - return ret; + if (WARN_ON(ret)) + DBG("Failed to retrieve dsi panel info"); + else { + struct drm_encoder *enc = + sde_encoder_virt_init(dev, + &probe_info); + if (IS_ERR(enc)) + return PTR_ERR(enc); - enc = sde_encoder_virt_init(dev, &probe_info); - if (IS_ERR(enc)) - return PTR_ERR(enc); + ret = dsi_display_drm_init(dsi, enc); + if (ret) + return ret; - ret = dsi_display_drm_init(dsi, enc); - if (ret) - return ret; - - /* Register new encoder with the upper layer */ - priv->encoders[priv->num_encoders++] = enc; - } + /* Register new encoder with the upper layer */ + priv->encoders[priv->num_encoders++] = enc; + } + } else + DBG("display %d/%d is not active", i, num_displays); } return ret; } void sde_encoder_register_vblank_callback(struct drm_encoder *drm_enc, - void (*cb)(void *), void *data) -{ - struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); + void (*cb)(void *), void *data) { + struct sde_encoder *sde_enc = to_sde_encoder(drm_enc); unsigned long lock_flags; DBG(""); - spin_lock_irqsave(&sde_enc->spin_lock, lock_flags); - sde_enc->kms_vblank_callback = cb; - sde_enc->kms_vblank_callback_data = data; - spin_unlock_irqrestore(&sde_enc->spin_lock, lock_flags); + spin_lock_irqsave(&sde_enc->intf_lock, lock_flags); + sde_enc->vblank_callback = cb; + sde_enc->vblank_callback_data = data; + spin_unlock_irqrestore(&sde_enc->intf_lock, lock_flags); } /* encoders init, @@ -516,14 +566,14 @@ void sde_encoders_init(struct drm_device *dev) DBG(""); - /* Start num_encoders at 0, probe functions will increment */ + /* Start num_encoders at 0, probe functions will increment */ priv->num_encoders = 0; ret = sde_encoder_probe_dsi(dev); if (ret) - DRM_ERROR("Error probing DSI, %d\n", ret); + DBG("Error probing DSI, %d", ret); else { ret = sde_encoder_probe_hdmi(dev); if (ret) - DRM_ERROR("Error probing HDMI, %d\n", ret); + DBG("Error probing HDMI, %d", ret); } } diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h deleted file mode 100644 index 427a6d94322e..000000000000 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2015 The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef __SDE_ENCODER_PHYS_H__ -#define __SDE_ENCODER_PHYS_H__ - -#include "sde_kms.h" -#include "sde_hw_intf.h" -#include "sde_hw_mdp_ctl.h" - -#define MAX_PHYS_ENCODERS_PER_VIRTUAL 4 - -struct sde_encoder_phys; - -struct sde_encoder_virt_ops { - void (*handle_vblank_virt)(struct drm_encoder *); -}; - -struct sde_encoder_phys_ops { - void (*mode_set)(struct sde_encoder_phys *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); - bool (*mode_fixup)(struct sde_encoder_phys *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); - void (*enable)(struct sde_encoder_phys *encoder); - void (*disable)(struct sde_encoder_phys *encoder); - void (*destroy)(struct sde_encoder_phys *encoder); - void (*get_hw_resources)(struct sde_encoder_phys *encoder, - struct sde_encoder_hw_resources *hw_res); -}; - -struct sde_encoder_phys { - struct drm_encoder *parent; - struct sde_encoder_virt_ops parent_ops; - struct sde_encoder_phys_ops phys_ops; - struct sde_hw_intf *hw_intf; - struct sde_hw_ctl *hw_ctl; - struct mdp_kms *mdp_kms; - struct drm_display_mode cached_mode; - bool enabled; - spinlock_t spin_lock; -}; - -struct sde_encoder_phys_vid { - struct sde_encoder_phys base; - struct mdp_irq vblank_irq; -}; - -struct sde_encoder_virt { - struct drm_encoder base; - spinlock_t spin_lock; - uint32_t bus_scaling_client; - - int num_phys_encs; - struct sde_encoder_phys *phys_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL]; - - void (*kms_vblank_callback)(void *); - void *kms_vblank_callback_data; -}; - -struct sde_encoder_phys *sde_encoder_phys_vid_init(struct sde_kms *sde_kms, - enum sde_intf intf_idx, - enum sde_ctl ctl_idx, - struct drm_encoder *parent, - struct sde_encoder_virt_ops - parent_ops); - -#endif /* __sde_encoder_phys_H__ */ diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c deleted file mode 100644 index 693e1f33e7d8..000000000000 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2015 The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include "msm_drv.h" -#include "sde_kms.h" -#include "drm_crtc.h" -#include "drm_crtc_helper.h" - -#include "sde_hwio.h" -#include "sde_hw_catalog.h" -#include "sde_hw_intf.h" -#include "sde_mdp_formats.h" - -#include "sde_encoder_phys.h" diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c deleted file mode 100644 index 55fad67cbf12..000000000000 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 2015 The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include "msm_drv.h" -#include "sde_kms.h" -#include "drm_crtc.h" -#include "drm_crtc_helper.h" - -#include "sde_encoder_phys.h" -#include "sde_mdp_formats.h" - - -#define to_sde_encoder_phys_vid(x) \ - container_of(x, struct sde_encoder_phys_vid, base) - -static bool sde_encoder_phys_vid_mode_fixup(struct sde_encoder_phys *drm_enc, - const struct drm_display_mode *mode, - struct drm_display_mode - *adjusted_mode) -{ - DBG(""); - return true; -} - -static void sde_encoder_phys_vid_mode_set(struct sde_encoder_phys *phys_enc, - struct drm_display_mode *mode, - struct drm_display_mode - *adjusted_mode) -{ - mode = adjusted_mode; - phys_enc->cached_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); -} - -static void sde_encoder_phys_vid_setup_timing_engine(struct sde_encoder_phys - *phys_enc) -{ - struct drm_display_mode *mode = &phys_enc->cached_mode; - struct intf_timing_params p = { 0 }; - uint32_t hsync_polarity = 0; - uint32_t vsync_polarity = 0; - struct sde_mdp_format_params *sde_fmt_params = NULL; - u32 fmt_fourcc = DRM_FORMAT_RGB888; - u32 fmt_mod = 0; - unsigned long lock_flags; - struct sde_hw_intf_cfg intf_cfg = {0}; - - DBG("enable 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); - - /* DSI controller cannot handle active-low sync signals. */ - if (phys_enc->hw_intf->cap->type != INTF_DSI) { - if (mode->flags & DRM_MODE_FLAG_NHSYNC) - hsync_polarity = 1; - if (mode->flags & DRM_MODE_FLAG_NVSYNC) - vsync_polarity = 1; - } - - /* - * For edp only: - * DISPLAY_V_START = (VBP * HCYCLE) + HBP - * DISPLAY_V_END = (VBP + VACTIVE) * HCYCLE - 1 - HFP - */ - /* - * if (vid_enc->hw->cap->type == INTF_EDP) { - * display_v_start += mode->htotal - mode->hsync_start; - * display_v_end -= mode->hsync_start - mode->hdisplay; - * } - */ - - /* - * https://www.kernel.org/doc/htmldocs/drm/ch02s05.html - * Active Region Front Porch Sync Back Porch - * <---------------------><----------------><---------><--------------> - * <--- [hv]display -----> - * <----------- [hv]sync_start ------------> - * <------------------- [hv]sync_end -----------------> - * <------------------------------ [hv]total -------------------------> - */ - - sde_fmt_params = sde_mdp_get_format_params(fmt_fourcc, fmt_mod); - - p.width = mode->hdisplay; /* active width */ - p.height = mode->vdisplay; /* active height */ - p.xres = p.width; /* Display panel width */ - p.yres = p.height; /* Display panel height */ - p.h_back_porch = mode->htotal - mode->hsync_end; - p.h_front_porch = mode->hsync_start - mode->hdisplay; - p.v_back_porch = mode->vtotal - mode->vsync_end; - p.v_front_porch = mode->vsync_start - mode->vdisplay; - p.hsync_pulse_width = mode->hsync_end - mode->hsync_start; - p.vsync_pulse_width = mode->vsync_end - mode->vsync_start; - p.hsync_polarity = hsync_polarity; - p.vsync_polarity = vsync_polarity; - p.border_clr = 0; - p.underflow_clr = 0xff; - p.hsync_skew = mode->hskew; - - intf_cfg.intf = phys_enc->hw_intf->idx; - intf_cfg.wb = SDE_NONE; - - spin_lock_irqsave(&phys_enc->spin_lock, lock_flags); - phys_enc->hw_intf->ops.setup_timing_gen(phys_enc->hw_intf, &p, - sde_fmt_params); - phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg); - spin_unlock_irqrestore(&phys_enc->spin_lock, lock_flags); -} - -static void sde_encoder_phys_vid_wait_for_vblank(struct sde_encoder_phys_vid - *vid_enc) -{ - DBG(""); - mdp_irq_wait(vid_enc->base.mdp_kms, vid_enc->vblank_irq.irqmask); -} - -static void sde_encoder_phys_vid_vblank_irq(struct mdp_irq *irq, - uint32_t irqstatus) -{ - struct sde_encoder_phys_vid *vid_enc = - container_of(irq, struct sde_encoder_phys_vid, - vblank_irq); - struct sde_encoder_phys *phys_enc = &vid_enc->base; - struct intf_status status = { 0 }; - - phys_enc->hw_intf->ops.get_status(phys_enc->hw_intf, &status); - phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent); -} - -static void sde_encoder_phys_vid_enable(struct sde_encoder_phys *phys_enc) -{ - struct sde_encoder_phys_vid *vid_enc = - to_sde_encoder_phys_vid(phys_enc); - unsigned long lock_flags; - - DBG(""); - - if (WARN_ON(phys_enc->enabled)) - return; - - sde_encoder_phys_vid_setup_timing_engine(phys_enc); - - spin_lock_irqsave(&phys_enc->spin_lock, lock_flags); - phys_enc->hw_intf->ops.enable_timing(phys_enc->hw_intf, 1); - spin_unlock_irqrestore(&phys_enc->spin_lock, lock_flags); - - phys_enc->enabled = true; - - mdp_irq_register(phys_enc->mdp_kms, &vid_enc->vblank_irq); - DBG("Registered IRQ for intf %d mask 0x%X", phys_enc->hw_intf->idx, - vid_enc->vblank_irq.irqmask); -} - -static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc) -{ - struct sde_encoder_phys_vid *vid_enc = - to_sde_encoder_phys_vid(phys_enc); - unsigned long lock_flags; - - DBG(""); - - if (WARN_ON(!phys_enc->enabled)) - return; - - spin_lock_irqsave(&phys_enc->spin_lock, lock_flags); - phys_enc->hw_intf->ops.enable_timing(phys_enc->hw_intf, 0); - spin_unlock_irqrestore(&phys_enc->spin_lock, lock_flags); - - /* - * 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.. - */ - sde_encoder_phys_vid_wait_for_vblank(vid_enc); - mdp_irq_unregister(phys_enc->mdp_kms, &vid_enc->vblank_irq); - phys_enc->enabled = false; -} - -static void sde_encoder_phys_vid_destroy(struct sde_encoder_phys *phys_enc) -{ - struct sde_encoder_phys_vid *vid_enc = - to_sde_encoder_phys_vid(phys_enc); - DBG(""); - kfree(phys_enc->hw_intf); - kfree(vid_enc); -} - -static void sde_encoder_phys_vid_get_hw_resources(struct sde_encoder_phys - *phys_enc, struct - sde_encoder_hw_resources - *hw_res) -{ - DBG(""); - hw_res->intfs[phys_enc->hw_intf->idx] = true; -} - -static void sde_encoder_phys_vid_init_cbs(struct sde_encoder_phys_ops *ops) -{ - ops->mode_set = sde_encoder_phys_vid_mode_set; - ops->mode_fixup = sde_encoder_phys_vid_mode_fixup; - ops->enable = sde_encoder_phys_vid_enable; - ops->disable = sde_encoder_phys_vid_disable; - ops->destroy = sde_encoder_phys_vid_destroy; - ops->get_hw_resources = sde_encoder_phys_vid_get_hw_resources; -} - -struct sde_encoder_phys *sde_encoder_phys_vid_init(struct sde_kms *sde_kms, - enum sde_intf intf_idx, - enum sde_ctl ctl_idx, - struct drm_encoder *parent, - struct sde_encoder_virt_ops - parent_ops) -{ - struct sde_encoder_phys *phys_enc = NULL; - struct sde_encoder_phys_vid *vid_enc = NULL; - int ret = 0; - - DBG(""); - - vid_enc = kzalloc(sizeof(*vid_enc), GFP_KERNEL); - if (!vid_enc) { - ret = -ENOMEM; - goto fail; - } - phys_enc = &vid_enc->base; - - phys_enc->hw_intf = - sde_hw_intf_init(intf_idx, sde_kms->mmio, sde_kms->catalog); - if (!phys_enc->hw_intf) { - ret = -ENOMEM; - goto fail; - } - - phys_enc->hw_ctl = sde_hw_ctl_init(ctl_idx, sde_kms->mmio, - sde_kms->catalog); - if (!phys_enc->hw_ctl) { - ret = -ENOMEM; - goto fail; - } - - sde_encoder_phys_vid_init_cbs(&phys_enc->phys_ops); - phys_enc->parent = parent; - phys_enc->parent_ops = parent_ops; - phys_enc->mdp_kms = &sde_kms->base; - vid_enc->vblank_irq.irq = sde_encoder_phys_vid_vblank_irq; - vid_enc->vblank_irq.irqmask = 0x8000000; - spin_lock_init(&phys_enc->spin_lock); - - DBG("Created sde_encoder_phys_vid for intf %d", phys_enc->hw_intf->idx); - - return phys_enc; - -fail: - DRM_ERROR("Failed to create encoder\n"); - if (vid_enc) - sde_encoder_phys_vid_destroy(phys_enc); - - return ERR_PTR(ret); -}