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