196f60e37SRussell King /* 296f60e37SRussell King * Copyright (C) 2012 Russell King 396f60e37SRussell King * Rewritten from the dovefb driver, and Armada510 manuals. 496f60e37SRussell King * 596f60e37SRussell King * This program is free software; you can redistribute it and/or modify 696f60e37SRussell King * it under the terms of the GNU General Public License version 2 as 796f60e37SRussell King * published by the Free Software Foundation. 896f60e37SRussell King */ 996f60e37SRussell King #include <drm/drmP.h> 1098fb74f4SRussell King #include <drm/drm_plane_helper.h> 1196f60e37SRussell King #include "armada_crtc.h" 1296f60e37SRussell King #include "armada_drm.h" 1396f60e37SRussell King #include "armada_fb.h" 1496f60e37SRussell King #include "armada_gem.h" 1596f60e37SRussell King #include "armada_hw.h" 1696f60e37SRussell King #include <drm/armada_drm.h> 1796f60e37SRussell King #include "armada_ioctlP.h" 18c8a220c6SRussell King #include "armada_trace.h" 1996f60e37SRussell King 2028a2aebeSRussell King struct armada_ovl_plane_properties { 2196f60e37SRussell King uint32_t colorkey_yr; 2296f60e37SRussell King uint32_t colorkey_ug; 2396f60e37SRussell King uint32_t colorkey_vb; 2496f60e37SRussell King #define K2R(val) (((val) >> 0) & 0xff) 2596f60e37SRussell King #define K2G(val) (((val) >> 8) & 0xff) 2696f60e37SRussell King #define K2B(val) (((val) >> 16) & 0xff) 2796f60e37SRussell King int16_t brightness; 2896f60e37SRussell King uint16_t contrast; 2996f60e37SRussell King uint16_t saturation; 3096f60e37SRussell King uint32_t colorkey_mode; 3196f60e37SRussell King }; 3296f60e37SRussell King 3328a2aebeSRussell King struct armada_ovl_plane { 34561f60bcSRussell King struct armada_plane base; 3596f60e37SRussell King struct drm_framebuffer *old_fb; 3696f60e37SRussell King struct { 374a8506d2SRussell King struct armada_plane_work work; 3896f60e37SRussell King struct armada_regs regs[13]; 3996f60e37SRussell King } vbl; 4028a2aebeSRussell King struct armada_ovl_plane_properties prop; 4196f60e37SRussell King }; 42561f60bcSRussell King #define drm_to_armada_ovl_plane(p) \ 43561f60bcSRussell King container_of(p, struct armada_ovl_plane, base.base) 4496f60e37SRussell King 4596f60e37SRussell King 4696f60e37SRussell King static void 4728a2aebeSRussell King armada_ovl_update_attr(struct armada_ovl_plane_properties *prop, 4896f60e37SRussell King struct armada_crtc *dcrtc) 4996f60e37SRussell King { 5096f60e37SRussell King writel_relaxed(prop->colorkey_yr, dcrtc->base + LCD_SPU_COLORKEY_Y); 5196f60e37SRussell King writel_relaxed(prop->colorkey_ug, dcrtc->base + LCD_SPU_COLORKEY_U); 5296f60e37SRussell King writel_relaxed(prop->colorkey_vb, dcrtc->base + LCD_SPU_COLORKEY_V); 5396f60e37SRussell King 5496f60e37SRussell King writel_relaxed(prop->brightness << 16 | prop->contrast, 5596f60e37SRussell King dcrtc->base + LCD_SPU_CONTRAST); 5696f60e37SRussell King /* Docs say 15:0, but it seems to actually be 31:16 on Armada 510 */ 5796f60e37SRussell King writel_relaxed(prop->saturation << 16, 5896f60e37SRussell King dcrtc->base + LCD_SPU_SATURATION); 5996f60e37SRussell King writel_relaxed(0x00002000, dcrtc->base + LCD_SPU_CBSH_HUE); 6096f60e37SRussell King 6196f60e37SRussell King spin_lock_irq(&dcrtc->irq_lock); 6296f60e37SRussell King armada_updatel(prop->colorkey_mode | CFG_ALPHAM_GRA, 6396f60e37SRussell King CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK, 6496f60e37SRussell King dcrtc->base + LCD_SPU_DMA_CTRL1); 6596f60e37SRussell King 6696f60e37SRussell King armada_updatel(ADV_GRACOLORKEY, 0, dcrtc->base + LCD_SPU_ADV_REG); 6796f60e37SRussell King spin_unlock_irq(&dcrtc->irq_lock); 6896f60e37SRussell King } 6996f60e37SRussell King 70fecfdb2dSRussell King static void armada_ovl_retire_fb(struct armada_ovl_plane *dplane, 71fecfdb2dSRussell King struct drm_framebuffer *fb) 72fecfdb2dSRussell King { 73fecfdb2dSRussell King struct drm_framebuffer *old_fb; 74fecfdb2dSRussell King 7566377efaSRussell King old_fb = xchg(&dplane->old_fb, fb); 76fecfdb2dSRussell King 77fecfdb2dSRussell King if (old_fb) 78561f60bcSRussell King armada_drm_queue_unref_work(dplane->base.base.dev, old_fb); 79fecfdb2dSRussell King } 80fecfdb2dSRussell King 8196f60e37SRussell King /* === Plane support === */ 824a8506d2SRussell King static void armada_ovl_plane_work(struct armada_crtc *dcrtc, 834a8506d2SRussell King struct armada_plane *plane, struct armada_plane_work *work) 8496f60e37SRussell King { 854a8506d2SRussell King struct armada_ovl_plane *dplane = container_of(plane, struct armada_ovl_plane, base); 8696f60e37SRussell King 87c8a220c6SRussell King trace_armada_ovl_plane_work(&dcrtc->crtc, &plane->base); 88c8a220c6SRussell King 8996f60e37SRussell King armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); 90fecfdb2dSRussell King armada_ovl_retire_fb(dplane, NULL); 9196f60e37SRussell King } 9296f60e37SRussell King 9396f60e37SRussell King static int 9428a2aebeSRussell King armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, 9596f60e37SRussell King struct drm_framebuffer *fb, 9696f60e37SRussell King int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h, 9734a2ab5eSDaniel Vetter uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, 9834a2ab5eSDaniel Vetter struct drm_modeset_acquire_ctx *ctx) 9996f60e37SRussell King { 10028a2aebeSRussell King struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); 10196f60e37SRussell King struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); 10298fb74f4SRussell King struct drm_rect src = { 10398fb74f4SRussell King .x1 = src_x, 10498fb74f4SRussell King .y1 = src_y, 10598fb74f4SRussell King .x2 = src_x + src_w, 10698fb74f4SRussell King .y2 = src_y + src_h, 10798fb74f4SRussell King }; 10898fb74f4SRussell King struct drm_rect dest = { 10998fb74f4SRussell King .x1 = crtc_x, 11098fb74f4SRussell King .y1 = crtc_y, 11198fb74f4SRussell King .x2 = crtc_x + crtc_w, 11298fb74f4SRussell King .y2 = crtc_y + crtc_h, 11398fb74f4SRussell King }; 11498fb74f4SRussell King const struct drm_rect clip = { 11598fb74f4SRussell King .x2 = crtc->mode.hdisplay, 11698fb74f4SRussell King .y2 = crtc->mode.vdisplay, 11798fb74f4SRussell King }; 11896f60e37SRussell King uint32_t val, ctrl0; 11996f60e37SRussell King unsigned idx = 0; 12098fb74f4SRussell King bool visible; 12196f60e37SRussell King int ret; 12296f60e37SRussell King 123c8a220c6SRussell King trace_armada_ovl_plane_update(plane, crtc, fb, 124c8a220c6SRussell King crtc_x, crtc_y, crtc_w, crtc_h, 125c8a220c6SRussell King src_x, src_y, src_w, src_h); 126c8a220c6SRussell King 12798fb74f4SRussell King ret = drm_plane_helper_check_update(plane, crtc, fb, &src, &dest, &clip, 128c2c446adSRobert Foss DRM_MODE_ROTATE_0, 12998fb74f4SRussell King 0, INT_MAX, true, false, &visible); 13098fb74f4SRussell King if (ret) 13198fb74f4SRussell King return ret; 13298fb74f4SRussell King 13396f60e37SRussell King ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) | 13496f60e37SRussell King CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) | 13596f60e37SRussell King CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA; 13696f60e37SRussell King 13796f60e37SRussell King /* Does the position/size result in nothing to display? */ 13898fb74f4SRussell King if (!visible) 13996f60e37SRussell King ctrl0 &= ~CFG_DMA_ENA; 14096f60e37SRussell King 14196f60e37SRussell King if (!dcrtc->plane) { 14296f60e37SRussell King dcrtc->plane = plane; 14396f60e37SRussell King armada_ovl_update_attr(&dplane->prop, dcrtc); 14496f60e37SRussell King } 14596f60e37SRussell King 14696f60e37SRussell King /* FIXME: overlay on an interlaced display */ 14796f60e37SRussell King /* Just updating the position/size? */ 1488be523dbSRussell King if (plane->fb == fb && dplane->base.state.ctrl0 == ctrl0) { 14998fb74f4SRussell King val = (drm_rect_height(&src) & 0xffff0000) | 15098fb74f4SRussell King drm_rect_width(&src) >> 16; 1518be523dbSRussell King dplane->base.state.src_hw = val; 15296f60e37SRussell King writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN); 15398fb74f4SRussell King 15498fb74f4SRussell King val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest); 1558be523dbSRussell King dplane->base.state.dst_hw = val; 15696f60e37SRussell King writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN); 15798fb74f4SRussell King 15898fb74f4SRussell King val = dest.y1 << 16 | dest.x1; 1598be523dbSRussell King dplane->base.state.dst_yx = val; 16096f60e37SRussell King writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN); 16198fb74f4SRussell King 16296f60e37SRussell King return 0; 1638be523dbSRussell King } else if (~dplane->base.state.ctrl0 & ctrl0 & CFG_DMA_ENA) { 16496f60e37SRussell King /* Power up the Y/U/V FIFOs on ENA 0->1 transitions */ 16596f60e37SRussell King armada_updatel(0, CFG_PDWN16x66 | CFG_PDWN32x66, 16696f60e37SRussell King dcrtc->base + LCD_SPU_SRAM_PARA1); 16796f60e37SRussell King } 16896f60e37SRussell King 1694a8506d2SRussell King if (armada_drm_plane_work_wait(&dplane->base, HZ / 25) == 0) 1704a8506d2SRussell King armada_drm_plane_work_cancel(dcrtc, &dplane->base); 17196f60e37SRussell King 17296f60e37SRussell King if (plane->fb != fb) { 173f0b24871SRussell King u32 addrs[3], pixel_format; 174f0b24871SRussell King int num_planes, hsub; 17596f60e37SRussell King 17696f60e37SRussell King /* 17796f60e37SRussell King * Take a reference on the new framebuffer - we want to 17896f60e37SRussell King * hold on to it while the hardware is displaying it. 17996f60e37SRussell King */ 18096f60e37SRussell King drm_framebuffer_reference(fb); 18196f60e37SRussell King 182fecfdb2dSRussell King if (plane->fb) 183fecfdb2dSRussell King armada_ovl_retire_fb(dplane, plane->fb); 18496f60e37SRussell King 18598fb74f4SRussell King src_y = src.y1 >> 16; 18698fb74f4SRussell King src_x = src.x1 >> 16; 18796f60e37SRussell King 188f0b24871SRussell King armada_drm_plane_calc_addrs(addrs, fb, src_x, src_y); 189f0b24871SRussell King 190438b74a5SVille Syrjälä pixel_format = fb->format->format; 19173068ce3SRussell King hsub = drm_format_horz_chroma_subsampling(pixel_format); 192bcb0b461SVille Syrjälä num_planes = fb->format->num_planes; 19373068ce3SRussell King 19473068ce3SRussell King /* 19573068ce3SRussell King * Annoyingly, shifting a YUYV-format image by one pixel 19673068ce3SRussell King * causes the U/V planes to toggle. Toggle the UV swap. 19773068ce3SRussell King * (Unfortunately, this causes momentary colour flickering.) 19873068ce3SRussell King */ 19973068ce3SRussell King if (src_x & (hsub - 1) && num_planes == 1) 20073068ce3SRussell King ctrl0 ^= CFG_DMA_MOD(CFG_SWAPUV); 20173068ce3SRussell King 202f0b24871SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addrs[0], 20396f60e37SRussell King LCD_SPU_DMA_START_ADDR_Y0); 204f0b24871SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addrs[1], 20596f60e37SRussell King LCD_SPU_DMA_START_ADDR_U0); 206f0b24871SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addrs[2], 20796f60e37SRussell King LCD_SPU_DMA_START_ADDR_V0); 208f0b24871SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addrs[0], 20996f60e37SRussell King LCD_SPU_DMA_START_ADDR_Y1); 210f0b24871SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addrs[1], 21196f60e37SRussell King LCD_SPU_DMA_START_ADDR_U1); 212f0b24871SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addrs[2], 21396f60e37SRussell King LCD_SPU_DMA_START_ADDR_V1); 21496f60e37SRussell King 21596f60e37SRussell King val = fb->pitches[0] << 16 | fb->pitches[0]; 21696f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 21796f60e37SRussell King LCD_SPU_DMA_PITCH_YC); 21896f60e37SRussell King val = fb->pitches[1] << 16 | fb->pitches[2]; 21996f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 22096f60e37SRussell King LCD_SPU_DMA_PITCH_UV); 22196f60e37SRussell King } 22296f60e37SRussell King 22398fb74f4SRussell King val = (drm_rect_height(&src) & 0xffff0000) | drm_rect_width(&src) >> 16; 2248be523dbSRussell King if (dplane->base.state.src_hw != val) { 2258be523dbSRussell King dplane->base.state.src_hw = val; 22696f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 22796f60e37SRussell King LCD_SPU_DMA_HPXL_VLN); 22896f60e37SRussell King } 22998fb74f4SRussell King 23098fb74f4SRussell King val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest); 2318be523dbSRussell King if (dplane->base.state.dst_hw != val) { 2328be523dbSRussell King dplane->base.state.dst_hw = val; 23396f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 23496f60e37SRussell King LCD_SPU_DZM_HPXL_VLN); 23596f60e37SRussell King } 23698fb74f4SRussell King 23798fb74f4SRussell King val = dest.y1 << 16 | dest.x1; 2388be523dbSRussell King if (dplane->base.state.dst_yx != val) { 2398be523dbSRussell King dplane->base.state.dst_yx = val; 24096f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 24196f60e37SRussell King LCD_SPU_DMA_OVSA_HPXL_VLN); 24296f60e37SRussell King } 24398fb74f4SRussell King 2448be523dbSRussell King if (dplane->base.state.ctrl0 != ctrl0) { 2458be523dbSRussell King dplane->base.state.ctrl0 = ctrl0; 24696f60e37SRussell King armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0, 24796f60e37SRussell King CFG_CBSH_ENA | CFG_DMAFORMAT | CFG_DMA_FTOGGLE | 24896f60e37SRussell King CFG_DMA_HSMOOTH | CFG_DMA_TSTMODE | 24996f60e37SRussell King CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV | CFG_SWAPYU | 25096f60e37SRussell King CFG_YUV2RGB) | CFG_DMA_ENA, 25196f60e37SRussell King LCD_SPU_DMA_CTRL0); 25296f60e37SRussell King } 25396f60e37SRussell King if (idx) { 25496f60e37SRussell King armada_reg_queue_end(dplane->vbl.regs, idx); 2554a8506d2SRussell King armada_drm_plane_work_queue(dcrtc, &dplane->base, 2564a8506d2SRussell King &dplane->vbl.work); 25796f60e37SRussell King } 25896f60e37SRussell King return 0; 25996f60e37SRussell King } 26096f60e37SRussell King 26119315294SDaniel Vetter static int armada_ovl_plane_disable(struct drm_plane *plane, 26219315294SDaniel Vetter struct drm_modeset_acquire_ctx *ctx) 26396f60e37SRussell King { 26428a2aebeSRussell King struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); 26596f60e37SRussell King struct drm_framebuffer *fb; 26696f60e37SRussell King struct armada_crtc *dcrtc; 26796f60e37SRussell King 268561f60bcSRussell King if (!dplane->base.base.crtc) 26996f60e37SRussell King return 0; 27096f60e37SRussell King 271561f60bcSRussell King dcrtc = drm_to_armada_crtc(dplane->base.base.crtc); 27296f60e37SRussell King 2734a8506d2SRussell King armada_drm_plane_work_cancel(dcrtc, &dplane->base); 27458326803SRussell King armada_drm_crtc_plane_disable(dcrtc, plane); 27596f60e37SRussell King 2764a8506d2SRussell King dcrtc->plane = NULL; 2778be523dbSRussell King dplane->base.state.ctrl0 = 0; 2784a8506d2SRussell King 27966377efaSRussell King fb = xchg(&dplane->old_fb, NULL); 28096f60e37SRussell King if (fb) 28196f60e37SRussell King drm_framebuffer_unreference(fb); 28296f60e37SRussell King 28396f60e37SRussell King return 0; 28496f60e37SRussell King } 28596f60e37SRussell King 28628a2aebeSRussell King static void armada_ovl_plane_destroy(struct drm_plane *plane) 28796f60e37SRussell King { 28828a2aebeSRussell King struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); 28941dbb2dbSRussell King 29041dbb2dbSRussell King drm_plane_cleanup(plane); 29141dbb2dbSRussell King 29241dbb2dbSRussell King kfree(dplane); 29396f60e37SRussell King } 29496f60e37SRussell King 29528a2aebeSRussell King static int armada_ovl_plane_set_property(struct drm_plane *plane, 29696f60e37SRussell King struct drm_property *property, uint64_t val) 29796f60e37SRussell King { 29896f60e37SRussell King struct armada_private *priv = plane->dev->dev_private; 29928a2aebeSRussell King struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); 30096f60e37SRussell King bool update_attr = false; 30196f60e37SRussell King 30296f60e37SRussell King if (property == priv->colorkey_prop) { 30396f60e37SRussell King #define CCC(v) ((v) << 24 | (v) << 16 | (v) << 8) 30496f60e37SRussell King dplane->prop.colorkey_yr = CCC(K2R(val)); 30596f60e37SRussell King dplane->prop.colorkey_ug = CCC(K2G(val)); 30696f60e37SRussell King dplane->prop.colorkey_vb = CCC(K2B(val)); 30796f60e37SRussell King #undef CCC 30896f60e37SRussell King update_attr = true; 30996f60e37SRussell King } else if (property == priv->colorkey_min_prop) { 31096f60e37SRussell King dplane->prop.colorkey_yr &= ~0x00ff0000; 31196f60e37SRussell King dplane->prop.colorkey_yr |= K2R(val) << 16; 31296f60e37SRussell King dplane->prop.colorkey_ug &= ~0x00ff0000; 31396f60e37SRussell King dplane->prop.colorkey_ug |= K2G(val) << 16; 31496f60e37SRussell King dplane->prop.colorkey_vb &= ~0x00ff0000; 31596f60e37SRussell King dplane->prop.colorkey_vb |= K2B(val) << 16; 31696f60e37SRussell King update_attr = true; 31796f60e37SRussell King } else if (property == priv->colorkey_max_prop) { 31896f60e37SRussell King dplane->prop.colorkey_yr &= ~0xff000000; 31996f60e37SRussell King dplane->prop.colorkey_yr |= K2R(val) << 24; 32096f60e37SRussell King dplane->prop.colorkey_ug &= ~0xff000000; 32196f60e37SRussell King dplane->prop.colorkey_ug |= K2G(val) << 24; 32296f60e37SRussell King dplane->prop.colorkey_vb &= ~0xff000000; 32396f60e37SRussell King dplane->prop.colorkey_vb |= K2B(val) << 24; 32496f60e37SRussell King update_attr = true; 32596f60e37SRussell King } else if (property == priv->colorkey_val_prop) { 32696f60e37SRussell King dplane->prop.colorkey_yr &= ~0x0000ff00; 32796f60e37SRussell King dplane->prop.colorkey_yr |= K2R(val) << 8; 32896f60e37SRussell King dplane->prop.colorkey_ug &= ~0x0000ff00; 32996f60e37SRussell King dplane->prop.colorkey_ug |= K2G(val) << 8; 33096f60e37SRussell King dplane->prop.colorkey_vb &= ~0x0000ff00; 33196f60e37SRussell King dplane->prop.colorkey_vb |= K2B(val) << 8; 33296f60e37SRussell King update_attr = true; 33396f60e37SRussell King } else if (property == priv->colorkey_alpha_prop) { 33496f60e37SRussell King dplane->prop.colorkey_yr &= ~0x000000ff; 33596f60e37SRussell King dplane->prop.colorkey_yr |= K2R(val); 33696f60e37SRussell King dplane->prop.colorkey_ug &= ~0x000000ff; 33796f60e37SRussell King dplane->prop.colorkey_ug |= K2G(val); 33896f60e37SRussell King dplane->prop.colorkey_vb &= ~0x000000ff; 33996f60e37SRussell King dplane->prop.colorkey_vb |= K2B(val); 34096f60e37SRussell King update_attr = true; 34196f60e37SRussell King } else if (property == priv->colorkey_mode_prop) { 34296f60e37SRussell King dplane->prop.colorkey_mode &= ~CFG_CKMODE_MASK; 34396f60e37SRussell King dplane->prop.colorkey_mode |= CFG_CKMODE(val); 34496f60e37SRussell King update_attr = true; 34596f60e37SRussell King } else if (property == priv->brightness_prop) { 34696f60e37SRussell King dplane->prop.brightness = val - 256; 34796f60e37SRussell King update_attr = true; 34896f60e37SRussell King } else if (property == priv->contrast_prop) { 34996f60e37SRussell King dplane->prop.contrast = val; 35096f60e37SRussell King update_attr = true; 35196f60e37SRussell King } else if (property == priv->saturation_prop) { 35296f60e37SRussell King dplane->prop.saturation = val; 35396f60e37SRussell King update_attr = true; 35496f60e37SRussell King } 35596f60e37SRussell King 356561f60bcSRussell King if (update_attr && dplane->base.base.crtc) 35796f60e37SRussell King armada_ovl_update_attr(&dplane->prop, 358561f60bcSRussell King drm_to_armada_crtc(dplane->base.base.crtc)); 35996f60e37SRussell King 36096f60e37SRussell King return 0; 36196f60e37SRussell King } 36296f60e37SRussell King 36328a2aebeSRussell King static const struct drm_plane_funcs armada_ovl_plane_funcs = { 36428a2aebeSRussell King .update_plane = armada_ovl_plane_update, 36528a2aebeSRussell King .disable_plane = armada_ovl_plane_disable, 36628a2aebeSRussell King .destroy = armada_ovl_plane_destroy, 36728a2aebeSRussell King .set_property = armada_ovl_plane_set_property, 36896f60e37SRussell King }; 36996f60e37SRussell King 37028a2aebeSRussell King static const uint32_t armada_ovl_formats[] = { 37196f60e37SRussell King DRM_FORMAT_UYVY, 37296f60e37SRussell King DRM_FORMAT_YUYV, 37396f60e37SRussell King DRM_FORMAT_YUV420, 37496f60e37SRussell King DRM_FORMAT_YVU420, 37596f60e37SRussell King DRM_FORMAT_YUV422, 37696f60e37SRussell King DRM_FORMAT_YVU422, 37796f60e37SRussell King DRM_FORMAT_VYUY, 37896f60e37SRussell King DRM_FORMAT_YVYU, 37996f60e37SRussell King DRM_FORMAT_ARGB8888, 38096f60e37SRussell King DRM_FORMAT_ABGR8888, 38196f60e37SRussell King DRM_FORMAT_XRGB8888, 38296f60e37SRussell King DRM_FORMAT_XBGR8888, 38396f60e37SRussell King DRM_FORMAT_RGB888, 38496f60e37SRussell King DRM_FORMAT_BGR888, 38596f60e37SRussell King DRM_FORMAT_ARGB1555, 38696f60e37SRussell King DRM_FORMAT_ABGR1555, 38796f60e37SRussell King DRM_FORMAT_RGB565, 38896f60e37SRussell King DRM_FORMAT_BGR565, 38996f60e37SRussell King }; 39096f60e37SRussell King 3918a63ca58SArvind Yadav static const struct drm_prop_enum_list armada_drm_colorkey_enum_list[] = { 39296f60e37SRussell King { CKMODE_DISABLE, "disabled" }, 39396f60e37SRussell King { CKMODE_Y, "Y component" }, 39496f60e37SRussell King { CKMODE_U, "U component" }, 39596f60e37SRussell King { CKMODE_V, "V component" }, 39696f60e37SRussell King { CKMODE_RGB, "RGB" }, 39796f60e37SRussell King { CKMODE_R, "R component" }, 39896f60e37SRussell King { CKMODE_G, "G component" }, 39996f60e37SRussell King { CKMODE_B, "B component" }, 40096f60e37SRussell King }; 40196f60e37SRussell King 40296f60e37SRussell King static int armada_overlay_create_properties(struct drm_device *dev) 40396f60e37SRussell King { 40496f60e37SRussell King struct armada_private *priv = dev->dev_private; 40596f60e37SRussell King 40696f60e37SRussell King if (priv->colorkey_prop) 40796f60e37SRussell King return 0; 40896f60e37SRussell King 40996f60e37SRussell King priv->colorkey_prop = drm_property_create_range(dev, 0, 41096f60e37SRussell King "colorkey", 0, 0xffffff); 41196f60e37SRussell King priv->colorkey_min_prop = drm_property_create_range(dev, 0, 41296f60e37SRussell King "colorkey_min", 0, 0xffffff); 41396f60e37SRussell King priv->colorkey_max_prop = drm_property_create_range(dev, 0, 41496f60e37SRussell King "colorkey_max", 0, 0xffffff); 41596f60e37SRussell King priv->colorkey_val_prop = drm_property_create_range(dev, 0, 41696f60e37SRussell King "colorkey_val", 0, 0xffffff); 41796f60e37SRussell King priv->colorkey_alpha_prop = drm_property_create_range(dev, 0, 41896f60e37SRussell King "colorkey_alpha", 0, 0xffffff); 41996f60e37SRussell King priv->colorkey_mode_prop = drm_property_create_enum(dev, 0, 42096f60e37SRussell King "colorkey_mode", 42196f60e37SRussell King armada_drm_colorkey_enum_list, 42296f60e37SRussell King ARRAY_SIZE(armada_drm_colorkey_enum_list)); 42396f60e37SRussell King priv->brightness_prop = drm_property_create_range(dev, 0, 42496f60e37SRussell King "brightness", 0, 256 + 255); 42596f60e37SRussell King priv->contrast_prop = drm_property_create_range(dev, 0, 42696f60e37SRussell King "contrast", 0, 0x7fff); 42796f60e37SRussell King priv->saturation_prop = drm_property_create_range(dev, 0, 42896f60e37SRussell King "saturation", 0, 0x7fff); 42996f60e37SRussell King 43096f60e37SRussell King if (!priv->colorkey_prop) 43196f60e37SRussell King return -ENOMEM; 43296f60e37SRussell King 43396f60e37SRussell King return 0; 43496f60e37SRussell King } 43596f60e37SRussell King 43696f60e37SRussell King int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) 43796f60e37SRussell King { 43896f60e37SRussell King struct armada_private *priv = dev->dev_private; 43996f60e37SRussell King struct drm_mode_object *mobj; 44028a2aebeSRussell King struct armada_ovl_plane *dplane; 44196f60e37SRussell King int ret; 44296f60e37SRussell King 44396f60e37SRussell King ret = armada_overlay_create_properties(dev); 44496f60e37SRussell King if (ret) 44596f60e37SRussell King return ret; 44696f60e37SRussell King 44796f60e37SRussell King dplane = kzalloc(sizeof(*dplane), GFP_KERNEL); 44896f60e37SRussell King if (!dplane) 44996f60e37SRussell King return -ENOMEM; 45096f60e37SRussell King 4515740d27fSRussell King ret = armada_drm_plane_init(&dplane->base); 4525740d27fSRussell King if (ret) { 4535740d27fSRussell King kfree(dplane); 4545740d27fSRussell King return ret; 4555740d27fSRussell King } 4565740d27fSRussell King 4574a8506d2SRussell King dplane->vbl.work.fn = armada_ovl_plane_work; 45896f60e37SRussell King 459561f60bcSRussell King ret = drm_universal_plane_init(dev, &dplane->base.base, crtcs, 460d563c245SRussell King &armada_ovl_plane_funcs, 461d563c245SRussell King armada_ovl_formats, 462d563c245SRussell King ARRAY_SIZE(armada_ovl_formats), 463e6fc3b68SBen Widawsky NULL, 464b0b3b795SVille Syrjälä DRM_PLANE_TYPE_OVERLAY, NULL); 46528a2aebeSRussell King if (ret) { 46628a2aebeSRussell King kfree(dplane); 46728a2aebeSRussell King return ret; 46828a2aebeSRussell King } 46996f60e37SRussell King 47096f60e37SRussell King dplane->prop.colorkey_yr = 0xfefefe00; 47196f60e37SRussell King dplane->prop.colorkey_ug = 0x01010100; 47296f60e37SRussell King dplane->prop.colorkey_vb = 0x01010100; 47396f60e37SRussell King dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB); 47496f60e37SRussell King dplane->prop.brightness = 0; 47596f60e37SRussell King dplane->prop.contrast = 0x4000; 47696f60e37SRussell King dplane->prop.saturation = 0x4000; 47796f60e37SRussell King 478561f60bcSRussell King mobj = &dplane->base.base.base; 47996f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_prop, 48096f60e37SRussell King 0x0101fe); 48196f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_min_prop, 48296f60e37SRussell King 0x0101fe); 48396f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_max_prop, 48496f60e37SRussell King 0x0101fe); 48596f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_val_prop, 48696f60e37SRussell King 0x0101fe); 48796f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_alpha_prop, 48896f60e37SRussell King 0x000000); 48996f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_mode_prop, 49096f60e37SRussell King CKMODE_RGB); 49196f60e37SRussell King drm_object_attach_property(mobj, priv->brightness_prop, 256); 49296f60e37SRussell King drm_object_attach_property(mobj, priv->contrast_prop, 49396f60e37SRussell King dplane->prop.contrast); 49496f60e37SRussell King drm_object_attach_property(mobj, priv->saturation_prop, 49596f60e37SRussell King dplane->prop.saturation); 49696f60e37SRussell King 49796f60e37SRussell King return 0; 49896f60e37SRussell King } 499