diff options
Diffstat (limited to 'drivers/gpu/drm/arm')
-rw-r--r-- | drivers/gpu/drm/arm/hdlcd_crtc.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/hdlcd_drv.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_drv.c | 43 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_hw.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_hw.h | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_planes.c | 99 |
7 files changed, 122 insertions, 73 deletions
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 28341b32067f..7d4e5aa77195 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -222,14 +222,12 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane, { struct hdlcd_drm_private *hdlcd; struct drm_gem_cma_object *gem; - unsigned int depth, bpp; u32 src_w, src_h, dest_w, dest_h; dma_addr_t scanout_start; if (!plane->state->fb) return; - drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp); src_w = plane->state->src_w >> 16; src_h = plane->state->src_h >> 16; dest_w = plane->state->crtc_w; @@ -237,7 +235,8 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane, gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0); scanout_start = gem->paddr + plane->state->fb->offsets[0] + plane->state->crtc_y * plane->state->fb->pitches[0] + - plane->state->crtc_x * bpp / 8; + plane->state->crtc_x * + drm_format_plane_cpp(plane->state->fb->pixel_format, 0); hdlcd = plane->dev->dev_private; hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]); diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index e138fb51e8ce..e5f4f4a6546d 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -268,9 +268,7 @@ static const struct file_operations fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = noop_llseek, @@ -337,14 +335,10 @@ static int hdlcd_drm_bind(struct device *dev) if (ret) goto err_free; - ret = drm_dev_register(drm, 0); - if (ret) - goto err_unload; - ret = component_bind_all(dev, drm); if (ret) { DRM_ERROR("Failed to bind all components\n"); - goto err_unregister; + goto err_unload; } ret = pm_runtime_set_active(dev); @@ -371,8 +365,17 @@ static int hdlcd_drm_bind(struct device *dev) goto err_fbdev; } + ret = drm_dev_register(drm, 0); + if (ret) + goto err_register; + return 0; +err_register: + if (hdlcd->fbdev) { + drm_fbdev_cma_fini(hdlcd->fbdev); + hdlcd->fbdev = NULL; + } err_fbdev: drm_kms_helper_poll_fini(drm); drm_vblank_cleanup(drm); @@ -380,8 +383,6 @@ err_vblank: pm_runtime_disable(drm->dev); err_pm_active: component_unbind_all(dev, drm); -err_unregister: - drm_dev_unregister(drm); err_unload: drm_irq_uninstall(drm); of_reserved_mem_device_release(drm->dev); @@ -398,6 +399,7 @@ static void hdlcd_drm_unbind(struct device *dev) struct drm_device *drm = dev_get_drvdata(dev); struct hdlcd_drm_private *hdlcd = drm->dev_private; + drm_dev_unregister(drm); if (hdlcd->fbdev) { drm_fbdev_cma_fini(hdlcd->fbdev); hdlcd->fbdev = NULL; @@ -411,7 +413,6 @@ static void hdlcd_drm_unbind(struct device *dev) pm_runtime_disable(drm->dev); of_reserved_mem_device_release(drm->dev); drm_mode_config_cleanup(drm); - drm_dev_unregister(drm); drm_dev_unref(drm); drm->dev_private = NULL; dev_set_drvdata(dev, NULL); @@ -453,7 +454,8 @@ static int hdlcd_probe(struct platform_device *pdev) return -EAGAIN; } - component_match_add(&pdev->dev, &match, compare_dev, port); + drm_of_component_match_add(&pdev->dev, &match, compare_dev, port); + of_node_put(port); return component_master_add_with_match(&pdev->dev, &hdlcd_master_ops, match); diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 9280358b8f15..32f746e31379 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -42,6 +42,7 @@ static int malidp_set_and_wait_config_valid(struct drm_device *drm) struct malidp_hw_device *hwdev = malidp->dev; int ret; + atomic_set(&malidp->config_valid, 0); hwdev->set_config_valid(hwdev); /* don't wait for config_valid flag if we are in config mode */ if (hwdev->in_config_mode(hwdev)) @@ -91,8 +92,7 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_helper_commit_modeset_disables(drm, state); drm_atomic_helper_commit_modeset_enables(drm, state); - drm_atomic_helper_commit_planes(drm, state, - DRM_PLANE_COMMIT_ACTIVE_ONLY); + drm_atomic_helper_commit_planes(drm, state, 0); malidp_atomic_commit_hw_done(state); @@ -155,6 +155,12 @@ static int malidp_init(struct drm_device *drm) return 0; } +static void malidp_fini(struct drm_device *drm) +{ + malidp_de_planes_destroy(drm); + drm_mode_config_cleanup(drm); +} + static int malidp_irq_init(struct platform_device *pdev) { int irq_de, irq_se, ret = 0; @@ -197,9 +203,7 @@ static const struct file_operations fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, -#endif .poll = drm_poll, .read = drm_read, .llseek = noop_llseek, @@ -355,10 +359,6 @@ static int malidp_bind(struct device *dev) if (ret < 0) goto init_fail; - ret = drm_dev_register(drm, 0); - if (ret) - goto register_fail; - /* Set the CRTC's port so that the encoder component can find it */ ep = of_graph_get_next_endpoint(dev->of_node, NULL); if (!ep) { @@ -377,6 +377,8 @@ static int malidp_bind(struct device *dev) if (ret < 0) goto irq_init_fail; + drm->irq_enabled = true; + ret = drm_vblank_init(drm, drm->mode_config.num_crtc); if (ret < 0) { DRM_ERROR("failed to initialise vblank\n"); @@ -395,23 +397,31 @@ static int malidp_bind(struct device *dev) } drm_kms_helper_poll_init(drm); + + ret = drm_dev_register(drm, 0); + if (ret) + goto register_fail; + return 0; +register_fail: + if (malidp->fbdev) { + drm_fbdev_cma_fini(malidp->fbdev); + malidp->fbdev = NULL; + } fbdev_fail: drm_vblank_cleanup(drm); vblank_fail: malidp_se_irq_fini(drm); malidp_de_irq_fini(drm); + drm->irq_enabled = false; irq_init_fail: component_unbind_all(dev, drm); bind_fail: of_node_put(malidp->crtc.port); malidp->crtc.port = NULL; port_fail: - drm_dev_unregister(drm); -register_fail: - malidp_de_planes_destroy(drm); - drm_mode_config_cleanup(drm); + malidp_fini(drm); init_fail: drm->dev_private = NULL; dev_set_drvdata(dev, NULL); @@ -432,6 +442,7 @@ static void malidp_unbind(struct device *dev) struct malidp_drm *malidp = drm->dev_private; struct malidp_hw_device *hwdev = malidp->dev; + drm_dev_unregister(drm); if (malidp->fbdev) { drm_fbdev_cma_fini(malidp->fbdev); malidp->fbdev = NULL; @@ -443,9 +454,7 @@ static void malidp_unbind(struct device *dev) component_unbind_all(dev, drm); of_node_put(malidp->crtc.port); malidp->crtc.port = NULL; - drm_dev_unregister(drm); - malidp_de_planes_destroy(drm); - drm_mode_config_cleanup(drm); + malidp_fini(drm); drm->dev_private = NULL; dev_set_drvdata(dev, NULL); clk_disable_unprepare(hwdev->mclk); @@ -493,7 +502,9 @@ static int malidp_platform_probe(struct platform_device *pdev) return -EAGAIN; } - component_match_add(&pdev->dev, &match, malidp_compare_dev, port); + drm_of_component_match_add(&pdev->dev, &match, malidp_compare_dev, + port); + of_node_put(port); return component_master_add_with_match(&pdev->dev, &malidp_master_ops, match); } diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h index 271d2fb9711c..9fc8a2e405e4 100644 --- a/drivers/gpu/drm/arm/malidp_drv.h +++ b/drivers/gpu/drm/arm/malidp_drv.h @@ -39,6 +39,9 @@ struct malidp_plane_state { /* size of the required rotation memory if plane is rotated */ u32 rotmem_size; + /* internal format ID */ + u8 format; + u8 n_planes; }; #define to_malidp_plane(x) container_of(x, struct malidp_plane, base) diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index a6132f1d58c1..4bdf531f7844 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -125,6 +125,7 @@ static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev) { u32 status, count = 100; + malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID); malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL); while (count) { status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS); @@ -198,9 +199,6 @@ static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode * static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt) { - unsigned int depth; - int bpp; - /* RGB888 or BGR888 can't be rotated */ if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888)) return -EINVAL; @@ -210,9 +208,7 @@ static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 * worth of pixel data. Required size is then: * size = rotated_width * (bpp / 8) * 8; */ - drm_fb_get_bpp_depth(fmt, &depth, &bpp); - - return w * bpp; + return w * drm_format_plane_cpp(fmt, 0) * 8; } static int malidp550_query_hw(struct malidp_hw_device *hwdev) @@ -271,6 +267,7 @@ static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev) { u32 status, count = 100; + malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID); malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL); while (count) { status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS); @@ -441,6 +438,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { }, .input_formats = malidp500_de_formats, .n_input_formats = ARRAY_SIZE(malidp500_de_formats), + .bus_align_bytes = 8, }, .query_hw = malidp500_query_hw, .enter_config_mode = malidp500_enter_config_mode, @@ -473,6 +471,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { }, .input_formats = malidp550_de_formats, .n_input_formats = ARRAY_SIZE(malidp550_de_formats), + .bus_align_bytes = 8, }, .query_hw = malidp550_query_hw, .enter_config_mode = malidp550_enter_config_mode, @@ -506,6 +505,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { }, .input_formats = malidp550_de_formats, .n_input_formats = ARRAY_SIZE(malidp550_de_formats), + .bus_align_bytes = 16, }, .query_hw = malidp650_query_hw, .enter_config_mode = malidp550_enter_config_mode, diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h index 141743e9f3a6..087e1202db3d 100644 --- a/drivers/gpu/drm/arm/malidp_hw.h +++ b/drivers/gpu/drm/arm/malidp_hw.h @@ -88,6 +88,9 @@ struct malidp_hw_regmap { /* list of supported input formats for each layer */ const struct malidp_input_format *input_formats; const u8 n_input_formats; + + /* pitch alignment requirement in bytes */ + const u8 bus_align_bytes; }; struct malidp_hw_device { @@ -229,6 +232,12 @@ void malidp_se_irq_fini(struct drm_device *drm); u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map, u8 layer_id, u32 format); +static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev, + unsigned int pitch) +{ + return !(pitch & (hwdev->map.bus_align_bytes - 1)); +} + /* * background color components are defined as 12bits values, * they will be shifted right when stored on hardware that diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 82c193e5e0d6..63eec8f37cfc 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -27,6 +27,10 @@ #define LAYER_H_FLIP (1 << 10) #define LAYER_V_FLIP (1 << 11) #define LAYER_ROT_MASK (0xf << 8) +#define LAYER_COMP_MASK (0x3 << 12) +#define LAYER_COMP_PIXEL (0x3 << 12) +#define LAYER_COMP_PLANE (0x2 << 12) +#define MALIDP_LAYER_COMPOSE 0x008 #define MALIDP_LAYER_SIZE 0x00c #define LAYER_H_VAL(x) (((x) & 0x1fff) << 0) #define LAYER_V_VAL(x) (((x) & 0x1fff) << 16) @@ -34,6 +38,14 @@ #define MALIDP_LAYER_OFFSET 0x014 #define MALIDP_LAYER_STRIDE 0x018 +/* + * This 4-entry look-up-table is used to determine the full 8-bit alpha value + * for formats with 1- or 2-bit alpha channels. + * We set it to give 100%/0% opacity for 1-bit formats and 100%/66%/33%/0% + * opacity for 2-bit formats. + */ +#define MALIDP_ALPHA_LUT 0xffaa5500 + static void malidp_de_plane_destroy(struct drm_plane *plane) { struct malidp_plane *mp = to_malidp_plane(plane); @@ -46,7 +58,8 @@ static void malidp_de_plane_destroy(struct drm_plane *plane) devm_kfree(plane->dev->dev, mp); } -struct drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) +static struct +drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) { struct malidp_plane_state *state, *m_state; @@ -58,13 +71,15 @@ struct drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) m_state = to_malidp_plane_state(plane->state); __drm_atomic_helper_plane_duplicate_state(plane, &state->base); state->rotmem_size = m_state->rotmem_size; + state->format = m_state->format; + state->n_planes = m_state->n_planes; } return &state->base; } -void malidp_destroy_plane_state(struct drm_plane *plane, - struct drm_plane_state *state) +static void malidp_destroy_plane_state(struct drm_plane *plane, + struct drm_plane_state *state) { struct malidp_plane_state *m_state = to_malidp_plane_state(state); @@ -75,6 +90,7 @@ void malidp_destroy_plane_state(struct drm_plane *plane, static const struct drm_plane_funcs malidp_de_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, + .set_property = drm_atomic_helper_plane_set_property, .destroy = malidp_de_plane_destroy, .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = malidp_duplicate_plane_state, @@ -86,17 +102,29 @@ static int malidp_de_plane_check(struct drm_plane *plane, { struct malidp_plane *mp = to_malidp_plane(plane); struct malidp_plane_state *ms = to_malidp_plane_state(state); - u8 format_id; + struct drm_framebuffer *fb; + int i; u32 src_w, src_h; if (!state->crtc || !state->fb) return 0; - format_id = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id, - state->fb->pixel_format); - if (format_id == MALIDP_INVALID_FORMAT_ID) + fb = state->fb; + + ms->format = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id, + fb->pixel_format); + if (ms->format == MALIDP_INVALID_FORMAT_ID) return -EINVAL; + ms->n_planes = drm_format_num_planes(fb->pixel_format); + for (i = 0; i < ms->n_planes; i++) { + if (!malidp_hw_pitch_valid(mp->hwdev, fb->pitches[i])) { + DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n", + fb->pitches[i], i); + return -EINVAL; + } + } + src_w = state->src_w >> 16; src_h = state->src_h >> 16; @@ -135,17 +163,13 @@ static void malidp_de_plane_update(struct drm_plane *plane, struct drm_gem_cma_object *obj; struct malidp_plane *mp; const struct malidp_hw_regmap *map; - u8 format_id; + struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); u16 ptr; - u32 format, src_w, src_h, dest_w, dest_h, val = 0; - int num_planes, i; + u32 src_w, src_h, dest_w, dest_h, val; + int i; mp = to_malidp_plane(plane); - map = &mp->hwdev->map; - format = plane->state->fb->pixel_format; - format_id = malidp_hw_get_format_id(map, mp->layer->id, format); - num_planes = drm_format_num_planes(format); /* convert src values from Q16 fixed point to integer */ src_w = plane->state->src_w >> 16; @@ -158,9 +182,9 @@ static void malidp_de_plane_update(struct drm_plane *plane, dest_h = plane->state->crtc_h; } - malidp_hw_write(mp->hwdev, format_id, mp->layer->base); + malidp_hw_write(mp->hwdev, ms->format, mp->layer->base); - for (i = 0; i < num_planes; i++) { + for (i = 0; i < ms->n_planes; i++) { /* calculate the offset for the layer's plane registers */ ptr = mp->layer->ptr + (i << 4); @@ -181,9 +205,9 @@ static void malidp_de_plane_update(struct drm_plane *plane, LAYER_V_VAL(plane->state->crtc_y), mp->layer->base + MALIDP_LAYER_OFFSET); - /* first clear the rotation bits in the register */ - malidp_hw_clearbits(mp->hwdev, LAYER_ROT_MASK, - mp->layer->base + MALIDP_LAYER_CONTROL); + /* first clear the rotation bits */ + val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL); + val &= ~LAYER_ROT_MASK; /* setup the rotation and axis flip bits */ if (plane->state->rotation & DRM_ROTATE_MASK) @@ -193,11 +217,18 @@ static void malidp_de_plane_update(struct drm_plane *plane, if (plane->state->rotation & DRM_REFLECT_Y) val |= LAYER_H_FLIP; + /* + * always enable pixel alpha blending until we have a way to change + * blend modes + */ + val &= ~LAYER_COMP_MASK; + val |= LAYER_COMP_PIXEL; + /* set the 'enable layer' bit */ val |= LAYER_ENABLE; - malidp_hw_setbits(mp->hwdev, val, - mp->layer->base + MALIDP_LAYER_CONTROL); + malidp_hw_write(mp->hwdev, val, + mp->layer->base + MALIDP_LAYER_CONTROL); } static void malidp_de_plane_disable(struct drm_plane *plane, @@ -222,6 +253,8 @@ int malidp_de_planes_init(struct drm_device *drm) struct malidp_plane *plane = NULL; enum drm_plane_type plane_type; unsigned long crtcs = 1 << drm->mode_config.num_crtc; + unsigned long flags = DRM_ROTATE_0 | DRM_ROTATE_90 | DRM_ROTATE_180 | + DRM_ROTATE_270 | DRM_REFLECT_X | DRM_REFLECT_Y; u32 *formats; int ret, i, j, n; @@ -254,26 +287,18 @@ int malidp_de_planes_init(struct drm_device *drm) if (ret < 0) goto cleanup; - if (!drm->mode_config.rotation_property) { - unsigned long flags = DRM_ROTATE_0 | - DRM_ROTATE_90 | - DRM_ROTATE_180 | - DRM_ROTATE_270 | - DRM_REFLECT_X | - DRM_REFLECT_Y; - drm->mode_config.rotation_property = - drm_mode_create_rotation_property(drm, flags); - } - /* SMART layer can't be rotated */ - if (drm->mode_config.rotation_property && (id != DE_SMART)) - drm_object_attach_property(&plane->base.base, - drm->mode_config.rotation_property, - DRM_ROTATE_0); - drm_plane_helper_add(&plane->base, &malidp_de_plane_helper_funcs); plane->hwdev = malidp->dev; plane->layer = &map->layers[i]; + + /* Skip the features which the SMART layer doesn't have */ + if (id == DE_SMART) + continue; + + drm_plane_create_rotation_property(&plane->base, DRM_ROTATE_0, flags); + malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT, + plane->layer->base + MALIDP_LAYER_COMPOSE); } kfree(formats); |