xref: /openbmc/linux/drivers/gpu/drm/sti/sti_vid.c (revision 05a142c2)
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