diff options
Diffstat (limited to 'drivers/gpu/drm/arm')
-rw-r--r-- | drivers/gpu/drm/arm/hdlcd_crtc.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/hdlcd_drv.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_crtc.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_drv.c | 76 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_hw.c | 41 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_hw.h | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_planes.c | 120 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_regs.h | 9 |
9 files changed, 212 insertions, 79 deletions
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 7d4e5aa77195..20ebfb4fbdfa 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -60,11 +60,12 @@ static int hdlcd_set_pxl_fmt(struct drm_crtc *crtc) { unsigned int btpp; struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); + const struct drm_framebuffer *fb = crtc->primary->state->fb; uint32_t pixel_format; struct simplefb_format *format = NULL; int i; - pixel_format = crtc->primary->state->fb->pixel_format; + pixel_format = fb->format->format; for (i = 0; i < ARRAY_SIZE(supported_formats); i++) { if (supported_formats[i].fourcc == pixel_format) @@ -220,27 +221,28 @@ static int hdlcd_plane_atomic_check(struct drm_plane *plane, static void hdlcd_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *state) { + 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; dma_addr_t scanout_start; - if (!plane->state->fb) + 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(plane->state->fb, 0); - scanout_start = gem->paddr + plane->state->fb->offsets[0] + - plane->state->crtc_y * plane->state->fb->pitches[0] + + 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 * - drm_format_plane_cpp(plane->state->fb->pixel_format, 0); + fb->format->cpp[0]; hdlcd = plane->dev->dev_private; - hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]); - hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, plane->state->fb->pitches[0]); + hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]); + hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, fb->pitches[0]); hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, dest_h - 1); hdlcd_write(hdlcd, HDLCD_REG_FB_BASE, scanout_start); } diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index e5f4f4a6546d..4ce4f970920b 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -255,12 +255,6 @@ static int hdlcd_debugfs_init(struct drm_minor *minor) return drm_debugfs_create_files(hdlcd_debugfs_list, ARRAY_SIZE(hdlcd_debugfs_list), minor->debugfs_root, minor); } - -static void hdlcd_debugfs_cleanup(struct drm_minor *minor) -{ - drm_debugfs_remove_files(hdlcd_debugfs_list, - ARRAY_SIZE(hdlcd_debugfs_list), minor); -} #endif static const struct file_operations fops = { @@ -303,7 +297,6 @@ static struct drm_driver hdlcd_driver = { .gem_prime_mmap = drm_gem_cma_prime_mmap, #ifdef CONFIG_DEBUG_FS .debugfs_init = hdlcd_debugfs_init, - .debugfs_cleanup = hdlcd_debugfs_cleanup, #endif .fops = &fops, .name = "hdlcd", @@ -356,7 +349,7 @@ static int hdlcd_drm_bind(struct device *dev) drm_mode_config_reset(drm); drm_kms_helper_poll_init(drm); - hdlcd->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc, + hdlcd->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_connector); if (IS_ERR(hdlcd->fbdev)) { diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index 08e6a71f5d05..294b53697334 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -63,8 +63,7 @@ static void malidp_crtc_enable(struct drm_crtc *crtc) clk_prepare_enable(hwdev->pxlclk); - /* mclk needs to be set to the same or higher rate than pxlclk */ - clk_set_rate(hwdev->mclk, crtc->state->adjusted_mode.crtc_clock * 1000); + /* We rely on firmware to set mclk to a sensible level. */ clk_set_rate(hwdev->pxlclk, crtc->state->adjusted_mode.crtc_clock * 1000); hwdev->modeset(hwdev, &vm); diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 32f746e31379..8b0672d4aee9 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -22,7 +22,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> -#include <drm/drm_fb_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_of.h> @@ -256,6 +255,60 @@ static const struct of_device_id malidp_drm_of_match[] = { }; MODULE_DEVICE_TABLE(of, malidp_drm_of_match); +static bool malidp_is_compatible_hw_id(struct malidp_hw_device *hwdev, + const struct of_device_id *dev_id) +{ + u32 core_id; + const char *compatstr_dp500 = "arm,mali-dp500"; + bool is_dp500; + bool dt_is_dp500; + + /* + * The DP500 CORE_ID register is in a different location, so check it + * first. If the product id field matches, then this is DP500, otherwise + * check the DP550/650 CORE_ID register. + */ + core_id = malidp_hw_read(hwdev, MALIDP500_DC_BASE + MALIDP_DE_CORE_ID); + /* Offset 0x18 will never read 0x500 on products other than DP500. */ + is_dp500 = (MALIDP_PRODUCT_ID(core_id) == 0x500); + dt_is_dp500 = strnstr(dev_id->compatible, compatstr_dp500, + sizeof(dev_id->compatible)) != NULL; + if (is_dp500 != dt_is_dp500) { + DRM_ERROR("Device-tree expects %s, but hardware %s DP500.\n", + dev_id->compatible, is_dp500 ? "is" : "is not"); + return false; + } else if (!dt_is_dp500) { + u16 product_id; + char buf[32]; + + core_id = malidp_hw_read(hwdev, + MALIDP550_DC_BASE + MALIDP_DE_CORE_ID); + product_id = MALIDP_PRODUCT_ID(core_id); + snprintf(buf, sizeof(buf), "arm,mali-dp%X", product_id); + if (!strnstr(dev_id->compatible, buf, + sizeof(dev_id->compatible))) { + DRM_ERROR("Device-tree expects %s, but hardware is DP%03X.\n", + dev_id->compatible, product_id); + return false; + } + } + return true; +} + +static bool malidp_has_sufficient_address_space(const struct resource *res, + const struct of_device_id *dev_id) +{ + resource_size_t res_size = resource_size(res); + const char *compatstr_dp500 = "arm,mali-dp500"; + + if (!strnstr(dev_id->compatible, compatstr_dp500, + sizeof(dev_id->compatible))) + return res_size >= MALIDP550_ADDR_SPACE_SIZE; + else if (res_size < MALIDP500_ADDR_SPACE_SIZE) + return false; + return true; +} + #define MAX_OUTPUT_CHANNELS 3 static int malidp_bind(struct device *dev) @@ -266,6 +319,7 @@ static int malidp_bind(struct device *dev) struct malidp_drm *malidp; struct malidp_hw_device *hwdev; struct platform_device *pdev = to_platform_device(dev); + struct of_device_id const *dev_id; /* number of lines for the R, G and B output */ u8 output_width[MAX_OUTPUT_CHANNELS]; int ret = 0, i; @@ -286,7 +340,6 @@ static int malidp_bind(struct device *dev) memcpy(hwdev, of_device_get_match_data(dev), sizeof(*hwdev)); malidp->dev = hwdev; - INIT_LIST_HEAD(&malidp->event_list); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); hwdev->regs = devm_ioremap_resource(dev, res); @@ -329,6 +382,23 @@ static int malidp_bind(struct device *dev) clk_prepare_enable(hwdev->aclk); clk_prepare_enable(hwdev->mclk); + dev_id = of_match_device(malidp_drm_of_match, dev); + if (!dev_id) { + ret = -EINVAL; + goto query_hw_fail; + } + + if (!malidp_has_sufficient_address_space(res, dev_id)) { + DRM_ERROR("Insufficient address space in device-tree.\n"); + ret = -EINVAL; + goto query_hw_fail; + } + + if (!malidp_is_compatible_hw_id(hwdev, dev_id)) { + ret = -EINVAL; + goto query_hw_fail; + } + ret = hwdev->query_hw(hwdev); if (ret) { DRM_ERROR("Invalid HW configuration\n"); @@ -387,7 +457,7 @@ static int malidp_bind(struct device *dev) drm_mode_config_reset(drm); - malidp->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc, + malidp->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_connector); if (IS_ERR(malidp->fbdev)) { diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h index 9fc8a2e405e4..dbc617c6e4ef 100644 --- a/drivers/gpu/drm/arm/malidp_drv.h +++ b/drivers/gpu/drm/arm/malidp_drv.h @@ -15,12 +15,12 @@ #include <linux/mutex.h> #include <linux/wait.h> +#include <drm/drmP.h> #include "malidp_hw.h" struct malidp_drm { struct malidp_hw_device *dev; struct drm_fbdev_cma *fbdev; - struct list_head event_list; struct drm_crtc crtc; wait_queue_head_t wq; atomic_t config_valid; diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index 4bdf531f7844..9f5513006eee 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -21,7 +21,7 @@ #include "malidp_drv.h" #include "malidp_hw.h" -static const struct malidp_input_format malidp500_de_formats[] = { +static const struct malidp_format_id malidp500_de_formats[] = { /* fourcc, layers supporting the format, internal id */ { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 0 }, { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 1 }, @@ -69,21 +69,21 @@ static const struct malidp_input_format malidp500_de_formats[] = { { DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 6) }, \ { DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) } -static const struct malidp_input_format malidp550_de_formats[] = { +static const struct malidp_format_id malidp550_de_formats[] = { MALIDP_COMMON_FORMATS, }; static const struct malidp_layer malidp500_layers[] = { - { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE }, - { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE }, - { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE }, + { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, MALIDP_DE_LV_STRIDE0 }, + { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, MALIDP_DE_LG_STRIDE }, + { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, MALIDP_DE_LG_STRIDE }, }; static const struct malidp_layer malidp550_layers[] = { - { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE }, - { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE }, - { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE }, - { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE }, + { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, MALIDP_DE_LV_STRIDE0 }, + { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, MALIDP_DE_LG_STRIDE }, + { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, MALIDP_DE_LV_STRIDE0 }, + { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, MALIDP550_DE_LS_R1_STRIDE }, }; #define MALIDP_DE_DEFAULT_PREFETCH_START 5 @@ -436,8 +436,8 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { .irq_mask = MALIDP500_DE_IRQ_CONF_VALID, .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID, }, - .input_formats = malidp500_de_formats, - .n_input_formats = ARRAY_SIZE(malidp500_de_formats), + .pixel_formats = malidp500_de_formats, + .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats), .bus_align_bytes = 8, }, .query_hw = malidp500_query_hw, @@ -447,6 +447,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { .set_config_valid = malidp500_set_config_valid, .modeset = malidp500_modeset, .rotmem_required = malidp500_rotmem_required, + .features = MALIDP_DEVICE_LV_HAS_3_STRIDES, }, [MALIDP_550] = { .map = { @@ -469,8 +470,8 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { .irq_mask = MALIDP550_DC_IRQ_CONF_VALID, .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID, }, - .input_formats = malidp550_de_formats, - .n_input_formats = ARRAY_SIZE(malidp550_de_formats), + .pixel_formats = malidp550_de_formats, + .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats), .bus_align_bytes = 8, }, .query_hw = malidp550_query_hw, @@ -480,6 +481,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { .set_config_valid = malidp550_set_config_valid, .modeset = malidp550_modeset, .rotmem_required = malidp550_rotmem_required, + .features = 0, }, [MALIDP_650] = { .map = { @@ -503,8 +505,8 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { .irq_mask = MALIDP550_DC_IRQ_CONF_VALID, .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID, }, - .input_formats = malidp550_de_formats, - .n_input_formats = ARRAY_SIZE(malidp550_de_formats), + .pixel_formats = malidp550_de_formats, + .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats), .bus_align_bytes = 16, }, .query_hw = malidp650_query_hw, @@ -514,6 +516,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { .set_config_valid = malidp550_set_config_valid, .modeset = malidp550_modeset, .rotmem_required = malidp550_rotmem_required, + .features = 0, }, }; @@ -522,10 +525,10 @@ u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map, { unsigned int i; - for (i = 0; i < map->n_input_formats; i++) { - if (((map->input_formats[i].layer & layer_id) == layer_id) && - (map->input_formats[i].format == format)) - return map->input_formats[i].id; + for (i = 0; i < map->n_pixel_formats; i++) { + if (((map->pixel_formats[i].layer & layer_id) == layer_id) && + (map->pixel_formats[i].format == format)) + return map->pixel_formats[i].id; } return MALIDP_INVALID_FORMAT_ID; diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h index 087e1202db3d..00974b59407d 100644 --- a/drivers/gpu/drm/arm/malidp_hw.h +++ b/drivers/gpu/drm/arm/malidp_hw.h @@ -35,7 +35,7 @@ enum { DE_SMART = BIT(4), }; -struct malidp_input_format { +struct malidp_format_id { u32 format; /* DRM fourcc */ u8 layer; /* bitmask of layers supporting it */ u8 id; /* used internally */ @@ -58,6 +58,7 @@ struct malidp_layer { u16 id; /* layer ID */ u16 base; /* address offset for the register bank */ u16 ptr; /* address offset for the pointer register */ + u16 stride_offset; /* Offset to the first stride register. */ }; /* regmap features */ @@ -85,14 +86,18 @@ struct malidp_hw_regmap { const struct malidp_irq_map se_irq_map; const struct malidp_irq_map dc_irq_map; - /* list of supported input formats for each layer */ - const struct malidp_input_format *input_formats; - const u8 n_input_formats; + /* list of supported pixel formats for each layer */ + const struct malidp_format_id *pixel_formats; + const u8 n_pixel_formats; /* pitch alignment requirement in bytes */ const u8 bus_align_bytes; }; +/* device features */ +/* Unlike DP550/650, DP500 has 3 stride registers in its video layer. */ +#define MALIDP_DEVICE_LV_HAS_3_STRIDES BIT(0) + struct malidp_hw_device { const struct malidp_hw_regmap map; void __iomem *regs; diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 63eec8f37cfc..d5aec082294c 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -11,6 +11,7 @@ */ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -36,7 +37,8 @@ #define LAYER_V_VAL(x) (((x) & 0x1fff) << 16) #define MALIDP_LAYER_COMP_SIZE 0x010 #define MALIDP_LAYER_OFFSET 0x014 -#define MALIDP_LAYER_STRIDE 0x018 +#define MALIDP550_LS_ENABLE 0x01c +#define MALIDP550_LS_R1_IN_SIZE 0x020 /* * This 4-entry look-up-table is used to determine the full 8-bit alpha value @@ -67,13 +69,14 @@ drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) return NULL; state = kmalloc(sizeof(*state), GFP_KERNEL); - if (state) { - 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; - } + if (!state) + return NULL; + + 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; } @@ -102,8 +105,10 @@ 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); + struct drm_crtc_state *crtc_state; struct drm_framebuffer *fb; - int i; + struct drm_rect clip = { 0 }; + int i, ret; u32 src_w, src_h; if (!state->crtc || !state->fb) @@ -112,11 +117,11 @@ static int malidp_de_plane_check(struct drm_plane *plane, fb = state->fb; ms->format = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id, - fb->pixel_format); + fb->format->format); if (ms->format == MALIDP_INVALID_FORMAT_ID) return -EINVAL; - ms->n_planes = drm_format_num_planes(fb->pixel_format); + ms->n_planes = fb->format->num_planes; 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", @@ -131,23 +136,42 @@ static int malidp_de_plane_check(struct drm_plane *plane, if ((state->crtc_w > mp->hwdev->max_line_size) || (state->crtc_h > mp->hwdev->max_line_size) || (state->crtc_w < mp->hwdev->min_line_size) || - (state->crtc_h < mp->hwdev->min_line_size) || - (state->crtc_w != src_w) || (state->crtc_h != src_h)) + (state->crtc_h < mp->hwdev->min_line_size)) + return -EINVAL; + + /* + * DP550/650 video layers can accept 3 plane formats only if + * fb->pitches[1] == fb->pitches[2] since they don't have a + * third plane stride register. + */ + if (ms->n_planes == 3 && + !(mp->hwdev->features & MALIDP_DEVICE_LV_HAS_3_STRIDES) && + (state->fb->pitches[1] != state->fb->pitches[2])) return -EINVAL; /* packed RGB888 / BGR888 can't be rotated or flipped */ if (state->rotation != DRM_ROTATE_0 && - (state->fb->pixel_format == DRM_FORMAT_RGB888 || - state->fb->pixel_format == DRM_FORMAT_BGR888)) + (fb->format->format == DRM_FORMAT_RGB888 || + fb->format->format == DRM_FORMAT_BGR888)) return -EINVAL; + crtc_state = drm_atomic_get_existing_crtc_state(state->state, state->crtc); + clip.x2 = crtc_state->adjusted_mode.hdisplay; + clip.y2 = crtc_state->adjusted_mode.vdisplay; + ret = drm_plane_helper_check_state(state, &clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true, true); + if (ret) + return ret; + ms->rotmem_size = 0; if (state->rotation & MALIDP_ROTATED_MASK) { int val; val = mp->hwdev->rotmem_required(mp->hwdev, state->crtc_h, state->crtc_w, - state->fb->pixel_format); + fb->format->format); if (val < 0) return val; @@ -157,6 +181,25 @@ static int malidp_de_plane_check(struct drm_plane *plane, return 0; } +static void malidp_de_set_plane_pitches(struct malidp_plane *mp, + int num_planes, unsigned int pitches[3]) +{ + int i; + int num_strides = num_planes; + + if (!mp->layer->stride_offset) + return; + + if (num_planes == 3) + num_strides = (mp->hwdev->features & + MALIDP_DEVICE_LV_HAS_3_STRIDES) ? 3 : 2; + + for (i = 0; i < num_strides; ++i) + malidp_hw_write(mp->hwdev, pitches[i], + mp->layer->base + + mp->layer->stride_offset + i * 4); +} + static void malidp_de_plane_update(struct drm_plane *plane, struct drm_plane_state *old_state) { @@ -174,13 +217,8 @@ static void malidp_de_plane_update(struct drm_plane *plane, /* convert src values from Q16 fixed point to integer */ src_w = plane->state->src_w >> 16; src_h = plane->state->src_h >> 16; - if (plane->state->rotation & MALIDP_ROTATED_MASK) { - dest_w = plane->state->crtc_h; - dest_h = plane->state->crtc_w; - } else { - dest_w = plane->state->crtc_w; - dest_h = plane->state->crtc_h; - } + dest_w = plane->state->crtc_w; + dest_h = plane->state->crtc_h; malidp_hw_write(mp->hwdev, ms->format, mp->layer->base); @@ -189,11 +227,12 @@ static void malidp_de_plane_update(struct drm_plane *plane, ptr = mp->layer->ptr + (i << 4); 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, plane->state->fb->pitches[i], - mp->layer->base + MALIDP_LAYER_STRIDE); } + malidp_de_set_plane_pitches(mp, ms->n_planes, + plane->state->fb->pitches); malidp_hw_write(mp->hwdev, LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h), mp->layer->base + MALIDP_LAYER_SIZE); @@ -205,17 +244,23 @@ static void malidp_de_plane_update(struct drm_plane *plane, LAYER_V_VAL(plane->state->crtc_y), mp->layer->base + MALIDP_LAYER_OFFSET); + if (mp->layer->id == DE_SMART) + malidp_hw_write(mp->hwdev, + LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h), + mp->layer->base + MALIDP550_LS_R1_IN_SIZE); + /* 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) - val = ilog2(plane->state->rotation & DRM_ROTATE_MASK) << LAYER_ROT_OFFSET; + val |= ilog2(plane->state->rotation & DRM_ROTATE_MASK) << + LAYER_ROT_OFFSET; if (plane->state->rotation & DRM_REFLECT_X) - val |= LAYER_V_FLIP; - if (plane->state->rotation & DRM_REFLECT_Y) val |= LAYER_H_FLIP; + if (plane->state->rotation & DRM_REFLECT_Y) + val |= LAYER_V_FLIP; /* * always enable pixel alpha blending until we have a way to change @@ -258,7 +303,7 @@ int malidp_de_planes_init(struct drm_device *drm) u32 *formats; int ret, i, j, n; - formats = kcalloc(map->n_input_formats, sizeof(*formats), GFP_KERNEL); + formats = kcalloc(map->n_pixel_formats, sizeof(*formats), GFP_KERNEL); if (!formats) { ret = -ENOMEM; goto cleanup; @@ -274,9 +319,9 @@ int malidp_de_planes_init(struct drm_device *drm) } /* build the list of DRM supported formats based on the map */ - for (n = 0, j = 0; j < map->n_input_formats; j++) { - if ((map->input_formats[j].layer & id) == id) - formats[n++] = map->input_formats[j].format; + for (n = 0, j = 0; j < map->n_pixel_formats; j++) { + if ((map->pixel_formats[j].layer & id) == id) + formats[n++] = map->pixel_formats[j].format; } plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY : @@ -292,9 +337,16 @@ int malidp_de_planes_init(struct drm_device *drm) plane->hwdev = malidp->dev; plane->layer = &map->layers[i]; - /* Skip the features which the SMART layer doesn't have */ - if (id == DE_SMART) + if (id == DE_SMART) { + /* + * Enable the first rectangle in the SMART layer to be + * able to use it as a drm plane. + */ + malidp_hw_write(malidp->dev, 1, + plane->layer->base + MALIDP550_LS_ENABLE); + /* Skip the features which the SMART layer doesn't have. */ continue; + } drm_plane_create_rotation_property(&plane->base, DRM_ROTATE_0, flags); malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT, diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h index 73fecb38f955..b816067a65c5 100644 --- a/drivers/gpu/drm/arm/malidp_regs.h +++ b/drivers/gpu/drm/arm/malidp_regs.h @@ -81,6 +81,11 @@ #define MALIDP_DE_SYNC_WIDTH 0x8 #define MALIDP_DE_HV_ACTIVE 0xc +/* Stride register offsets relative to Lx_BASE */ +#define MALIDP_DE_LG_STRIDE 0x18 +#define MALIDP_DE_LV_STRIDE0 0x18 +#define MALIDP550_DE_LS_R1_STRIDE 0x28 + /* macros to set values into registers */ #define MALIDP_DE_H_FRONTPORCH(x) (((x) & 0xfff) << 0) #define MALIDP_DE_H_BACKPORCH(x) (((x) & 0x3ff) << 16) @@ -92,7 +97,10 @@ #define MALIDP_DE_H_ACTIVE(x) (((x) & 0x1fff) << 0) #define MALIDP_DE_V_ACTIVE(x) (((x) & 0x1fff) << 16) +#define MALIDP_PRODUCT_ID(__core_id) ((u32)(__core_id) >> 16) + /* register offsets and bits specific to DP500 */ +#define MALIDP500_ADDR_SPACE_SIZE 0x01000 #define MALIDP500_DC_BASE 0x00000 #define MALIDP500_DC_CONTROL 0x0000c #define MALIDP500_DC_CONFIG_REQ (1 << 17) @@ -125,6 +133,7 @@ #define MALIDP500_CONFIG_ID 0x00fd4 /* register offsets and bits specific to DP550/DP650 */ +#define MALIDP550_ADDR_SPACE_SIZE 0x10000 #define MALIDP550_DE_CONTROL 0x00010 #define MALIDP550_DE_LINE_COUNTER 0x00014 #define MALIDP550_DE_AXI_CONTROL 0x00018 |