Linux Audio

Check our new training course

Loading...
v4.6
 
  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(off, _mask, s) \
 24		{.offset = off, \
 
 25		 .mask = _mask, \
 26		 .shift = s,}
 
 
 
 
 
 
 
 
 
 
 
 
 27
 28static const uint32_t formats_win_full[] = {
 29	DRM_FORMAT_XRGB8888,
 30	DRM_FORMAT_ARGB8888,
 31	DRM_FORMAT_XBGR8888,
 32	DRM_FORMAT_ABGR8888,
 33	DRM_FORMAT_RGB888,
 34	DRM_FORMAT_BGR888,
 35	DRM_FORMAT_RGB565,
 36	DRM_FORMAT_BGR565,
 37	DRM_FORMAT_NV12,
 
 38	DRM_FORMAT_NV16,
 
 39	DRM_FORMAT_NV24,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 40};
 41
 42static const uint32_t formats_win_lite[] = {
 43	DRM_FORMAT_XRGB8888,
 44	DRM_FORMAT_ARGB8888,
 45	DRM_FORMAT_XBGR8888,
 46	DRM_FORMAT_ABGR8888,
 47	DRM_FORMAT_RGB888,
 48	DRM_FORMAT_BGR888,
 49	DRM_FORMAT_RGB565,
 50	DRM_FORMAT_BGR565,
 51};
 52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 53static const struct vop_scl_extension rk3288_win_full_scl_ext = {
 54	.cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
 55	.cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
 56	.cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28),
 57	.cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26),
 58	.cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24),
 59	.yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23),
 60	.yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22),
 61	.yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20),
 62	.yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18),
 63	.yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16),
 64	.line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15),
 65	.cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12),
 66	.yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8),
 67	.vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7),
 68	.vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6),
 69	.vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5),
 70	.vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4),
 71	.bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2),
 72	.cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1),
 73	.yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0),
 74	.lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5),
 75};
 76
 77static const struct vop_scl_regs rk3288_win_full_scl = {
 78	.ext = &rk3288_win_full_scl_ext,
 79	.scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
 80	.scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
 81	.scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
 82	.scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
 83};
 84
 85static const struct vop_win_phy rk3288_win01_data = {
 86	.scl = &rk3288_win_full_scl,
 87	.data_formats = formats_win_full,
 88	.nformats = ARRAY_SIZE(formats_win_full),
 
 89	.enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
 90	.format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
 
 91	.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
 
 92	.act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
 93	.dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
 94	.dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
 95	.yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
 96	.uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
 97	.yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
 98	.uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
 99	.src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
100	.dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
 
101};
102
103static const struct vop_win_phy rk3288_win23_data = {
104	.data_formats = formats_win_lite,
105	.nformats = ARRAY_SIZE(formats_win_lite),
106	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0),
 
 
107	.format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1),
108	.rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12),
109	.dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0),
110	.dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0),
111	.yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0),
112	.yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0),
113	.src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
114	.dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0),
115};
116
117static const struct vop_ctrl rk3288_ctrl_data = {
118	.standby = VOP_REG(RK3288_SYS_CTRL, 0x1, 22),
119	.gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
120	.mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20),
121	.rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
122	.hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
123	.edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
124	.mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
125	.dither_down = VOP_REG(RK3288_DSP_CTRL1, 0xf, 1),
126	.dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6),
127	.data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19),
128	.out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0),
129	.pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4),
130	.htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
131	.hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0),
132	.vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
133	.vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0),
134	.hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
135	.vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
136	.cfg_done = VOP_REG(RK3288_REG_CFG_DONE, 0x1, 0),
137};
138
139static const struct vop_reg_data rk3288_init_reg_table[] = {
140	{RK3288_SYS_CTRL, 0x00c00000},
141	{RK3288_DSP_CTRL0, 0x00000000},
142	{RK3288_WIN0_CTRL0, 0x00000080},
143	{RK3288_WIN1_CTRL0, 0x00000080},
144	/* TODO: Win2/3 support multiple area function, but we haven't found
145	 * a suitable way to use it yet, so let's just use them as other windows
146	 * with only area 0 enabled.
147	 */
148	{RK3288_WIN2_CTRL0, 0x00000010},
149	{RK3288_WIN3_CTRL0, 0x00000010},
 
 
 
 
 
 
 
 
 
 
 
150};
151
152/*
153 * Note: rk3288 has a dedicated 'cursor' window, however, that window requires
154 * special support to get alpha blending working.  For now, just use overlay
155 * window 3 for the drm cursor.
156 *
157 */
158static const struct vop_win_data rk3288_vop_win_data[] = {
159	{ .base = 0x00, .phy = &rk3288_win01_data,
160	  .type = DRM_PLANE_TYPE_PRIMARY },
161	{ .base = 0x40, .phy = &rk3288_win01_data,
162	  .type = DRM_PLANE_TYPE_OVERLAY },
163	{ .base = 0x00, .phy = &rk3288_win23_data,
164	  .type = DRM_PLANE_TYPE_OVERLAY },
165	{ .base = 0x50, .phy = &rk3288_win23_data,
166	  .type = DRM_PLANE_TYPE_CURSOR },
167};
168
169static const int rk3288_vop_intrs[] = {
170	DSP_HOLD_VALID_INTR,
171	FS_INTR,
172	LINE_FLAG_INTR,
173	BUS_ERROR_INTR,
174};
175
176static const struct vop_intr rk3288_vop_intr = {
177	.intrs = rk3288_vop_intrs,
178	.nintrs = ARRAY_SIZE(rk3288_vop_intrs),
 
179	.status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0),
180	.enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4),
181	.clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8),
182};
183
184static const struct vop_data rk3288_vop = {
185	.init_table = rk3288_init_reg_table,
186	.table_size = ARRAY_SIZE(rk3288_init_reg_table),
187	.intr = &rk3288_vop_intr,
188	.ctrl = &rk3288_ctrl_data,
 
 
189	.win = rk3288_vop_win_data,
190	.win_size = ARRAY_SIZE(rk3288_vop_win_data),
 
 
 
 
 
 
 
191};
192
193static const struct vop_scl_regs rk3066_win_scl = {
194	.scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
195	.scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
196	.scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
197	.scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
 
 
 
198};
199
200static const struct vop_win_phy rk3036_win0_data = {
201	.scl = &rk3066_win_scl,
 
 
 
 
 
 
 
 
 
 
202	.data_formats = formats_win_full,
203	.nformats = ARRAY_SIZE(formats_win_full),
204	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0),
205	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3),
206	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15),
207	.act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0),
208	.dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0),
209	.dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0),
210	.yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0),
211	.uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0),
212	.yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0),
 
 
 
 
 
 
 
 
213};
214
215static const struct vop_win_phy rk3036_win1_data = {
216	.data_formats = formats_win_lite,
217	.nformats = ARRAY_SIZE(formats_win_lite),
218	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
219	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
220	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
221	.act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
222	.dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
223	.dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
224	.yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
225	.yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
 
 
 
 
226};
227
228static const struct vop_win_data rk3036_vop_win_data[] = {
229	{ .base = 0x00, .phy = &rk3036_win0_data,
230	  .type = DRM_PLANE_TYPE_PRIMARY },
231	{ .base = 0x00, .phy = &rk3036_win1_data,
 
 
 
 
232	  .type = DRM_PLANE_TYPE_CURSOR },
233};
234
235static const int rk3036_vop_intrs[] = {
236	DSP_HOLD_VALID_INTR,
237	FS_INTR,
238	LINE_FLAG_INTR,
239	BUS_ERROR_INTR,
 
 
 
 
 
 
 
 
240};
241
242static const struct vop_intr rk3036_intr = {
243	.intrs = rk3036_vop_intrs,
244	.nintrs = ARRAY_SIZE(rk3036_vop_intrs),
245	.status = VOP_REG(RK3036_INT_STATUS, 0xf, 0),
246	.enable = VOP_REG(RK3036_INT_STATUS, 0xf, 4),
247	.clear = VOP_REG(RK3036_INT_STATUS, 0xf, 8),
248};
249
250static const struct vop_ctrl rk3036_ctrl_data = {
251	.standby = VOP_REG(RK3036_SYS_CTRL, 0x1, 30),
252	.out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0),
253	.pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
254	.htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
255	.hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0),
256	.vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
257	.vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0),
258	.cfg_done = VOP_REG(RK3036_REG_CFG_DONE, 0x1, 0),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259};
260
261static const struct vop_reg_data rk3036_vop_init_reg_table[] = {
262	{RK3036_DSP_CTRL1, 0x00000000},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263};
264
265static const struct vop_data rk3036_vop = {
266	.init_table = rk3036_vop_init_reg_table,
267	.table_size = ARRAY_SIZE(rk3036_vop_init_reg_table),
268	.ctrl = &rk3036_ctrl_data,
269	.intr = &rk3036_intr,
270	.win = rk3036_vop_win_data,
271	.win_size = ARRAY_SIZE(rk3036_vop_win_data),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
272};
273
274static const struct of_device_id vop_driver_dt_match[] = {
275	{ .compatible = "rockchip,rk3288-vop",
276	  .data = &rk3288_vop },
277	{ .compatible = "rockchip,rk3036-vop",
278	  .data = &rk3036_vop },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279	{},
280};
281MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
282
283static int vop_probe(struct platform_device *pdev)
284{
285	struct device *dev = &pdev->dev;
286
287	if (!dev->of_node) {
288		dev_err(dev, "can't find vop devices\n");
289		return -ENODEV;
290	}
291
292	return component_add(dev, &vop_component_ops);
293}
294
295static int vop_remove(struct platform_device *pdev)
296{
297	component_del(&pdev->dev, &vop_component_ops);
298
299	return 0;
300}
301
302struct platform_driver vop_platform_driver = {
303	.probe = vop_probe,
304	.remove = vop_remove,
305	.driver = {
306		.name = "rockchip-vop",
307		.owner = THIS_MODULE,
308		.of_match_table = of_match_ptr(vop_driver_dt_match),
309	},
310};
311
312module_platform_driver(vop_platform_driver);
313
314MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>");
315MODULE_DESCRIPTION("ROCKCHIP VOP Driver");
316MODULE_LICENSE("GPL v2");
v6.8
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
   4 * Author:Mark Yao <mark.yao@rock-chips.com>
 
 
 
 
 
 
 
 
 
   5 */
   6
 
 
 
   7#include <linux/component.h>
   8#include <linux/mod_devicetable.h>
   9#include <linux/module.h>
  10#include <linux/of.h>
  11#include <linux/platform_device.h>
  12
  13#include <drm/drm_fourcc.h>
  14#include <drm/drm_plane.h>
  15#include <drm/drm_print.h>
  16
  17#include "rockchip_drm_vop.h"
  18#include "rockchip_vop_reg.h"
  19#include "rockchip_drm_drv.h"
  20
  21#define _VOP_REG(off, _mask, _shift, _write_mask, _relaxed) \
  22		{ \
  23		 .offset = off, \
  24		 .mask = _mask, \
  25		 .shift = _shift, \
  26		 .write_mask = _write_mask, \
  27		 .relaxed = _relaxed, \
  28		}
  29
  30#define VOP_REG(off, _mask, _shift) \
  31		_VOP_REG(off, _mask, _shift, false, true)
  32
  33#define VOP_REG_SYNC(off, _mask, _shift) \
  34		_VOP_REG(off, _mask, _shift, false, false)
  35
  36#define VOP_REG_MASK_SYNC(off, _mask, _shift) \
  37		_VOP_REG(off, _mask, _shift, true, false)
  38
  39static const uint32_t formats_win_full[] = {
  40	DRM_FORMAT_XRGB8888,
  41	DRM_FORMAT_ARGB8888,
  42	DRM_FORMAT_XBGR8888,
  43	DRM_FORMAT_ABGR8888,
  44	DRM_FORMAT_RGB888,
  45	DRM_FORMAT_BGR888,
  46	DRM_FORMAT_RGB565,
  47	DRM_FORMAT_BGR565,
  48	DRM_FORMAT_NV12,
  49	DRM_FORMAT_NV21,
  50	DRM_FORMAT_NV16,
  51	DRM_FORMAT_NV61,
  52	DRM_FORMAT_NV24,
  53	DRM_FORMAT_NV42,
  54};
  55
  56static const uint32_t formats_win_full_10[] = {
  57	DRM_FORMAT_XRGB8888,
  58	DRM_FORMAT_ARGB8888,
  59	DRM_FORMAT_XBGR8888,
  60	DRM_FORMAT_ABGR8888,
  61	DRM_FORMAT_RGB888,
  62	DRM_FORMAT_BGR888,
  63	DRM_FORMAT_RGB565,
  64	DRM_FORMAT_BGR565,
  65	DRM_FORMAT_NV12,
  66	DRM_FORMAT_NV21,
  67	DRM_FORMAT_NV16,
  68	DRM_FORMAT_NV61,
  69	DRM_FORMAT_NV24,
  70	DRM_FORMAT_NV42,
  71	DRM_FORMAT_NV15,
  72	DRM_FORMAT_NV20,
  73	DRM_FORMAT_NV30,
  74};
  75
  76static const uint64_t format_modifiers_win_full[] = {
  77	DRM_FORMAT_MOD_LINEAR,
  78	DRM_FORMAT_MOD_INVALID,
  79};
  80
  81static const uint64_t format_modifiers_win_full_afbc[] = {
  82	ROCKCHIP_AFBC_MOD,
  83	DRM_FORMAT_MOD_LINEAR,
  84	DRM_FORMAT_MOD_INVALID,
  85};
  86
  87static const uint32_t formats_win_lite[] = {
  88	DRM_FORMAT_XRGB8888,
  89	DRM_FORMAT_ARGB8888,
  90	DRM_FORMAT_XBGR8888,
  91	DRM_FORMAT_ABGR8888,
  92	DRM_FORMAT_RGB888,
  93	DRM_FORMAT_BGR888,
  94	DRM_FORMAT_RGB565,
  95	DRM_FORMAT_BGR565,
  96};
  97
  98static const uint64_t format_modifiers_win_lite[] = {
  99	DRM_FORMAT_MOD_LINEAR,
 100	DRM_FORMAT_MOD_INVALID,
 101};
 102
 103static const struct vop_scl_regs rk3036_win0_scl = {
 104	.scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
 105	.scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
 106	.scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
 107	.scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
 108};
 109
 110static const struct vop_scl_regs rk3036_win1_scl = {
 111	.scale_yrgb_x = VOP_REG(RK3036_WIN1_SCL_FACTOR_YRGB, 0xffff, 0x0),
 112	.scale_yrgb_y = VOP_REG(RK3036_WIN1_SCL_FACTOR_YRGB, 0xffff, 16),
 113};
 114
 115static const struct vop_win_phy rk3036_win0_data = {
 116	.scl = &rk3036_win0_scl,
 117	.data_formats = formats_win_full,
 118	.nformats = ARRAY_SIZE(formats_win_full),
 119	.format_modifiers = format_modifiers_win_full,
 120	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0),
 121	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3),
 122	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15),
 123	.act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0),
 124	.dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0),
 125	.dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0),
 126	.yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0),
 127	.uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0),
 128	.yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0),
 129	.uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16),
 130	.alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 18),
 131	.alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 0),
 132	.alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29),
 133};
 134
 135static const struct vop_win_phy rk3036_win1_data = {
 136	.scl = &rk3036_win1_scl,
 137	.data_formats = formats_win_lite,
 138	.nformats = ARRAY_SIZE(formats_win_lite),
 139	.format_modifiers = format_modifiers_win_lite,
 140	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
 141	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
 142	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
 143	.act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
 144	.dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
 145	.dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
 146	.yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
 147	.yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
 148	.alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19),
 149	.alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1),
 150	.alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29),
 151};
 152
 153static const struct vop_win_data rk3036_vop_win_data[] = {
 154	{ .base = 0x00, .phy = &rk3036_win0_data,
 155	  .type = DRM_PLANE_TYPE_PRIMARY },
 156	{ .base = 0x00, .phy = &rk3036_win1_data,
 157	  .type = DRM_PLANE_TYPE_CURSOR },
 158};
 159
 160static const int rk3036_vop_intrs[] = {
 161	DSP_HOLD_VALID_INTR,
 162	FS_INTR,
 163	LINE_FLAG_INTR,
 164	BUS_ERROR_INTR,
 165};
 166
 167static const struct vop_intr rk3036_intr = {
 168	.intrs = rk3036_vop_intrs,
 169	.nintrs = ARRAY_SIZE(rk3036_vop_intrs),
 170	.line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12),
 171	.status = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 0),
 172	.enable = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 4),
 173	.clear = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 8),
 174};
 175
 176static const struct vop_modeset rk3036_modeset = {
 177	.htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
 178	.hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0),
 179	.vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
 180	.vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0),
 181};
 182
 183static const struct vop_output rk3036_output = {
 184	.pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
 185};
 186
 187static const struct vop_common rk3036_common = {
 188	.standby = VOP_REG_SYNC(RK3036_SYS_CTRL, 0x1, 30),
 189	.out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0),
 190	.dsp_blank = VOP_REG(RK3036_DSP_CTRL1, 0x1, 24),
 191	.dither_down_sel = VOP_REG(RK3036_DSP_CTRL0, 0x1, 27),
 192	.dither_down_en = VOP_REG(RK3036_DSP_CTRL0, 0x1, 11),
 193	.dither_down_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 10),
 194	.cfg_done = VOP_REG_SYNC(RK3036_REG_CFG_DONE, 0x1, 0),
 195};
 196
 197static const struct vop_data rk3036_vop = {
 198	.intr = &rk3036_intr,
 199	.common = &rk3036_common,
 200	.modeset = &rk3036_modeset,
 201	.output = &rk3036_output,
 202	.win = rk3036_vop_win_data,
 203	.win_size = ARRAY_SIZE(rk3036_vop_win_data),
 204	.max_output = { 1920, 1080 },
 205};
 206
 207static const struct vop_win_phy rk3126_win1_data = {
 208	.data_formats = formats_win_lite,
 209	.nformats = ARRAY_SIZE(formats_win_lite),
 210	.format_modifiers = format_modifiers_win_lite,
 211	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
 212	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
 213	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
 214	.dsp_info = VOP_REG(RK3126_WIN1_DSP_INFO, 0x0fff0fff, 0),
 215	.dsp_st = VOP_REG(RK3126_WIN1_DSP_ST, 0x1fff1fff, 0),
 216	.yrgb_mst = VOP_REG(RK3126_WIN1_MST, 0xffffffff, 0),
 217	.yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
 218	.alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19),
 219	.alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1),
 220	.alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29),
 221};
 222
 223static const struct vop_win_data rk3126_vop_win_data[] = {
 224	{ .base = 0x00, .phy = &rk3036_win0_data,
 225	  .type = DRM_PLANE_TYPE_PRIMARY },
 226	{ .base = 0x00, .phy = &rk3126_win1_data,
 227	  .type = DRM_PLANE_TYPE_CURSOR },
 228};
 229
 230static const struct vop_data rk3126_vop = {
 231	.intr = &rk3036_intr,
 232	.common = &rk3036_common,
 233	.modeset = &rk3036_modeset,
 234	.output = &rk3036_output,
 235	.win = rk3126_vop_win_data,
 236	.win_size = ARRAY_SIZE(rk3126_vop_win_data),
 237	.max_output = { 1920, 1080 },
 238};
 239
 240static const int px30_vop_intrs[] = {
 241	FS_INTR,
 242	0, 0,
 243	LINE_FLAG_INTR,
 244	0,
 245	BUS_ERROR_INTR,
 246	0, 0,
 247	DSP_HOLD_VALID_INTR,
 248};
 249
 250static const struct vop_intr px30_intr = {
 251	.intrs = px30_vop_intrs,
 252	.nintrs = ARRAY_SIZE(px30_vop_intrs),
 253	.line_flag_num[0] = VOP_REG(PX30_LINE_FLAG, 0xfff, 0),
 254	.status = VOP_REG_MASK_SYNC(PX30_INTR_STATUS, 0xffff, 0),
 255	.enable = VOP_REG_MASK_SYNC(PX30_INTR_EN, 0xffff, 0),
 256	.clear = VOP_REG_MASK_SYNC(PX30_INTR_CLEAR, 0xffff, 0),
 257};
 258
 259static const struct vop_common px30_common = {
 260	.standby = VOP_REG_SYNC(PX30_SYS_CTRL2, 0x1, 1),
 261	.out_mode = VOP_REG(PX30_DSP_CTRL2, 0xf, 16),
 262	.dsp_blank = VOP_REG(PX30_DSP_CTRL2, 0x1, 14),
 263	.dither_down_en = VOP_REG(PX30_DSP_CTRL2, 0x1, 8),
 264	.dither_down_sel = VOP_REG(PX30_DSP_CTRL2, 0x1, 7),
 265	.dither_down_mode = VOP_REG(PX30_DSP_CTRL2, 0x1, 6),
 266	.cfg_done = VOP_REG_SYNC(PX30_REG_CFG_DONE, 0x1, 0),
 267};
 268
 269static const struct vop_modeset px30_modeset = {
 270	.htotal_pw = VOP_REG(PX30_DSP_HTOTAL_HS_END, 0x0fff0fff, 0),
 271	.hact_st_end = VOP_REG(PX30_DSP_HACT_ST_END, 0x0fff0fff, 0),
 272	.vtotal_pw = VOP_REG(PX30_DSP_VTOTAL_VS_END, 0x0fff0fff, 0),
 273	.vact_st_end = VOP_REG(PX30_DSP_VACT_ST_END, 0x0fff0fff, 0),
 274};
 275
 276static const struct vop_output px30_output = {
 277	.rgb_dclk_pol = VOP_REG(PX30_DSP_CTRL0, 0x1, 1),
 278	.rgb_pin_pol = VOP_REG(PX30_DSP_CTRL0, 0x7, 2),
 279	.rgb_en = VOP_REG(PX30_DSP_CTRL0, 0x1, 0),
 280	.mipi_dclk_pol = VOP_REG(PX30_DSP_CTRL0, 0x1, 25),
 281	.mipi_pin_pol = VOP_REG(PX30_DSP_CTRL0, 0x7, 26),
 282	.mipi_en = VOP_REG(PX30_DSP_CTRL0, 0x1, 24),
 283};
 284
 285static const struct vop_scl_regs px30_win_scl = {
 286	.scale_yrgb_x = VOP_REG(PX30_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
 287	.scale_yrgb_y = VOP_REG(PX30_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
 288	.scale_cbcr_x = VOP_REG(PX30_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
 289	.scale_cbcr_y = VOP_REG(PX30_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
 290};
 291
 292static const struct vop_win_phy px30_win0_data = {
 293	.scl = &px30_win_scl,
 294	.data_formats = formats_win_full,
 295	.nformats = ARRAY_SIZE(formats_win_full),
 296	.format_modifiers = format_modifiers_win_full,
 297	.enable = VOP_REG(PX30_WIN0_CTRL0, 0x1, 0),
 298	.format = VOP_REG(PX30_WIN0_CTRL0, 0x7, 1),
 299	.rb_swap = VOP_REG(PX30_WIN0_CTRL0, 0x1, 12),
 300	.uv_swap = VOP_REG(PX30_WIN0_CTRL0, 0x1, 15),
 301	.act_info = VOP_REG(PX30_WIN0_ACT_INFO, 0xffffffff, 0),
 302	.dsp_info = VOP_REG(PX30_WIN0_DSP_INFO, 0xffffffff, 0),
 303	.dsp_st = VOP_REG(PX30_WIN0_DSP_ST, 0xffffffff, 0),
 304	.yrgb_mst = VOP_REG(PX30_WIN0_YRGB_MST0, 0xffffffff, 0),
 305	.uv_mst = VOP_REG(PX30_WIN0_CBR_MST0, 0xffffffff, 0),
 306	.yrgb_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 0),
 307	.uv_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 16),
 308	.alpha_pre_mul = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 2),
 309	.alpha_mode = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 1),
 310	.alpha_en = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 0),
 311};
 312
 313static const struct vop_win_phy px30_win1_data = {
 314	.data_formats = formats_win_lite,
 315	.nformats = ARRAY_SIZE(formats_win_lite),
 316	.format_modifiers = format_modifiers_win_lite,
 317	.enable = VOP_REG(PX30_WIN1_CTRL0, 0x1, 0),
 318	.format = VOP_REG(PX30_WIN1_CTRL0, 0x7, 4),
 319	.rb_swap = VOP_REG(PX30_WIN1_CTRL0, 0x1, 12),
 320	.uv_swap = VOP_REG(PX30_WIN1_CTRL0, 0x1, 15),
 321	.dsp_info = VOP_REG(PX30_WIN1_DSP_INFO, 0xffffffff, 0),
 322	.dsp_st = VOP_REG(PX30_WIN1_DSP_ST, 0xffffffff, 0),
 323	.yrgb_mst = VOP_REG(PX30_WIN1_MST, 0xffffffff, 0),
 324	.yrgb_vir = VOP_REG(PX30_WIN1_VIR, 0x1fff, 0),
 325	.alpha_pre_mul = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 2),
 326	.alpha_mode = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 1),
 327	.alpha_en = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 0),
 328};
 329
 330static const struct vop_win_phy px30_win2_data = {
 331	.data_formats = formats_win_lite,
 332	.nformats = ARRAY_SIZE(formats_win_lite),
 333	.format_modifiers = format_modifiers_win_lite,
 334	.gate = VOP_REG(PX30_WIN2_CTRL0, 0x1, 4),
 335	.enable = VOP_REG(PX30_WIN2_CTRL0, 0x1, 0),
 336	.format = VOP_REG(PX30_WIN2_CTRL0, 0x3, 5),
 337	.rb_swap = VOP_REG(PX30_WIN2_CTRL0, 0x1, 20),
 338	.dsp_info = VOP_REG(PX30_WIN2_DSP_INFO0, 0x0fff0fff, 0),
 339	.dsp_st = VOP_REG(PX30_WIN2_DSP_ST0, 0x1fff1fff, 0),
 340	.yrgb_mst = VOP_REG(PX30_WIN2_MST0, 0xffffffff, 0),
 341	.yrgb_vir = VOP_REG(PX30_WIN2_VIR0_1, 0x1fff, 0),
 342	.alpha_pre_mul = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 2),
 343	.alpha_mode = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 1),
 344	.alpha_en = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 0),
 345};
 346
 347static const struct vop_win_data px30_vop_big_win_data[] = {
 348	{ .base = 0x00, .phy = &px30_win0_data,
 349	  .type = DRM_PLANE_TYPE_PRIMARY },
 350	{ .base = 0x00, .phy = &px30_win1_data,
 351	  .type = DRM_PLANE_TYPE_OVERLAY },
 352	{ .base = 0x00, .phy = &px30_win2_data,
 353	  .type = DRM_PLANE_TYPE_CURSOR },
 354};
 355
 356static const struct vop_data px30_vop_big = {
 357	.version = VOP_VERSION(2, 6),
 358	.intr = &px30_intr,
 359	.feature = VOP_FEATURE_INTERNAL_RGB,
 360	.common = &px30_common,
 361	.modeset = &px30_modeset,
 362	.output = &px30_output,
 363	.win = px30_vop_big_win_data,
 364	.win_size = ARRAY_SIZE(px30_vop_big_win_data),
 365	.max_output = { 1920, 1080 },
 366};
 367
 368static const struct vop_win_data px30_vop_lit_win_data[] = {
 369	{ .base = 0x00, .phy = &px30_win1_data,
 370	  .type = DRM_PLANE_TYPE_PRIMARY },
 371};
 372
 373static const struct vop_data px30_vop_lit = {
 374	.version = VOP_VERSION(2, 5),
 375	.intr = &px30_intr,
 376	.feature = VOP_FEATURE_INTERNAL_RGB,
 377	.common = &px30_common,
 378	.modeset = &px30_modeset,
 379	.output = &px30_output,
 380	.win = px30_vop_lit_win_data,
 381	.win_size = ARRAY_SIZE(px30_vop_lit_win_data),
 382	.max_output = { 1920, 1080 },
 383};
 384
 385static const struct vop_scl_regs rk3066_win_scl = {
 386	.scale_yrgb_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
 387	.scale_yrgb_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
 388	.scale_cbcr_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
 389	.scale_cbcr_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
 390};
 391
 392static const struct vop_win_phy rk3066_win0_data = {
 393	.scl = &rk3066_win_scl,
 394	.data_formats = formats_win_full,
 395	.nformats = ARRAY_SIZE(formats_win_full),
 396	.format_modifiers = format_modifiers_win_full,
 397	.enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0),
 398	.format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 4),
 399	.rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 19),
 400	.uv_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 22),
 401	.act_info = VOP_REG(RK3066_WIN0_ACT_INFO, 0x1fff1fff, 0),
 402	.dsp_info = VOP_REG(RK3066_WIN0_DSP_INFO, 0x0fff0fff, 0),
 403	.dsp_st = VOP_REG(RK3066_WIN0_DSP_ST, 0x1fff1fff, 0),
 404	.yrgb_mst = VOP_REG(RK3066_WIN0_YRGB_MST0, 0xffffffff, 0),
 405	.uv_mst = VOP_REG(RK3066_WIN0_CBR_MST0, 0xffffffff, 0),
 406	.yrgb_vir = VOP_REG(RK3066_WIN0_VIR, 0xffff, 0),
 407	.uv_vir = VOP_REG(RK3066_WIN0_VIR, 0x1fff, 16),
 408	.alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 21),
 409	.alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 0),
 410};
 411
 412static const struct vop_win_phy rk3066_win1_data = {
 413	.data_formats = formats_win_full,
 414	.nformats = ARRAY_SIZE(formats_win_full),
 415	.format_modifiers = format_modifiers_win_full,
 416	.enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1),
 417	.format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 7),
 418	.rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 23),
 419	.uv_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 26),
 420	.act_info = VOP_REG(RK3066_WIN1_ACT_INFO, 0x1fff1fff, 0),
 421	.dsp_info = VOP_REG(RK3066_WIN1_DSP_INFO, 0x0fff0fff, 0),
 422	.dsp_st = VOP_REG(RK3066_WIN1_DSP_ST, 0x1fff1fff, 0),
 423	.yrgb_mst = VOP_REG(RK3066_WIN1_YRGB_MST, 0xffffffff, 0),
 424	.uv_mst = VOP_REG(RK3066_WIN1_CBR_MST, 0xffffffff, 0),
 425	.yrgb_vir = VOP_REG(RK3066_WIN1_VIR, 0xffff, 0),
 426	.uv_vir = VOP_REG(RK3066_WIN1_VIR, 0x1fff, 16),
 427	.alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 22),
 428	.alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 1),
 429};
 430
 431static const struct vop_win_phy rk3066_win2_data = {
 432	.data_formats = formats_win_lite,
 433	.nformats = ARRAY_SIZE(formats_win_lite),
 434	.format_modifiers = format_modifiers_win_lite,
 435	.enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2),
 436	.format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 10),
 437	.rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 27),
 438	.dsp_info = VOP_REG(RK3066_WIN2_DSP_INFO, 0x0fff0fff, 0),
 439	.dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0),
 440	.yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0),
 441	.yrgb_vir = VOP_REG(RK3066_WIN2_VIR, 0xffff, 0),
 442	.alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 23),
 443	.alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 2),
 444};
 445
 446static const struct vop_modeset rk3066_modeset = {
 447	.htotal_pw = VOP_REG(RK3066_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
 448	.hact_st_end = VOP_REG(RK3066_DSP_HACT_ST_END, 0x1fff1fff, 0),
 449	.vtotal_pw = VOP_REG(RK3066_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
 450	.vact_st_end = VOP_REG(RK3066_DSP_VACT_ST_END, 0x1fff1fff, 0),
 451};
 452
 453static const struct vop_output rk3066_output = {
 454	.pin_pol = VOP_REG(RK3066_DSP_CTRL0, 0x7, 4),
 455};
 456
 457static const struct vop_common rk3066_common = {
 458	.standby = VOP_REG(RK3066_SYS_CTRL0, 0x1, 1),
 459	.out_mode = VOP_REG(RK3066_DSP_CTRL0, 0xf, 0),
 460	.cfg_done = VOP_REG(RK3066_REG_CFG_DONE, 0x1, 0),
 461	.dither_down_en = VOP_REG(RK3066_DSP_CTRL0, 0x1, 11),
 462	.dither_down_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 10),
 463	.dsp_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 24),
 464	.dither_up = VOP_REG(RK3066_DSP_CTRL0, 0x1, 9),
 465	.dsp_lut_en = VOP_REG(RK3066_SYS_CTRL1, 0x1, 31),
 466	.data_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 25),
 467};
 468
 469static const struct vop_win_data rk3066_vop_win_data[] = {
 470	{ .base = 0x00, .phy = &rk3066_win0_data,
 471	  .type = DRM_PLANE_TYPE_PRIMARY },
 472	{ .base = 0x00, .phy = &rk3066_win1_data,
 473	  .type = DRM_PLANE_TYPE_OVERLAY },
 474	{ .base = 0x00, .phy = &rk3066_win2_data,
 475	  .type = DRM_PLANE_TYPE_CURSOR },
 476};
 477
 478static const int rk3066_vop_intrs[] = {
 479	/*
 480	 * hs_start interrupt fires at frame-start, so serves
 481	 * the same purpose as dsp_hold in the driver.
 482	 */
 483	DSP_HOLD_VALID_INTR,
 484	FS_INTR,
 485	LINE_FLAG_INTR,
 486	BUS_ERROR_INTR,
 487};
 488
 489static const struct vop_intr rk3066_intr = {
 490	.intrs = rk3066_vop_intrs,
 491	.nintrs = ARRAY_SIZE(rk3066_vop_intrs),
 492	.line_flag_num[0] = VOP_REG(RK3066_INT_STATUS, 0xfff, 12),
 493	.status = VOP_REG(RK3066_INT_STATUS, 0xf, 0),
 494	.enable = VOP_REG(RK3066_INT_STATUS, 0xf, 4),
 495	.clear = VOP_REG(RK3066_INT_STATUS, 0xf, 8),
 496};
 497
 498static const struct vop_data rk3066_vop = {
 499	.version = VOP_VERSION(2, 1),
 500	.intr = &rk3066_intr,
 501	.common = &rk3066_common,
 502	.modeset = &rk3066_modeset,
 503	.output = &rk3066_output,
 504	.win = rk3066_vop_win_data,
 505	.win_size = ARRAY_SIZE(rk3066_vop_win_data),
 506	.max_output = { 1920, 1080 },
 507};
 508
 509static const struct vop_scl_regs rk3188_win_scl = {
 510	.scale_yrgb_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
 511	.scale_yrgb_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
 512	.scale_cbcr_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
 513	.scale_cbcr_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
 514};
 515
 516static const struct vop_win_phy rk3188_win0_data = {
 517	.scl = &rk3188_win_scl,
 518	.data_formats = formats_win_full,
 519	.nformats = ARRAY_SIZE(formats_win_full),
 520	.format_modifiers = format_modifiers_win_full,
 521	.enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 0),
 522	.format = VOP_REG(RK3188_SYS_CTRL, 0x7, 3),
 523	.rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 15),
 524	.uv_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 18),
 525	.act_info = VOP_REG(RK3188_WIN0_ACT_INFO, 0x1fff1fff, 0),
 526	.dsp_info = VOP_REG(RK3188_WIN0_DSP_INFO, 0x0fff0fff, 0),
 527	.dsp_st = VOP_REG(RK3188_WIN0_DSP_ST, 0x1fff1fff, 0),
 528	.yrgb_mst = VOP_REG(RK3188_WIN0_YRGB_MST0, 0xffffffff, 0),
 529	.uv_mst = VOP_REG(RK3188_WIN0_CBR_MST0, 0xffffffff, 0),
 530	.yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 0),
 531	.alpha_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 18),
 532	.alpha_en = VOP_REG(RK3188_ALPHA_CTRL, 0x1, 0),
 533	.alpha_pre_mul = VOP_REG(RK3188_DSP_CTRL0, 0x1, 29),
 534};
 535
 536static const struct vop_win_phy rk3188_win1_data = {
 537	.data_formats = formats_win_lite,
 538	.nformats = ARRAY_SIZE(formats_win_lite),
 539	.format_modifiers = format_modifiers_win_lite,
 540	.enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 1),
 541	.format = VOP_REG(RK3188_SYS_CTRL, 0x7, 6),
 542	.rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 19),
 543	/* no act_info on window1 */
 544	.dsp_info = VOP_REG(RK3188_WIN1_DSP_INFO, 0x07ff07ff, 0),
 545	.dsp_st = VOP_REG(RK3188_WIN1_DSP_ST, 0x0fff0fff, 0),
 546	.yrgb_mst = VOP_REG(RK3188_WIN1_MST, 0xffffffff, 0),
 547	.yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 16),
 548	.alpha_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 19),
 549	.alpha_en = VOP_REG(RK3188_ALPHA_CTRL, 0x1, 1),
 550	.alpha_pre_mul = VOP_REG(RK3188_DSP_CTRL0, 0x1, 29),
 551};
 552
 553static const struct vop_modeset rk3188_modeset = {
 554	.htotal_pw = VOP_REG(RK3188_DSP_HTOTAL_HS_END, 0x0fff0fff, 0),
 555	.hact_st_end = VOP_REG(RK3188_DSP_HACT_ST_END, 0x0fff0fff, 0),
 556	.vtotal_pw = VOP_REG(RK3188_DSP_VTOTAL_VS_END, 0x0fff0fff, 0),
 557	.vact_st_end = VOP_REG(RK3188_DSP_VACT_ST_END, 0x0fff0fff, 0),
 558};
 559
 560static const struct vop_output rk3188_output = {
 561	.pin_pol = VOP_REG(RK3188_DSP_CTRL0, 0xf, 4),
 562};
 563
 564static const struct vop_common rk3188_common = {
 565	.gate_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 31),
 566	.standby = VOP_REG(RK3188_SYS_CTRL, 0x1, 30),
 567	.out_mode = VOP_REG(RK3188_DSP_CTRL0, 0xf, 0),
 568	.cfg_done = VOP_REG(RK3188_REG_CFG_DONE, 0x1, 0),
 569	.dither_down_sel = VOP_REG(RK3188_DSP_CTRL0, 0x1, 27),
 570	.dither_down_en = VOP_REG(RK3188_DSP_CTRL0, 0x1, 11),
 571	.dither_down_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 10),
 572	.dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 24),
 573	.dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9),
 574	.dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28),
 575	.data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25),
 576};
 577
 578static const struct vop_win_data rk3188_vop_win_data[] = {
 579	{ .base = 0x00, .phy = &rk3188_win0_data,
 580	  .type = DRM_PLANE_TYPE_PRIMARY },
 581	{ .base = 0x00, .phy = &rk3188_win1_data,
 582	  .type = DRM_PLANE_TYPE_CURSOR },
 583};
 584
 585static const int rk3188_vop_intrs[] = {
 586	/*
 587	 * hs_start interrupt fires at frame-start, so serves
 588	 * the same purpose as dsp_hold in the driver.
 589	 */
 590	DSP_HOLD_VALID_INTR,
 591	FS_INTR,
 592	LINE_FLAG_INTR,
 593	BUS_ERROR_INTR,
 594};
 595
 596static const struct vop_intr rk3188_vop_intr = {
 597	.intrs = rk3188_vop_intrs,
 598	.nintrs = ARRAY_SIZE(rk3188_vop_intrs),
 599	.line_flag_num[0] = VOP_REG(RK3188_INT_STATUS, 0xfff, 12),
 600	.status = VOP_REG(RK3188_INT_STATUS, 0xf, 0),
 601	.enable = VOP_REG(RK3188_INT_STATUS, 0xf, 4),
 602	.clear = VOP_REG(RK3188_INT_STATUS, 0xf, 8),
 603};
 604
 605static const struct vop_data rk3188_vop = {
 606	.intr = &rk3188_vop_intr,
 607	.common = &rk3188_common,
 608	.modeset = &rk3188_modeset,
 609	.output = &rk3188_output,
 610	.win = rk3188_vop_win_data,
 611	.win_size = ARRAY_SIZE(rk3188_vop_win_data),
 612	.feature = VOP_FEATURE_INTERNAL_RGB,
 613	.max_output = { 2048, 1536 },
 614};
 615
 616static const struct vop_scl_extension rk3288_win_full_scl_ext = {
 617	.cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
 618	.cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
 619	.cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28),
 620	.cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26),
 621	.cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24),
 622	.yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23),
 623	.yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22),
 624	.yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20),
 625	.yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18),
 626	.yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16),
 627	.line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15),
 628	.cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12),
 629	.yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8),
 630	.vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7),
 631	.vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6),
 632	.vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5),
 633	.vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4),
 634	.bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2),
 635	.cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1),
 636	.yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0),
 637	.lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5),
 638};
 639
 640static const struct vop_scl_regs rk3288_win_full_scl = {
 641	.ext = &rk3288_win_full_scl_ext,
 642	.scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
 643	.scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
 644	.scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
 645	.scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
 646};
 647
 648static const struct vop_win_phy rk3288_win01_data = {
 649	.scl = &rk3288_win_full_scl,
 650	.data_formats = formats_win_full_10,
 651	.nformats = ARRAY_SIZE(formats_win_full_10),
 652	.format_modifiers = format_modifiers_win_full,
 653	.enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
 654	.format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
 655	.fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 4),
 656	.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
 657	.uv_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 15),
 658	.act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
 659	.dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
 660	.dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
 661	.yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
 662	.uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
 663	.yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
 664	.uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
 665	.src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
 666	.dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
 667	.channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0),
 668};
 669
 670static const struct vop_win_phy rk3288_win23_data = {
 671	.data_formats = formats_win_lite,
 672	.nformats = ARRAY_SIZE(formats_win_lite),
 673	.format_modifiers = format_modifiers_win_lite,
 674	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4),
 675	.gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0),
 676	.format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1),
 677	.rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12),
 678	.dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0),
 679	.dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0),
 680	.yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0),
 681	.yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0),
 682	.src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
 683	.dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0),
 684};
 685
 686static const struct vop_modeset rk3288_modeset = {
 
 
 
 
 
 
 
 
 
 
 
 
 687	.htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
 688	.hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0),
 689	.vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
 690	.vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0),
 691	.hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
 692	.vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
 
 693};
 694
 695static const struct vop_output rk3288_output = {
 696	.pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4),
 697	.rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
 698	.hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
 699	.edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
 700	.mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
 701};
 702
 703static const struct vop_common rk3288_common = {
 704	.standby = VOP_REG_SYNC(RK3288_SYS_CTRL, 0x1, 22),
 705	.gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
 706	.mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20),
 707	.dither_down_sel = VOP_REG(RK3288_DSP_CTRL1, 0x1, 4),
 708	.dither_down_mode = VOP_REG(RK3288_DSP_CTRL1, 0x1, 3),
 709	.dither_down_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 2),
 710	.pre_dither_down = VOP_REG(RK3288_DSP_CTRL1, 0x1, 1),
 711	.dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6),
 712	.dsp_lut_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 0),
 713	.data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19),
 714	.dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18),
 715	.out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0),
 716	.cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0),
 717};
 718
 719/*
 720 * Note: rk3288 has a dedicated 'cursor' window, however, that window requires
 721 * special support to get alpha blending working.  For now, just use overlay
 722 * window 3 for the drm cursor.
 723 *
 724 */
 725static const struct vop_win_data rk3288_vop_win_data[] = {
 726	{ .base = 0x00, .phy = &rk3288_win01_data,
 727	  .type = DRM_PLANE_TYPE_PRIMARY },
 728	{ .base = 0x40, .phy = &rk3288_win01_data,
 729	  .type = DRM_PLANE_TYPE_OVERLAY },
 730	{ .base = 0x00, .phy = &rk3288_win23_data,
 731	  .type = DRM_PLANE_TYPE_OVERLAY },
 732	{ .base = 0x50, .phy = &rk3288_win23_data,
 733	  .type = DRM_PLANE_TYPE_CURSOR },
 734};
 735
 736static const int rk3288_vop_intrs[] = {
 737	DSP_HOLD_VALID_INTR,
 738	FS_INTR,
 739	LINE_FLAG_INTR,
 740	BUS_ERROR_INTR,
 741};
 742
 743static const struct vop_intr rk3288_vop_intr = {
 744	.intrs = rk3288_vop_intrs,
 745	.nintrs = ARRAY_SIZE(rk3288_vop_intrs),
 746	.line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12),
 747	.status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0),
 748	.enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4),
 749	.clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8),
 750};
 751
 752static const struct vop_data rk3288_vop = {
 753	.version = VOP_VERSION(3, 1),
 754	.feature = VOP_FEATURE_OUTPUT_RGB10,
 755	.intr = &rk3288_vop_intr,
 756	.common = &rk3288_common,
 757	.modeset = &rk3288_modeset,
 758	.output = &rk3288_output,
 759	.win = rk3288_vop_win_data,
 760	.win_size = ARRAY_SIZE(rk3288_vop_win_data),
 761	.lut_size = 1024,
 762	/*
 763	 * This is the maximum resolution for the VOPB, the VOPL can only do
 764	 * 2560x1600, but we can't distinguish them as they have the same
 765	 * compatible.
 766	 */
 767	.max_output = { 3840, 2160 },
 768};
 769
 770static const int rk3368_vop_intrs[] = {
 771	FS_INTR,
 772	0, 0,
 773	LINE_FLAG_INTR,
 774	0,
 775	BUS_ERROR_INTR,
 776	0, 0, 0, 0, 0, 0, 0,
 777	DSP_HOLD_VALID_INTR,
 778};
 779
 780static const struct vop_intr rk3368_vop_intr = {
 781	.intrs = rk3368_vop_intrs,
 782	.nintrs = ARRAY_SIZE(rk3368_vop_intrs),
 783	.line_flag_num[0] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 0),
 784	.line_flag_num[1] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 16),
 785	.status = VOP_REG_MASK_SYNC(RK3368_INTR_STATUS, 0x3fff, 0),
 786	.enable = VOP_REG_MASK_SYNC(RK3368_INTR_EN, 0x3fff, 0),
 787	.clear = VOP_REG_MASK_SYNC(RK3368_INTR_CLEAR, 0x3fff, 0),
 788};
 789
 790static const struct vop_win_phy rk3368_win01_data = {
 791	.scl = &rk3288_win_full_scl,
 792	.data_formats = formats_win_full,
 793	.nformats = ARRAY_SIZE(formats_win_full),
 794	.format_modifiers = format_modifiers_win_full,
 795	.enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0),
 796	.format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1),
 797	.rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12),
 798	.uv_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 15),
 799	.x_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 21),
 800	.y_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 22),
 801	.act_info = VOP_REG(RK3368_WIN0_ACT_INFO, 0x1fff1fff, 0),
 802	.dsp_info = VOP_REG(RK3368_WIN0_DSP_INFO, 0x0fff0fff, 0),
 803	.dsp_st = VOP_REG(RK3368_WIN0_DSP_ST, 0x1fff1fff, 0),
 804	.yrgb_mst = VOP_REG(RK3368_WIN0_YRGB_MST, 0xffffffff, 0),
 805	.uv_mst = VOP_REG(RK3368_WIN0_CBR_MST, 0xffffffff, 0),
 806	.yrgb_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 0),
 807	.uv_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 16),
 808	.src_alpha_ctl = VOP_REG(RK3368_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
 809	.dst_alpha_ctl = VOP_REG(RK3368_WIN0_DST_ALPHA_CTRL, 0xff, 0),
 810	.channel = VOP_REG(RK3368_WIN0_CTRL2, 0xff, 0),
 811};
 812
 813static const struct vop_win_phy rk3368_win23_data = {
 814	.data_formats = formats_win_lite,
 815	.nformats = ARRAY_SIZE(formats_win_lite),
 816	.format_modifiers = format_modifiers_win_lite,
 817	.gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0),
 818	.enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4),
 819	.format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5),
 820	.rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20),
 821	.y_mir_en = VOP_REG(RK3368_WIN2_CTRL1, 0x1, 15),
 822	.dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0),
 823	.dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0),
 824	.yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0),
 825	.yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0),
 826	.src_alpha_ctl = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
 827	.dst_alpha_ctl = VOP_REG(RK3368_WIN2_DST_ALPHA_CTRL, 0xff, 0),
 828};
 829
 830static const struct vop_win_data rk3368_vop_win_data[] = {
 831	{ .base = 0x00, .phy = &rk3368_win01_data,
 832	  .type = DRM_PLANE_TYPE_PRIMARY },
 833	{ .base = 0x40, .phy = &rk3368_win01_data,
 834	  .type = DRM_PLANE_TYPE_OVERLAY },
 835	{ .base = 0x00, .phy = &rk3368_win23_data,
 836	  .type = DRM_PLANE_TYPE_OVERLAY },
 837	{ .base = 0x50, .phy = &rk3368_win23_data,
 838	  .type = DRM_PLANE_TYPE_CURSOR },
 839};
 840
 841static const struct vop_output rk3368_output = {
 842	.rgb_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 19),
 843	.hdmi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 23),
 844	.edp_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 27),
 845	.mipi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 31),
 846	.rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 16),
 847	.hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 20),
 848	.edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 24),
 849	.mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 28),
 850	.rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
 851	.hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
 852	.edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
 853	.mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
 854};
 855
 856static const struct vop_misc rk3368_misc = {
 857	.global_regdone_en = VOP_REG(RK3368_SYS_CTRL, 0x1, 11),
 
 
 
 
 858};
 859
 860static const struct vop_data rk3368_vop = {
 861	.version = VOP_VERSION(3, 2),
 862	.intr = &rk3368_vop_intr,
 863	.common = &rk3288_common,
 864	.modeset = &rk3288_modeset,
 865	.output = &rk3368_output,
 866	.misc = &rk3368_misc,
 867	.win = rk3368_vop_win_data,
 868	.win_size = ARRAY_SIZE(rk3368_vop_win_data),
 869	.max_output = { 4096, 2160 },
 870};
 871
 872static const struct vop_intr rk3366_vop_intr = {
 873	.intrs = rk3368_vop_intrs,
 874	.nintrs = ARRAY_SIZE(rk3368_vop_intrs),
 875	.line_flag_num[0] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 0),
 876	.line_flag_num[1] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 16),
 877	.status = VOP_REG_MASK_SYNC(RK3366_INTR_STATUS0, 0xffff, 0),
 878	.enable = VOP_REG_MASK_SYNC(RK3366_INTR_EN0, 0xffff, 0),
 879	.clear = VOP_REG_MASK_SYNC(RK3366_INTR_CLEAR0, 0xffff, 0),
 880};
 881
 882static const struct vop_data rk3366_vop = {
 883	.version = VOP_VERSION(3, 4),
 884	.intr = &rk3366_vop_intr,
 885	.common = &rk3288_common,
 886	.modeset = &rk3288_modeset,
 887	.output = &rk3368_output,
 888	.misc = &rk3368_misc,
 889	.win = rk3368_vop_win_data,
 890	.win_size = ARRAY_SIZE(rk3368_vop_win_data),
 891	.max_output = { 4096, 2160 },
 892};
 893
 894static const struct vop_output rk3399_output = {
 895	.dp_dclk_pol = VOP_REG(RK3399_DSP_CTRL1, 0x1, 19),
 896	.rgb_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 19),
 897	.hdmi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 23),
 898	.edp_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 27),
 899	.mipi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 31),
 900	.dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0x7, 16),
 901	.rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 16),
 902	.hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 20),
 903	.edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 24),
 904	.mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 28),
 905	.dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11),
 906	.rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
 907	.hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
 908	.edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
 909	.mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
 910	.mipi_dual_channel_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 3),
 911};
 912
 913static const struct vop_common rk3399_common = {
 914	.standby = VOP_REG_SYNC(RK3399_SYS_CTRL, 0x1, 22),
 915	.gate_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 23),
 916	.mmu_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 20),
 917	.dither_down_sel = VOP_REG(RK3399_DSP_CTRL1, 0x1, 4),
 918	.dither_down_mode = VOP_REG(RK3399_DSP_CTRL1, 0x1, 3),
 919	.dither_down_en = VOP_REG(RK3399_DSP_CTRL1, 0x1, 2),
 920	.pre_dither_down = VOP_REG(RK3399_DSP_CTRL1, 0x1, 1),
 921	.dither_up = VOP_REG(RK3399_DSP_CTRL1, 0x1, 6),
 922	.dsp_lut_en = VOP_REG(RK3399_DSP_CTRL1, 0x1, 0),
 923	.update_gamma_lut = VOP_REG(RK3399_DSP_CTRL1, 0x1, 7),
 924	.lut_buffer_index = VOP_REG(RK3399_DBG_POST_REG1, 0x1, 1),
 925	.data_blank = VOP_REG(RK3399_DSP_CTRL0, 0x1, 19),
 926	.dsp_blank = VOP_REG(RK3399_DSP_CTRL0, 0x3, 18),
 927	.out_mode = VOP_REG(RK3399_DSP_CTRL0, 0xf, 0),
 928	.cfg_done = VOP_REG_SYNC(RK3399_REG_CFG_DONE, 0x1, 0),
 929};
 930
 931static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win01_data = {
 932	.y2r_coefficients = {
 933		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 0),
 934		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 16),
 935		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 0),
 936		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 16),
 937		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 0),
 938		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 16),
 939		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 0),
 940		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 16),
 941		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 16, 0xffff, 0),
 942		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 20, 0xffffffff, 0),
 943		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 24, 0xffffffff, 0),
 944		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 28, 0xffffffff, 0),
 945	},
 946};
 947
 948static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win23_data = { };
 949
 950static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = {
 951	{ .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data,
 952	  .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1) },
 953	{ .base = 0x60, .phy = &rk3399_yuv2yuv_win01_data,
 954	  .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 9) },
 955	{ .base = 0xC0, .phy = &rk3399_yuv2yuv_win23_data },
 956	{ .base = 0x120, .phy = &rk3399_yuv2yuv_win23_data },
 957
 958};
 959
 960static const struct vop_win_phy rk3399_win0_data = {
 961	.scl = &rk3288_win_full_scl,
 962	.data_formats = formats_win_full_10,
 963	.nformats = ARRAY_SIZE(formats_win_full_10),
 964	.format_modifiers = format_modifiers_win_full_afbc,
 965	.enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
 966	.format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
 967	.fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 4),
 968	.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
 969	.uv_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 15),
 970	.x_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 21),
 971	.y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22),
 972	.act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
 973	.dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
 974	.dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
 975	.yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
 976	.uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
 977	.yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
 978	.uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
 979	.src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
 980	.dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
 981	.channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0),
 982};
 983
 984static const struct vop_win_phy rk3399_win1_data = {
 985	.scl = &rk3288_win_full_scl,
 986	.data_formats = formats_win_full_10,
 987	.nformats = ARRAY_SIZE(formats_win_full_10),
 988	.format_modifiers = format_modifiers_win_full,
 989	.enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
 990	.format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
 991	.fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 4),
 992	.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
 993	.uv_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 15),
 994	.x_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 21),
 995	.y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22),
 996	.act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
 997	.dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
 998	.dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
 999	.yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
