Merge branch 'msm-fixes-4.0' of git://people.freedesktop.org/~robclark/linux into drm-fixes

Fixup some fallout of the fallout of atomic dpms, few mdp5 cursor
fixes, fix a leak in error path, and some fixes for kexec

* 'msm-fixes-4.0' of git://people.freedesktop.org/~robclark/linux:
  drm/msm: kexec fixes
  drm/msm/mdp5: fix cursor blending
  drm/msm/mdp5: fix cursor ROI
  drm/msm/atomic: Don't leak atomic commit object when commit fails
  drm/msm/mdp5: Avoid flushing registers when CRTC is disabled
  drm/msm: update generated headers (add 6th lm.base entry)
  drm/msm/mdp5: fixup "drm/msm: fix fallout of atomic dpms changes"
This commit is contained in:
Dave Airlie 2015-03-05 09:36:27 +10:00
commit 4afb153477
6 changed files with 81 additions and 53 deletions

View File

@ -32,7 +32,10 @@ static void mdp4_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus)
void mdp4_irq_preinstall(struct msm_kms *kms) void mdp4_irq_preinstall(struct msm_kms *kms)
{ {
struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
mdp4_enable(mdp4_kms);
mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, 0xffffffff); mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, 0xffffffff);
mdp4_write(mdp4_kms, REG_MDP4_INTR_ENABLE, 0x00000000);
mdp4_disable(mdp4_kms);
} }
int mdp4_irq_postinstall(struct msm_kms *kms) int mdp4_irq_postinstall(struct msm_kms *kms)
@ -53,7 +56,9 @@ int mdp4_irq_postinstall(struct msm_kms *kms)
void mdp4_irq_uninstall(struct msm_kms *kms) void mdp4_irq_uninstall(struct msm_kms *kms)
{ {
struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
mdp4_enable(mdp4_kms);
mdp4_write(mdp4_kms, REG_MDP4_INTR_ENABLE, 0x00000000); mdp4_write(mdp4_kms, REG_MDP4_INTR_ENABLE, 0x00000000);
mdp4_disable(mdp4_kms);
} }
irqreturn_t mdp4_irq(struct msm_kms *kms) irqreturn_t mdp4_irq(struct msm_kms *kms)

View File

@ -8,17 +8,9 @@ http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are: The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2014-12-05 15:34:49) - /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp5.xml ( 27229 bytes, from 2015-02-10 17:00:41)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27) - /local/mnt2/workspace2/sviau/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2014-06-02 18:31:15)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00) - /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2015-01-23 16:20:19)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
Copyright (C) 2013-2015 by the following authors: Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark) - Rob Clark <robdclark@gmail.com> (robclark)
@ -910,6 +902,7 @@ static inline uint32_t __offset_LM(uint32_t idx)
case 2: return (mdp5_cfg->lm.base[2]); case 2: return (mdp5_cfg->lm.base[2]);
case 3: return (mdp5_cfg->lm.base[3]); case 3: return (mdp5_cfg->lm.base[3]);
case 4: return (mdp5_cfg->lm.base[4]); case 4: return (mdp5_cfg->lm.base[4]);
case 5: return (mdp5_cfg->lm.base[5]);
default: return INVALID_IDX(idx); default: return INVALID_IDX(idx);
} }
} }

View File

