Merge tag 'lsk-v4.4-17.05-android' of git://git.linaro.org/kernel/linux-linaro-stable.git
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / rockchip / rockchip_vop_reg.c
1 /*
2  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
3  * Author:Mark Yao <mark.yao@rock-chips.com>
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  */
14
15 #include <drm/drmP.h>
16
17 #include <linux/kernel.h>
18 #include <linux/component.h>
19
20 #include "rockchip_drm_vop.h"
21 #include "rockchip_vop_reg.h"
22
23 #define VOP_REG_VER_MASK(off, _mask, s, _write_mask, _major, \
24                          _begin_minor, _end_minor) \
25                 {.offset = off, \
26                  .mask = _mask, \
27                  .shift = s, \
28                  .write_mask = _write_mask, \
29                  .major = _major, \
30                  .begin_minor = _begin_minor, \
31                  .end_minor = _end_minor,}
32
33 #define VOP_REG(off, _mask, s) \
34                 VOP_REG_VER_MASK(off, _mask, s, false, 0, 0, -1)
35
36 #define VOP_REG_MASK(off, _mask, s) \
37                 VOP_REG_VER_MASK(off, _mask, s, true, 0, 0, -1)
38
39 #define VOP_REG_VER(off, _mask, s, _major, _begin_minor, _end_minor) \
40                 VOP_REG_VER_MASK(off, _mask, s, false, \
41                                  _major, _begin_minor, _end_minor)
42
43
44 static const uint32_t formats_win_full[] = {
45         DRM_FORMAT_XRGB8888,
46         DRM_FORMAT_ARGB8888,
47         DRM_FORMAT_XBGR8888,
48         DRM_FORMAT_ABGR8888,
49         DRM_FORMAT_RGB888,
50         DRM_FORMAT_BGR888,
51         DRM_FORMAT_RGB565,
52         DRM_FORMAT_BGR565,
53         DRM_FORMAT_NV12,
54         DRM_FORMAT_NV16,
55         DRM_FORMAT_NV24,
56         DRM_FORMAT_NV12_10,
57         DRM_FORMAT_NV16_10,
58         DRM_FORMAT_NV24_10,
59 };
60
61 static const uint32_t formats_win_lite[] = {
62         DRM_FORMAT_XRGB8888,
63         DRM_FORMAT_ARGB8888,
64         DRM_FORMAT_XBGR8888,
65         DRM_FORMAT_ABGR8888,
66         DRM_FORMAT_RGB888,
67         DRM_FORMAT_BGR888,
68         DRM_FORMAT_RGB565,
69         DRM_FORMAT_BGR565,
70 };
71
72 static const struct vop_scl_extension rk3288_win_full_scl_ext = {
73         .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
74         .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
75         .cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28),
76         .cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26),
77         .cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24),
78         .yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23),
79         .yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22),
80         .yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20),
81         .yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18),
82         .yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16),
83         .line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15),
84         .cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12),
85         .yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8),
86         .vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7),
87         .vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6),
88         .vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5),
89         .vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4),
90         .bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2),
91         .cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1),
92         .yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0),
93         .lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5),
94 };
95
96 static const struct vop_scl_regs rk3288_win_full_scl = {
97         .ext = &rk3288_win_full_scl_ext,
98         .scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
99         .scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
100         .scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
101         .scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
102 };
103
104 static const struct vop_win_phy rk3288_win01_data = {
105         .scl = &rk3288_win_full_scl,
106         .data_formats = formats_win_full,
107         .nformats = ARRAY_SIZE(formats_win_full),
108         .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
109         .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
110         .fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 4),
111         .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
112         .xmirror = VOP_REG_VER(RK3368_WIN0_CTRL0, 0x1, 21, 3, 2, -1),
113         .ymirror = VOP_REG_VER(RK3368_WIN0_CTRL0, 0x1, 22, 3, 2, -1),
114         .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
115         .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
116         .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
117         .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
118         .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
119         .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
120         .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
121         .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xffffffff, 0),
122         .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xffffffff, 0),
123         .channel = VOP_REG_VER(RK3288_WIN0_CTRL2, 0xff, 0, 3, 8, 8),
124 };
125
126 static const struct vop_win_phy rk3288_win23_data = {
127         .data_formats = formats_win_lite,
128         .nformats = ARRAY_SIZE(formats_win_lite),
129         .gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0),
130         .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4),
131         .format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1),
132         .rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12),
133         .dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0),
134         .dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0),
135         .yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0),
136         .yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0),
137         .src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
138         .dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0),
139 };
140
141 static const struct vop_win_phy rk3288_area1_data = {
142         .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 5),
143         .dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO1, 0x0fff0fff, 0),
144         .dsp_st = VOP_REG(RK3288_WIN2_DSP_ST1, 0x1fff1fff, 0),
145         .yrgb_mst = VOP_REG(RK3288_WIN2_MST1, 0xffffffff, 0),
146         .yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 16),
147 };
148
149 static const struct vop_win_phy rk3288_area2_data = {
150         .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 6),
151         .dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO2, 0x0fff0fff, 0),
152         .dsp_st = VOP_REG(RK3288_WIN2_DSP_ST2, 0x1fff1fff, 0),
153         .yrgb_mst = VOP_REG(RK3288_WIN2_MST2, 0xffffffff, 0),
154         .yrgb_vir = VOP_REG(RK3288_WIN2_VIR2_3, 0x1fff, 0),
155 };
156
157 static const struct vop_win_phy rk3288_area3_data = {
158         .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 7),
159         .dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO3, 0x0fff0fff, 0),
160         .dsp_st = VOP_REG(RK3288_WIN2_DSP_ST3, 0x1fff1fff, 0),
161         .yrgb_mst = VOP_REG(RK3288_WIN2_MST3, 0xffffffff, 0),
162         .yrgb_vir = VOP_REG(RK3288_WIN2_VIR2_3, 0x1fff, 16),
163 };
164
165 static const struct vop_win_phy *rk3288_area_data[] = {
166         &rk3288_area1_data,
167         &rk3288_area2_data,
168         &rk3288_area3_data
169 };
170
171 static const struct vop_ctrl rk3288_ctrl_data = {
172         .standby = VOP_REG(RK3288_SYS_CTRL, 0x1, 22),
173         .htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
174         .hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0),
175         .vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
176         .vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0),
177         .vact_st_end_f1 = VOP_REG(RK3288_DSP_VACT_ST_END_F1, 0x1fff1fff, 0),
178         .vs_st_end_f1 = VOP_REG(RK3288_DSP_VS_ST_END_F1, 0x1fff1fff, 0),
179         .hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
180         .vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
181         .vpost_st_end_f1 = VOP_REG(RK3288_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0),
182         .post_scl_factor = VOP_REG(RK3288_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
183         .post_scl_ctrl = VOP_REG(RK3288_POST_SCL_CTRL, 0x3, 0),
184
185         .dsp_interlace = VOP_REG(RK3288_DSP_CTRL0, 0x1, 10),
186         .auto_gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
187         .dsp_layer_sel = VOP_REG(RK3288_DSP_CTRL1, 0xff, 8),
188         .post_lb_mode = VOP_REG_VER(RK3288_SYS_CTRL, 0x1, 18, 3, 2, -1),
189         .global_regdone_en = VOP_REG_VER(RK3288_SYS_CTRL, 0x1, 11, 3, 2, -1),
190         .overlay_mode = VOP_REG_VER(RK3288_SYS_CTRL, 0x1, 16, 3, 2, -1),
191         .core_dclk_div = VOP_REG_VER(RK3399_DSP_CTRL0, 0x1, 4, 3, 4, -1),
192         .p2i_en = VOP_REG_VER(RK3399_DSP_CTRL0, 0x1, 5, 3, 4, -1),
193         .dclk_ddr = VOP_REG_VER(RK3399_DSP_CTRL0, 0x1, 8, 3, 4, -1),
194         .dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11),
195         .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
196         .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
197         .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
198         .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
199         .pin_pol = VOP_REG_VER(RK3288_DSP_CTRL0, 0xf, 4, 3, 0, 1),
200         .dp_pin_pol = VOP_REG_VER(RK3368_DSP_CTRL1, 0xf, 16, 3, 2, -1),
201         .rgb_pin_pol = VOP_REG_VER(RK3368_DSP_CTRL1, 0xf, 16, 3, 2, -1),
202         .hdmi_pin_pol = VOP_REG_VER(RK3368_DSP_CTRL1, 0xf, 20, 3, 2, -1),
203         .edp_pin_pol = VOP_REG_VER(RK3368_DSP_CTRL1, 0xf, 24, 3, 2, -1),
204         .mipi_pin_pol = VOP_REG_VER(RK3368_DSP_CTRL1, 0xf, 28, 3, 2, -1),
205
206         .dither_down = VOP_REG(RK3288_DSP_CTRL1, 0xf, 1),
207         .dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6),
208
209         .dsp_out_yuv = VOP_REG_VER(RK3399_POST_SCL_CTRL, 0x1, 2, 3, 5, -1),
210         .dsp_data_swap = VOP_REG(RK3288_DSP_CTRL0, 0x1f, 12),
211         .dsp_ccir656_avg = VOP_REG(RK3288_DSP_CTRL0, 0x1, 20),
212         .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18),
213         .update_gamma_lut = VOP_REG_VER(RK3288_DSP_CTRL1, 0x1, 7, 3, 5, -1),
214         .lut_buffer_index = VOP_REG_VER(RK3399_DBG_POST_REG1, 0x1, 1, 3, 5, -1),
215         .dsp_lut_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 0),
216         .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0),
217
218         .afbdc_rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3),
219         .afbdc_en = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0),
220         .afbdc_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1),
221         .afbdc_format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16),
222         .afbdc_hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21),
223         .afbdc_hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0),
224         .afbdc_pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0),
225
226         .xmirror = VOP_REG(RK3288_DSP_CTRL0, 0x1, 22),
227         .ymirror = VOP_REG(RK3288_DSP_CTRL0, 0x1, 23),
228
229         .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0),
230
231         .cfg_done = VOP_REG(RK3288_REG_CFG_DONE, 0x1, 0),
232 };
233
234 /*
235  * Note: rk3288 has a dedicated 'cursor' window, however, that window requires
236  * special support to get alpha blending working.  For now, just use overlay
237  * window 3 for the drm cursor.
238  *
239  */
240 static const struct vop_win_data rk3288_vop_win_data[] = {
241         { .base = 0x00, .phy = &rk3288_win01_data,
242           .type = DRM_PLANE_TYPE_PRIMARY },
243         { .base = 0x40, .phy = &rk3288_win01_data,
244           .type = DRM_PLANE_TYPE_OVERLAY },
245         { .base = 0x00, .phy = &rk3288_win23_data,
246           .type = DRM_PLANE_TYPE_OVERLAY,
247           .area = rk3288_area_data,
248           .area_size = ARRAY_SIZE(rk3288_area_data), },
249         { .base = 0x50, .phy = &rk3288_win23_data,
250           .type = DRM_PLANE_TYPE_CURSOR,
251           .area = rk3288_area_data,
252           .area_size = ARRAY_SIZE(rk3288_area_data), },
253 };
254
255 static const int rk3288_vop_intrs[] = {
256         DSP_HOLD_VALID_INTR,
257         FS_INTR,
258         LINE_FLAG_INTR,
259         BUS_ERROR_INTR,
260 };
261
262 static const struct vop_intr rk3288_vop_intr = {
263         .intrs = rk3288_vop_intrs,
264         .nintrs = ARRAY_SIZE(rk3288_vop_intrs),
265         .line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12),
266         .status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0),
267         .enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4),
268         .clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8),
269 };
270
271 static const struct vop_data rk3288_vop = {
272         .version = VOP_VERSION(3, 1),
273         .feature = VOP_FEATURE_OUTPUT_10BIT,
274         .max_input = {4096, 8192},
275         /*
276          * TODO: rk3288 have two vop, big one support 3840x2160,
277          * little one only support 2560x1600.
278          * Now force use 3840x2160.
279          */
280         .max_output = {3840, 2160},
281         .intr = &rk3288_vop_intr,
282         .ctrl = &rk3288_ctrl_data,
283         .win = rk3288_vop_win_data,
284         .win_size = ARRAY_SIZE(rk3288_vop_win_data),
285 };
286
287 static const int rk3368_vop_intrs[] = {
288         FS_INTR,
289         FS_NEW_INTR,
290         ADDR_SAME_INTR,
291         LINE_FLAG_INTR,
292         LINE_FLAG1_INTR,
293         BUS_ERROR_INTR,
294         WIN0_EMPTY_INTR,
295         WIN1_EMPTY_INTR,
296         WIN2_EMPTY_INTR,
297         WIN3_EMPTY_INTR,
298         HWC_EMPTY_INTR,
299         POST_BUF_EMPTY_INTR,
300         PWM_GEN_INTR,
301         DSP_HOLD_VALID_INTR,
302 };
303
304 static const struct vop_intr rk3368_vop_intr = {
305         .intrs = rk3368_vop_intrs,
306         .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
307         .line_flag_num[0] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 0),
308         .line_flag_num[1] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 16),
309         .status = VOP_REG_MASK(RK3368_INTR_STATUS, 0x3fff, 0),
310         .enable = VOP_REG_MASK(RK3368_INTR_EN, 0x3fff, 0),
311         .clear = VOP_REG_MASK(RK3368_INTR_CLEAR, 0x3fff, 0),
312 };
313
314 static const struct vop_win_phy rk3368_win23_data = {
315         .data_formats = formats_win_lite,
316         .nformats = ARRAY_SIZE(formats_win_lite),
317         .gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0),
318         .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4),
319         .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5),
320         .ymirror = VOP_REG(RK3368_WIN2_CTRL1, 0x1, 15),
321         .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20),
322         .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0),
323         .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0),
324         .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0),
325         .yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0),
326         .src_alpha_ctl = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
327         .dst_alpha_ctl = VOP_REG(RK3368_WIN2_DST_ALPHA_CTRL, 0xff, 0),
328 };
329
330 static const struct vop_win_phy rk3368_area1_data = {
331         .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 8),
332         .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 9),
333         .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 23),
334         .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO1, 0x0fff0fff, 0),
335         .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST1, 0x1fff1fff, 0),
336         .yrgb_mst = VOP_REG(RK3368_WIN2_MST1, 0xffffffff, 0),
337         .yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 16),
338 };
339
340 static const struct vop_win_phy rk3368_area2_data = {
341         .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 12),
342         .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 13),
343         .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 26),
344         .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO2, 0x0fff0fff, 0),
345         .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST2, 0x1fff1fff, 0),
346         .yrgb_mst = VOP_REG(RK3368_WIN2_MST2, 0xffffffff, 0),
347         .yrgb_vir = VOP_REG(RK3368_WIN2_VIR2_3, 0x1fff, 0),
348 };
349
350 static const struct vop_win_phy rk3368_area3_data = {
351         .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 16),
352         .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 17),
353         .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 29),
354         .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO3, 0x0fff0fff, 0),
355         .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST3, 0x1fff1fff, 0),
356         .yrgb_mst = VOP_REG(RK3368_WIN2_MST3, 0xffffffff, 0),
357         .yrgb_vir = VOP_REG(RK3368_WIN2_VIR2_3, 0x1fff, 16),
358 };
359
360 static const struct vop_win_phy *rk3368_area_data[] = {
361         &rk3368_area1_data,
362         &rk3368_area2_data,
363         &rk3368_area3_data
364 };
365
366 static const struct vop_win_data rk3368_vop_win_data[] = {
367         { .base = 0x00, .phy = &rk3288_win01_data,
368           .type = DRM_PLANE_TYPE_PRIMARY },
369         { .base = 0x40, .phy = &rk3288_win01_data,
370           .type = DRM_PLANE_TYPE_OVERLAY },
371         { .base = 0x00, .phy = &rk3368_win23_data,
372           .type = DRM_PLANE_TYPE_OVERLAY,
373           .area = rk3368_area_data,
374           .area_size = ARRAY_SIZE(rk3368_area_data), },
375         { .base = 0x50, .phy = &rk3368_win23_data,
376           .type = DRM_PLANE_TYPE_CURSOR,
377           .area = rk3368_area_data,
378           .area_size = ARRAY_SIZE(rk3368_area_data), },
379 };
380
381 static const struct vop_data rk3368_vop = {
382         .version = VOP_VERSION(3, 2),
383         .max_input = {4096, 8192},
384         .max_output = {4096, 2160},
385         .intr = &rk3368_vop_intr,
386         .ctrl = &rk3288_ctrl_data,
387         .win = rk3368_vop_win_data,
388         .win_size = ARRAY_SIZE(rk3368_vop_win_data),
389 };
390
391 static const struct vop_intr rk3366_vop_intr = {
392         .intrs = rk3368_vop_intrs,
393         .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
394         .line_flag_num[0] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 0),
395         .line_flag_num[1] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 16),
396         .status = VOP_REG_MASK(RK3366_INTR_STATUS0, 0xffff, 0),
397         .enable = VOP_REG_MASK(RK3366_INTR_EN0, 0xffff, 0),
398         .clear = VOP_REG_MASK(RK3366_INTR_CLEAR0, 0xffff, 0),
399 };
400
401 static const struct vop_data rk3366_vop = {
402         .version = VOP_VERSION(3, 4),
403         .max_input = {4096, 8192},
404         .max_output = {4096, 2160},
405         .intr = &rk3366_vop_intr,
406         .ctrl = &rk3288_ctrl_data,
407         .win = rk3368_vop_win_data,
408         .win_size = ARRAY_SIZE(rk3368_vop_win_data),
409 };
410
411 static const uint32_t vop_csc_y2r_bt601[] = {
412         0x00000400, 0x0400059c, 0xfd25fea0, 0x07170400,
413         0x00000000, 0xfffecab4, 0x00087932, 0xfff1d4f2,
414 };
415
416 static const uint32_t vop_csc_y2r_bt601_12_235[] = {
417         0x000004a8, 0x04a80662, 0xfcbffe6f, 0x081204a8,
418         0x00000000, 0xfff2134e, 0x00087b58, 0xffeeb4b0,
419 };
420
421 static const uint32_t vop_csc_r2y_bt601[] = {
422         0x02590132, 0xff530075, 0x0200fead, 0xfe530200,
423         0x0000ffad, 0x00000200, 0x00080200, 0x00080200,
424 };
425
426 static const uint32_t vop_csc_r2y_bt601_12_235[] = {
427         0x02040107, 0xff680064, 0x01c2fed6, 0xffb7fe87,
428         0x0000ffb7, 0x00010200, 0x00080200, 0x00080200,
429 };
430
431 static const uint32_t vop_csc_y2r_bt709[] = {
432         0x000004a8, 0x04a8072c, 0xfddeff26, 0x087304a8,
433         0x00000000, 0xfff08077, 0x0004cfed, 0xffedf1b8,
434 };
435
436 static const uint32_t vop_csc_r2y_bt709[] = {
437         0x027500bb, 0xff99003f, 0x01c2fea5, 0xfe6801c2,
438         0x0000ffd7, 0x00010200, 0x00080200, 0x00080200,
439 };
440
441 static const uint32_t vop_csc_y2r_bt2020[] = {
442         0x000004a8, 0x04a806b6, 0xfd66ff40, 0x089004a8,
443         0x00000000, 0xfff16bfc, 0x00058ae9, 0xffedb828,
444 };
445
446 static const uint32_t vop_csc_r2y_bt2020[] = {
447         0x025300e6, 0xff830034, 0x01c1febd, 0xfe6401c1,
448         0x0000ffdc, 0x00010200, 0x00080200, 0x00080200,
449 };
450
451 static const uint32_t vop_csc_r2r_bt709_to_bt2020[] = {
452         0xfda606a4, 0xff80ffb5, 0xfff80488, 0xff99ffed,
453         0x0000047a, 0x00000200, 0x00000200, 0x00000200,
454 };
455
456 static const uint32_t vop_csc_r2r_bt2020_to_bt709[] = {
457         0x01510282, 0x0047002c, 0x000c03ae, 0x005a0011,
458         0x00000394, 0x00000200, 0x00000200, 0x00000200,
459 };
460
461 static const struct vop_csc_table rk3399_csc_table = {
462         .y2r_bt601              = vop_csc_y2r_bt601,
463         .y2r_bt601_12_235       = vop_csc_y2r_bt601_12_235,
464         .r2y_bt601              = vop_csc_r2y_bt601,
465         .r2y_bt601_12_235       = vop_csc_r2y_bt601_12_235,
466
467         .y2r_bt709              = vop_csc_y2r_bt709,
468         .r2y_bt709              = vop_csc_r2y_bt709,
469
470         .y2r_bt2020             = vop_csc_y2r_bt2020,
471         .r2y_bt2020             = vop_csc_r2y_bt2020,
472
473         .r2r_bt709_to_bt2020    = vop_csc_r2r_bt709_to_bt2020,
474         .r2r_bt2020_to_bt709    = vop_csc_r2r_bt2020_to_bt709,
475 };
476
477 static const struct vop_csc rk3399_win0_csc = {
478         .r2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 0),
479         .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1),
480         .r2y_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 2),
481         .y2r_offset = RK3399_WIN0_YUV2YUV_Y2R,
482         .r2r_offset = RK3399_WIN0_YUV2YUV_3X3,
483         .r2y_offset = RK3399_WIN0_YUV2YUV_R2Y,
484 };
485
486 static const struct vop_csc rk3399_win1_csc = {
487         .r2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 8),
488         .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 9),
489         .r2y_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 10),
490         .y2r_offset = RK3399_WIN1_YUV2YUV_Y2R,
491         .r2r_offset = RK3399_WIN1_YUV2YUV_3X3,
492         .r2y_offset = RK3399_WIN1_YUV2YUV_R2Y,
493 };
494
495 static const struct vop_win_data rk3399_vop_win_data[] = {
496         { .base = 0x00, .phy = &rk3288_win01_data, .csc = &rk3399_win0_csc,
497           .type = DRM_PLANE_TYPE_PRIMARY },
498         { .base = 0x40, .phy = &rk3288_win01_data, .csc = &rk3399_win1_csc,
499           .type = DRM_PLANE_TYPE_OVERLAY },
500         { .base = 0x00, .phy = &rk3368_win23_data,
501           .type = DRM_PLANE_TYPE_OVERLAY,
502           .area = rk3368_area_data,
503           .area_size = ARRAY_SIZE(rk3368_area_data), },
504         { .base = 0x50, .phy = &rk3368_win23_data,
505           .type = DRM_PLANE_TYPE_CURSOR,
506           .area = rk3368_area_data,
507           .area_size = ARRAY_SIZE(rk3368_area_data), },
508 };
509
510 static const struct vop_data rk3399_vop_big = {
511         .version = VOP_VERSION(3, 5),
512         .csc_table = &rk3399_csc_table,
513         .feature = VOP_FEATURE_OUTPUT_10BIT | VOP_FEATURE_AFBDC,
514         .max_input = {4096, 8192},
515         .max_output = {4096, 2160},
516         .intr = &rk3366_vop_intr,
517         .ctrl = &rk3288_ctrl_data,
518         .win = rk3399_vop_win_data,
519         .win_size = ARRAY_SIZE(rk3399_vop_win_data),
520 };
521
522 static const struct vop_win_data rk3399_vop_lit_win_data[] = {
523         { .base = 0x00, .phy = &rk3288_win01_data, .csc = &rk3399_win0_csc,
524           .type = DRM_PLANE_TYPE_PRIMARY },
525         { .phy = NULL },
526         { .base = 0x00, .phy = &rk3368_win23_data,
527           .type = DRM_PLANE_TYPE_CURSOR,
528           .area = rk3368_area_data,
529           .area_size = ARRAY_SIZE(rk3368_area_data), },
530         { .phy = NULL },
531 };
532
533
534 static const struct vop_data rk3399_vop_lit = {
535         .version = VOP_VERSION(3, 6),
536         .csc_table = &rk3399_csc_table,
537         .max_input = {4096, 8192},
538         .max_output = {2560, 1600},
539         .intr = &rk3366_vop_intr,
540         .ctrl = &rk3288_ctrl_data,
541         .win = rk3399_vop_lit_win_data,
542         .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data),
543 };
544
545 static const struct vop_win_data rk322x_vop_win_data[] = {
546         { .base = 0x00, .phy = &rk3288_win01_data,
547           .type = DRM_PLANE_TYPE_PRIMARY },
548         { .base = 0x40, .phy = &rk3288_win01_data,
549           .type = DRM_PLANE_TYPE_CURSOR },
550 };
551
552 static const struct vop_data rk322x_vop = {
553         .version = VOP_VERSION(3, 7),
554         .feature = VOP_FEATURE_OUTPUT_10BIT,
555         .max_input = {4096, 8192},
556         .max_output = {4096, 2160},
557         .intr = &rk3366_vop_intr,
558         .ctrl = &rk3288_ctrl_data,
559         .win = rk322x_vop_win_data,
560         .win_size = ARRAY_SIZE(rk322x_vop_win_data),
561 };
562
563 static const struct vop_ctrl rk3328_ctrl_data = {
564         .standby = VOP_REG(RK3328_SYS_CTRL, 0x1, 22),
565         .auto_gate_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 23),
566         .htotal_pw = VOP_REG(RK3328_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
567         .hact_st_end = VOP_REG(RK3328_DSP_HACT_ST_END, 0x1fff1fff, 0),
568         .vtotal_pw = VOP_REG(RK3328_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
569         .vact_st_end = VOP_REG(RK3328_DSP_VACT_ST_END, 0x1fff1fff, 0),
570         .vact_st_end_f1 = VOP_REG(RK3328_DSP_VACT_ST_END_F1, 0x1fff1fff, 0),
571         .vs_st_end_f1 = VOP_REG(RK3328_DSP_VS_ST_END_F1, 0x1fff1fff, 0),
572         .hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
573         .vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
574         .vpost_st_end_f1 = VOP_REG(RK3328_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0),
575         .dsp_interlace = VOP_REG(RK3328_DSP_CTRL0, 0x1, 10),
576         .dsp_layer_sel = VOP_REG(RK3328_DSP_CTRL1, 0xff, 8),
577         .post_lb_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 18),
578         .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11),
579         .overlay_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 16),
580         .core_dclk_div = VOP_REG(RK3328_DSP_CTRL0, 0x1, 4),
581         .p2i_en = VOP_REG(RK3328_DSP_CTRL0, 0x1, 5),
582         .rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12),
583         .hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13),
584         .edp_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 14),
585         .mipi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 15),
586         .rgb_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 16),
587         .hdmi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 20),
588         .edp_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 24),
589         .mipi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 28),
590
591         .dither_down = VOP_REG(RK3328_DSP_CTRL1, 0xf, 1),
592         .dither_up = VOP_REG(RK3328_DSP_CTRL1, 0x1, 6),
593
594         .dsp_data_swap = VOP_REG(RK3328_DSP_CTRL0, 0x1f, 12),
595         .dsp_ccir656_avg = VOP_REG(RK3328_DSP_CTRL0, 0x1, 20),
596         .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18),
597         .dsp_lut_en = VOP_REG(RK3328_DSP_CTRL1, 0x1, 0),
598         .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0),
599
600         .xmirror = VOP_REG(RK3328_DSP_CTRL0, 0x1, 22),
601         .ymirror = VOP_REG(RK3328_DSP_CTRL0, 0x1, 23),
602
603         .dsp_background = VOP_REG(RK3328_DSP_BG, 0xffffffff, 0),
604
605         .cfg_done = VOP_REG(RK3328_REG_CFG_DONE, 0x1, 0),
606 };
607
608 static const struct vop_intr rk3328_vop_intr = {
609         .intrs = rk3368_vop_intrs,
610         .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
611         .line_flag_num[0] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 0),
612         .line_flag_num[1] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 16),
613         .status = VOP_REG_MASK(RK3328_INTR_STATUS0, 0xffff, 0),
614         .enable = VOP_REG_MASK(RK3328_INTR_EN0, 0xffff, 0),
615         .clear = VOP_REG_MASK(RK3328_INTR_CLEAR0, 0xffff, 0),
616 };
617
618 static const struct vop_win_data rk3328_vop_win_data[] = {
619         { .base = 0xd0, .phy = &rk3288_win01_data,
620           .type = DRM_PLANE_TYPE_PRIMARY },
621         { .base = 0x1d0, .phy = &rk3288_win01_data,
622           .type = DRM_PLANE_TYPE_OVERLAY },
623         { .base = 0x2d0, .phy = &rk3288_win01_data,
624           .type = DRM_PLANE_TYPE_CURSOR },
625 };
626
627 static const struct vop_data rk3328_vop = {
628         .version = VOP_VERSION(3, 8),
629         .feature = VOP_FEATURE_OUTPUT_10BIT,
630         .max_input = {4096, 8192},
631         .max_output = {4096, 2160},
632         .intr = &rk3328_vop_intr,
633         .ctrl = &rk3328_ctrl_data,
634         .win = rk3328_vop_win_data,
635         .win_size = ARRAY_SIZE(rk3328_vop_win_data),
636 };
637
638 static const struct vop_scl_regs rk3066_win_scl = {
639         .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
640         .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
641         .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
642         .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
643 };
644
645 static const struct vop_win_phy rk3036_win0_data = {
646         .scl = &rk3066_win_scl,
647         .data_formats = formats_win_full,
648         .nformats = ARRAY_SIZE(formats_win_full),
649         .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0),
650         .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3),
651         .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15),
652         .act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0),
653         .dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0),
654         .dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0),
655         .yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0),
656         .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0),
657         .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0),
658         .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16),
659         .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 18),
660         .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 0)
661 };
662
663 static const struct vop_win_phy rk3036_win1_data = {
664         .data_formats = formats_win_lite,
665         .nformats = ARRAY_SIZE(formats_win_lite),
666         .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
667         .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
668         .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
669         .act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
670         .dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
671         .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
672         .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
673         .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
674         .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19),
675         .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1)
676 };
677
678 static const struct vop_win_data rk3036_vop_win_data[] = {
679         { .base = 0x00, .phy = &rk3036_win0_data,
680           .type = DRM_PLANE_TYPE_PRIMARY },
681         { .base = 0x00, .phy = &rk3036_win1_data,
682           .type = DRM_PLANE_TYPE_CURSOR },
683 };
684
685 static const int rk3036_vop_intrs[] = {
686         DSP_HOLD_VALID_INTR,
687         FS_INTR,
688         LINE_FLAG_INTR,
689         BUS_ERROR_INTR,
690 };
691
692 static const struct vop_intr rk3036_intr = {
693         .intrs = rk3036_vop_intrs,
694         .nintrs = ARRAY_SIZE(rk3036_vop_intrs),
695         .line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12),
696         .status = VOP_REG(RK3036_INT_STATUS, 0xf, 0),
697         .enable = VOP_REG(RK3036_INT_STATUS, 0xf, 4),
698         .clear = VOP_REG(RK3036_INT_STATUS, 0xf, 8),
699 };
700
701 static const struct vop_ctrl rk3036_ctrl_data = {
702         .standby = VOP_REG(RK3036_SYS_CTRL, 0x1, 30),
703         .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0),
704         .dsp_blank = VOP_REG(RK3036_DSP_CTRL1, 0x1, 24),
705         .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
706         .dsp_layer_sel = VOP_REG(RK3036_DSP_CTRL0, 0x1, 8),
707         .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
708         .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0),
709         .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
710         .vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0),
711         .cfg_done = VOP_REG(RK3036_REG_CFG_DONE, 0x1, 0),
712 };
713
714 static const struct vop_data rk3036_vop = {
715         .version = VOP_VERSION(2, 2),
716         .max_input = {1920, 1080},
717         .max_output = {1920, 1080},
718         .ctrl = &rk3036_ctrl_data,
719         .intr = &rk3036_intr,
720         .win = rk3036_vop_win_data,
721         .win_size = ARRAY_SIZE(rk3036_vop_win_data),
722 };
723
724 static const struct of_device_id vop_driver_dt_match[] = {
725         { .compatible = "rockchip,rk3036-vop",
726           .data = &rk3036_vop },
727         { .compatible = "rockchip,rk3288-vop",
728           .data = &rk3288_vop },
729         { .compatible = "rockchip,rk3368-vop",
730           .data = &rk3368_vop },
731         { .compatible = "rockchip,rk3366-vop",
732           .data = &rk3366_vop },
733         { .compatible = "rockchip,rk3399-vop-big",
734           .data = &rk3399_vop_big },
735         { .compatible = "rockchip,rk3399-vop-lit",
736           .data = &rk3399_vop_lit },
737         { .compatible = "rockchip,rk322x-vop",
738           .data = &rk322x_vop },
739         { .compatible = "rockchip,rk3328-vop",
740           .data = &rk3328_vop },
741         {},
742 };
743 MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
744
745 static int vop_probe(struct platform_device *pdev)
746 {
747         struct device *dev = &pdev->dev;
748
749         if (!dev->of_node) {
750                 dev_err(dev, "can't find vop devices\n");
751                 return -ENODEV;
752         }
753
754         return component_add(dev, &vop_component_ops);
755 }
756
757 static int vop_remove(struct platform_device *pdev)
758 {
759         component_del(&pdev->dev, &vop_component_ops);
760
761         return 0;
762 }
763
764 struct platform_driver vop_platform_driver = {
765         .probe = vop_probe,
766         .remove = vop_remove,
767         .driver = {
768                 .name = "rockchip-vop",
769                 .owner = THIS_MODULE,
770                 .of_match_table = of_match_ptr(vop_driver_dt_match),
771         },
772 };
773
774 module_platform_driver(vop_platform_driver);
775
776 MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>");
777 MODULE_DESCRIPTION("ROCKCHIP VOP Driver");
778 MODULE_LICENSE("GPL v2");