1cfd8d744SBenjamin Gaignard /* 2cfd8d744SBenjamin Gaignard * Copyright (C) STMicroelectronics SA 2014 3cfd8d744SBenjamin Gaignard * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. 4cfd8d744SBenjamin Gaignard * License terms: GNU General Public License (GPL), version 2 5cfd8d744SBenjamin Gaignard */ 6cfd8d744SBenjamin Gaignard 7cfd8d744SBenjamin Gaignard #include <drm/drmP.h> 8cfd8d744SBenjamin Gaignard 99e1f05b2SVincent Abriou #include "sti_plane.h" 10cfd8d744SBenjamin Gaignard #include "sti_vid.h" 11cfd8d744SBenjamin Gaignard #include "sti_vtg.h" 12cfd8d744SBenjamin Gaignard 13cfd8d744SBenjamin Gaignard /* Registers */ 14cfd8d744SBenjamin Gaignard #define VID_CTL 0x00 15cfd8d744SBenjamin Gaignard #define VID_ALP 0x04 16cfd8d744SBenjamin Gaignard #define VID_CLF 0x08 17cfd8d744SBenjamin Gaignard #define VID_VPO 0x0C 18cfd8d744SBenjamin Gaignard #define VID_VPS 0x10 19cfd8d744SBenjamin Gaignard #define VID_KEY1 0x28 20cfd8d744SBenjamin Gaignard #define VID_KEY2 0x2C 21cfd8d744SBenjamin Gaignard #define VID_MPR0 0x30 22cfd8d744SBenjamin Gaignard #define VID_MPR1 0x34 23cfd8d744SBenjamin Gaignard #define VID_MPR2 0x38 24cfd8d744SBenjamin Gaignard #define VID_MPR3 0x3C 25cfd8d744SBenjamin Gaignard #define VID_MST 0x68 26cfd8d744SBenjamin Gaignard #define VID_BC 0x70 27cfd8d744SBenjamin Gaignard #define VID_TINT 0x74 28cfd8d744SBenjamin Gaignard #define VID_CSAT 0x78 29cfd8d744SBenjamin Gaignard 30cfd8d744SBenjamin Gaignard /* Registers values */ 31cfd8d744SBenjamin Gaignard #define VID_CTL_IGNORE (BIT(31) | BIT(30)) 32cfd8d744SBenjamin Gaignard #define VID_CTL_PSI_ENABLE (BIT(2) | BIT(1) | BIT(0)) 33cfd8d744SBenjamin Gaignard #define VID_ALP_OPAQUE 0x00000080 34cfd8d744SBenjamin Gaignard #define VID_BC_DFLT 0x00008000 35cfd8d744SBenjamin Gaignard #define VID_TINT_DFLT 0x00000000 36cfd8d744SBenjamin Gaignard #define VID_CSAT_DFLT 0x00000080 37cfd8d744SBenjamin Gaignard /* YCbCr to RGB BT709: 38cfd8d744SBenjamin Gaignard * R = Y+1.5391Cr 39cfd8d744SBenjamin Gaignard * G = Y-0.4590Cr-0.1826Cb 40cfd8d744SBenjamin Gaignard * B = Y+1.8125Cb */ 41cfd8d744SBenjamin Gaignard #define VID_MPR0_BT709 0x0A800000 42cfd8d744SBenjamin Gaignard #define VID_MPR1_BT709 0x0AC50000 43cfd8d744SBenjamin Gaignard #define VID_MPR2_BT709 0x07150545 44cfd8d744SBenjamin Gaignard #define VID_MPR3_BT709 0x00000AE8 4505a142c2SBich Hemon /* YCbCr to RGB BT709: 4605a142c2SBich Hemon * R = Y+1.3711Cr 4705a142c2SBich Hemon * G = Y-0.6992Cr-0.3359Cb 4805a142c2SBich Hemon * B = Y+1.7344Cb 4905a142c2SBich Hemon */ 5005a142c2SBich Hemon #define VID_MPR0_BT601 0x0A800000 5105a142c2SBich Hemon #define VID_MPR1_BT601 0x0AAF0000 5205a142c2SBich Hemon #define VID_MPR2_BT601 0x094E0754 5305a142c2SBich Hemon #define VID_MPR3_BT601 0x00000ADD 5405a142c2SBich Hemon 5505a142c2SBich Hemon #define VID_MIN_HD_HEIGHT 720 56cfd8d744SBenjamin Gaignard 5729d1dc62SVincent Abriou void sti_vid_commit(struct sti_vid *vid, 5829d1dc62SVincent Abriou struct drm_plane_state *state) 59cfd8d744SBenjamin Gaignard { 6029d1dc62SVincent Abriou struct drm_crtc *crtc = state->crtc; 6129d1dc62SVincent Abriou struct drm_display_mode *mode = &crtc->mode; 6229d1dc62SVincent Abriou int dst_x = state->crtc_x; 6329d1dc62SVincent Abriou int dst_y = state->crtc_y; 6429d1dc62SVincent Abriou int dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x); 6529d1dc62SVincent Abriou int dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y); 6605a142c2SBich Hemon int src_h = state->src_h >> 16; 67871bcdfeSVincent Abriou u32 val, ydo, xdo, yds, xds; 68cfd8d744SBenjamin Gaignard 6929d1dc62SVincent Abriou /* Input / output size 7029d1dc62SVincent Abriou * Align to upper even value */ 7129d1dc62SVincent Abriou dst_w = ALIGN(dst_w, 2); 7229d1dc62SVincent Abriou dst_h = ALIGN(dst_h, 2); 7329d1dc62SVincent Abriou 74cfd8d744SBenjamin Gaignard /* Unmask */ 75cfd8d744SBenjamin Gaignard val = readl(vid->regs + VID_CTL); 76cfd8d744SBenjamin Gaignard val &= ~VID_CTL_IGNORE; 77cfd8d744SBenjamin Gaignard writel(val, vid->regs + VID_CTL); 78cfd8d744SBenjamin Gaignard 7929d1dc62SVincent Abriou ydo = sti_vtg_get_line_number(*mode, dst_y); 8029d1dc62SVincent Abriou yds = sti_vtg_get_line_number(*mode, dst_y + dst_h - 1); 8129d1dc62SVincent Abriou xdo = sti_vtg_get_pixel_number(*mode, dst_x); 8229d1dc62SVincent Abriou xds = sti_vtg_get_pixel_number(*mode, dst_x + dst_w - 1); 83cfd8d744SBenjamin Gaignard 84cfd8d744SBenjamin Gaignard writel((ydo << 16) | xdo, vid->regs + VID_VPO); 85cfd8d744SBenjamin Gaignard writel((yds << 16) | xds, vid->regs + VID_VPS); 8605a142c2SBich Hemon 8705a142c2SBich Hemon /* Color conversion parameters */ 8805a142c2SBich Hemon if (src_h >= VID_MIN_HD_HEIGHT) { 8905a142c2SBich Hemon writel(VID_MPR0_BT709, vid->regs + VID_MPR0); 9005a142c2SBich Hemon writel(VID_MPR1_BT709, vid->regs + VID_MPR1); 9105a142c2SBich Hemon writel(VID_MPR2_BT709, vid->regs + VID_MPR2); 9205a142c2SBich Hemon writel(VID_MPR3_BT709, vid->regs + VID_MPR3); 9305a142c2SBich Hemon } else { 9405a142c2SBich Hemon writel(VID_MPR0_BT601, vid->regs + VID_MPR0); 9505a142c2SBich Hemon writel(VID_MPR1_BT601, vid->regs + VID_MPR1); 9605a142c2SBich Hemon writel(VID_MPR2_BT601, vid->regs + VID_MPR2); 9705a142c2SBich Hemon writel(VID_MPR3_BT601, vid->regs + VID_MPR3); 9805a142c2SBich Hemon } 99cfd8d744SBenjamin Gaignard } 100cfd8d744SBenjamin Gaignard 10129d1dc62SVincent Abriou void sti_vid_disable(struct sti_vid *vid) 102cfd8d744SBenjamin Gaignard { 103cfd8d744SBenjamin Gaignard u32 val; 104cfd8d744SBenjamin Gaignard 105cfd8d744SBenjamin Gaignard /* Mask */ 106cfd8d744SBenjamin Gaignard val = readl(vid->regs + VID_CTL); 107cfd8d744SBenjamin Gaignard val |= VID_CTL_IGNORE; 108cfd8d744SBenjamin Gaignard writel(val, vid->regs + VID_CTL); 109cfd8d744SBenjamin Gaignard } 110cfd8d744SBenjamin Gaignard 111871bcdfeSVincent Abriou static void sti_vid_init(struct sti_vid *vid) 112cfd8d744SBenjamin Gaignard { 113cfd8d744SBenjamin Gaignard /* Enable PSI, Mask layer */ 114cfd8d744SBenjamin Gaignard writel(VID_CTL_PSI_ENABLE | VID_CTL_IGNORE, vid->regs + VID_CTL); 115cfd8d744SBenjamin Gaignard 116cfd8d744SBenjamin Gaignard /* Opaque */ 117cfd8d744SBenjamin Gaignard writel(VID_ALP_OPAQUE, vid->regs + VID_ALP); 118cfd8d744SBenjamin Gaignard 119cfd8d744SBenjamin Gaignard /* Brightness, contrast, tint, saturation */ 120cfd8d744SBenjamin Gaignard writel(VID_BC_DFLT, vid->regs + VID_BC); 121cfd8d744SBenjamin Gaignard writel(VID_TINT_DFLT, vid->regs + VID_TINT); 122cfd8d744SBenjamin Gaignard writel(VID_CSAT_DFLT, vid->regs + VID_CSAT); 123cfd8d744SBenjamin Gaignard } 124cfd8d744SBenjamin Gaignard 125871bcdfeSVincent Abriou struct sti_vid *sti_vid_create(struct device *dev, int id, 126871bcdfeSVincent Abriou void __iomem *baseaddr) 127cfd8d744SBenjamin Gaignard { 128871bcdfeSVincent Abriou struct sti_vid *vid; 129cfd8d744SBenjamin Gaignard 130cfd8d744SBenjamin Gaignard vid = devm_kzalloc(dev, sizeof(*vid), GFP_KERNEL); 131cfd8d744SBenjamin Gaignard if (!vid) { 132cfd8d744SBenjamin Gaignard DRM_ERROR("Failed to allocate memory for VID\n"); 133cfd8d744SBenjamin Gaignard return NULL; 134cfd8d744SBenjamin Gaignard } 135cfd8d744SBenjamin Gaignard 136871bcdfeSVincent Abriou vid->dev = dev; 137871bcdfeSVincent Abriou vid->regs = baseaddr; 138871bcdfeSVincent Abriou vid->id = id; 139871bcdfeSVincent Abriou 140871bcdfeSVincent Abriou sti_vid_init(vid); 141cfd8d744SBenjamin Gaignard 142cfd8d744SBenjamin Gaignard return vid; 143cfd8d744SBenjamin Gaignard } 144