@ -62,8 +62,8 @@ struct mdp5_crtc {
/* current cursor being scanned out: */ /* current cursor being scanned out: */
struct drm_gem_object *scanout_bo; struct drm_gem_object *scanout_bo;
uint32_t width; uint32_t width, height;
uint32_t height; uint32_t x, y;
} cursor; } cursor;
}; };
#define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base) #define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base)
@ -103,8 +103,8 @@ static void crtc_flush_all(struct drm_crtc *crtc)
struct drm_plane *plane; struct drm_plane *plane;
uint32_t flush_mask = 0; uint32_t flush_mask = 0;
/* we could have already released CTL in the disable path: */ /* this should not happen: */
if (!mdp5_crtc->ctl) if (WARN_ON(!mdp5_crtc->ctl))
return; return;
drm_atomic_crtc_for_each_plane(plane, crtc) { drm_atomic_crtc_for_each_plane(plane, crtc) {
@ -143,6 +143,11 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
drm_atomic_crtc_for_each_plane(plane, crtc) { drm_atomic_crtc_for_each_plane(plane, crtc) {
mdp5_plane_complete_flip(plane); mdp5_plane_complete_flip(plane);
} }
if (mdp5_crtc->ctl && !crtc->state->enable) {
mdp5_ctl_release(mdp5_crtc->ctl);
mdp5_crtc->ctl = NULL;
}
} }
static void unref_cursor_worker(struct drm_flip_work *work, void *val) static void unref_cursor_worker(struct drm_flip_work *work, void *val)
@ -386,14 +391,17 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc)
mdp5_crtc->event = crtc->state->event; mdp5_crtc->event = crtc->state->event;
spin_unlock_irqrestore(&dev->event_lock, flags); spin_unlock_irqrestore(&dev->event_lock, flags);
/*
* If no CTL has been allocated in mdp5_crtc_atomic_check(),
* it means we are trying to flush a CRTC whose state is disabled:
* nothing else needs to be done.
*/
if (unlikely(!mdp5_crtc->ctl))
return;
blend_setup(crtc); blend_setup(crtc);
crtc_flush_all(crtc); crtc_flush_all(crtc);
request_pending(crtc, PENDING_FLIP); request_pending(crtc, PENDING_FLIP);
if (mdp5_crtc->ctl && !crtc->state->enable) {
mdp5_ctl_release(mdp5_crtc->ctl);
mdp5_crtc->ctl = NULL;
}
} }
static int mdp5_crtc_set_property(struct drm_crtc *crtc, static int mdp5_crtc_set_property(struct drm_crtc *crtc,
@ -403,6 +411,32 @@ static int mdp5_crtc_set_property(struct drm_crtc *crtc,
return -EINVAL; return -EINVAL;
} }
static void get_roi(struct drm_crtc *crtc, uint32_t *roi_w, uint32_t *roi_h)
{
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
uint32_t xres = crtc->mode.hdisplay;
uint32_t yres = crtc->mode.vdisplay;
/*
* Cursor Region Of Interest (ROI) is a plane read from cursor
* buffer to render. The ROI region is determined by the visibility of
* the cursor point. In the default Cursor image the cursor point will
* be at the top left of the cursor image, unless it is specified
* otherwise using hotspot feature.
*
* If the cursor point reaches the right (xres - x < cursor.width) or
* bottom (yres - y < cursor.height) boundary of the screen, then ROI
* width and ROI height need to be evaluated to crop the cursor image
* accordingly.
* (xres-x) will be new cursor width when x > (xres - cursor.width)
* (yres-y) will be new cursor height when y > (yres - cursor.height)
*/
*roi_w = min(mdp5_crtc->cursor.width, xres -
mdp5_crtc->cursor.x);
*roi_h = min(mdp5_crtc->cursor.height, yres -
mdp5_crtc->cursor.y);
}
static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
struct drm_file *file, uint32_t handle, struct drm_file *file, uint32_t handle,
uint32_t width, uint32_t height) uint32_t width, uint32_t height)
@ -416,6 +450,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
unsigned int depth; unsigned int depth;
enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL; enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL;
uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0); uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
uint32_t roi_w, roi_h;
unsigned long flags; unsigned long flags;
if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) { if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
@ -446,6 +481,12 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags); spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
old_bo = mdp5_crtc->cursor.scanout_bo; old_bo = mdp5_crtc->cursor.scanout_bo;
mdp5_crtc->cursor.scanout_bo = cursor_bo;
mdp5_crtc->cursor.width = width;
mdp5_crtc->cursor.height = height;
get_roi(crtc, &roi_w, &roi_h);
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride); mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride);
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm), mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm),
MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888)); MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888));
@ -453,19 +494,14 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
MDP5_LM_CURSOR_IMG_SIZE_SRC_H(height) | MDP5_LM_CURSOR_IMG_SIZE_SRC_H(height) |
MDP5_LM_CURSOR_IMG_SIZE_SRC_W(width)); MDP5_LM_CURSOR_IMG_SIZE_SRC_W(width));
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm), mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm),
MDP5_LM_CURSOR_SIZE_ROI_H(height) | MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) |
MDP5_LM_CURSOR_SIZE_ROI_W(width)); MDP5_LM_CURSOR_SIZE_ROI_W(roi_w));
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm), cursor_addr); mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm), cursor_addr);
blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN; blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN;
blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_TRANSP_EN;
blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha); blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha);
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg); mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg);
mdp5_crtc->cursor.scanout_bo = cursor_bo;
mdp5_crtc->cursor.width = width;
mdp5_crtc->cursor.height = height;
spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags); spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
ret = mdp5_ctl_set_cursor(mdp5_crtc->ctl, true); ret = mdp5_ctl_set_cursor(mdp5_crtc->ctl, true);
@ -489,31 +525,18 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
struct mdp5_kms *mdp5_kms = get_kms(crtc); struct mdp5_kms *mdp5_kms = get_kms(crtc);
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0); uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
uint32_t xres = crtc->mode.hdisplay;
uint32_t yres = crtc->mode.vdisplay;
uint32_t roi_w; uint32_t roi_w;
uint32_t roi_h; uint32_t roi_h;
unsigned long flags; unsigned long flags;
x = (x > 0) ? x : 0; /* In case the CRTC is disabled, just drop the cursor update */
y = (y > 0) ? y : 0; if (unlikely(!crtc->state->enable))
return 0;
/* mdp5_crtc->cursor.x = x = max(x, 0);
* Cursor Region Of Interest (ROI) is a plane read from cursor mdp5_crtc->cursor.y = y = max(y, 0);
* buffer to render. The ROI region is determined by the visiblity of
* the cursor point. In the default Cursor image the cursor point will get_roi(crtc, &roi_w, &roi_h);
* be at the top left of the cursor image, unless it is specified
* otherwise using hotspot feature.
*
* If the cursor point reaches the right (xres - x < cursor.width) or
* bottom (yres - y < cursor.height) boundary of the screen, then ROI
* width and ROI height need to be evaluated to crop the cursor image
* accordingly.
* (xres-x) will be new cursor width when x > (xres - cursor.width)
* (yres-y) will be new cursor height when y > (yres - cursor.height)
*/
roi_w = min(mdp5_crtc->cursor.width, xres - x);
roi_h = min(mdp5_crtc->cursor.height, yres - y);
spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags); spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(mdp5_crtc->lm), mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(mdp5_crtc->lm),
@ -544,8 +567,8 @@ static const struct drm_crtc_funcs mdp5_crtc_funcs = {
static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = { static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = {
.mode_fixup = mdp5_crtc_mode_fixup, .mode_fixup = mdp5_crtc_mode_fixup,
.mode_set_nofb = mdp5_crtc_mode_set_nofb, .mode_set_nofb = mdp5_crtc_mode_set_nofb,
.prepare = mdp5_crtc_disable, .disable = mdp5_crtc_disable,
.commit = mdp5_crtc_enable, .enable = mdp5_crtc_enable,
.atomic_check = mdp5_crtc_atomic_check, .atomic_check = mdp5_crtc_atomic_check,
.atomic_begin = mdp5_crtc_atomic_begin, .atomic_begin = mdp5_crtc_atomic_begin,
.atomic_flush = mdp5_crtc_atomic_flush, .atomic_flush = mdp5_crtc_atomic_flush,

View File

@ -267,14 +267,14 @@ static void mdp5_encoder_enable(struct drm_encoder *encoder)
mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 1); mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 1);
spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
mdp5_encoder->enabled = false; mdp5_encoder->enabled = true;
} }
static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = { static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = {
.mode_fixup = mdp5_encoder_mode_fixup, .mode_fixup = mdp5_encoder_mode_fixup,
.mode_set = mdp5_encoder_mode_set, .mode_set = mdp5_encoder_mode_set,
.prepare = mdp5_encoder_disable, .disable = mdp5_encoder_disable,
.commit = mdp5_encoder_enable, .enable = mdp5_encoder_enable,
}; };
/* initialize encoder */ /* initialize encoder */

