diff options
Diffstat (limited to 'drivers/gpu/drm/arm')
-rw-r--r-- | drivers/gpu/drm/arm/hdlcd_crtc.c | 46 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/hdlcd_drv.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_crtc.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_hw.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_planes.c | 12 |
5 files changed, 62 insertions, 35 deletions
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 798a3cc480a2..d67b6f15e8b8 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -10,6 +10,7 @@ */ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> @@ -226,16 +227,33 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = { static int hdlcd_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { - u32 src_w, src_h; + struct drm_rect clip = { 0 }; + struct drm_crtc_state *crtc_state; + u32 src_h = state->src_h >> 16; - src_w = state->src_w >> 16; - src_h = state->src_h >> 16; + /* only the HDLCD_REG_FB_LINE_COUNT register has a limit */ + if (src_h >= HDLCD_MAX_YRES) { + DRM_DEBUG_KMS("Invalid source width: %d\n", src_h); + return -EINVAL; + } + + if (!state->fb || !state->crtc) + return 0; - /* we can't do any scaling of the plane source */ - if ((src_w != state->crtc_w) || (src_h != state->crtc_h)) + crtc_state = drm_atomic_get_existing_crtc_state(state->state, + state->crtc); + if (!crtc_state) { + DRM_DEBUG_KMS("Invalid crtc state\n"); return -EINVAL; + } - return 0; + clip.x2 = crtc_state->adjusted_mode.hdisplay; + clip.y2 = crtc_state->adjusted_mode.vdisplay; + + return drm_plane_helper_check_state(state, &clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true); } static void hdlcd_plane_atomic_update(struct drm_plane *plane, @@ -243,22 +261,14 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane, { struct drm_framebuffer *fb = plane->state->fb; struct hdlcd_drm_private *hdlcd; - struct drm_gem_cma_object *gem; - u32 src_w, src_h, dest_w, dest_h; + u32 dest_h; dma_addr_t scanout_start; if (!fb) return; - src_w = plane->state->src_w >> 16; - src_h = plane->state->src_h >> 16; - dest_w = plane->state->crtc_w; - dest_h = plane->state->crtc_h; - gem = drm_fb_cma_get_gem_obj(fb, 0); - scanout_start = gem->paddr + fb->offsets[0] + - plane->state->crtc_y * fb->pitches[0] + - plane->state->crtc_x * - fb->format->cpp[0]; + dest_h = drm_rect_height(&plane->state->dst); + scanout_start = drm_fb_cma_get_gem_addr(fb, plane->state, 0); hdlcd = plane->dev->dev_private; hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]); @@ -305,7 +315,6 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm) formats, ARRAY_SIZE(formats), DRM_PLANE_TYPE_PRIMARY, NULL); if (ret) { - devm_kfree(drm->dev, plane); return ERR_PTR(ret); } @@ -329,7 +338,6 @@ int hdlcd_setup_crtc(struct drm_device *drm) &hdlcd_crtc_funcs, NULL); if (ret) { hdlcd_plane_destroy(primary); - devm_kfree(drm->dev, primary); return ret; } diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index 345c8357b273..d3da87fbd85a 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -297,6 +297,9 @@ static int hdlcd_drm_bind(struct device *dev) if (ret) goto err_free; + /* Set the CRTC's port so that the encoder component can find it */ + hdlcd->crtc.port = of_graph_get_port_by_id(dev->of_node, 0); + ret = component_bind_all(dev, drm); if (ret) { DRM_ERROR("Failed to bind all components\n"); @@ -340,11 +343,14 @@ err_register: } err_fbdev: drm_kms_helper_poll_fini(drm); + drm_vblank_cleanup(drm); err_vblank: pm_runtime_disable(drm->dev); err_pm_active: component_unbind_all(dev, drm); err_unload: + of_node_put(hdlcd->crtc.port); + hdlcd->crtc.port = NULL; drm_irq_uninstall(drm); of_reserved_mem_device_release(drm->dev); err_free: @@ -367,6 +373,9 @@ static void hdlcd_drm_unbind(struct device *dev) } drm_kms_helper_poll_fini(drm); component_unbind_all(dev, drm); + of_node_put(hdlcd->crtc.port); + hdlcd->crtc.port = NULL; + drm_vblank_cleanup(drm); pm_runtime_get_sync(drm->dev); drm_irq_uninstall(drm); pm_runtime_put_sync(drm->dev); diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index 9446a673d469..4bb38a21efec 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -22,9 +22,8 @@ #include "malidp_drv.h" #include "malidp_hw.h" -static bool malidp_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +static enum drm_mode_status malidp_crtc_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { struct malidp_drm *malidp = crtc_to_malidp_device(crtc); struct malidp_hw_device *hwdev = malidp->dev; @@ -40,11 +39,11 @@ static bool malidp_crtc_mode_fixup(struct drm_crtc *crtc, if (rate != req_rate) { DRM_DEBUG_DRIVER("pxlclk doesn't support %ld Hz\n", req_rate); - return false; + return MODE_NOCLOCK; } } - return true; + return MODE_OK; } static void malidp_crtc_enable(struct drm_crtc *crtc) @@ -408,7 +407,7 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs malidp_crtc_helper_funcs = { - .mode_fixup = malidp_crtc_mode_fixup, + .mode_valid = malidp_crtc_mode_valid, .enable = malidp_crtc_enable, .disable = malidp_crtc_disable, .atomic_check = malidp_crtc_atomic_check, diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index 28360b8542f7..17bca99e8ac8 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -766,12 +766,17 @@ static irqreturn_t malidp_de_irq(int irq, void *arg) u32 status, mask, dc_status; irqreturn_t ret = IRQ_NONE; - if (!drm->dev_private) - return IRQ_HANDLED; - hwdev = malidp->dev; de = &hwdev->map.de_irq_map; + /* + * if we are suspended it is likely that we were invoked because + * we share an interrupt line with some other driver, don't try + * to read the hardware registers + */ + if (hwdev->pm_suspended) + return IRQ_NONE; + /* first handle the config valid IRQ */ dc_status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS); if (dc_status & hwdev->map.dc_irq_map.vsync_irq) { @@ -854,6 +859,14 @@ static irqreturn_t malidp_se_irq(int irq, void *arg) struct malidp_hw_device *hwdev = malidp->dev; u32 status, mask; + /* + * if we are suspended it is likely that we were invoked because + * we share an interrupt line with some other driver, don't try + * to read the hardware registers + */ + if (hwdev->pm_suspended) + return IRQ_NONE; + status = malidp_hw_read(hwdev, hwdev->map.se_base + MALIDP_REG_STATUS); if (!(status & hwdev->map.se_irq_map.irq_mask)) return IRQ_NONE; diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 063a8d2b0be3..600fa7bd7f52 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -264,11 +264,9 @@ static void malidp_de_set_plane_pitches(struct malidp_plane *mp, static void malidp_de_plane_update(struct drm_plane *plane, struct drm_plane_state *old_state) { - struct drm_gem_cma_object *obj; struct malidp_plane *mp; const struct malidp_hw_regmap *map; struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); - u16 ptr; u32 src_w, src_h, dest_w, dest_h, val; int i; @@ -285,12 +283,12 @@ static void malidp_de_plane_update(struct drm_plane *plane, for (i = 0; i < ms->n_planes; i++) { /* calculate the offset for the layer's plane registers */ - ptr = mp->layer->ptr + (i << 4); + u16 ptr = mp->layer->ptr + (i << 4); + dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(plane->state->fb, + plane->state, i); - obj = drm_fb_cma_get_gem_obj(plane->state->fb, i); - obj->paddr += plane->state->fb->offsets[i]; - malidp_hw_write(mp->hwdev, lower_32_bits(obj->paddr), ptr); - malidp_hw_write(mp->hwdev, upper_32_bits(obj->paddr), ptr + 4); + malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr); + malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4); } malidp_de_set_plane_pitches(mp, ms->n_planes, plane->state->fb->pitches); |