xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/imx/dcss/dcss-ss.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright 2019 NXP.
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <linux/device.h>
7*4882a593Smuzhiyun #include <linux/slab.h>
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include "dcss-dev.h"
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #define DCSS_SS_SYS_CTRL			0x00
12*4882a593Smuzhiyun #define   RUN_EN				BIT(0)
13*4882a593Smuzhiyun #define DCSS_SS_DISPLAY				0x10
14*4882a593Smuzhiyun #define   LRC_X_POS				0
15*4882a593Smuzhiyun #define   LRC_X_MASK				GENMASK(12, 0)
16*4882a593Smuzhiyun #define   LRC_Y_POS				16
17*4882a593Smuzhiyun #define   LRC_Y_MASK				GENMASK(28, 16)
18*4882a593Smuzhiyun #define DCSS_SS_HSYNC				0x20
19*4882a593Smuzhiyun #define DCSS_SS_VSYNC				0x30
20*4882a593Smuzhiyun #define   SYNC_START_POS			0
21*4882a593Smuzhiyun #define   SYNC_START_MASK			GENMASK(12, 0)
22*4882a593Smuzhiyun #define   SYNC_END_POS				16
23*4882a593Smuzhiyun #define   SYNC_END_MASK				GENMASK(28, 16)
24*4882a593Smuzhiyun #define   SYNC_POL				BIT(31)
25*4882a593Smuzhiyun #define DCSS_SS_DE_ULC				0x40
26*4882a593Smuzhiyun #define   ULC_X_POS				0
27*4882a593Smuzhiyun #define   ULC_X_MASK				GENMASK(12, 0)
28*4882a593Smuzhiyun #define   ULC_Y_POS				16
29*4882a593Smuzhiyun #define   ULC_Y_MASK				GENMASK(28, 16)
30*4882a593Smuzhiyun #define   ULC_POL				BIT(31)
31*4882a593Smuzhiyun #define DCSS_SS_DE_LRC				0x50
32*4882a593Smuzhiyun #define DCSS_SS_MODE				0x60
33*4882a593Smuzhiyun #define   PIPE_MODE_POS				0
34*4882a593Smuzhiyun #define   PIPE_MODE_MASK			GENMASK(1, 0)
35*4882a593Smuzhiyun #define DCSS_SS_COEFF				0x70
36*4882a593Smuzhiyun #define   HORIZ_A_POS				0
37*4882a593Smuzhiyun #define   HORIZ_A_MASK				GENMASK(3, 0)
38*4882a593Smuzhiyun #define   HORIZ_B_POS				4
39*4882a593Smuzhiyun #define   HORIZ_B_MASK				GENMASK(7, 4)
40*4882a593Smuzhiyun #define   HORIZ_C_POS				8
41*4882a593Smuzhiyun #define   HORIZ_C_MASK				GENMASK(11, 8)
42*4882a593Smuzhiyun #define   HORIZ_H_NORM_POS			12
43*4882a593Smuzhiyun #define   HORIZ_H_NORM_MASK			GENMASK(14, 12)
44*4882a593Smuzhiyun #define   VERT_A_POS				16
45*4882a593Smuzhiyun #define   VERT_A_MASK				GENMASK(19, 16)
46*4882a593Smuzhiyun #define   VERT_B_POS				20
47*4882a593Smuzhiyun #define   VERT_B_MASK				GENMASK(23, 20)
48*4882a593Smuzhiyun #define   VERT_C_POS				24
49*4882a593Smuzhiyun #define   VERT_C_MASK				GENMASK(27, 24)
50*4882a593Smuzhiyun #define   VERT_H_NORM_POS			28
51*4882a593Smuzhiyun #define   VERT_H_NORM_MASK			GENMASK(30, 28)
52*4882a593Smuzhiyun #define DCSS_SS_CLIP_CB				0x80
53*4882a593Smuzhiyun #define DCSS_SS_CLIP_CR				0x90
54*4882a593Smuzhiyun #define   CLIP_MIN_POS				0
55*4882a593Smuzhiyun #define   CLIP_MIN_MASK				GENMASK(9, 0)
56*4882a593Smuzhiyun #define   CLIP_MAX_POS				0
57*4882a593Smuzhiyun #define   CLIP_MAX_MASK				GENMASK(23, 16)
58*4882a593Smuzhiyun #define DCSS_SS_INTER_MODE			0xA0
59*4882a593Smuzhiyun #define   INT_EN				BIT(0)
60*4882a593Smuzhiyun #define   VSYNC_SHIFT				BIT(1)
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun struct dcss_ss {
63*4882a593Smuzhiyun 	struct device *dev;
64*4882a593Smuzhiyun 	void __iomem *base_reg;
65*4882a593Smuzhiyun 	u32 base_ofs;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	struct dcss_ctxld *ctxld;
68*4882a593Smuzhiyun 	u32 ctx_id;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	bool in_use;
71*4882a593Smuzhiyun };
72*4882a593Smuzhiyun 
dcss_ss_write(struct dcss_ss * ss,u32 val,u32 ofs)73*4882a593Smuzhiyun static void dcss_ss_write(struct dcss_ss *ss, u32 val, u32 ofs)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	if (!ss->in_use)
76*4882a593Smuzhiyun 		dcss_writel(val, ss->base_reg + ofs);
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	dcss_ctxld_write(ss->ctxld, ss->ctx_id, val,
79*4882a593Smuzhiyun 			 ss->base_ofs + ofs);
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun 
dcss_ss_init(struct dcss_dev * dcss,unsigned long ss_base)82*4882a593Smuzhiyun int dcss_ss_init(struct dcss_dev *dcss, unsigned long ss_base)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	struct dcss_ss *ss;
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	ss = kzalloc(sizeof(*ss), GFP_KERNEL);
87*4882a593Smuzhiyun 	if (!ss)
88*4882a593Smuzhiyun 		return -ENOMEM;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	dcss->ss = ss;
91*4882a593Smuzhiyun 	ss->dev = dcss->dev;
92*4882a593Smuzhiyun 	ss->ctxld = dcss->ctxld;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	ss->base_reg = ioremap(ss_base, SZ_4K);
95*4882a593Smuzhiyun 	if (!ss->base_reg) {
96*4882a593Smuzhiyun 		dev_err(dcss->dev, "ss: unable to remap ss base\n");
97*4882a593Smuzhiyun 		kfree(ss);
98*4882a593Smuzhiyun 		return -ENOMEM;
99*4882a593Smuzhiyun 	}
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	ss->base_ofs = ss_base;
102*4882a593Smuzhiyun 	ss->ctx_id = CTX_SB_HP;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	return 0;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun 
dcss_ss_exit(struct dcss_ss * ss)107*4882a593Smuzhiyun void dcss_ss_exit(struct dcss_ss *ss)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun 	/* stop SS */
110*4882a593Smuzhiyun 	dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL);
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	if (ss->base_reg)
113*4882a593Smuzhiyun 		iounmap(ss->base_reg);
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	kfree(ss);
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun 
dcss_ss_subsam_set(struct dcss_ss * ss)118*4882a593Smuzhiyun void dcss_ss_subsam_set(struct dcss_ss *ss)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun 	dcss_ss_write(ss, 0x41614161, DCSS_SS_COEFF);
121*4882a593Smuzhiyun 	dcss_ss_write(ss, 0, DCSS_SS_MODE);
122*4882a593Smuzhiyun 	dcss_ss_write(ss, 0x03ff0000, DCSS_SS_CLIP_CB);
123*4882a593Smuzhiyun 	dcss_ss_write(ss, 0x03ff0000, DCSS_SS_CLIP_CR);
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun 
dcss_ss_sync_set(struct dcss_ss * ss,struct videomode * vm,bool phsync,bool pvsync)126*4882a593Smuzhiyun void dcss_ss_sync_set(struct dcss_ss *ss, struct videomode *vm,
127*4882a593Smuzhiyun 		      bool phsync, bool pvsync)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun 	u16 lrc_x, lrc_y;
130*4882a593Smuzhiyun 	u16 hsync_start, hsync_end;
131*4882a593Smuzhiyun 	u16 vsync_start, vsync_end;
132*4882a593Smuzhiyun 	u16 de_ulc_x, de_ulc_y;
133*4882a593Smuzhiyun 	u16 de_lrc_x, de_lrc_y;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	lrc_x = vm->hfront_porch + vm->hback_porch + vm->hsync_len +
136*4882a593Smuzhiyun 		vm->hactive - 1;
137*4882a593Smuzhiyun 	lrc_y = vm->vfront_porch + vm->vback_porch + vm->vsync_len +
138*4882a593Smuzhiyun 		vm->vactive - 1;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	dcss_ss_write(ss, (lrc_y << LRC_Y_POS) | lrc_x, DCSS_SS_DISPLAY);
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	hsync_start = vm->hfront_porch + vm->hback_porch + vm->hsync_len +
143*4882a593Smuzhiyun 		      vm->hactive - 1;
144*4882a593Smuzhiyun 	hsync_end = vm->hsync_len - 1;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	dcss_ss_write(ss, (phsync ? SYNC_POL : 0) |
147*4882a593Smuzhiyun 		      ((u32)hsync_end << SYNC_END_POS) | hsync_start,
148*4882a593Smuzhiyun 		      DCSS_SS_HSYNC);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	vsync_start = vm->vfront_porch - 1;
151*4882a593Smuzhiyun 	vsync_end = vm->vfront_porch + vm->vsync_len - 1;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	dcss_ss_write(ss, (pvsync ? SYNC_POL : 0) |
154*4882a593Smuzhiyun 		      ((u32)vsync_end << SYNC_END_POS) | vsync_start,
155*4882a593Smuzhiyun 		      DCSS_SS_VSYNC);
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	de_ulc_x = vm->hsync_len + vm->hback_porch - 1;
158*4882a593Smuzhiyun 	de_ulc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	dcss_ss_write(ss, SYNC_POL | ((u32)de_ulc_y << ULC_Y_POS) | de_ulc_x,
161*4882a593Smuzhiyun 		      DCSS_SS_DE_ULC);
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	de_lrc_x = vm->hsync_len + vm->hback_porch + vm->hactive - 1;
164*4882a593Smuzhiyun 	de_lrc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch +
165*4882a593Smuzhiyun 		   vm->vactive - 1;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	dcss_ss_write(ss, (de_lrc_y << LRC_Y_POS) | de_lrc_x, DCSS_SS_DE_LRC);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun 
dcss_ss_enable(struct dcss_ss * ss)170*4882a593Smuzhiyun void dcss_ss_enable(struct dcss_ss *ss)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun 	dcss_ss_write(ss, RUN_EN, DCSS_SS_SYS_CTRL);
173*4882a593Smuzhiyun 	ss->in_use = true;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
dcss_ss_shutoff(struct dcss_ss * ss)176*4882a593Smuzhiyun void dcss_ss_shutoff(struct dcss_ss *ss)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL);
179*4882a593Smuzhiyun 	ss->in_use = false;
180*4882a593Smuzhiyun }
181