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 { 4096f60e37SRussell King struct armada_vbl_event update; 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 === */ 8528a2aebeSRussell King static void armada_ovl_plane_vbl(struct armada_crtc *dcrtc, void *data) 8696f60e37SRussell King { 8728a2aebeSRussell King struct armada_ovl_plane *dplane = data; 8896f60e37SRussell King 8996f60e37SRussell King armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); 90fecfdb2dSRussell King armada_ovl_retire_fb(dplane, NULL); 91070f3f6bSRussell King 925740d27fSRussell King wake_up(&dplane->base.frame_wait); 9396f60e37SRussell King } 9496f60e37SRussell King 9596f60e37SRussell King static int 9628a2aebeSRussell King armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, 9796f60e37SRussell King struct drm_framebuffer *fb, 9896f60e37SRussell King int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h, 9996f60e37SRussell King uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) 10096f60e37SRussell King { 10128a2aebeSRussell King struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); 10296f60e37SRussell King struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); 10398fb74f4SRussell King struct drm_rect src = { 10498fb74f4SRussell King .x1 = src_x, 10598fb74f4SRussell King .y1 = src_y, 10698fb74f4SRussell King .x2 = src_x + src_w, 10798fb74f4SRussell King .y2 = src_y + src_h, 10898fb74f4SRussell King }; 10998fb74f4SRussell King struct drm_rect dest = { 11098fb74f4SRussell King .x1 = crtc_x, 11198fb74f4SRussell King .y1 = crtc_y, 11298fb74f4SRussell King .x2 = crtc_x + crtc_w, 11398fb74f4SRussell King .y2 = crtc_y + crtc_h, 11498fb74f4SRussell King }; 11598fb74f4SRussell King const struct drm_rect clip = { 11698fb74f4SRussell King .x2 = crtc->mode.hdisplay, 11798fb74f4SRussell King .y2 = crtc->mode.vdisplay, 11898fb74f4SRussell King }; 11996f60e37SRussell King uint32_t val, ctrl0; 12096f60e37SRussell King unsigned idx = 0; 12198fb74f4SRussell King bool visible; 12296f60e37SRussell King int ret; 12396f60e37SRussell King 12498fb74f4SRussell King ret = drm_plane_helper_check_update(plane, crtc, fb, &src, &dest, &clip, 12598fb74f4SRussell King 0, INT_MAX, true, false, &visible); 12698fb74f4SRussell King if (ret) 12798fb74f4SRussell King return ret; 12898fb74f4SRussell King 12996f60e37SRussell King ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) | 13096f60e37SRussell King CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) | 13196f60e37SRussell King CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA; 13296f60e37SRussell King 13396f60e37SRussell King /* Does the position/size result in nothing to display? */ 13498fb74f4SRussell King if (!visible) 13596f60e37SRussell King ctrl0 &= ~CFG_DMA_ENA; 13696f60e37SRussell King 13796f60e37SRussell King if (!dcrtc->plane) { 13896f60e37SRussell King dcrtc->plane = plane; 13996f60e37SRussell King armada_ovl_update_attr(&dplane->prop, dcrtc); 14096f60e37SRussell King } 14196f60e37SRussell King 14296f60e37SRussell King /* FIXME: overlay on an interlaced display */ 14396f60e37SRussell King /* Just updating the position/size? */ 14496f60e37SRussell King if (plane->fb == fb && dplane->ctrl0 == ctrl0) { 14598fb74f4SRussell King val = (drm_rect_height(&src) & 0xffff0000) | 14698fb74f4SRussell King drm_rect_width(&src) >> 16; 14796f60e37SRussell King dplane->src_hw = val; 14896f60e37SRussell King writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN); 14998fb74f4SRussell King 15098fb74f4SRussell King val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest); 15196f60e37SRussell King dplane->dst_hw = val; 15296f60e37SRussell King writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN); 15398fb74f4SRussell King 15498fb74f4SRussell King val = dest.y1 << 16 | dest.x1; 15596f60e37SRussell King dplane->dst_yx = val; 15696f60e37SRussell King writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN); 15798fb74f4SRussell King 15896f60e37SRussell King return 0; 15996f60e37SRussell King } else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) { 16096f60e37SRussell King /* Power up the Y/U/V FIFOs on ENA 0->1 transitions */ 16196f60e37SRussell King armada_updatel(0, CFG_PDWN16x66 | CFG_PDWN32x66, 16296f60e37SRussell King dcrtc->base + LCD_SPU_SRAM_PARA1); 16396f60e37SRussell King } 16496f60e37SRussell King 1655740d27fSRussell King wait_event_timeout(dplane->base.frame_wait, 16696f60e37SRussell King list_empty(&dplane->vbl.update.node), 16796f60e37SRussell King HZ/25); 16896f60e37SRussell King 16996f60e37SRussell King if (plane->fb != fb) { 17096f60e37SRussell King struct armada_gem_object *obj = drm_fb_obj(fb); 17173068ce3SRussell King uint32_t addr[3], pixel_format; 17273068ce3SRussell King int i, num_planes, hsub; 17396f60e37SRussell King 17496f60e37SRussell King /* 17596f60e37SRussell King * Take a reference on the new framebuffer - we want to 17696f60e37SRussell King * hold on to it while the hardware is displaying it. 17796f60e37SRussell King */ 17896f60e37SRussell King drm_framebuffer_reference(fb); 17996f60e37SRussell King 180fecfdb2dSRussell King if (plane->fb) 181fecfdb2dSRussell King armada_ovl_retire_fb(dplane, plane->fb); 18296f60e37SRussell King 18398fb74f4SRussell King src_y = src.y1 >> 16; 18498fb74f4SRussell King src_x = src.x1 >> 16; 18596f60e37SRussell King 18673068ce3SRussell King pixel_format = fb->pixel_format; 18773068ce3SRussell King hsub = drm_format_horz_chroma_subsampling(pixel_format); 18873068ce3SRussell King num_planes = drm_format_num_planes(pixel_format); 18973068ce3SRussell King 19073068ce3SRussell King /* 19173068ce3SRussell King * Annoyingly, shifting a YUYV-format image by one pixel 19273068ce3SRussell King * causes the U/V planes to toggle. Toggle the UV swap. 19373068ce3SRussell King * (Unfortunately, this causes momentary colour flickering.) 19473068ce3SRussell King */ 19573068ce3SRussell King if (src_x & (hsub - 1) && num_planes == 1) 19673068ce3SRussell King ctrl0 ^= CFG_DMA_MOD(CFG_SWAPUV); 19773068ce3SRussell King 19873068ce3SRussell King for (i = 0; i < num_planes; i++) 19973068ce3SRussell King addr[i] = obj->dev_addr + fb->offsets[i] + 20073068ce3SRussell King src_y * fb->pitches[i] + 20173068ce3SRussell King src_x * drm_format_plane_cpp(pixel_format, i); 20273068ce3SRussell King for (; i < ARRAY_SIZE(addr); i++) 20373068ce3SRussell King addr[i] = 0; 20473068ce3SRussell King 20573068ce3SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addr[0], 20696f60e37SRussell King LCD_SPU_DMA_START_ADDR_Y0); 20773068ce3SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addr[1], 20896f60e37SRussell King LCD_SPU_DMA_START_ADDR_U0); 20973068ce3SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addr[2], 21096f60e37SRussell King LCD_SPU_DMA_START_ADDR_V0); 21173068ce3SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addr[0], 21296f60e37SRussell King LCD_SPU_DMA_START_ADDR_Y1); 21373068ce3SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addr[1], 21496f60e37SRussell King LCD_SPU_DMA_START_ADDR_U1); 21573068ce3SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, addr[2], 21696f60e37SRussell King LCD_SPU_DMA_START_ADDR_V1); 21796f60e37SRussell King 21896f60e37SRussell King val = fb->pitches[0] << 16 | fb->pitches[0]; 21996f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 22096f60e37SRussell King LCD_SPU_DMA_PITCH_YC); 22196f60e37SRussell King val = fb->pitches[1] << 16 | fb->pitches[2]; 22296f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 22396f60e37SRussell King LCD_SPU_DMA_PITCH_UV); 22496f60e37SRussell King } 22596f60e37SRussell King 22698fb74f4SRussell King val = (drm_rect_height(&src) & 0xffff0000) | drm_rect_width(&src) >> 16; 22796f60e37SRussell King if (dplane->src_hw != val) { 22896f60e37SRussell King dplane->src_hw = val; 22996f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 23096f60e37SRussell King LCD_SPU_DMA_HPXL_VLN); 23196f60e37SRussell King } 23298fb74f4SRussell King 23398fb74f4SRussell King val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest); 23496f60e37SRussell King if (dplane->dst_hw != val) { 23596f60e37SRussell King dplane->dst_hw = val; 23696f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 23796f60e37SRussell King LCD_SPU_DZM_HPXL_VLN); 23896f60e37SRussell King } 23998fb74f4SRussell King 24098fb74f4SRussell King val = dest.y1 << 16 | dest.x1; 24196f60e37SRussell King if (dplane->dst_yx != val) { 24296f60e37SRussell King dplane->dst_yx = val; 24396f60e37SRussell King armada_reg_queue_set(dplane->vbl.regs, idx, val, 24496f60e37SRussell King LCD_SPU_DMA_OVSA_HPXL_VLN); 24596f60e37SRussell King } 24698fb74f4SRussell King 24796f60e37SRussell King if (dplane->ctrl0 != ctrl0) { 24896f60e37SRussell King dplane->ctrl0 = ctrl0; 24996f60e37SRussell King armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0, 25096f60e37SRussell King CFG_CBSH_ENA | CFG_DMAFORMAT | CFG_DMA_FTOGGLE | 25196f60e37SRussell King CFG_DMA_HSMOOTH | CFG_DMA_TSTMODE | 25296f60e37SRussell King CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV | CFG_SWAPYU | 25396f60e37SRussell King CFG_YUV2RGB) | CFG_DMA_ENA, 25496f60e37SRussell King LCD_SPU_DMA_CTRL0); 25596f60e37SRussell King } 25696f60e37SRussell King if (idx) { 25796f60e37SRussell King armada_reg_queue_end(dplane->vbl.regs, idx); 25896f60e37SRussell King armada_drm_vbl_event_add(dcrtc, &dplane->vbl.update); 25996f60e37SRussell King } 26096f60e37SRussell King return 0; 26196f60e37SRussell King } 26296f60e37SRussell King 26328a2aebeSRussell King static int armada_ovl_plane_disable(struct drm_plane *plane) 26496f60e37SRussell King { 26528a2aebeSRussell King struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); 26696f60e37SRussell King struct drm_framebuffer *fb; 26796f60e37SRussell King struct armada_crtc *dcrtc; 26896f60e37SRussell King 269561f60bcSRussell King if (!dplane->base.base.crtc) 27096f60e37SRussell King return 0; 27196f60e37SRussell King 272561f60bcSRussell King dcrtc = drm_to_armada_crtc(dplane->base.base.crtc); 27396f60e37SRussell King dcrtc->plane = NULL; 27496f60e37SRussell King 27596f60e37SRussell King armada_drm_vbl_event_remove(dcrtc, &dplane->vbl.update); 27696f60e37SRussell King 2775c8752c6SRussell King dplane->ctrl0 = 0; 2785c8752c6SRussell King 27958326803SRussell King armada_drm_crtc_plane_disable(dcrtc, plane); 28096f60e37SRussell King 28166377efaSRussell King fb = xchg(&dplane->old_fb, NULL); 28296f60e37SRussell King if (fb) 28396f60e37SRussell King drm_framebuffer_unreference(fb); 28496f60e37SRussell King 28596f60e37SRussell King return 0; 28696f60e37SRussell King } 28796f60e37SRussell King 28828a2aebeSRussell King static void armada_ovl_plane_destroy(struct drm_plane *plane) 28996f60e37SRussell King { 29028a2aebeSRussell King struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); 29141dbb2dbSRussell King 29241dbb2dbSRussell King drm_plane_cleanup(plane); 29341dbb2dbSRussell King 29441dbb2dbSRussell King kfree(dplane); 29596f60e37SRussell King } 29696f60e37SRussell King 29728a2aebeSRussell King static int armada_ovl_plane_set_property(struct drm_plane *plane, 29896f60e37SRussell King struct drm_property *property, uint64_t val) 29996f60e37SRussell King { 30096f60e37SRussell King struct armada_private *priv = plane->dev->dev_private; 30128a2aebeSRussell King struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); 30296f60e37SRussell King bool update_attr = false; 30396f60e37SRussell King 30496f60e37SRussell King if (property == priv->colorkey_prop) { 30596f60e37SRussell King #define CCC(v) ((v) << 24 | (v) << 16 | (v) << 8) 30696f60e37SRussell King dplane->prop.colorkey_yr = CCC(K2R(val)); 30796f60e37SRussell King dplane->prop.colorkey_ug = CCC(K2G(val)); 30896f60e37SRussell King dplane->prop.colorkey_vb = CCC(K2B(val)); 30996f60e37SRussell King #undef CCC 31096f60e37SRussell King update_attr = true; 31196f60e37SRussell King } else if (property == priv->colorkey_min_prop) { 31296f60e37SRussell King dplane->prop.colorkey_yr &= ~0x00ff0000; 31396f60e37SRussell King dplane->prop.colorkey_yr |= K2R(val) << 16; 31496f60e37SRussell King dplane->prop.colorkey_ug &= ~0x00ff0000; 31596f60e37SRussell King dplane->prop.colorkey_ug |= K2G(val) << 16; 31696f60e37SRussell King dplane->prop.colorkey_vb &= ~0x00ff0000; 31796f60e37SRussell King dplane->prop.colorkey_vb |= K2B(val) << 16; 31896f60e37SRussell King update_attr = true; 31996f60e37SRussell King } else if (property == priv->colorkey_max_prop) { 32096f60e37SRussell King dplane->prop.colorkey_yr &= ~0xff000000; 32196f60e37SRussell King dplane->prop.colorkey_yr |= K2R(val) << 24; 32296f60e37SRussell King dplane->prop.colorkey_ug &= ~0xff000000; 32396f60e37SRussell King dplane->prop.colorkey_ug |= K2G(val) << 24; 32496f60e37SRussell King dplane->prop.colorkey_vb &= ~0xff000000; 32596f60e37SRussell King dplane->prop.colorkey_vb |= K2B(val) << 24; 32696f60e37SRussell King update_attr = true; 32796f60e37SRussell King } else if (property == priv->colorkey_val_prop) { 32896f60e37SRussell King dplane->prop.colorkey_yr &= ~0x0000ff00; 32996f60e37SRussell King dplane->prop.colorkey_yr |= K2R(val) << 8; 33096f60e37SRussell King dplane->prop.colorkey_ug &= ~0x0000ff00; 33196f60e37SRussell King dplane->prop.colorkey_ug |= K2G(val) << 8; 33296f60e37SRussell King dplane->prop.colorkey_vb &= ~0x0000ff00; 33396f60e37SRussell King dplane->prop.colorkey_vb |= K2B(val) << 8; 33496f60e37SRussell King update_attr = true; 33596f60e37SRussell King } else if (property == priv->colorkey_alpha_prop) { 33696f60e37SRussell King dplane->prop.colorkey_yr &= ~0x000000ff; 33796f60e37SRussell King dplane->prop.colorkey_yr |= K2R(val); 33896f60e37SRussell King dplane->prop.colorkey_ug &= ~0x000000ff; 33996f60e37SRussell King dplane->prop.colorkey_ug |= K2G(val); 34096f60e37SRussell King dplane->prop.colorkey_vb &= ~0x000000ff; 34196f60e37SRussell King dplane->prop.colorkey_vb |= K2B(val); 34296f60e37SRussell King update_attr = true; 34396f60e37SRussell King } else if (property == priv->colorkey_mode_prop) { 34496f60e37SRussell King dplane->prop.colorkey_mode &= ~CFG_CKMODE_MASK; 34596f60e37SRussell King dplane->prop.colorkey_mode |= CFG_CKMODE(val); 34696f60e37SRussell King update_attr = true; 34796f60e37SRussell King } else if (property == priv->brightness_prop) { 34896f60e37SRussell King dplane->prop.brightness = val - 256; 34996f60e37SRussell King update_attr = true; 35096f60e37SRussell King } else if (property == priv->contrast_prop) { 35196f60e37SRussell King dplane->prop.contrast = val; 35296f60e37SRussell King update_attr = true; 35396f60e37SRussell King } else if (property == priv->saturation_prop) { 35496f60e37SRussell King dplane->prop.saturation = val; 35596f60e37SRussell King update_attr = true; 35696f60e37SRussell King } 35796f60e37SRussell King 358561f60bcSRussell King if (update_attr && dplane->base.base.crtc) 35996f60e37SRussell King armada_ovl_update_attr(&dplane->prop, 360561f60bcSRussell King drm_to_armada_crtc(dplane->base.base.crtc)); 36196f60e37SRussell King 36296f60e37SRussell King return 0; 36396f60e37SRussell King } 36496f60e37SRussell King 36528a2aebeSRussell King static const struct drm_plane_funcs armada_ovl_plane_funcs = { 36628a2aebeSRussell King .update_plane = armada_ovl_plane_update, 36728a2aebeSRussell King .disable_plane = armada_ovl_plane_disable, 36828a2aebeSRussell King .destroy = armada_ovl_plane_destroy, 36928a2aebeSRussell King .set_property = armada_ovl_plane_set_property, 37096f60e37SRussell King }; 37196f60e37SRussell King 37228a2aebeSRussell King static const uint32_t armada_ovl_formats[] = { 37396f60e37SRussell King DRM_FORMAT_UYVY, 37496f60e37SRussell King DRM_FORMAT_YUYV, 37596f60e37SRussell King DRM_FORMAT_YUV420, 37696f60e37SRussell King DRM_FORMAT_YVU420, 37796f60e37SRussell King DRM_FORMAT_YUV422, 37896f60e37SRussell King DRM_FORMAT_YVU422, 37996f60e37SRussell King DRM_FORMAT_VYUY, 38096f60e37SRussell King DRM_FORMAT_YVYU, 38196f60e37SRussell King DRM_FORMAT_ARGB8888, 38296f60e37SRussell King DRM_FORMAT_ABGR8888, 38396f60e37SRussell King DRM_FORMAT_XRGB8888, 38496f60e37SRussell King DRM_FORMAT_XBGR8888, 38596f60e37SRussell King DRM_FORMAT_RGB888, 38696f60e37SRussell King DRM_FORMAT_BGR888, 38796f60e37SRussell King DRM_FORMAT_ARGB1555, 38896f60e37SRussell King DRM_FORMAT_ABGR1555, 38996f60e37SRussell King DRM_FORMAT_RGB565, 39096f60e37SRussell King DRM_FORMAT_BGR565, 39196f60e37SRussell King }; 39296f60e37SRussell King 39396f60e37SRussell King static struct drm_prop_enum_list armada_drm_colorkey_enum_list[] = { 39496f60e37SRussell King { CKMODE_DISABLE, "disabled" }, 39596f60e37SRussell King { CKMODE_Y, "Y component" }, 39696f60e37SRussell King { CKMODE_U, "U component" }, 39796f60e37SRussell King { CKMODE_V, "V component" }, 39896f60e37SRussell King { CKMODE_RGB, "RGB" }, 39996f60e37SRussell King { CKMODE_R, "R component" }, 40096f60e37SRussell King { CKMODE_G, "G component" }, 40196f60e37SRussell King { CKMODE_B, "B component" }, 40296f60e37SRussell King }; 40396f60e37SRussell King 40496f60e37SRussell King static int armada_overlay_create_properties(struct drm_device *dev) 40596f60e37SRussell King { 40696f60e37SRussell King struct armada_private *priv = dev->dev_private; 40796f60e37SRussell King 40896f60e37SRussell King if (priv->colorkey_prop) 40996f60e37SRussell King return 0; 41096f60e37SRussell King 41196f60e37SRussell King priv->colorkey_prop = drm_property_create_range(dev, 0, 41296f60e37SRussell King "colorkey", 0, 0xffffff); 41396f60e37SRussell King priv->colorkey_min_prop = drm_property_create_range(dev, 0, 41496f60e37SRussell King "colorkey_min", 0, 0xffffff); 41596f60e37SRussell King priv->colorkey_max_prop = drm_property_create_range(dev, 0, 41696f60e37SRussell King "colorkey_max", 0, 0xffffff); 41796f60e37SRussell King priv->colorkey_val_prop = drm_property_create_range(dev, 0, 41896f60e37SRussell King "colorkey_val", 0, 0xffffff); 41996f60e37SRussell King priv->colorkey_alpha_prop = drm_property_create_range(dev, 0, 42096f60e37SRussell King "colorkey_alpha", 0, 0xffffff); 42196f60e37SRussell King priv->colorkey_mode_prop = drm_property_create_enum(dev, 0, 42296f60e37SRussell King "colorkey_mode", 42396f60e37SRussell King armada_drm_colorkey_enum_list, 42496f60e37SRussell King ARRAY_SIZE(armada_drm_colorkey_enum_list)); 42596f60e37SRussell King priv->brightness_prop = drm_property_create_range(dev, 0, 42696f60e37SRussell King "brightness", 0, 256 + 255); 42796f60e37SRussell King priv->contrast_prop = drm_property_create_range(dev, 0, 42896f60e37SRussell King "contrast", 0, 0x7fff); 42996f60e37SRussell King priv->saturation_prop = drm_property_create_range(dev, 0, 43096f60e37SRussell King "saturation", 0, 0x7fff); 43196f60e37SRussell King 43296f60e37SRussell King if (!priv->colorkey_prop) 43396f60e37SRussell King return -ENOMEM; 43496f60e37SRussell King 43596f60e37SRussell King return 0; 43696f60e37SRussell King } 43796f60e37SRussell King 43896f60e37SRussell King int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) 43996f60e37SRussell King { 44096f60e37SRussell King struct armada_private *priv = dev->dev_private; 44196f60e37SRussell King struct drm_mode_object *mobj; 44228a2aebeSRussell King struct armada_ovl_plane *dplane; 44396f60e37SRussell King int ret; 44496f60e37SRussell King 44596f60e37SRussell King ret = armada_overlay_create_properties(dev); 44696f60e37SRussell King if (ret) 44796f60e37SRussell King return ret; 44896f60e37SRussell King 44996f60e37SRussell King dplane = kzalloc(sizeof(*dplane), GFP_KERNEL); 45096f60e37SRussell King if (!dplane) 45196f60e37SRussell King return -ENOMEM; 45296f60e37SRussell King 4535740d27fSRussell King ret = armada_drm_plane_init(&dplane->base); 4545740d27fSRussell King if (ret) { 4555740d27fSRussell King kfree(dplane); 4565740d27fSRussell King return ret; 4575740d27fSRussell King } 4585740d27fSRussell King 45928a2aebeSRussell King armada_drm_vbl_event_init(&dplane->vbl.update, armada_ovl_plane_vbl, 46096f60e37SRussell King dplane); 46196f60e37SRussell King 462561f60bcSRussell King ret = drm_universal_plane_init(dev, &dplane->base.base, crtcs, 463d563c245SRussell King &armada_ovl_plane_funcs, 464d563c245SRussell King armada_ovl_formats, 465d563c245SRussell King ARRAY_SIZE(armada_ovl_formats), 466d563c245SRussell King DRM_PLANE_TYPE_OVERLAY); 46728a2aebeSRussell King if (ret) { 46828a2aebeSRussell King kfree(dplane); 46928a2aebeSRussell King return ret; 47028a2aebeSRussell King } 47196f60e37SRussell King 47296f60e37SRussell King dplane->prop.colorkey_yr = 0xfefefe00; 47396f60e37SRussell King dplane->prop.colorkey_ug = 0x01010100; 47496f60e37SRussell King dplane->prop.colorkey_vb = 0x01010100; 47596f60e37SRussell King dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB); 47696f60e37SRussell King dplane->prop.brightness = 0; 47796f60e37SRussell King dplane->prop.contrast = 0x4000; 47896f60e37SRussell King dplane->prop.saturation = 0x4000; 47996f60e37SRussell King 480561f60bcSRussell King mobj = &dplane->base.base.base; 48196f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_prop, 48296f60e37SRussell King 0x0101fe); 48396f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_min_prop, 48496f60e37SRussell King 0x0101fe); 48596f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_max_prop, 48696f60e37SRussell King 0x0101fe); 48796f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_val_prop, 48896f60e37SRussell King 0x0101fe); 48996f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_alpha_prop, 49096f60e37SRussell King 0x000000); 49196f60e37SRussell King drm_object_attach_property(mobj, priv->colorkey_mode_prop, 49296f60e37SRussell King CKMODE_RGB); 49396f60e37SRussell King drm_object_attach_property(mobj, priv->brightness_prop, 256); 49496f60e37SRussell King drm_object_attach_property(mobj, priv->contrast_prop, 49596f60e37SRussell King dplane->prop.contrast); 49696f60e37SRussell King drm_object_attach_property(mobj, priv->saturation_prop, 49796f60e37SRussell King dplane->prop.saturation); 49896f60e37SRussell King 49996f60e37SRussell King return 0; 50096f60e37SRussell King } 501