1000	.uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
1001	.yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
1002	.uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
1003	.src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
1004	.dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
1005	.channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0),
1006};
1007
1008/*
1009 * rk3399 vop big windows register layout is same as rk3288, but we
1010 * have a separate rk3399 win data array here so that we can advertise
1011 * AFBC on the primary plane.
1012 */
1013static const struct vop_win_data rk3399_vop_win_data[] = {
1014	{ .base = 0x00, .phy = &rk3399_win0_data,
1015	  .type = DRM_PLANE_TYPE_PRIMARY },
1016	{ .base = 0x40, .phy = &rk3399_win1_data,
1017	  .type = DRM_PLANE_TYPE_OVERLAY },
1018	{ .base = 0x00, .phy = &rk3368_win23_data,
1019	  .type = DRM_PLANE_TYPE_OVERLAY },
1020	{ .base = 0x50, .phy = &rk3368_win23_data,
1021	  .type = DRM_PLANE_TYPE_CURSOR },
1022};
1023
1024static const struct vop_afbc rk3399_vop_afbc = {
1025	.rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3),
1026	.enable = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0),
1027	.win_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1),
1028	.format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16),
1029	.hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21),
1030	.hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0),
1031	.pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0),
1032};
1033
1034static const struct vop_data rk3399_vop_big = {
1035	.version = VOP_VERSION(3, 5),
1036	.feature = VOP_FEATURE_OUTPUT_RGB10,
1037	.intr = &rk3366_vop_intr,
1038	.common = &rk3399_common,
1039	.modeset = &rk3288_modeset,
1040	.output = &rk3399_output,
1041	.afbc = &rk3399_vop_afbc,
1042	.misc = &rk3368_misc,
1043	.win = rk3399_vop_win_data,
1044	.win_size = ARRAY_SIZE(rk3399_vop_win_data),
1045	.win_yuv2yuv = rk3399_vop_big_win_yuv2yuv_data,
1046	.lut_size = 1024,
1047	.max_output = { 4096, 2160 },
1048};
1049
1050static const struct vop_win_data rk3399_vop_lit_win_data[] = {
1051	{ .base = 0x00, .phy = &rk3368_win01_data,
1052	  .type = DRM_PLANE_TYPE_PRIMARY },
1053	{ .base = 0x00, .phy = &rk3368_win23_data,
1054	  .type = DRM_PLANE_TYPE_CURSOR},
1055};
1056
1057static const struct vop_win_yuv2yuv_data rk3399_vop_lit_win_yuv2yuv_data[] = {
1058	{ .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data,
1059	  .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1)},
1060	{ .base = 0x60, .phy = &rk3399_yuv2yuv_win23_data },
1061};
1062
1063static const struct vop_data rk3399_vop_lit = {
1064	.version = VOP_VERSION(3, 6),
1065	.intr = &rk3366_vop_intr,
1066	.common = &rk3399_common,
1067	.modeset = &rk3288_modeset,
1068	.output = &rk3399_output,
1069	.misc = &rk3368_misc,
1070	.win = rk3399_vop_lit_win_data,
1071	.win_size = ARRAY_SIZE(rk3399_vop_lit_win_data),
1072	.win_yuv2yuv = rk3399_vop_lit_win_yuv2yuv_data,
1073	.lut_size = 256,
1074	.max_output = { 2560, 1600 },
1075};
1076
1077static const struct vop_win_data rk3228_vop_win_data[] = {
1078	{ .base = 0x00, .phy = &rk3288_win01_data,
1079	  .type = DRM_PLANE_TYPE_PRIMARY },
1080	{ .base = 0x40, .phy = &rk3288_win01_data,
1081	  .type = DRM_PLANE_TYPE_CURSOR },
1082};
1083
1084static const struct vop_data rk3228_vop = {
1085	.version = VOP_VERSION(3, 7),
1086	.feature = VOP_FEATURE_OUTPUT_RGB10,
1087	.intr = &rk3366_vop_intr,
1088	.common = &rk3288_common,
1089	.modeset = &rk3288_modeset,
1090	.output = &rk3399_output,
1091	.misc = &rk3368_misc,
1092	.win = rk3228_vop_win_data,
1093	.win_size = ARRAY_SIZE(rk3228_vop_win_data),
1094	.max_output = { 4096, 2160 },
1095};
1096
1097static const struct vop_modeset rk3328_modeset = {
1098	.htotal_pw = VOP_REG(RK3328_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
1099	.hact_st_end = VOP_REG(RK3328_DSP_HACT_ST_END, 0x1fff1fff, 0),
1100	.vtotal_pw = VOP_REG(RK3328_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
1101	.vact_st_end = VOP_REG(RK3328_DSP_VACT_ST_END, 0x1fff1fff, 0),
1102	.hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
1103	.vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
1104};
1105
1106static const struct vop_output rk3328_output = {
1107	.rgb_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 19),
1108	.hdmi_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 23),
1109	.edp_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 27),
1110	.mipi_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 31),
1111	.rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12),
1112	.hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13),
1113	.edp_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 14),
1114	.mipi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 15),
1115	.rgb_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 16),
1116	.hdmi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 20),
1117	.edp_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 24),
1118	.mipi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 28),
1119};
1120
1121static const struct vop_misc rk3328_misc = {
1122	.global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11),
1123};
1124
1125static const struct vop_common rk3328_common = {
1126	.standby = VOP_REG_SYNC(RK3328_SYS_CTRL, 0x1, 22),
1127	.dither_down_sel = VOP_REG(RK3328_DSP_CTRL1, 0x1, 4),
1128	.dither_down_mode = VOP_REG(RK3328_DSP_CTRL1, 0x1, 3),
1129	.dither_down_en = VOP_REG(RK3328_DSP_CTRL1, 0x1, 2),
1130	.pre_dither_down = VOP_REG(RK3328_DSP_CTRL1, 0x1, 1),
1131	.dither_up = VOP_REG(RK3328_DSP_CTRL1, 0x1, 6),
1132	.dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18),
1133	.out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0),
1134	.cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0),
1135};
1136
1137static const struct vop_intr rk3328_vop_intr = {
1138	.intrs = rk3368_vop_intrs,
1139	.nintrs = ARRAY_SIZE(rk3368_vop_intrs),
1140	.line_flag_num[0] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 0),
1141	.line_flag_num[1] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 16),
1142	.status = VOP_REG_MASK_SYNC(RK3328_INTR_STATUS0, 0xffff, 0),
1143	.enable = VOP_REG_MASK_SYNC(RK3328_INTR_EN0, 0xffff, 0),
1144	.clear = VOP_REG_MASK_SYNC(RK3328_INTR_CLEAR0, 0xffff, 0),
1145};
1146
1147static const struct vop_win_data rk3328_vop_win_data[] = {
1148	{ .base = 0xd0, .phy = &rk3399_win1_data,
1149	  .type = DRM_PLANE_TYPE_PRIMARY },
1150	{ .base = 0x1d0, .phy = &rk3399_win1_data,
1151	  .type = DRM_PLANE_TYPE_OVERLAY },
1152	{ .base = 0x2d0, .phy = &rk3399_win1_data,
1153	  .type = DRM_PLANE_TYPE_CURSOR },
1154};
1155
1156static const struct vop_data rk3328_vop = {
1157	.version = VOP_VERSION(3, 8),
1158	.feature = VOP_FEATURE_OUTPUT_RGB10,
1159	.intr = &rk3328_vop_intr,
1160	.common = &rk3328_common,
1161	.modeset = &rk3328_modeset,
1162	.output = &rk3328_output,
1163	.misc = &rk3328_misc,
1164	.win = rk3328_vop_win_data,
1165	.win_size = ARRAY_SIZE(rk3328_vop_win_data),
1166	.max_output = { 4096, 2160 },
1167};
1168
1169static const struct vop_common rv1126_common = {
1170	.standby = VOP_REG_SYNC(PX30_SYS_CTRL2, 0x1, 1),
1171	.out_mode = VOP_REG(PX30_DSP_CTRL2, 0xf, 16),
1172	.dsp_blank = VOP_REG(PX30_DSP_CTRL2, 0x1, 14),
1173	.dither_down_en = VOP_REG(PX30_DSP_CTRL2, 0x1, 8),
1174	.dither_down_sel = VOP_REG(PX30_DSP_CTRL2, 0x1, 7),
1175	.dither_down_mode = VOP_REG(PX30_DSP_CTRL2, 0x1, 6),
1176	.cfg_done = VOP_REG_SYNC(PX30_REG_CFG_DONE, 0x1, 0),
1177	.dither_up = VOP_REG(PX30_DSP_CTRL2, 0x1, 2),
1178	.dsp_lut_en = VOP_REG(PX30_DSP_CTRL2, 0x1, 5),
1179	.gate_en = VOP_REG(PX30_DSP_CTRL2, 0x1, 0),
1180};
1181
1182static const struct vop_modeset rv1126_modeset = {
1183	.htotal_pw = VOP_REG(PX30_DSP_HTOTAL_HS_END, 0x0fff0fff, 0),
1184	.hact_st_end = VOP_REG(PX30_DSP_HACT_ST_END, 0x0fff0fff, 0),
1185	.vtotal_pw = VOP_REG(PX30_DSP_VTOTAL_VS_END, 0x0fff0fff, 0),
1186	.vact_st_end = VOP_REG(PX30_DSP_VACT_ST_END, 0x0fff0fff, 0),
1187};
1188
1189static const struct vop_output rv1126_output = {
1190	.rgb_dclk_pol = VOP_REG(PX30_DSP_CTRL0, 0x1, 1),
1191	.rgb_pin_pol = VOP_REG(PX30_DSP_CTRL0, 0x7, 2),
1192	.rgb_en = VOP_REG(PX30_DSP_CTRL0, 0x1, 0),
1193	.mipi_dclk_pol = VOP_REG(PX30_DSP_CTRL0, 0x1, 25),
1194	.mipi_pin_pol = VOP_REG(PX30_DSP_CTRL0, 0x7, 26),
1195	.mipi_en = VOP_REG(PX30_DSP_CTRL0, 0x1, 24),
1196};
1197
1198static const struct vop_misc rv1126_misc = {
1199	.global_regdone_en = VOP_REG(PX30_SYS_CTRL2, 0x1, 13),
1200};
1201
1202static const struct vop_win_data rv1126_vop_win_data[] = {
1203	{ .base = 0x00, .phy = &px30_win0_data,
1204	  .type = DRM_PLANE_TYPE_OVERLAY },
1205	{ .base = 0x00, .phy = &px30_win2_data,
1206	  .type = DRM_PLANE_TYPE_PRIMARY },
1207};
1208
1209static const struct vop_data rv1126_vop = {
1210	.version = VOP_VERSION(2, 0xb),
1211	.intr = &px30_intr,
1212	.common = &rv1126_common,
1213	.modeset = &rv1126_modeset,
1214	.output = &rv1126_output,
1215	.misc = &rv1126_misc,
1216	.win = rv1126_vop_win_data,
1217	.win_size = ARRAY_SIZE(rv1126_vop_win_data),
1218	.max_output = { 1920, 1080 },
1219	.lut_size = 1024,
1220};
1221
1222static const struct of_device_id vop_driver_dt_match[] = {
 
 
1223	{ .compatible = "rockchip,rk3036-vop",
1224	  .data = &rk3036_vop },
1225	{ .compatible = "rockchip,rk3126-vop",
1226	  .data = &rk3126_vop },
1227	{ .compatible = "rockchip,px30-vop-big",
1228	  .data = &px30_vop_big },
1229	{ .compatible = "rockchip,px30-vop-lit",
1230	  .data = &px30_vop_lit },
1231	{ .compatible = "rockchip,rk3066-vop",
1232	  .data = &rk3066_vop },
1233	{ .compatible = "rockchip,rk3188-vop",
1234	  .data = &rk3188_vop },
1235	{ .compatible = "rockchip,rk3288-vop",
1236	  .data = &rk3288_vop },
1237	{ .compatible = "rockchip,rk3368-vop",
1238	  .data = &rk3368_vop },
1239	{ .compatible = "rockchip,rk3366-vop",
1240	  .data = &rk3366_vop },
1241	{ .compatible = "rockchip,rk3399-vop-big",
1242	  .data = &rk3399_vop_big },
1243	{ .compatible = "rockchip,rk3399-vop-lit",
1244	  .data = &rk3399_vop_lit },
1245	{ .compatible = "rockchip,rk3228-vop",
1246	  .data = &rk3228_vop },
1247	{ .compatible = "rockchip,rk3328-vop",
1248	  .data = &rk3328_vop },
1249	{ .compatible = "rockchip,rv1126-vop",
1250	  .data = &rv1126_vop },
1251	{},
1252};
1253MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
1254
1255static int vop_probe(struct platform_device *pdev)
1256{
1257	struct device *dev = &pdev->dev;
1258
1259	if (!dev->of_node) {
1260		DRM_DEV_ERROR(dev, "can't find vop devices\n");
1261		return -ENODEV;
1262	}
1263
1264	return component_add(dev, &vop_component_ops);
1265}
1266
1267static void vop_remove(struct platform_device *pdev)
1268{
1269	component_del(&pdev->dev, &vop_component_ops);
 
 
1270}
1271
1272struct platform_driver vop_platform_driver = {
1273	.probe = vop_probe,
1274	.remove_new = vop_remove,
1275	.driver = {
1276		.name = "rockchip-vop",
1277		.of_match_table = vop_driver_dt_match,
 
1278	},
1279};