View File

@ -34,7 +34,10 @@ static void mdp5_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus)
void mdp5_irq_preinstall(struct msm_kms *kms) void mdp5_irq_preinstall(struct msm_kms *kms)
{ {
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
mdp5_enable(mdp5_kms);
mdp5_write(mdp5_kms, REG_MDP5_INTR_CLEAR, 0xffffffff); mdp5_write(mdp5_kms, REG_MDP5_INTR_CLEAR, 0xffffffff);
mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000);
mdp5_disable(mdp5_kms);
} }
int mdp5_irq_postinstall(struct msm_kms *kms) int mdp5_irq_postinstall(struct msm_kms *kms)
@ -57,7 +60,9 @@ int mdp5_irq_postinstall(struct msm_kms *kms)
void mdp5_irq_uninstall(struct msm_kms *kms) void mdp5_irq_uninstall(struct msm_kms *kms)
{ {
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
mdp5_enable(mdp5_kms);
mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000); mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000);
mdp5_disable(mdp5_kms);
} }
static void mdp5_irq_mdp(struct mdp_kms *mdp_kms) static void mdp5_irq_mdp(struct mdp_kms *mdp_kms)

View File

@ -219,8 +219,10 @@ int msm_atomic_commit(struct drm_device *dev,
* mark our set of crtc's as busy: * mark our set of crtc's as busy:
*/ */
ret = start_atomic(dev->dev_private, c->crtc_mask); ret = start_atomic(dev->dev_private, c->crtc_mask);
if (ret) if (ret) {
kfree(c);
return ret; return ret;
}
/* /*
* This is the point of no return - everything below never fails except * This is the point of no return - everything below never fails except