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> 1096f60e37SRussell King #include "armada_crtc.h" 1196f60e37SRussell King #include "armada_drm.h" 1296f60e37SRussell King #include "armada_fb.h" 1396f60e37SRussell King #include "armada_gem.h" 1496f60e37SRussell King #include "armada_hw.h" 1596f60e37SRussell King #include <drm/armada_drm.h> 1696f60e37SRussell King #include "armada_ioctlP.h" 1796f60e37SRussell King 1896f60e37SRussell King struct armada_plane_properties { 1996f60e37SRussell King uint32_t colorkey_yr; 2096f60e37SRussell King uint32_t colorkey_ug; 2196f60e37SRussell King uint32_t colorkey_vb; 2296f60e37SRussell King #define K2R(val) (((val) >> 0) & 0xff) 2396f60e37SRussell King #define K2G(val) (((val) >> 8) & 0xff) 2496f60e37SRussell King #define K2B(val) (((val) >> 16) & 0xff) 2596f60e37SRussell King int16_t brightness; 2696f60e37SRussell King uint16_t contrast; 2796f60e37SRussell King uint16_t saturation; 2896f60e37SRussell King uint32_t colorkey_mode; 2996f60e37SRussell King }; 3096f60e37SRussell King 3196f60e37SRussell King struct armada_plane { 3296f60e37SRussell King struct drm_plane base; 3396f60e37SRussell King spinlock_t lock; 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 { 4096f60e37SRussell King struct armada_vbl_event update; 4196f60e37SRussell King struct armada_regs regs[13]; 4296f60e37SRussell King wait_queue_head_t wait; 4396f60e37SRussell King } vbl; 4496f60e37SRussell King struct armada_plane_properties prop; 4596f60e37SRussell King }; 4696f60e37SRussell King #define drm_to_armada_plane(p) container_of(p, struct armada_plane, base) 4796f60e37SRussell King 4896f60e37SRussell King 4996f60e37SRussell King static void 5096f60e37SRussell King armada_ovl_update_attr(struct armada_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 7396f60e37SRussell King /* === Plane support === */ 7496f60e37SRussell King static void armada_plane_vbl(struct armada_crtc *dcrtc, void *data) 7596f60e37SRussell King { 7696f60e37SRussell King struct armada_plane *dplane = data; 7796f60e37SRussell King struct drm_framebuffer *fb; 7896f60e37SRussell King 7996f60e37SRussell King armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); 8096f60e37SRussell King 8196f60e37SRussell King spin_lock(&dplane->lock); 8296f60e37SRussell King fb = dplane->old_fb; 8396f60e37SRussell King dplane->old_fb = NULL; 8496f60e37SRussell King spin_unlock(&dplane->lock); 8596f60e37SRussell King 8696f60e37SRussell King if (fb) 8796f60e37SRussell King armada_drm_queue_unref_work(dcrtc->crtc.dev, fb); 8896f60e37SRussell King } 8996f60e37SRussell King 9096f60e37SRussell King static unsigned armada_limit(int start, unsigned size, unsigned max) 9196f60e37SRussell King { 9296f60e37SRussell King int end = start + size; 9396f60e37SRussell King if (end < 0) 9496f60e37SRussell King return 0; 9596f60e37SRussell King if (start < 0) 9696f60e37SRussell King start = 0; 9796f60e37SRussell King return (unsigned)end > max ? max - start : end - start; 9896f60e37SRussell King } 9996f60e37SRussell King 10096f60e37SRussell King static int 10196f60e37SRussell King armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, 10296f60e37SRussell King struct drm_framebuffer *fb, 10396f60e37SRussell King int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h, 10496f60e37SRussell King uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) 10596f60e37SRussell King { 10696f60e37SRussell King struct armada_plane *dplane = drm_to_armada_plane(plane); 10796f60e37SRussell King struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); 10896f60e37SRussell King uint32_t val, ctrl0; 10996f60e37SRussell King unsigned idx = 0; 11096f60e37SRussell King int ret; 11196f60e37SRussell King 11296f60e37SRussell King crtc_w = armada_limit(crtc_x, crtc_w, dcrtc->crtc.mode.hdisplay); 11396f60e37SRussell King crtc_h = armada_limit(crtc_y, crtc_h, dcrtc->crtc.mode.vdisplay); 11496f60e37SRussell King ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) | 11596f60e37SRussell King CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) | 11696f60e37SRussell King CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA; 11796f60e37SRussell King 11896f60e37SRussell King /* Does the position/size result in nothing to display? */ 11996f60e37SRussell King if (crtc_w == 0 || crtc_h == 0) { 12096f60e37SRussell King ctrl0 &= ~CFG_DMA_ENA; 12196f60e37SRussell King } 12296f60e37SRussell King 12396f60e37SRussell King /* 12496f60e37SRussell King * FIXME: if the starting point is off screen, we need to 12596f60e37SRussell King * adjust src_x, src_y, src_w, src_h appropriately, and 12696f60e37SRussell King * according to the scale. 12796f60e37SRussell King */ 12896f60e37SRussell King 12996f60e37SRussell King if (!dcrtc->plane) { 13096f60e37SRussell King dcrtc->plane = plane; 13196f60e37SRussell King armada_ovl_update_attr(&dplane->prop, dcrtc); 13296f60e37SRussell King } 13396f60e37SRussell King 13496f60e37SRussell King /* FIXME: overlay on an interlaced display */ 13596f60e37SRussell King /* Just updating the position/size? */ 13696f60e37SRussell King if (plane->fb == fb && dplane->ctrl0 == ctrl0) { 13796f60e37SRussell King val = (src_h & 0xffff0000) | src_w >> 16; 13896f60e37SRussell King dplane->src_hw = val; 13996f60e37SRussell King writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN); 14096f60e37SRussell King val = crtc_h << 16 | crtc_w; 14196f60e37SRussell King dplane->dst_hw = val; 14296f60e37SRussell King writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN); 14396f60e37SRussell King val = crtc_y << 16 | crtc_x; 14496f60e37SRussell King dplane->dst_yx = val; 14596f60e37SRussell King writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN); 14696f60e37SRussell King return 0; 14796f60e37SRussell King } else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) { 14896f60e37SRussell King /* Power up the Y/U/V FIFOs on ENA 0->1 transitions */ 14996f60e37SRussell King armada_updatel(0, CFG_PDWN16x66 | CFG_PDWN32x66, 15096f60e37SRussell King dcrtc->base + LCD_SPU_SRAM_PARA1); 15196f60e37SRussell King } 15296f60e37SRussell King 15396f60e37SRussell King ret = wait_event_timeout(dplane->vbl.wait, 15496f60e37SRussell King list_empty(&dplane->vbl.update.node), 15596f60e37SRussell King HZ/25); 15696f60e37SRussell King if (ret < 0) 15796f60e37SRussell King return ret; 15896f60e37SRussell King 15996f60e37SRussell King if (plane->fb != fb) { 16096f60e37SRussell King struct armada_gem_object *obj = drm_fb_obj(fb); 16196f60e37SRussell King uint32_t sy, su, sv; 16296f60e37SRussell King 16396f60e37SRussell King /* 16496f60e37SRussell King * Take a reference on the new framebuffer - we want to 16596f60e37SRussell King * hold on to it while the hardware is displaying it. 16696f60e37SRussell King */ 16796f60e37SRussell King drm_framebuffer_reference(fb); 16896f60e37SRussell King 16996f60e37SRussell King if (plane->fb) { 17096f60e37SRussell King struct drm_framebuffer *older_fb; 17196f60e37SRussell King 17296f60e37SRussell King spin_lock_irq(&dplane->lock); 17396f60e37SRussell King older_fb = dplane->old_fb; 17496f60e37SRussell King dplane->old_fb = plane->fb; 17596f60e37SRussell King spin_unlock_irq(&dplane->lock); 17696f60e37SRussell King if (older_fb) 17796f60e37SRussell King armada_drm_queue_unref_work(dcrtc->crtc.dev, 17896f60e37SRussell King older_fb); 17996f60e37SRussell King } 18096f60e37SRussell King 18196f60e37SRussell King src_y >>= 16; 18296f60e37SRussell King src_x >>= 16; 18396f60e37SRussell King sy = obj->dev_addr + fb->offsets[0] + src_y * fb->pitches[0] + 18496f60e37SRussell King src_x * fb->bits_per_pixel / 8; 18596f60e37SRussell King su = obj->dev_addr + fb->offsets[1] + src_y * fb->pitches[1] + 18696f60e37SRussell King src_x; 18796f60e37SRussell King sv = obj->dev_addr + fb->offsets[2] + src_y * fb->pitches[2] + 18896f60e37SRussell King src_x; 18996f60e37SRussell King 19096f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, sy, 19196f60e37SRussell King LCD_SPU_DMA_START_ADDR_Y0); 19296f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, su, 19396f60e37SRussell King LCD_SPU_DMA_START_ADDR_U0); 19496f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, sv, 19596f60e37SRussell King LCD_SPU_DMA_START_ADDR_V0); 19696f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, sy, 19796f60e37SRussell King LCD_SPU_DMA_START_ADDR_Y1); 19896f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, su, 19996f60e37SRussell King LCD_SPU_DMA_START_ADDR_U1); 20096f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, sv, 20196f60e37SRussell King LCD_SPU_DMA_START_ADDR_V1); 20296f60e37SRussell King 20396f60e37SRussell King val = fb->pitches[0] << 16 | fb->pitches[0]; 20496f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 20596f60e37SRussell King LCD_SPU_DMA_PITCH_YC); 20696f60e37SRussell King val = fb->pitches[1] << 16 | fb->pitches[2]; 20796f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 20896f60e37SRussell King LCD_SPU_DMA_PITCH_UV); 20996f60e37SRussell King } 21096f60e37SRussell King 21196f60e37SRussell King val = (src_h & 0xffff0000) | src_w >> 16; 21296f60e37SRussell King if (dplane->src_hw != val) { 21396f60e37SRussell King dplane->src_hw = val; 21496f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 21596f60e37SRussell King LCD_SPU_DMA_HPXL_VLN); 21696f60e37SRussell King } 21796f60e37SRussell King val = crtc_h << 16 | crtc_w; 21896f60e37SRussell King if (dplane->dst_hw != val) { 21996f60e37SRussell King dplane->dst_hw = val; 22096f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 22196f60e37SRussell King LCD_SPU_DZM_HPXL_VLN); 22296f60e37SRussell King } 22396f60e37SRussell King val = crtc_y << 16 | crtc_x; 22496f60e37SRussell King if (dplane->dst_yx != val) { 22596f60e37SRussell King dplane->dst_yx = val; 22696f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 22796f60e37SRussell King LCD_SPU_DMA_OVSA_HPXL_VLN); 22896f60e37SRussell King } 22996f60e37SRussell King if (dplane->ctrl0 != ctrl0) { 23096f60e37SRussell King dplane->ctrl0 = ctrl0; 23196f60e37SRussell King armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0, 23296f60e37SRussell King CFG_CBSH_ENA | CFG_DMAFORMAT | CFG_DMA_FTOGGLE | 23396f60e37SRussell King CFG_DMA_HSMOOTH | CFG_DMA_TSTMODE | 23496f60e37SRussell King CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV | CFG_SWAPYU | 23596f60e37SRussell King CFG_YUV2RGB) | CFG_DMA_ENA, 23696f60e37SRussell King LCD_SPU_DMA_CTRL0); 23796f60e37SRussell King } 23896f60e37SRussell King if (idx) { 23996f60e37SRussell King armada_reg_queue_end(dplane->vbl.regs, idx); 24096f60e37SRussell King armada_drm_vbl_event_add(dcrtc, &dplane->vbl.update); 24196f60e37SRussell King } 24296f60e37SRussell King return 0; 24396f60e37SRussell King } 24496f60e37SRussell King 24596f60e37SRussell King static int armada_plane_disable(struct drm_plane *plane) 24696f60e37SRussell King { 24796f60e37SRussell King struct armada_plane *dplane = drm_to_armada_plane(plane); 24896f60e37SRussell King struct drm_framebuffer *fb; 24996f60e37SRussell King struct armada_crtc *dcrtc; 25096f60e37SRussell King 25196f60e37SRussell King if (!dplane->base.crtc) 25296f60e37SRussell King return 0; 25396f60e37SRussell King 25496f60e37SRussell King dcrtc = drm_to_armada_crtc(dplane->base.crtc); 25596f60e37SRussell King dcrtc->plane = NULL; 25696f60e37SRussell King 25796f60e37SRussell King spin_lock_irq(&dcrtc->irq_lock); 25896f60e37SRussell King armada_drm_vbl_event_remove(dcrtc, &dplane->vbl.update); 25996f60e37SRussell King armada_updatel(0, CFG_DMA_ENA, dcrtc->base + LCD_SPU_DMA_CTRL0); 26096f60e37SRussell King dplane->ctrl0 = 0; 26196f60e37SRussell King spin_unlock_irq(&dcrtc->irq_lock); 26296f60e37SRussell King 26396f60e37SRussell King /* Power down the Y/U/V FIFOs */ 26496f60e37SRussell King armada_updatel(CFG_PDWN16x66 | CFG_PDWN32x66, 0, 26596f60e37SRussell King dcrtc->base + LCD_SPU_SRAM_PARA1); 26696f60e37SRussell King 26796f60e37SRussell King if (plane->fb) 26896f60e37SRussell King drm_framebuffer_unreference(plane->fb); 26996f60e37SRussell King 27096f60e37SRussell King spin_lock_irq(&dplane->lock); 27196f60e37SRussell King fb = dplane->old_fb; 27296f60e37SRussell King dplane->old_fb = NULL; 27396f60e37SRussell King spin_unlock_irq(&dplane->lock); 27496f60e37SRussell King if (fb) 27596f60e37SRussell King drm_framebuffer_unreference(fb); 27696f60e37SRussell King 27796f60e37SRussell King return 0; 27896f60e37SRussell King } 27996f60e37SRussell King 28096f60e37SRussell King static void armada_plane_destroy(struct drm_plane *plane) 28196f60e37SRussell King { 28296f60e37SRussell King kfree(plane); 28396f60e37SRussell King } 28496f60e37SRussell King 28596f60e37SRussell King static int armada_plane_set_property(struct drm_plane *plane, 28696f60e37SRussell King struct drm_property *property, uint64_t val) 28796f60e37SRussell King { 28896f60e37SRussell King struct armada_private *priv = plane->dev->dev_private; 28996f60e37SRussell King struct armada_plane *dplane = drm_to_armada_plane(plane); 29096f60e37SRussell King bool update_attr = false; 29196f60e37SRussell King 29296f60e37SRussell King if (property == priv->colorkey_prop) { 29396f60e37SRussell King #define CCC(v) ((v) << 24 | (v) << 16 | (v) << 8) 29496f60e37SRussell King dplane->prop.colorkey_yr = CCC(K2R(val)); 29596f60e37SRussell King dplane->prop.colorkey_ug = CCC(K2G(val)); 29696f60e37SRussell King dplane->prop.colorkey_vb = CCC(K2B(val)); 29796f60e37SRussell King #undef CCC 29896f60e37SRussell King update_attr = true; 29996f60e37SRussell King } else if (property == priv->colorkey_min_prop) { 30096f60e37SRussell King dplane->prop.colorkey_yr &= ~0x00ff0000; 30196f60e37SRussell King dplane->prop.colorkey_yr |= K2R(val) << 16; 30296f60e37SRussell King dplane->prop.colorkey_ug &= ~0x00ff0000; 30396f60e37SRussell King dplane->prop.colorkey_ug |= K2G(val) << 16; 30496f60e37SRussell King dplane->prop.colorkey_vb &= ~0x00ff0000; 30596f60e37SRussell King dplane->prop.colorkey_vb |= K2B(val) << 16; 30696f60e37SRussell King update_attr = true; 30796f60e37SRussell King } else if (property == priv->colorkey_max_prop) { 30896f60e37SRussell King dplane->prop.colorkey_yr &= ~0xff000000; 30996f60e37SRussell King dplane->prop.colorkey_yr |= K2R(val) << 24; 31096f60e37SRussell King dplane->prop.colorkey_ug &= ~0xff000000; 31196f60e37SRussell King dplane->prop.colorkey_ug |= K2G(val) << 24; 31296f60e37SRussell King dplane->prop.colorkey_vb &= ~0xff000000; 31396f60e37SRussell King dplane->prop.colorkey_vb |= K2B(val) << 24; 31496f60e37SRussell King update_attr = true; 31596f60e37SRussell King } else if (property == priv->colorkey_val_prop) { 31696f60e37SRussell King dplane->prop.colorkey_yr &= ~0x0000ff00; 31796f60e37SRussell King dplane->prop.colorkey_yr |= K2R(val) << 8; 31896f60e37SRussell King dplane->prop.colorkey_ug &= ~0x0000ff00; 31996f60e37SRussell King dplane->prop.colorkey_ug |= K2G(val) << 8; 32096f60e37SRussell King dplane->prop.colorkey_vb &= ~0x0000ff00; 32196f60e37SRussell King dplane->prop.colorkey_vb |= K2B(val) << 8; 32296f60e37SRussell King update_attr = true; 32396f60e37SRussell King } else if (property == priv->colorkey_alpha_prop) { 32496f60e37SRussell King dplane->prop.colorkey_yr &= ~0x000000ff; 32596f60e37SRussell King dplane->prop.colorkey_yr |= K2R(val); 32696f60e37SRussell King dplane->prop.colorkey_ug &= ~0x000000ff; 32796f60e37SRussell King dplane->prop.colorkey_ug |= K2G(val); 32896f60e37SRussell King dplane->prop.colorkey_vb &= ~0x000000ff; 32996f60e37SRussell King dplane->prop.colorkey_vb |= K2B(val); 33096f60e37SRussell King update_attr = true; 33196f60e37SRussell King } else if (property == priv->colorkey_mode_prop) { 33296f60e37SRussell King dplane->prop.colorkey_mode &= ~CFG_CKMODE_MASK; 33396f60e37SRussell King dplane->prop.colorkey_mode |= CFG_CKMODE(val); 33496f60e37SRussell King update_attr = true; 33596f60e37SRussell King } else if (property == priv->brightness_prop) { 33696f60e37SRussell King dplane->prop.brightness = val - 256; 33796f60e37SRussell King update_attr = true; 33896f60e37SRussell King } else if (property == priv->contrast_prop) { 33996f60e37SRussell King dplane->prop.contrast = val; 34096f60e37SRussell King update_attr = true; 34196f60e37SRussell King } else if (property == priv->saturation_prop) { 34296f60e37SRussell King dplane->prop.saturation = val; 34396f60e37SRussell King update_attr = true; 34496f60e37SRussell King } 34596f60e37SRussell King 34696f60e37SRussell King if (update_attr && dplane->base.crtc) 34796f60e37SRussell King armada_ovl_update_attr(&dplane->prop, 34896f60e37SRussell King drm_to_armada_crtc(dplane->base.crtc)); 34996f60e37SRussell King 35096f60e37SRussell King return 0; 35196f60e37SRussell King } 35296f60e37SRussell King 35396f60e37SRussell King static const struct drm_plane_funcs armada_plane_funcs = { 35496f60e37SRussell King .update_plane = armada_plane_update, 35596f60e37SRussell King .disable_plane = armada_plane_disable, 35696f60e37SRussell King .destroy = armada_plane_destroy, 35796f60e37SRussell King .set_property = armada_plane_set_property, 35896f60e37SRussell King }; 35996f60e37SRussell King 36096f60e37SRussell King static const uint32_t armada_formats[] = { 36196f60e37SRussell King DRM_FORMAT_UYVY, 36296f60e37SRussell King DRM_FORMAT_YUYV, 36396f60e37SRussell King DRM_FORMAT_YUV420, 36496f60e37SRussell King DRM_FORMAT_YVU420, 36596f60e37SRussell King DRM_FORMAT_YUV422, 36696f60e37SRussell King DRM_FORMAT_YVU422, 36796f60e37SRussell King DRM_FORMAT_VYUY, 36896f60e37SRussell King DRM_FORMAT_YVYU, 36996f60e37SRussell King DRM_FORMAT_ARGB8888, 37096f60e37SRussell King DRM_FORMAT_ABGR8888, 37196f60e37SRussell King DRM_FORMAT_XRGB8888, 37296f60e37SRussell King DRM_FORMAT_XBGR8888, 37396f60e37SRussell King DRM_FORMAT_RGB888, 37496f60e37SRussell King DRM_FORMAT_BGR888, 37596f60e37SRussell King DRM_FORMAT_ARGB1555, 37696f60e37SRussell King DRM_FORMAT_ABGR1555, 37796f60e37SRussell King DRM_FORMAT_RGB565, 37896f60e37SRussell King DRM_FORMAT_BGR565, 37996f60e37SRussell King }; 38096f60e37SRussell King 38196f60e37SRussell King static struct drm_prop_enum_list armada_drm_colorkey_enum_list[] = { 38296f60e37SRussell King { CKMODE_DISABLE, "disabled" }, 38396f60e37SRussell King { CKMODE_Y, "Y component" }, 38496f60e37SRussell King { CKMODE_U, "U component" }, 38596f60e37SRussell King { CKMODE_V, "V component" }, 38696f60e37SRussell King { CKMODE_RGB, "RGB" }, 38796f60e37SRussell King { CKMODE_R, "R component" }, 38896f60e37SRussell King { CKMODE_G, "G component" }, 38996f60e37SRussell King { CKMODE_B, "B component" }, 39096f60e37SRussell King }; 39196f60e37SRussell King 39296f60e37SRussell King static int armada_overlay_create_properties(struct drm_device *dev) 39396f60e37SRussell King { 39496f60e37SRussell King struct armada_private *priv = dev->dev_private; 39596f60e37SRussell King 39696f60e37SRussell King if (priv->colorkey_prop) 39796f60e37SRussell King return 0; 39896f60e37SRussell King 39996f60e37SRussell King priv->colorkey_prop = drm_property_create_range(dev, 0, 40096f60e37SRussell King "colorkey", 0, 0xffffff); 40196f60e37SRussell King priv->colorkey_min_prop = drm_property_create_range(dev, 0, 40296f60e37SRussell King "colorkey_min", 0, 0xffffff); 40396f60e37SRussell King priv->colorkey_max_prop = drm_property_create_range(dev, 0, 40496f60e37SRussell King "colorkey_max", 0, 0xffffff); 40596f60e37SRussell King priv->colorkey_val_prop = drm_property_create_range(dev, 0, 40696f60e37SRussell King "colorkey_val", 0, 0xffffff); 40796f60e37SRussell King priv->colorkey_alpha_prop = drm_property_create_range(dev, 0, 40896f60e37SRussell King "colorkey_alpha", 0, 0xffffff); 40996f60e37SRussell King priv->colorkey_mode_prop = drm_property_create_enum(dev, 0, 41096f60e37SRussell King "colorkey_mode", 41196f60e37SRussell King armada_drm_colorkey_enum_list, 41296f60e37SRussell King ARRAY_SIZE(armada_drm_colorkey_enum_list)); 41396f60e37SRussell King priv->brightness_prop = drm_property_create_range(dev, 0, 41496f60e37SRussell King "brightness", 0, 256 + 255); 41596f60e37SRussell King priv->contrast_prop = drm_property_create_range(dev, 0, 41696f60e37SRussell King "contrast", 0, 0x7fff); 41796f60e37SRussell King priv->saturation_prop = drm_property_create_range(dev, 0, 41896f60e37SRussell King "saturation", 0, 0x7fff); 41996f60e37SRussell King 42096f60e37SRussell King if (!priv->colorkey_prop) 42196f60e37SRussell King return -ENOMEM; 42296f60e37SRussell King 42396f60e37SRussell King return 0; 42496f60e37SRussell King } 42596f60e37SRussell King 42696f60e37SRussell King int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) 42796f60e37SRussell King { 42896f60e37SRussell King struct armada_private *priv = dev->dev_private; 42996f60e37SRussell King struct drm_mode_object *mobj; 43096f60e37SRussell King struct armada_plane *dplane; 43196f60e37SRussell King int ret; 43296f60e37SRussell King 43396f60e37SRussell King ret = armada_overlay_create_properties(dev); 43496f60e37SRussell King if (ret) 43596f60e37SRussell King return ret; 43696f60e37SRussell King 43796f60e37SRussell King dplane = kzalloc(sizeof(*dplane), GFP_KERNEL); 43896f60e37SRussell King if (!dplane) 43996f60e37SRussell King return -ENOMEM; 44096f60e37SRussell King 44196f60e37SRussell King spin_lock_init(&dplane->lock); 44296f60e37SRussell King init_waitqueue_head(&dplane->vbl.wait); 44396f60e37SRussell King armada_drm_vbl_event_init(&dplane->vbl.update, armada_plane_vbl, 44496f60e37SRussell King dplane); 44596f60e37SRussell King 44696f60e37SRussell King drm_plane_init(dev, &dplane->base, crtcs, &armada_plane_funcs, 44796f60e37SRussell King armada_formats, ARRAY_SIZE(armada_formats), false); 44896f60e37SRussell King 44996f60e37SRussell King dplane->prop.colorkey_yr = 0xfefefe00; 45096f60e37SRussell King dplane->prop.colorkey_ug = 0x01010100; 45196f60e37SRussell King dplane->prop.colorkey_vb = 0x01010100; 45296f60e37SRussell King dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB); 45396f60e37SRussell King dplane->prop.brightness = 0; 45496f60e37SRussell King dplane->prop.contrast = 0x4000; 45596f60e37SRussell King dplane->prop.saturation = 0x4000; 45696f60e37SRussell King 45796f60e37SRussell King mobj = &dplane->base.base; 45896f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_prop, 45996f60e37SRussell King 0x0101fe); 46096f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_min_prop, 46196f60e37SRussell King 0x0101fe); 46296f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_max_prop, 46396f60e37SRussell King 0x0101fe); 46496f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_val_prop, 46596f60e37SRussell King 0x0101fe); 46696f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_alpha_prop, 46796f60e37SRussell King 0x000000); 46896f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_mode_prop, 46996f60e37SRussell King CKMODE_RGB); 47096f60e37SRussell King drm_object_attach_property(mobj, priv->brightness_prop, 256); 47196f60e37SRussell King drm_object_attach_property(mobj, priv->contrast_prop, 47296f60e37SRussell King dplane->prop.contrast); 47396f60e37SRussell King drm_object_attach_property(mobj, priv->saturation_prop, 47496f60e37SRussell King dplane->prop.saturation); 47596f60e37SRussell King 47696f60e37SRussell King return 0; 47796f60e37SRussell King } 478