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" 1896f60e37SRussell King 1928a2aebeSRussell King struct armada_ovl_plane_properties { 2096f60e37SRussell King uint32_t colorkey_yr; 2196f60e37SRussell King uint32_t colorkey_ug; 2296f60e37SRussell King uint32_t colorkey_vb; 2396f60e37SRussell King #define K2R(val) (((val) >> 0) & 0xff) 2496f60e37SRussell King #define K2G(val) (((val) >> 8) & 0xff) 2596f60e37SRussell King #define K2B(val) (((val) >> 16) & 0xff) 2696f60e37SRussell King int16_t brightness; 2796f60e37SRussell King uint16_t contrast; 2896f60e37SRussell King uint16_t saturation; 2996f60e37SRussell King uint32_t colorkey_mode; 3096f60e37SRussell King }; 3196f60e37SRussell King 3228a2aebeSRussell King struct armada_ovl_plane { 33561f60bcSRussell King struct armada_plane base; 3496f60e37SRussell King struct drm_framebuffer *old_fb; 3596f60e37SRussell King uint32_t src_hw; 3696f60e37SRussell King uint32_t dst_hw; 3796f60e37SRussell King uint32_t dst_yx; 3896f60e37SRussell King uint32_t ctrl0; 3996f60e37SRussell King struct { 404a8506d2SRussell King struct armada_plane_work work; 4196f60e37SRussell King struct armada_regs regs[13]; 4296f60e37SRussell King } vbl; 4328a2aebeSRussell King struct armada_ovl_plane_properties prop; 4496f60e37SRussell King }; 45561f60bcSRussell King #define drm_to_armada_ovl_plane(p) \ 46561f60bcSRussell King container_of(p, struct armada_ovl_plane, base.base) 4796f60e37SRussell King 4896f60e37SRussell King 4996f60e37SRussell King static void 5028a2aebeSRussell King armada_ovl_update_attr(struct armada_ovl_plane_properties *prop, 5196f60e37SRussell King struct armada_crtc *dcrtc) 5296f60e37SRussell King { 5396f60e37SRussell King writel_relaxed(prop->colorkey_yr, dcrtc->base + LCD_SPU_COLORKEY_Y); 5496f60e37SRussell King writel_relaxed(prop->colorkey_ug, dcrtc->base + LCD_SPU_COLORKEY_U); 5596f60e37SRussell King writel_relaxed(prop->colorkey_vb, dcrtc->base + LCD_SPU_COLORKEY_V); 5696f60e37SRussell King 5796f60e37SRussell King writel_relaxed(prop->brightness << 16 | prop->contrast, 5896f60e37SRussell King dcrtc->base + LCD_SPU_CONTRAST); 5996f60e37SRussell King /* Docs say 15:0, but it seems to actually be 31:16 on Armada 510 */ 6096f60e37SRussell King writel_relaxed(prop->saturation << 16, 6196f60e37SRussell King dcrtc->base + LCD_SPU_SATURATION); 6296f60e37SRussell King writel_relaxed(0x00002000, dcrtc->base + LCD_SPU_CBSH_HUE); 6396f60e37SRussell King 6496f60e37SRussell King spin_lock_irq(&dcrtc->irq_lock); 6596f60e37SRussell King armada_updatel(prop->colorkey_mode | CFG_ALPHAM_GRA, 6696f60e37SRussell King CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK, 6796f60e37SRussell King dcrtc->base + LCD_SPU_DMA_CTRL1); 6896f60e37SRussell King 6996f60e37SRussell King armada_updatel(ADV_GRACOLORKEY, 0, dcrtc->base + LCD_SPU_ADV_REG); 7096f60e37SRussell King spin_unlock_irq(&dcrtc->irq_lock); 7196f60e37SRussell King } 7296f60e37SRussell King 73fecfdb2dSRussell King static void armada_ovl_retire_fb(struct armada_ovl_plane *dplane, 74fecfdb2dSRussell King struct drm_framebuffer *fb) 75fecfdb2dSRussell King { 76fecfdb2dSRussell King struct drm_framebuffer *old_fb; 77fecfdb2dSRussell King 7866377efaSRussell King old_fb = xchg(&dplane->old_fb, fb); 79fecfdb2dSRussell King 80fecfdb2dSRussell King if (old_fb) 81561f60bcSRussell King armada_drm_queue_unref_work(dplane->base.base.dev, old_fb); 82fecfdb2dSRussell King } 83fecfdb2dSRussell King 8496f60e37SRussell King /* === Plane support === */ 854a8506d2SRussell King static void armada_ovl_plane_work(struct armada_crtc *dcrtc, 864a8506d2SRussell King struct armada_plane *plane, struct armada_plane_work *work) 8796f60e37SRussell King { 884a8506d2SRussell King struct armada_ovl_plane *dplane = container_of(plane, struct armada_ovl_plane, base); 8996f60e37SRussell King 9096f60e37SRussell King armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); 91fecfdb2dSRussell King armada_ovl_retire_fb(dplane, NULL); 9296f60e37SRussell King } 9396f60e37SRussell King 9496f60e37SRussell King static int 9528a2aebeSRussell King armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, 9696f60e37SRussell King struct drm_framebuffer *fb, 9796f60e37SRussell King int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h, 9896f60e37SRussell King uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) 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 12398fb74f4SRussell King ret = drm_plane_helper_check_update(plane, crtc, fb, &src, &dest, &clip, 12498fb74f4SRussell King 0, INT_MAX, true, false, &visible); 12598fb74f4SRussell King if (ret) 12698fb74f4SRussell King return ret; 12798fb74f4SRussell King 12896f60e37SRussell King ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) | 12996f60e37SRussell King CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) | 13096f60e37SRussell King CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA; 13196f60e37SRussell King 13296f60e37SRussell King /* Does the position/size result in nothing to display? */ 13398fb74f4SRussell King if (!visible) 13496f60e37SRussell King ctrl0 &= ~CFG_DMA_ENA; 13596f60e37SRussell King 13696f60e37SRussell King if (!dcrtc->plane) { 13796f60e37SRussell King dcrtc->plane = plane; 13896f60e37SRussell King armada_ovl_update_attr(&dplane->prop, dcrtc); 13996f60e37SRussell King } 14096f60e37SRussell King 14196f60e37SRussell King /* FIXME: overlay on an interlaced display */ 14296f60e37SRussell King /* Just updating the position/size? */ 14396f60e37SRussell King if (plane->fb == fb && dplane->ctrl0 == ctrl0) { 14498fb74f4SRussell King val = (drm_rect_height(&src) & 0xffff0000) | 14598fb74f4SRussell King drm_rect_width(&src) >> 16; 14696f60e37SRussell King dplane->src_hw = val; 14796f60e37SRussell King writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN); 14898fb74f4SRussell King 14998fb74f4SRussell King val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest); 15096f60e37SRussell King dplane->dst_hw = val; 15196f60e37SRussell King writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN); 15298fb74f4SRussell King 15398fb74f4SRussell King val = dest.y1 << 16 | dest.x1; 15496f60e37SRussell King dplane->dst_yx = val; 15596f60e37SRussell King writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN); 15698fb74f4SRussell King 15796f60e37SRussell King return 0; 15896f60e37SRussell King } else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) { 15996f60e37SRussell King /* Power up the Y/U/V FIFOs on ENA 0->1 transitions */ 16096f60e37SRussell King armada_updatel(0, CFG_PDWN16x66 | CFG_PDWN32x66, 16196f60e37SRussell King dcrtc->base + LCD_SPU_SRAM_PARA1); 16296f60e37SRussell King } 16396f60e37SRussell King 1644a8506d2SRussell King if (armada_drm_plane_work_wait(&dplane->base, HZ / 25) == 0) 1654a8506d2SRussell King armada_drm_plane_work_cancel(dcrtc, &dplane->base); 16696f60e37SRussell King 16796f60e37SRussell King if (plane->fb != fb) { 16896f60e37SRussell King struct armada_gem_object *obj = drm_fb_obj(fb); 16973068ce3SRussell King uint32_t addr[3], pixel_format; 17073068ce3SRussell King int i, num_planes, hsub; 17196f60e37SRussell King 17296f60e37SRussell King /* 17396f60e37SRussell King * Take a reference on the new framebuffer - we want to 17496f60e37SRussell King * hold on to it while the hardware is displaying it. 17596f60e37SRussell King */ 17696f60e37SRussell King drm_framebuffer_reference(fb); 17796f60e37SRussell King 178fecfdb2dSRussell King if (plane->fb) 179fecfdb2dSRussell King armada_ovl_retire_fb(dplane, plane->fb); 18096f60e37SRussell King 18198fb74f4SRussell King src_y = src.y1 >> 16; 18298fb74f4SRussell King src_x = src.x1 >> 16; 18396f60e37SRussell King 18473068ce3SRussell King pixel_format = fb->pixel_format; 18573068ce3SRussell King hsub = drm_format_horz_chroma_subsampling(pixel_format); 18673068ce3SRussell King num_planes = drm_format_num_planes(pixel_format); 18773068ce3SRussell King 18873068ce3SRussell King /* 18973068ce3SRussell King * Annoyingly, shifting a YUYV-format image by one pixel 19073068ce3SRussell King * causes the U/V planes to toggle. Toggle the UV swap. 19173068ce3SRussell King * (Unfortunately, this causes momentary colour flickering.) 19273068ce3SRussell King */ 19373068ce3SRussell King if (src_x & (hsub - 1) && num_planes == 1) 19473068ce3SRussell King ctrl0 ^= CFG_DMA_MOD(CFG_SWAPUV); 19573068ce3SRussell King 19673068ce3SRussell King for (i = 0; i < num_planes; i++) 19773068ce3SRussell King addr[i] = obj->dev_addr + fb->offsets[i] + 19873068ce3SRussell King src_y * fb->pitches[i] + 19973068ce3SRussell King src_x * drm_format_plane_cpp(pixel_format, i); 20073068ce3SRussell King for (; i < ARRAY_SIZE(addr); i++) 20173068ce3SRussell King addr[i] = 0; 20273068ce3SRussell King 20373068ce3SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addr[0], 20496f60e37SRussell King LCD_SPU_DMA_START_ADDR_Y0); 20573068ce3SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addr[1], 20696f60e37SRussell King LCD_SPU_DMA_START_ADDR_U0); 20773068ce3SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addr[2], 20896f60e37SRussell King LCD_SPU_DMA_START_ADDR_V0); 20973068ce3SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addr[0], 21096f60e37SRussell King LCD_SPU_DMA_START_ADDR_Y1); 21173068ce3SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addr[1], 21296f60e37SRussell King LCD_SPU_DMA_START_ADDR_U1); 21373068ce3SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addr[2], 21496f60e37SRussell King LCD_SPU_DMA_START_ADDR_V1); 21596f60e37SRussell King 21696f60e37SRussell King val = fb->pitches[0] << 16 | fb->pitches[0]; 21796f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 21896f60e37SRussell King LCD_SPU_DMA_PITCH_YC); 21996f60e37SRussell King val = fb->pitches[1] << 16 | fb->pitches[2]; 22096f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 22196f60e37SRussell King LCD_SPU_DMA_PITCH_UV); 22296f60e37SRussell King } 22396f60e37SRussell King 22498fb74f4SRussell King val = (drm_rect_height(&src) & 0xffff0000) | drm_rect_width(&src) >> 16; 22596f60e37SRussell King if (dplane->src_hw != val) { 22696f60e37SRussell King dplane->src_hw = val; 22796f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 22896f60e37SRussell King LCD_SPU_DMA_HPXL_VLN); 22996f60e37SRussell King } 23098fb74f4SRussell King 23198fb74f4SRussell King val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest); 23296f60e37SRussell King if (dplane->dst_hw != val) { 23396f60e37SRussell King dplane->dst_hw = val; 23496f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 23596f60e37SRussell King LCD_SPU_DZM_HPXL_VLN); 23696f60e37SRussell King } 23798fb74f4SRussell King 23898fb74f4SRussell King val = dest.y1 << 16 | dest.x1; 23996f60e37SRussell King if (dplane->dst_yx != val) { 24096f60e37SRussell King dplane->dst_yx = val; 24196f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 24296f60e37SRussell King LCD_SPU_DMA_OVSA_HPXL_VLN); 24396f60e37SRussell King } 24498fb74f4SRussell King 24596f60e37SRussell King if (dplane->ctrl0 != ctrl0) { 24696f60e37SRussell King dplane->ctrl0 = ctrl0; 24796f60e37SRussell King armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0, 24896f60e37SRussell King CFG_CBSH_ENA | CFG_DMAFORMAT | CFG_DMA_FTOGGLE | 24996f60e37SRussell King CFG_DMA_HSMOOTH | CFG_DMA_TSTMODE | 25096f60e37SRussell King CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV | CFG_SWAPYU | 25196f60e37SRussell King CFG_YUV2RGB) | CFG_DMA_ENA, 25296f60e37SRussell King LCD_SPU_DMA_CTRL0); 25396f60e37SRussell King } 25496f60e37SRussell King if (idx) { 25596f60e37SRussell King armada_reg_queue_end(dplane->vbl.regs, idx); 2564a8506d2SRussell King armada_drm_plane_work_queue(dcrtc, &dplane->base, 2574a8506d2SRussell King &dplane->vbl.work); 25896f60e37SRussell King } 25996f60e37SRussell King return 0; 26096f60e37SRussell King } 26196f60e37SRussell King 26228a2aebeSRussell King static int armada_ovl_plane_disable(struct drm_plane *plane) 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; 2774a8506d2SRussell King dplane->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 39196f60e37SRussell King static 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), 463b0b3b795SVille Syrjälä DRM_PLANE_TYPE_OVERLAY, NULL); 46428a2aebeSRussell King if (ret) { 46528a2aebeSRussell King kfree(dplane); 46628a2aebeSRussell King return ret; 46728a2aebeSRussell King } 46896f60e37SRussell King 46996f60e37SRussell King dplane->prop.colorkey_yr = 0xfefefe00; 47096f60e37SRussell King dplane->prop.colorkey_ug = 0x01010100; 47196f60e37SRussell King dplane->prop.colorkey_vb = 0x01010100; 47296f60e37SRussell King dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB); 47396f60e37SRussell King dplane->prop.brightness = 0; 47496f60e37SRussell King dplane->prop.contrast = 0x4000; 47596f60e37SRussell King dplane->prop.saturation = 0x4000; 47696f60e37SRussell King 477561f60bcSRussell King mobj = &dplane->base.base.base; 47896f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_prop, 47996f60e37SRussell King 0x0101fe); 48096f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_min_prop, 48196f60e37SRussell King 0x0101fe); 48296f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_max_prop, 48396f60e37SRussell King 0x0101fe); 48496f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_val_prop, 48596f60e37SRussell King 0x0101fe); 48696f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_alpha_prop, 48796f60e37SRussell King 0x000000); 48896f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_mode_prop, 48996f60e37SRussell King CKMODE_RGB); 49096f60e37SRussell King drm_object_attach_property(mobj, priv->brightness_prop, 256); 49196f60e37SRussell King drm_object_attach_property(mobj, priv->contrast_prop, 49296f60e37SRussell King dplane->prop.contrast); 49396f60e37SRussell King drm_object_attach_property(mobj, priv->saturation_prop, 49496f60e37SRussell King dplane->prop.saturation); 49596f60e37SRussell King 49696f60e37SRussell King return 0; 49796f60e37SRussell King } 498