summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNarendra Muppalla <NarendraM@codeaurora.org>2017-01-25 11:23:56 -0800
committerNarendra Muppalla <NarendraM@codeaurora.org>2017-01-25 17:09:21 -0800
commit6aeb68e3f4ce9853a74bc121408b167ac5c1e41c (patch)
tree11cbfb97646c92b587119d7ad0890d007de42bde
parent314869eb56763d34f91d5483b0d510267894fadd (diff)
Revert "drm/msm/sde: add resource manager to enable dual dsi"
This reverts 'commit e14b3005bdf9 ("drm/msm/sde: add resource manager to enable dual dsi")'. This is partial change for display drm driver, that will break drm/sde merge commit. Change-Id: I2d4f915aa5d3382ce22aa1b4d6e02183ab2f7c5c Signed-off-by: Narendra Muppalla <NarendraM@codeaurora.org>
-rw-r--r--drivers/gpu/drm/msm/Makefile1
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.c282
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.h79
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder.c62
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys.h7
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c87
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.c23
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.h88
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms_utils.c173
9 files changed, 147 insertions, 655 deletions
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 05b6ca9b5c55..b7fa5c05e12d 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -43,7 +43,6 @@ msm-y := \
sde/sde_encoder_phys_vid.o \
sde/sde_encoder_phys_cmd.o \
sde/sde_irq.o \
- sde/sde_kms_utils.o \
sde/sde_kms.o \
sde/sde_plane.o \
msm_atomic.o \
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 5fc1664fd9a0..3c30267e7283 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -19,11 +19,40 @@
#include "sde_kms.h"
#include "sde_hw_lm.h"
#include "sde_hw_mdp_ctl.h"
-#include "sde_crtc.h"
-#define CTL(i) (CTL_0 + (i))
-#define LM(i) (LM_0 + (i))
-#define INTF(i) (INTF_0 + (i))
+#define CRTC_DUAL_MIXERS 2
+#define PENDING_FLIP 2
+
+#define CRTC_HW_MIXER_MAXSTAGES(c, idx) ((c)->mixer[idx].sblk->maxblendstages)
+
+struct sde_crtc_mixer {
+ struct sde_hw_dspp *hw_dspp;
+ struct sde_hw_mixer *hw_lm;
+ struct sde_hw_ctl *hw_ctl;
+ u32 flush_mask;
+};
+
+struct sde_crtc {
+ struct drm_crtc base;
+ char name[8];
+ struct drm_plane *plane;
+ struct drm_plane *planes[8];
+ struct drm_encoder *encoder;
+ int id;
+ bool enabled;
+
+ spinlock_t lm_lock; /* protect registers */
+
+ /* HW Resources reserved for the crtc */
+ u32 num_ctls;
+ u32 num_mixers;
+ struct sde_crtc_mixer mixer[CRTC_DUAL_MIXERS];
+
+ /*if there is a pending flip, these will be non-null */
+ struct drm_pending_vblank_event *event;
+};
+
+#define to_sde_crtc(x) container_of(x, struct sde_crtc, base)
static struct sde_kms *get_kms(struct drm_crtc *crtc)
{
@@ -31,91 +60,89 @@ static struct sde_kms *get_kms(struct drm_crtc *crtc)
return to_sde_kms(priv->kms);
}
+static inline struct sde_hw_ctl *sde_crtc_rm_get_ctl_path(enum sde_ctl idx,
+ void __iomem *addr,
+ struct sde_mdss_cfg *m)
+{
+ /*
+ * This module keeps track of the requested hw resources state,
+ * if the requested resource is being used it returns NULL,
+ * otherwise it returns the hw driver struct
+ */
+ return sde_hw_ctl_init(idx, addr, m);
+}
+
+static inline struct sde_hw_mixer *sde_crtc_rm_get_mixer(enum sde_lm idx,
+ void __iomem *addr,
+ struct sde_mdss_cfg *m)
+{
+ /*
+ * This module keeps track of the requested hw resources state,
+ * if the requested resource is being used it returns NULL,
+ * otherwise it returns the hw driver struct
+ */
+ return sde_hw_lm_init(idx, addr, m);
+}
+
static int sde_crtc_reserve_hw_resources(struct drm_crtc *crtc,
struct drm_encoder *encoder)
{
+ /*
+ * Assign CRTC resources
+ * num_ctls;
+ * num_mixers;
+ * sde_lm mixer[CRTC_MAX_PIPES];
+ * sde_ctl ctl[CRTC_MAX_PIPES];
+ */
struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- struct sde_kms *sde_kms = get_kms(crtc);
- struct sde_encoder_hw_resources enc_hw_res;
- const struct sde_hw_res_map *plat_hw_res_map;
- enum sde_lm unused_lm_id[CRTC_DUAL_MIXERS] = {0};
- enum sde_lm lm_idx;
- int i, count = 0;
-
- if (!sde_kms) {
- DBG("[%s] invalid kms", __func__);
+ struct sde_kms *kms = get_kms(crtc);
+ enum sde_lm lm_id[CRTC_DUAL_MIXERS];
+ enum sde_ctl ctl_id[CRTC_DUAL_MIXERS];
+ int i;
+
+ if (!kms) {
+ DBG("[%s] invalid kms\n", __func__);
return -EINVAL;
}
- if (!sde_kms->mmio)
+ if (!kms->mmio)
return -EINVAL;
- /* Get unused LMs */
- for (i = 0; i < sde_kms->catalog->mixer_count; i++) {
- if (!sde_rm_get_mixer(sde_kms, LM(i))) {
- unused_lm_id[count++] = LM(i);
- if (count == CRTC_DUAL_MIXERS)
- break;
+ /*
+ * simple check validate against catalog
+ */
+ sde_crtc->num_ctls = 1;
+ sde_crtc->num_mixers = 1;
+ ctl_id[0] = CTL_0;
+ lm_id[0] = LM_0;
+
+ /*
+ * need to also enable MDP core clock and AHB CLK
+ * before touching HW driver
+ */
+ DBG("%s Enable clocks\n", __func__);
+ sde_enable(kms);
+ for (i = 0; i < sde_crtc->num_ctls; i++) {
+ sde_crtc->mixer[i].hw_ctl = sde_crtc_rm_get_ctl_path(ctl_id[i],
+ kms->mmio, kms->catalog);
+ if (!sde_crtc->mixer[i].hw_ctl) {
+ DBG("[%s], Invalid ctl_path", __func__);
+ return -EACCES;
}
}
- /* query encoder resources */
- sde_encoder_get_hw_resources(sde_crtc->encoder, &enc_hw_res);
-
- /* parse encoder hw resources, find CTL paths */
- for (i = CTL_0; i <= sde_kms->catalog->ctl_count; i++) {
- WARN_ON(sde_crtc->num_ctls > CRTC_DUAL_MIXERS);
- if (enc_hw_res.ctls[i]) {
- struct sde_crtc_mixer *mixer =
- &sde_crtc->mixer[sde_crtc->num_ctls];
- mixer->hw_ctl = sde_rm_get_ctl_path(sde_kms, i);
- if (IS_ERR_OR_NULL(mixer->hw_ctl)) {
- DBG("[%s], Invalid ctl_path", __func__);
- return -EACCES;
- }
- sde_crtc->num_ctls++;
+ for (i = 0; i < sde_crtc->num_mixers; i++) {
+ sde_crtc->mixer[i].hw_lm = sde_crtc_rm_get_mixer(lm_id[i],
+ kms->mmio, kms->catalog);
+ if (!sde_crtc->mixer[i].hw_lm) {
+ DBG("[%s], Invalid ctl_path", __func__);
+ return -EACCES;
}
}
-
- /* shortcut this process if encoder has no ctl paths */
- if (!sde_crtc->num_ctls)
- return 0;
-
/*
- * Get default LMs if specified in platform config
- * other wise acquire the free LMs
+ * need to disable MDP core clock and AHB CLK
*/
- for (i = INTF_0; i <= sde_kms->catalog->intf_count; i++) {
- if (enc_hw_res.intfs[i]) {
- struct sde_crtc_mixer *mixer =
- &sde_crtc->mixer[sde_crtc->num_mixers];
- plat_hw_res_map = sde_rm_get_res_map(sde_kms, i);
-
- lm_idx = plat_hw_res_map->lm;
- if (!lm_idx)
- lm_idx = unused_lm_id[sde_crtc->num_mixers];
-
- DBG("Acquiring LM %d", lm_idx);
- mixer->hw_lm = sde_rm_acquire_mixer(sde_kms, lm_idx);
- if (IS_ERR_OR_NULL(mixer->hw_lm)) {
- DBG("[%s], Invalid mixer", __func__);
- return -EACCES;
- }
- /* interface info */
- mixer->intf_idx = i;
- mixer->mode = enc_hw_res.intfs[i];
- sde_crtc->num_mixers++;
- }
- }
-
- DBG("control paths %d, num_mixers %d, lm[0] %d, ctl[0] %d ",
- sde_crtc->num_ctls, sde_crtc->num_mixers,
- sde_crtc->mixer[0].hw_lm->idx,
- sde_crtc->mixer[0].hw_ctl->idx);
- if (sde_crtc->num_mixers == CRTC_DUAL_MIXERS)
- DBG("lm[1] %d, ctl[1], %d",
- sde_crtc->mixer[1].hw_lm->idx,
- sde_crtc->mixer[1].hw_ctl->idx);
+ sde_disable(kms);
return 0;
}
@@ -251,7 +278,6 @@ static void blend_setup(struct drm_crtc *crtc)
unsigned long flags;
int i, j, plane_cnt = 0;
- DBG("");
spin_lock_irqsave(&sde_crtc->lm_lock, flags);
/* ctl could be reserved already */
@@ -327,104 +353,10 @@ out:
spin_unlock_irqrestore(&sde_crtc->lm_lock, flags);
}
-/* if file!=NULL, this is preclose potential cancel-flip path */
-static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
-{
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- struct drm_device *dev = crtc->dev;
- struct drm_pending_vblank_event *event;
- unsigned long flags;
-
- spin_lock_irqsave(&dev->event_lock, flags);
- event = sde_crtc->event;
- if (event) {
- /* if regular vblank case (!file) or if cancel-flip from
- * preclose on file that requested flip, then send the
- * event:
- */
- if (!file || (event->base.file_priv == file)) {
- sde_crtc->event = NULL;
- DBG("%s: send event: %pK", sde_crtc->name, event);
- drm_send_vblank_event(dev, sde_crtc->id, event);
- }
- }
- spin_unlock_irqrestore(&dev->event_lock, flags);
-}
-
-static void sde_crtc_vblank_cb(void *data)
-{
- struct drm_crtc *crtc = (struct drm_crtc *)data;
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- unsigned pending;
-
- /* unregister callback */
- sde_encoder_register_vblank_callback(sde_crtc->encoder, NULL, NULL);
-
- pending = atomic_xchg(&sde_crtc->pending, 0);
-
- if (pending & PENDING_FLIP)
- complete_flip(crtc, NULL);
-}
-
-static int frame_flushed(struct sde_crtc *sde_crtc)
-{
- struct vsync_info vsync;
-
- /* encoder get vsync_info */
- /* if frame_count does not match frame is flushed */
- sde_encoder_get_vsync_info(sde_crtc->encoder, &vsync);
-
- return (vsync.frame_count & sde_crtc->vsync_count);
-
-}
-
-void sde_crtc_wait_for_commit_done(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- u32 pending;
- int i, ret;
-
- /* ref count the vblank event */
- ret = drm_crtc_vblank_get(crtc);
- if (ret)
- return;
-
- /* register callback */
- sde_encoder_register_vblank_callback(sde_crtc->encoder,
- sde_crtc_vblank_cb,
- (void *)crtc);
-
- /* wait */
- pending = atomic_read(&sde_crtc->pending);
- if (pending & PENDING_FLIP) {
- wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue,
- (frame_flushed(sde_crtc) != 0),
- msecs_to_jiffies(CRTC_MAX_WAIT_ONE_FRAME));
- if (ret <= 0)
- dev_warn(dev->dev, "vblank time out, crtc=%d\n",
- sde_crtc->id);
- }
-
- for (i = 0; i < sde_crtc->num_ctls; i++)
- sde_crtc->mixer[i].flush_mask = 0;
-
- /* release */
- drm_crtc_vblank_put(crtc);
-}
-
static void request_pending(struct drm_crtc *crtc, u32 pending)
{
- struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
- struct vsync_info vsync;
-
- /* request vsync info, cache the current frame count */
- sde_encoder_get_vsync_info(sde_crtc->encoder, &vsync);
- sde_crtc->vsync_count = vsync.frame_count;
-
- atomic_or(pending, &sde_crtc->pending);
+ DBG("");
}
-
/**
* Flush the CTL PATH
*/
@@ -437,12 +369,14 @@ static u32 crtc_flush_all(struct drm_crtc *crtc)
DBG("");
for (i = 0; i < sde_crtc->num_ctls; i++) {
+ /*
+ * Query flush_mask from encoder
+ * and append to the ctl_path flush_mask
+ */
ctl = sde_crtc->mixer[i].hw_ctl;
ctl->ops.get_bitmask_intf(ctl,
&(sde_crtc->mixer[i].flush_mask),
- sde_crtc->mixer[i].intf_idx);
- DBG("Flushing CTL_ID %d, flush_mask %x", ctl->idx,
- sde_crtc->mixer[i].flush_mask);
+ INTF_1);
ctl->ops.setup_flush(ctl,
sde_crtc->mixer[i].flush_mask);
}
@@ -491,7 +425,7 @@ static void sde_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_device *dev = crtc->dev;
unsigned long flags;
- DBG("%s: event: %pK", sde_crtc->name, crtc->state->event);
+ DBG("");
WARN_ON(sde_crtc->event);
@@ -671,6 +605,6 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev,
return ERR_PTR(-EINVAL);
}
- DBG("%s: Successfully initialized crtc", __func__);
+ DBG("%s: Successfully initialized crtc\n", __func__);
return crtc;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
deleted file mode 100644
index 9f14f999913d..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Copyright (c) 2015-2016, 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_CRTC_H_
-#define _SDE_CRTC_H_
-
-#include "drm_crtc.h"
-
-#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
-
-#define CRTC_DUAL_MIXERS 2
-#define PENDING_FLIP 2
-/* worst case one frame wait time based on 30 FPS : 33.33ms*/
-#define CRTC_MAX_WAIT_ONE_FRAME 34
-#define CRTC_HW_MIXER_MAXSTAGES(c, idx) ((c)->mixer[idx].sblk->maxblendstages)
-
-/**
- * struct sde_crtc_mixer - stores the map for each virtual pipeline in the CRTC
- * @hw_dspp : DSPP HW Driver context
- * @hw_lm : LM HW Driver context
- * @hw_ctl : CTL Path HW driver context
- * @intf_idx : Interface idx
- * @mode : Interface mode Active/CMD
- * @flush_mask : Flush mask value for this commit
- */
-struct sde_crtc_mixer {
- struct sde_hw_dspp *hw_dspp;
- struct sde_hw_mixer *hw_lm;
- struct sde_hw_ctl *hw_ctl;
- enum sde_intf intf_idx;
- enum sde_intf_mode mode;
- u32 flush_mask;
-};
-
-/**
- * struct sde_crtc - virtualized CRTC data structure
- * @base : Base drm crtc structure
- * @name : ASCII description of this crtc
- * @encoder : Associated drm encoder object
- * @id : Unique crtc identifier
- * @lm_lock : LM register access spinlock
- * @num_ctls : Number of ctl paths in use
- * @num_mixers : Number of mixers in use
- * @mixer : List of active mixers
- * @event : Pointer to last received drm vblank event
- * @pending : Whether or not an update is pending
- * @vsync_count : Running count of received vsync events
- */
-struct sde_crtc {
- struct drm_crtc base;
- char name[8];
- struct drm_encoder *encoder;
- int id;
-
- spinlock_t lm_lock; /* protect registers */
-
- /* HW Resources reserved for the crtc */
- u32 num_ctls;
- u32 num_mixers;
- struct sde_crtc_mixer mixer[CRTC_DUAL_MIXERS];
-
- /*if there is a pending flip, these will be non-null */
- struct drm_pending_vblank_event *event;
- atomic_t pending;
- u32 vsync_count;
-};
-
-#define to_sde_crtc(x) container_of(x, struct sde_crtc, base)
-
-#endif /* _SDE_CRTC_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index ad72bca11669..2a3bc3004e6c 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -148,7 +148,7 @@ static void sde_encoder_destroy(struct drm_encoder *drm_enc)
if (sde_enc->num_phys_encs) {
DRM_ERROR("Expected num_phys_encs to be 0 not %d\n",
- sde_enc->num_phys_encs);
+ sde_enc->num_phys_encs);
}
drm_encoder_cleanup(drm_enc);
@@ -201,7 +201,6 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
{
struct sde_encoder_virt *sde_enc = NULL;
int i = 0;
- bool splitmode = false;
DBG("");
@@ -212,23 +211,11 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
sde_enc = to_sde_encoder_virt(drm_enc);
- /*
- * Panel is driven by two interfaces ,each interface drives half of
- * the horizontal
- */
- if (sde_enc->num_phys_encs == 2)
- splitmode = true;
-
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_set(phys,
- mode,
- adjusted_mode,
- splitmode);
- if (memcmp(mode, adjusted_mode, sizeof(*mode)) != 0)
- DRM_ERROR("adjusted modes not supported\n");
- }
+
+ if (phys && phys->phys_ops.mode_set)
+ phys->phys_ops.mode_set(phys, mode, adjusted_mode);
}
}
@@ -236,7 +223,6 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
{
struct sde_encoder_virt *sde_enc = NULL;
int i = 0;
- bool splitmode = false;
DBG("");
@@ -249,19 +235,10 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
bs_set(sde_enc, 1);
- if (sde_enc->num_phys_encs == 2)
- splitmode = true;
-
-
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)
-
- /* enable/disable dual interface top config */
- if (phys->phys_ops.enable_split_config)
- phys->phys_ops.enable_split_config(phys,
- splitmode);
phys->phys_ops.enable(phys);
}
}
@@ -403,11 +380,13 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc,
* h_tile_instance_ids[2] = {0, 1}; DSI0 = left, DSI1 = right
* h_tile_instance_ids[2] = {1, 0}; DSI1 = left, DSI0 = right
*/
- const struct sde_hw_res_map *hw_res_map = NULL;
enum sde_intf intf_idx = INTF_MAX;
- enum sde_ctl ctl_idx = CTL_MAX;
+ enum sde_ctl ctl_idx = CTL_0;
u32 controller_id = disp_info->h_tile_instance[i];
+ if (intf_type == INTF_HDMI)
+ ctl_idx = CTL_2;
+
DBG("h_tile_instance %d = %d", i, controller_id);
intf_idx = sde_encoder_get_intf(sde_kms->catalog,
@@ -417,12 +396,6 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc,
ret = -EINVAL;
}
- hw_res_map = sde_rm_get_res_map(sde_kms, intf_idx);
- if (IS_ERR_OR_NULL(hw_res_map))
- ret = -EINVAL;
- else
- ctl_idx = hw_res_map->ctl;
-
/* Create both VID and CMD Phys Encoders here */
if (!ret)
ret = sde_encoder_virt_add_phys_vid_enc(
@@ -488,25 +461,6 @@ void sde_encoder_register_vblank_callback(struct drm_encoder *drm_enc,
spin_unlock_irqrestore(&sde_enc->spin_lock, lock_flags);
}
-void sde_encoder_get_vsync_info(struct drm_encoder *drm_enc,
- struct vsync_info *vsync)
-{
- struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
- struct sde_encoder_phys *phys;
-
- DBG("");
-
- if (!vsync) {
- DRM_ERROR("Invalid pointer");
- return;
- }
-
- /* we get the vsync info from the intf at index 0: master index */
- phys = sde_enc->phys_encs[0];
- if (phys)
- phys->phys_ops.get_vsync_info(phys, vsync);
-}
-
/* encoders init,
* initialize encoder based on displays
*/
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
index d35e084f9bef..27fc11175c19 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
@@ -30,8 +30,7 @@ struct sde_encoder_virt_ops {
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 splitmode);
+ 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);
@@ -40,10 +39,6 @@ struct sde_encoder_phys_ops {
void (*destroy)(struct sde_encoder_phys *encoder);
void (*get_hw_resources)(struct sde_encoder_phys *encoder,
struct sde_encoder_hw_resources *hw_res);
- void (*get_vsync_info)(struct sde_encoder_phys *enc,
- struct vsync_info *vsync);
- void (*enable_split_config)(struct sde_encoder_phys *enc,
- bool enable);
};
struct sde_encoder_phys {
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index aefa11d5cdde..33d1a8eef7a5 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/*
+ * 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
@@ -8,6 +9,7 @@
* 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"
@@ -17,7 +19,6 @@
#include "sde_encoder_phys.h"
#include "sde_mdp_formats.h"
-#include "sde_hw_mdp_top.h"
#define VBLANK_TIMEOUT msecs_to_jiffies(100)
@@ -231,26 +232,14 @@ static void sde_encoder_phys_vid_flush_intf(struct sde_encoder_phys *phys_enc)
ctl->idx, flush_mask, intf->idx);
}
-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,
- bool splitmode)
+static void sde_encoder_phys_vid_mode_set(
+ struct sde_encoder_phys *phys_enc,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adj_mode)
{
- mode = adjusted_mode;
- phys_enc->cached_mode = *adjusted_mode;
- if (splitmode) {
- phys_enc->cached_mode.hdisplay >>= 1;
- phys_enc->cached_mode.htotal >>= 1;
- phys_enc->cached_mode.hsync_start >>= 1;
- phys_enc->cached_mode.hsync_end >>= 1;
- }
-
- 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);
+ phys_enc->cached_mode = *adj_mode;
+ DBG("intf %d, caching mode:", phys_enc->hw_intf->idx);
+ drm_mode_debug_printmodeline(adj_mode);
}
static void sde_encoder_phys_vid_setup_timing_engine(
@@ -439,57 +428,8 @@ static void sde_encoder_phys_vid_get_hw_resources(
struct sde_encoder_phys *phys_enc,
struct sde_encoder_hw_resources *hw_res)
{
- struct msm_drm_private *priv = phys_enc->parent->dev->dev_private;
- struct sde_kms *sde_kms = to_sde_kms(priv->kms);
- const struct sde_hw_res_map *hw_res_map;
-
- DBG("Intf %d\n", phys_enc->hw_intf->idx);
-
- hw_res->intfs[phys_enc->hw_intf->idx] = INTF_MODE_VIDEO;
- /*
- * defaults should not be in use,
- * otherwise signal/return failure
- */
- hw_res_map = sde_rm_get_res_map(sde_kms, phys_enc->hw_intf->idx);
-
- /* This is video mode panel so PINGPONG will be in by-pass mode
- * only assign ctl path.For cmd panel check if pp_split is
- * enabled, override default map
- */
- hw_res->ctls[hw_res_map->ctl] = true;
-}
-
-/**
- * video mode will use the intf (get_status)
- * cmd mode will use the pingpong (get_vsync_info)
- * to get this information
- */
-static void sde_encoder_intf_get_vsync_info(struct sde_encoder_phys *phys_enc,
- struct vsync_info *vsync)
-{
- struct intf_status status;
-
DBG("");
- phys_enc->hw_intf->ops.get_status(phys_enc->hw_intf, &status);
- vsync->frame_count = status.frame_count;
- vsync->line_count = status.line_count;
- DBG(" sde_encoder_intf_get_vsync_info, count %d", vsync->frame_count);
-}
-
-static void sde_encoder_intf_split_config(struct sde_encoder_phys *phys_enc,
- bool enable)
-{
- struct msm_drm_private *priv = phys_enc->parent->dev->dev_private;
- struct sde_kms *sde_kms = to_sde_kms(priv->kms);
- struct sde_hw_mdp *mdp = sde_hw_mdptop_init(MDP_TOP, sde_kms->mmio,
- sde_kms->catalog);
- struct split_pipe_cfg cfg;
-
- DBG("%p", mdp);
- cfg.en = true;
- cfg.mode = INTF_MODE_VIDEO;
- if (!IS_ERR_OR_NULL(mdp))
- mdp->ops.setup_split_pipe(mdp, &cfg);
+ hw_res->intfs[phys_enc->hw_intf->idx] = true;
}
static void sde_encoder_phys_vid_init_cbs(struct sde_encoder_phys_ops *ops)
@@ -500,8 +440,6 @@ static void sde_encoder_phys_vid_init_cbs(struct sde_encoder_phys_ops *ops)
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;
- ops->get_vsync_info = sde_encoder_intf_get_vsync_info;
- ops->enable_split_config = sde_encoder_intf_split_config;
}
struct sde_encoder_phys *sde_encoder_phys_vid_init(
@@ -534,7 +472,8 @@ struct sde_encoder_phys *sde_encoder_phys_vid_init(
goto fail;
}
- phys_enc->hw_ctl = sde_rm_acquire_ctl_path(sde_kms, ctl_idx);
+ 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;
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 7fba38b9e60d..251003e5382c 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -21,21 +21,18 @@ static const char * const iommu_ports[] = {
"mdp_0",
};
-static const struct sde_hw_res_map res_table[INTF_MAX] = {
- { SDE_NONE, SDE_NONE, SDE_NONE, SDE_NONE},
- { INTF_0, SDE_NONE, SDE_NONE, SDE_NONE},
- { INTF_1, LM_0, PINGPONG_0, CTL_0},
- { INTF_2, LM_1, PINGPONG_1, CTL_1},
- { INTF_3, SDE_NONE, SDE_NONE, CTL_2},
-};
-
-
#define DEFAULT_MDP_SRC_CLK 200000000
int sde_disable(struct sde_kms *sde_kms)
{
DBG("");
+ clk_disable_unprepare(sde_kms->ahb_clk);
+ clk_disable_unprepare(sde_kms->axi_clk);
+ clk_disable_unprepare(sde_kms->core_clk);
+ if (sde_kms->lut_clk)
+ clk_disable_unprepare(sde_kms->lut_clk);
+
return 0;
}
@@ -67,9 +64,8 @@ static void sde_complete_commit(struct msm_kms *kms,
}
static void sde_wait_for_crtc_commit_done(struct msm_kms *kms,
- struct drm_crtc *crtc)
+ struct drm_crtc *crtc)
{
- sde_crtc_wait_for_commit_done(crtc);
}
static int modeset_init(struct sde_kms *sde_kms)
{
@@ -459,7 +455,6 @@ struct msm_kms *sde_kms_init(struct drm_device *dev)
clk_set_rate(sde_kms->src_clk, DEFAULT_MDP_SRC_CLK);
sde_enable(sde_kms);
- sde_kms->hw_res.res_table = res_table;
/*
* Now we need to read the HW catalog and initialize resources such as
@@ -484,7 +479,9 @@ struct msm_kms *sde_kms_init(struct drm_device *dev)
dev->mode_config.max_width = catalog->mixer[0].sblk->maxwidth;
dev->mode_config.max_height = 4096;
- sde_kms->hw_intr = sde_rm_acquire_intr(sde_kms);
+ sde_enable(sde_kms);
+ sde_kms->hw_intr = sde_hw_intr_init(sde_kms->mmio, sde_kms->catalog);
+ sde_disable(sde_kms);
if (IS_ERR_OR_NULL(sde_kms->hw_intr))
goto fail;
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index 7ac1b6b827bc..e56fa16423e5 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -17,8 +17,7 @@
#include "msm_kms.h"
#include "mdp/mdp_kms.h"
#include "sde_hw_catalog.h"
-#include "sde_hw_mdp_ctl.h"
-#include "sde_hw_lm.h"
+#include "sde_hw_mdss.h"
#include "sde_hw_interrupts.h"
/*
@@ -43,38 +42,6 @@ struct sde_irq {
spinlock_t cb_lock;
};
-/**
- * struct sde_hw_res_map : Default resource table identifying default
- * hw resource map. Primarily used for forcing DSI to use CTL_0/1
- * and Pingpong 0/1, if the field is set to SDE_NONE means any HW
- * intstance for that tpye is allowed as long as it is unused.
- */
-struct sde_hw_res_map {
- enum sde_intf intf;
- enum sde_lm lm;
- enum sde_pingpong pp;
- enum sde_ctl ctl;
-};
-
-/* struct sde_hw_resource_manager : Resource mananger maintains the current
- * platform configuration and manages shared
- * hw resources ex:ctl_path hw driver context
- * is needed by CRTCs/PLANEs/ENCODERs
- * @ctl : table of control path hw driver contexts allocated
- * @mixer : list of mixer hw drivers contexts allocated
- * @intr : pointer to hw interrupt context
- * @res_table : pointer to default hw_res table for this platform
- * @feature_map :BIT map for default enabled features ex:specifies if PP_SPLIT
- * is enabled/disabled by defalt for this platform
- */
-struct sde_hw_resource_manager {
- struct sde_hw_ctl *ctl[CTL_MAX];
- struct sde_hw_mixer *mixer[LM_MAX];
- struct sde_hw_intr *intr;
- const struct sde_hw_res_map *res_table;
- bool feature_map;
-};
-
struct sde_kms {
struct msm_kms base;
struct drm_device *dev;
@@ -107,7 +74,6 @@ struct sde_kms {
struct sde_hw_intr *hw_intr;
struct sde_irq irq_obj;
- struct sde_hw_resource_manager hw_res;
};
struct vsync_info {
@@ -143,36 +109,6 @@ int sde_disable(struct sde_kms *sde_kms);
int sde_enable(struct sde_kms *sde_kms);
/**
- * HW resource manager functions
- * @sde_rm_acquire_ctl_path : Allocates control path
- * @sde_rm_get_ctl_path : returns control path driver context for already
- * acquired ctl path
- * @sde_rm_release_ctl_path : Frees control path driver context
- * @sde_rm_acquire_mixer : Allocates mixer hw driver context
- * @sde_rm_get_mixer : returns mixer context for already
- * acquired mixer
- * @sde_rm_release_mixer : Frees mixer hw driver context
- * @sde_rm_get_hw_res_map : Returns map for the passed INTF
- */
-struct sde_hw_ctl *sde_rm_acquire_ctl_path(struct sde_kms *sde_kms,
- enum sde_ctl idx);
-struct sde_hw_ctl *sde_rm_get_ctl_path(struct sde_kms *sde_kms,
- enum sde_ctl idx);
-void sde_rm_release_ctl_path(struct sde_kms *sde_kms,
- enum sde_ctl idx);
-struct sde_hw_mixer *sde_rm_acquire_mixer(struct sde_kms *sde_kms,
- enum sde_lm idx);
-struct sde_hw_mixer *sde_rm_get_mixer(struct sde_kms *sde_kms,
- enum sde_lm idx);
-void sde_rm_release_mixer(struct sde_kms *sde_kms,
- enum sde_lm idx);
-struct sde_hw_intr *sde_rm_acquire_intr(struct sde_kms *sde_kms);
-struct sde_hw_intr *sde_rm_get_intr(struct sde_kms *sde_kms);
-
-const struct sde_hw_res_map *sde_rm_get_res_map(struct sde_kms *sde_kms,
- enum sde_intf idx);
-
-/**
* IRQ functions
*/
int sde_irq_domain_init(struct sde_kms *sde_kms);
@@ -264,41 +200,31 @@ void sde_disable_all_irqs(struct sde_kms *sde_kms);
int sde_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
void sde_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
-/**
- * Plane functions
- */
enum sde_sspp sde_plane_pipe(struct drm_plane *plane);
struct drm_plane *sde_plane_init(struct drm_device *dev, uint32_t pipe,
bool private_plane);
-/**
- * CRTC functions
- */
uint32_t sde_crtc_vblank(struct drm_crtc *crtc);
-void sde_crtc_wait_for_commit_done(struct drm_crtc *crtc);
+
void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
+void sde_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane);
+void sde_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane);
struct drm_crtc *sde_crtc_init(struct drm_device *dev,
struct drm_encoder *encoder,
struct drm_plane *plane, int id);
-/**
- * Encoder functions and data types
- */
struct sde_encoder_hw_resources {
- enum sde_intf_mode intfs[INTF_MAX];
+ bool intfs[INTF_MAX];
bool pingpongs[PINGPONG_MAX];
- bool ctls[CTL_MAX];
- bool pingpongsplit;
};
-
void sde_encoder_get_hw_resources(struct drm_encoder *encoder,
struct sde_encoder_hw_resources *hw_res);
void sde_encoder_register_vblank_callback(struct drm_encoder *drm_enc,
void (*cb)(void *), void *data);
void sde_encoders_init(struct drm_device *dev);
-void sde_encoder_get_vsync_info(struct drm_encoder *encoder,
- struct vsync_info *vsync);
+int sde_irq_domain_init(struct sde_kms *sde_kms);
+int sde_irq_domain_fini(struct sde_kms *sde_kms);
#endif /* __sde_kms_H__ */
diff --git a/drivers/gpu/drm/msm/sde/sde_kms_utils.c b/drivers/gpu/drm/msm/sde/sde_kms_utils.c
deleted file mode 100644
index 9d6f28cfc06c..000000000000
--- a/drivers/gpu/drm/msm/sde/sde_kms_utils.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* Copyright (c) 2015-2016, 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 "sde_kms.h"
-#include "sde_hw_lm.h"
-#include "sde_hw_mdp_ctl.h"
-
-struct sde_hw_intr *sde_rm_acquire_intr(struct sde_kms *sde_kms)
-{
- struct sde_hw_intr *hw_intr;
-
- if (!sde_kms) {
- DRM_ERROR("Invalid KMS Driver");
- return ERR_PTR(-EINVAL);
- }
-
- if (sde_kms->hw_res.intr) {
- DRM_ERROR("intr already in use ");
- return ERR_PTR(-ENODEV);
- }
-
- sde_enable(sde_kms);
- hw_intr = sde_hw_intr_init(sde_kms->mmio,
- sde_kms->catalog);
- sde_disable(sde_kms);
-
- if (!IS_ERR_OR_NULL(hw_intr))
- sde_kms->hw_res.intr = hw_intr;
-
- return hw_intr;
-}
-
-struct sde_hw_intr *sde_rm_get_intr(struct sde_kms *sde_kms)
-{
- if (!sde_kms) {
- DRM_ERROR("Invalid KMS Driver");
- return ERR_PTR(-EINVAL);
- }
-
- return sde_kms->hw_res.intr;
-}
-
-struct sde_hw_ctl *sde_rm_acquire_ctl_path(struct sde_kms *sde_kms,
- enum sde_ctl idx)
-{
- struct sde_hw_ctl *hw_ctl;
-
- if (!sde_kms) {
- DRM_ERROR("Invalid KMS driver");
- return ERR_PTR(-EINVAL);
- }
-
- if ((idx == SDE_NONE) || (idx > sde_kms->catalog->ctl_count)) {
- DRM_ERROR("Invalid Ctl Path Idx %d", idx);
- return ERR_PTR(-EINVAL);
- }
-
- if (sde_kms->hw_res.ctl[idx]) {
- DRM_ERROR("CTL path %d already in use ", idx);
- return ERR_PTR(-ENODEV);
- }
-
- sde_enable(sde_kms);
- hw_ctl = sde_hw_ctl_init(idx, sde_kms->mmio, sde_kms->catalog);
- sde_disable(sde_kms);
-
- if (!IS_ERR_OR_NULL(hw_ctl))
- sde_kms->hw_res.ctl[idx] = hw_ctl;
-
- return hw_ctl;
-}
-
-struct sde_hw_ctl *sde_rm_get_ctl_path(struct sde_kms *sde_kms,
- enum sde_ctl idx)
-{
- if (!sde_kms) {
- DRM_ERROR("Invalid KMS Driver");
- return ERR_PTR(-EINVAL);
- }
- if ((idx == SDE_NONE) || (idx > sde_kms->catalog->ctl_count)) {
- DRM_ERROR("Invalid Ctl path Idx %d", idx);
- return ERR_PTR(-EINVAL);
- }
-
- return sde_kms->hw_res.ctl[idx];
-}
-
-void sde_rm_release_ctl_path(struct sde_kms *sde_kms, enum sde_ctl idx)
-{
- if (!sde_kms) {
- DRM_ERROR("Invalid pointer\n");
- return;
- }
- if ((idx == SDE_NONE) || (idx > sde_kms->catalog->ctl_count)) {
- DRM_ERROR("Invalid Ctl path Idx %d", idx);
- return;
- }
-}
-
-struct sde_hw_mixer *sde_rm_acquire_mixer(struct sde_kms *sde_kms,
- enum sde_lm idx)
-{
- struct sde_hw_mixer *mixer;
-
- if (!sde_kms) {
- DRM_ERROR("Invalid KMS Driver");
- return ERR_PTR(-EINVAL);
- }
-
- if ((idx == SDE_NONE) || (idx > sde_kms->catalog->mixer_count)) {
- DBG("Invalid mixer id %d", idx);
- return ERR_PTR(-EINVAL);
- }
-
- if (sde_kms->hw_res.mixer[idx]) {
- DRM_ERROR("mixer %d already in use ", idx);
- return ERR_PTR(-ENODEV);
- }
-
- sde_enable(sde_kms);
- mixer = sde_hw_lm_init(idx, sde_kms->mmio, sde_kms->catalog);
- sde_disable(sde_kms);
-
- if (!IS_ERR_OR_NULL(mixer))
- sde_kms->hw_res.mixer[idx] = mixer;
-
- return mixer;
-}
-
-struct sde_hw_mixer *sde_rm_get_mixer(struct sde_kms *sde_kms,
- enum sde_lm idx)
-{
- if (!sde_kms) {
- DRM_ERROR("Invalid KMS Driver");
- return ERR_PTR(-EINVAL);
- }
-
- if ((idx == SDE_NONE) || (idx > sde_kms->catalog->mixer_count)) {
- DRM_ERROR("Invalid mixer id %d", idx);
- return ERR_PTR(-EINVAL);
- }
-
- return sde_kms->hw_res.mixer[idx];
-}
-
-const struct sde_hw_res_map *sde_rm_get_res_map(struct sde_kms *sde_kms,
- enum sde_intf idx)
-{
- if (!sde_kms) {
- DRM_ERROR("Invalid KMS Driver");
- return ERR_PTR(-EINVAL);
- }
- if ((idx == SDE_NONE) || (idx > sde_kms->catalog->intf_count)) {
- DRM_ERROR("Invalid intf id %d", idx);
- return ERR_PTR(-EINVAL);
- }
-
- DBG(" Platform Resource map for INTF %d -> lm %d, pp %d ctl %d",
- sde_kms->hw_res.res_table[idx].intf,
- sde_kms->hw_res.res_table[idx].lm,
- sde_kms->hw_res.res_table[idx].pp,
- sde_kms->hw_res.res_table[idx].ctl);
- return &(sde_kms->hw_res.res_table[idx]);
-}