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, _shift, _write_mask, _relaxed) \ 24 { \ 25 .offset = off, \ 26 .mask = _mask, \ 27 .shift = _shift, \ 28 .write_mask = _write_mask, \ 29 .relaxed = _relaxed, \ 30 } 31 32 #define VOP_REG(off, _mask, _shift) \ 33 _VOP_REG(off, _mask, _shift, false, true) 34 35 #define VOP_REG_SYNC(off, _mask, _shift) \ 36 _VOP_REG(off, _mask, _shift, false, false) 37 38 #define VOP_REG_MASK_SYNC(off, _mask, _shift) \ 39 _VOP_REG(off, _mask, _shift, true, false) 40 41 static const uint32_t formats_win_full[] = { 42 DRM_FORMAT_XRGB8888, 43 DRM_FORMAT_ARGB8888, 44 DRM_FORMAT_XBGR8888, 45 DRM_FORMAT_ABGR8888, 46 DRM_FORMAT_RGB888, 47 DRM_FORMAT_BGR888, 48 DRM_FORMAT_RGB565, 49 DRM_FORMAT_BGR565, 50 DRM_FORMAT_NV12, 51 DRM_FORMAT_NV16, 52 DRM_FORMAT_NV24, 53 }; 54 55 static const uint32_t formats_win_lite[] = { 56 DRM_FORMAT_XRGB8888, 57 DRM_FORMAT_ARGB8888, 58 DRM_FORMAT_XBGR8888, 59 DRM_FORMAT_ABGR8888, 60 DRM_FORMAT_RGB888, 61 DRM_FORMAT_BGR888, 62 DRM_FORMAT_RGB565, 63 DRM_FORMAT_BGR565, 64 }; 65 66 static const struct vop_scl_regs rk3036_win_scl = { 67 .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), 68 .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), 69 .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), 70 .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16), 71 }; 72 73 static const struct vop_win_phy rk3036_win0_data = { 74 .scl = &rk3036_win_scl, 75 .data_formats = formats_win_full, 76 .nformats = ARRAY_SIZE(formats_win_full), 77 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0), 78 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3), 79 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15), 80 .act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0), 81 .dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0), 82 .dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0), 83 .yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0), 84 .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0), 85 .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0), 86 .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16), 87 }; 88 89 static const struct vop_win_phy rk3036_win1_data = { 90 .data_formats = formats_win_lite, 91 .nformats = ARRAY_SIZE(formats_win_lite), 92 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1), 93 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6), 94 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19), 95 .act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0), 96 .dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0), 97 .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0), 98 .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0), 99 .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0), 100 }; 101 102 static const struct vop_win_data rk3036_vop_win_data[] = { 103 { .base = 0x00, .phy = &rk3036_win0_data, 104 .type = DRM_PLANE_TYPE_PRIMARY }, 105 { .base = 0x00, .phy = &rk3036_win1_data, 106 .type = DRM_PLANE_TYPE_CURSOR }, 107 }; 108 109 static const int rk3036_vop_intrs[] = { 110 DSP_HOLD_VALID_INTR, 111 FS_INTR, 112 LINE_FLAG_INTR, 113 BUS_ERROR_INTR, 114 }; 115 116 static const struct vop_intr rk3036_intr = { 117 .intrs = rk3036_vop_intrs, 118 .nintrs = ARRAY_SIZE(rk3036_vop_intrs), 119 .line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12), 120 .status = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 0), 121 .enable = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 4), 122 .clear = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 8), 123 }; 124 125 static const struct vop_modeset rk3036_modeset = { 126 .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 127 .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0), 128 .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 129 .vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0), 130 }; 131 132 static const struct vop_output rk3036_output = { 133 .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4), 134 }; 135 136 static const struct vop_common rk3036_common = { 137 .standby = VOP_REG_SYNC(RK3036_SYS_CTRL, 0x1, 30), 138 .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0), 139 .dsp_blank = VOP_REG(RK3036_DSP_CTRL1, 0x1, 24), 140 .cfg_done = VOP_REG_SYNC(RK3036_REG_CFG_DONE, 0x1, 0), 141 }; 142 143 static const struct vop_data rk3036_vop = { 144 .intr = &rk3036_intr, 145 .common = &rk3036_common, 146 .modeset = &rk3036_modeset, 147 .output = &rk3036_output, 148 .win = rk3036_vop_win_data, 149 .win_size = ARRAY_SIZE(rk3036_vop_win_data), 150 }; 151 152 static const struct vop_win_phy rk3126_win1_data = { 153 .data_formats = formats_win_lite, 154 .nformats = ARRAY_SIZE(formats_win_lite), 155 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1), 156 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6), 157 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19), 158 .dsp_info = VOP_REG(RK3126_WIN1_DSP_INFO, 0x0fff0fff, 0), 159 .dsp_st = VOP_REG(RK3126_WIN1_DSP_ST, 0x1fff1fff, 0), 160 .yrgb_mst = VOP_REG(RK3126_WIN1_MST, 0xffffffff, 0), 161 .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0), 162 }; 163 164 static const struct vop_win_data rk3126_vop_win_data[] = { 165 { .base = 0x00, .phy = &rk3036_win0_data, 166 .type = DRM_PLANE_TYPE_PRIMARY }, 167 { .base = 0x00, .phy = &rk3126_win1_data, 168 .type = DRM_PLANE_TYPE_CURSOR }, 169 }; 170 171 static const struct vop_data rk3126_vop = { 172 .intr = &rk3036_intr, 173 .common = &rk3036_common, 174 .modeset = &rk3036_modeset, 175 .output = &rk3036_output, 176 .win = rk3126_vop_win_data, 177 .win_size = ARRAY_SIZE(rk3126_vop_win_data), 178 }; 179 180 static const int px30_vop_intrs[] = { 181 FS_INTR, 182 0, 0, 183 LINE_FLAG_INTR, 184 0, 185 BUS_ERROR_INTR, 186 0, 0, 187 DSP_HOLD_VALID_INTR, 188 }; 189 190 static const struct vop_intr px30_intr = { 191 .intrs = px30_vop_intrs, 192 .nintrs = ARRAY_SIZE(px30_vop_intrs), 193 .line_flag_num[0] = VOP_REG(PX30_LINE_FLAG, 0xfff, 0), 194 .status = VOP_REG_MASK_SYNC(PX30_INTR_STATUS, 0xffff, 0), 195 .enable = VOP_REG_MASK_SYNC(PX30_INTR_EN, 0xffff, 0), 196 .clear = VOP_REG_MASK_SYNC(PX30_INTR_CLEAR, 0xffff, 0), 197 }; 198 199 static const struct vop_common px30_common = { 200 .standby = VOP_REG_SYNC(PX30_SYS_CTRL2, 0x1, 1), 201 .out_mode = VOP_REG(PX30_DSP_CTRL2, 0xf, 16), 202 .dsp_blank = VOP_REG(PX30_DSP_CTRL2, 0x1, 14), 203 .cfg_done = VOP_REG_SYNC(PX30_REG_CFG_DONE, 0x1, 0), 204 }; 205 206 static const struct vop_modeset px30_modeset = { 207 .htotal_pw = VOP_REG(PX30_DSP_HTOTAL_HS_END, 0x0fff0fff, 0), 208 .hact_st_end = VOP_REG(PX30_DSP_HACT_ST_END, 0x0fff0fff, 0), 209 .vtotal_pw = VOP_REG(PX30_DSP_VTOTAL_VS_END, 0x0fff0fff, 0), 210 .vact_st_end = VOP_REG(PX30_DSP_VACT_ST_END, 0x0fff0fff, 0), 211 }; 212 213 static const struct vop_output px30_output = { 214 .rgb_pin_pol = VOP_REG(PX30_DSP_CTRL0, 0xf, 1), 215 .mipi_pin_pol = VOP_REG(PX30_DSP_CTRL0, 0xf, 25), 216 .rgb_en = VOP_REG(PX30_DSP_CTRL0, 0x1, 0), 217 .mipi_en = VOP_REG(PX30_DSP_CTRL0, 0x1, 24), 218 }; 219 220 static const struct vop_scl_regs px30_win_scl = { 221 .scale_yrgb_x = VOP_REG(PX30_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), 222 .scale_yrgb_y = VOP_REG(PX30_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), 223 .scale_cbcr_x = VOP_REG(PX30_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), 224 .scale_cbcr_y = VOP_REG(PX30_WIN0_SCL_FACTOR_CBR, 0xffff, 16), 225 }; 226 227 static const struct vop_win_phy px30_win0_data = { 228 .scl = &px30_win_scl, 229 .data_formats = formats_win_full, 230 .nformats = ARRAY_SIZE(formats_win_full), 231 .enable = VOP_REG(PX30_WIN0_CTRL0, 0x1, 0), 232 .format = VOP_REG(PX30_WIN0_CTRL0, 0x7, 1), 233 .rb_swap = VOP_REG(PX30_WIN0_CTRL0, 0x1, 12), 234 .act_info = VOP_REG(PX30_WIN0_ACT_INFO, 0xffffffff, 0), 235 .dsp_info = VOP_REG(PX30_WIN0_DSP_INFO, 0xffffffff, 0), 236 .dsp_st = VOP_REG(PX30_WIN0_DSP_ST, 0xffffffff, 0), 237 .yrgb_mst = VOP_REG(PX30_WIN0_YRGB_MST0, 0xffffffff, 0), 238 .uv_mst = VOP_REG(PX30_WIN0_CBR_MST0, 0xffffffff, 0), 239 .yrgb_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 0), 240 .uv_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 16), 241 }; 242 243 static const struct vop_win_phy px30_win1_data = { 244 .data_formats = formats_win_lite, 245 .nformats = ARRAY_SIZE(formats_win_lite), 246 .enable = VOP_REG(PX30_WIN1_CTRL0, 0x1, 0), 247 .format = VOP_REG(PX30_WIN1_CTRL0, 0x7, 4), 248 .rb_swap = VOP_REG(PX30_WIN1_CTRL0, 0x1, 12), 249 .dsp_info = VOP_REG(PX30_WIN1_DSP_INFO, 0xffffffff, 0), 250 .dsp_st = VOP_REG(PX30_WIN1_DSP_ST, 0xffffffff, 0), 251 .yrgb_mst = VOP_REG(PX30_WIN1_MST, 0xffffffff, 0), 252 .yrgb_vir = VOP_REG(PX30_WIN1_VIR, 0x1fff, 0), 253 }; 254 255 static const struct vop_win_phy px30_win2_data = { 256 .data_formats = formats_win_lite, 257 .nformats = ARRAY_SIZE(formats_win_lite), 258 .gate = VOP_REG(PX30_WIN2_CTRL0, 0x1, 4), 259 .enable = VOP_REG(PX30_WIN2_CTRL0, 0x1, 0), 260 .format = VOP_REG(PX30_WIN2_CTRL0, 0x3, 5), 261 .rb_swap = VOP_REG(PX30_WIN2_CTRL0, 0x1, 20), 262 .dsp_info = VOP_REG(PX30_WIN2_DSP_INFO0, 0x0fff0fff, 0), 263 .dsp_st = VOP_REG(PX30_WIN2_DSP_ST0, 0x1fff1fff, 0), 264 .yrgb_mst = VOP_REG(PX30_WIN2_MST0, 0xffffffff, 0), 265 .yrgb_vir = VOP_REG(PX30_WIN2_VIR0_1, 0x1fff, 0), 266 }; 267 268 static const struct vop_win_data px30_vop_big_win_data[] = { 269 { .base = 0x00, .phy = &px30_win0_data, 270 .type = DRM_PLANE_TYPE_PRIMARY }, 271 { .base = 0x00, .phy = &px30_win1_data, 272 .type = DRM_PLANE_TYPE_OVERLAY }, 273 { .base = 0x00, .phy = &px30_win2_data, 274 .type = DRM_PLANE_TYPE_CURSOR }, 275 }; 276 277 static const struct vop_data px30_vop_big = { 278 .intr = &px30_intr, 279 .feature = VOP_FEATURE_INTERNAL_RGB, 280 .common = &px30_common, 281 .modeset = &px30_modeset, 282 .output = &px30_output, 283 .win = px30_vop_big_win_data, 284 .win_size = ARRAY_SIZE(px30_vop_big_win_data), 285 }; 286 287 static const struct vop_win_data px30_vop_lit_win_data[] = { 288 { .base = 0x00, .phy = &px30_win1_data, 289 .type = DRM_PLANE_TYPE_PRIMARY }, 290 }; 291 292 static const struct vop_data px30_vop_lit = { 293 .intr = &px30_intr, 294 .feature = VOP_FEATURE_INTERNAL_RGB, 295 .common = &px30_common, 296 .modeset = &px30_modeset, 297 .output = &px30_output, 298 .win = px30_vop_lit_win_data, 299 .win_size = ARRAY_SIZE(px30_vop_lit_win_data), 300 }; 301 302 static const struct vop_scl_regs rk3066_win_scl = { 303 .scale_yrgb_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), 304 .scale_yrgb_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), 305 .scale_cbcr_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), 306 .scale_cbcr_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 16), 307 }; 308 309 static const struct vop_win_phy rk3066_win0_data = { 310 .scl = &rk3066_win_scl, 311 .data_formats = formats_win_full, 312 .nformats = ARRAY_SIZE(formats_win_full), 313 .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0), 314 .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 4), 315 .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 19), 316 .act_info = VOP_REG(RK3066_WIN0_ACT_INFO, 0x1fff1fff, 0), 317 .dsp_info = VOP_REG(RK3066_WIN0_DSP_INFO, 0x0fff0fff, 0), 318 .dsp_st = VOP_REG(RK3066_WIN0_DSP_ST, 0x1fff1fff, 0), 319 .yrgb_mst = VOP_REG(RK3066_WIN0_YRGB_MST0, 0xffffffff, 0), 320 .uv_mst = VOP_REG(RK3066_WIN0_CBR_MST0, 0xffffffff, 0), 321 .yrgb_vir = VOP_REG(RK3066_WIN0_VIR, 0xffff, 0), 322 .uv_vir = VOP_REG(RK3066_WIN0_VIR, 0x1fff, 16), 323 }; 324 325 static const struct vop_win_phy rk3066_win1_data = { 326 .scl = &rk3066_win_scl, 327 .data_formats = formats_win_full, 328 .nformats = ARRAY_SIZE(formats_win_full), 329 .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1), 330 .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 7), 331 .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 23), 332 .act_info = VOP_REG(RK3066_WIN1_ACT_INFO, 0x1fff1fff, 0), 333 .dsp_info = VOP_REG(RK3066_WIN1_DSP_INFO, 0x0fff0fff, 0), 334 .dsp_st = VOP_REG(RK3066_WIN1_DSP_ST, 0x1fff1fff, 0), 335 .yrgb_mst = VOP_REG(RK3066_WIN1_YRGB_MST, 0xffffffff, 0), 336 .uv_mst = VOP_REG(RK3066_WIN1_CBR_MST, 0xffffffff, 0), 337 .yrgb_vir = VOP_REG(RK3066_WIN1_VIR, 0xffff, 0), 338 .uv_vir = VOP_REG(RK3066_WIN1_VIR, 0x1fff, 16), 339 }; 340 341 static const struct vop_win_phy rk3066_win2_data = { 342 .data_formats = formats_win_lite, 343 .nformats = ARRAY_SIZE(formats_win_lite), 344 .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2), 345 .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 10), 346 .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 27), 347 .dsp_info = VOP_REG(RK3066_WIN2_DSP_INFO, 0x0fff0fff, 0), 348 .dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0), 349 .yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0), 350 .yrgb_vir = VOP_REG(RK3066_WIN2_VIR, 0xffff, 0), 351 }; 352 353 static const struct vop_modeset rk3066_modeset = { 354 .htotal_pw = VOP_REG(RK3066_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 355 .hact_st_end = VOP_REG(RK3066_DSP_HACT_ST_END, 0x1fff1fff, 0), 356 .vtotal_pw = VOP_REG(RK3066_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 357 .vact_st_end = VOP_REG(RK3066_DSP_VACT_ST_END, 0x1fff1fff, 0), 358 }; 359 360 static const struct vop_output rk3066_output = { 361 .pin_pol = VOP_REG(RK3066_DSP_CTRL0, 0x7, 4), 362 }; 363 364 static const struct vop_common rk3066_common = { 365 .standby = VOP_REG(RK3066_SYS_CTRL0, 0x1, 1), 366 .out_mode = VOP_REG(RK3066_DSP_CTRL0, 0xf, 0), 367 .cfg_done = VOP_REG(RK3066_REG_CFG_DONE, 0x1, 0), 368 .dsp_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 24), 369 }; 370 371 static const struct vop_win_data rk3066_vop_win_data[] = { 372 { .base = 0x00, .phy = &rk3066_win0_data, 373 .type = DRM_PLANE_TYPE_PRIMARY }, 374 { .base = 0x00, .phy = &rk3066_win1_data, 375 .type = DRM_PLANE_TYPE_OVERLAY }, 376 { .base = 0x00, .phy = &rk3066_win2_data, 377 .type = DRM_PLANE_TYPE_CURSOR }, 378 }; 379 380 static const int rk3066_vop_intrs[] = { 381 /* 382 * hs_start interrupt fires at frame-start, so serves 383 * the same purpose as dsp_hold in the driver. 384 */ 385 DSP_HOLD_VALID_INTR, 386 FS_INTR, 387 LINE_FLAG_INTR, 388 BUS_ERROR_INTR, 389 }; 390 391 static const struct vop_intr rk3066_intr = { 392 .intrs = rk3066_vop_intrs, 393 .nintrs = ARRAY_SIZE(rk3066_vop_intrs), 394 .line_flag_num[0] = VOP_REG(RK3066_INT_STATUS, 0xfff, 12), 395 .status = VOP_REG(RK3066_INT_STATUS, 0xf, 0), 396 .enable = VOP_REG(RK3066_INT_STATUS, 0xf, 4), 397 .clear = VOP_REG(RK3066_INT_STATUS, 0xf, 8), 398 }; 399 400 static const struct vop_data rk3066_vop = { 401 .version = VOP_VERSION(2, 1), 402 .intr = &rk3066_intr, 403 .common = &rk3066_common, 404 .modeset = &rk3066_modeset, 405 .output = &rk3066_output, 406 .win = rk3066_vop_win_data, 407 .win_size = ARRAY_SIZE(rk3066_vop_win_data), 408 }; 409 410 static const struct vop_scl_regs rk3188_win_scl = { 411 .scale_yrgb_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), 412 .scale_yrgb_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), 413 .scale_cbcr_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), 414 .scale_cbcr_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 16), 415 }; 416 417 static const struct vop_win_phy rk3188_win0_data = { 418 .scl = &rk3188_win_scl, 419 .data_formats = formats_win_full, 420 .nformats = ARRAY_SIZE(formats_win_full), 421 .enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 0), 422 .format = VOP_REG(RK3188_SYS_CTRL, 0x7, 3), 423 .rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 15), 424 .act_info = VOP_REG(RK3188_WIN0_ACT_INFO, 0x1fff1fff, 0), 425 .dsp_info = VOP_REG(RK3188_WIN0_DSP_INFO, 0x0fff0fff, 0), 426 .dsp_st = VOP_REG(RK3188_WIN0_DSP_ST, 0x1fff1fff, 0), 427 .yrgb_mst = VOP_REG(RK3188_WIN0_YRGB_MST0, 0xffffffff, 0), 428 .uv_mst = VOP_REG(RK3188_WIN0_CBR_MST0, 0xffffffff, 0), 429 .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 0), 430 }; 431 432 static const struct vop_win_phy rk3188_win1_data = { 433 .data_formats = formats_win_lite, 434 .nformats = ARRAY_SIZE(formats_win_lite), 435 .enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 1), 436 .format = VOP_REG(RK3188_SYS_CTRL, 0x7, 6), 437 .rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 19), 438 /* no act_info on window1 */ 439 .dsp_info = VOP_REG(RK3188_WIN1_DSP_INFO, 0x07ff07ff, 0), 440 .dsp_st = VOP_REG(RK3188_WIN1_DSP_ST, 0x0fff0fff, 0), 441 .yrgb_mst = VOP_REG(RK3188_WIN1_MST, 0xffffffff, 0), 442 .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 16), 443 }; 444 445 static const struct vop_modeset rk3188_modeset = { 446 .htotal_pw = VOP_REG(RK3188_DSP_HTOTAL_HS_END, 0x0fff0fff, 0), 447 .hact_st_end = VOP_REG(RK3188_DSP_HACT_ST_END, 0x0fff0fff, 0), 448 .vtotal_pw = VOP_REG(RK3188_DSP_VTOTAL_VS_END, 0x0fff0fff, 0), 449 .vact_st_end = VOP_REG(RK3188_DSP_VACT_ST_END, 0x0fff0fff, 0), 450 }; 451 452 static const struct vop_output rk3188_output = { 453 .pin_pol = VOP_REG(RK3188_DSP_CTRL0, 0xf, 4), 454 }; 455 456 static const struct vop_common rk3188_common = { 457 .gate_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 31), 458 .standby = VOP_REG(RK3188_SYS_CTRL, 0x1, 30), 459 .out_mode = VOP_REG(RK3188_DSP_CTRL0, 0xf, 0), 460 .cfg_done = VOP_REG(RK3188_REG_CFG_DONE, 0x1, 0), 461 .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x3, 24), 462 }; 463 464 static const struct vop_win_data rk3188_vop_win_data[] = { 465 { .base = 0x00, .phy = &rk3188_win0_data, 466 .type = DRM_PLANE_TYPE_PRIMARY }, 467 { .base = 0x00, .phy = &rk3188_win1_data, 468 .type = DRM_PLANE_TYPE_CURSOR }, 469 }; 470 471 static const int rk3188_vop_intrs[] = { 472 /* 473 * hs_start interrupt fires at frame-start, so serves 474 * the same purpose as dsp_hold in the driver. 475 */ 476 DSP_HOLD_VALID_INTR, 477 FS_INTR, 478 LINE_FLAG_INTR, 479 BUS_ERROR_INTR, 480 }; 481 482 static const struct vop_intr rk3188_vop_intr = { 483 .intrs = rk3188_vop_intrs, 484 .nintrs = ARRAY_SIZE(rk3188_vop_intrs), 485 .line_flag_num[0] = VOP_REG(RK3188_INT_STATUS, 0xfff, 12), 486 .status = VOP_REG(RK3188_INT_STATUS, 0xf, 0), 487 .enable = VOP_REG(RK3188_INT_STATUS, 0xf, 4), 488 .clear = VOP_REG(RK3188_INT_STATUS, 0xf, 8), 489 }; 490 491 static const struct vop_data rk3188_vop = { 492 .intr = &rk3188_vop_intr, 493 .common = &rk3188_common, 494 .modeset = &rk3188_modeset, 495 .output = &rk3188_output, 496 .win = rk3188_vop_win_data, 497 .win_size = ARRAY_SIZE(rk3188_vop_win_data), 498 .feature = VOP_FEATURE_INTERNAL_RGB, 499 }; 500 501 static const struct vop_scl_extension rk3288_win_full_scl_ext = { 502 .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31), 503 .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30), 504 .cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28), 505 .cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26), 506 .cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24), 507 .yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23), 508 .yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22), 509 .yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20), 510 .yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18), 511 .yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16), 512 .line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15), 513 .cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12), 514 .yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8), 515 .vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7), 516 .vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6), 517 .vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5), 518 .vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4), 519 .bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2), 520 .cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1), 521 .yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0), 522 .lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5), 523 }; 524 525 static const struct vop_scl_regs rk3288_win_full_scl = { 526 .ext = &rk3288_win_full_scl_ext, 527 .scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), 528 .scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), 529 .scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), 530 .scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16), 531 }; 532 533 static const struct vop_win_phy rk3288_win01_data = { 534 .scl = &rk3288_win_full_scl, 535 .data_formats = formats_win_full, 536 .nformats = ARRAY_SIZE(formats_win_full), 537 .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), 538 .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), 539 .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), 540 .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), 541 .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), 542 .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0), 543 .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0), 544 .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0), 545 .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0), 546 .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), 547 .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), 548 .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), 549 .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0), 550 }; 551 552 static const struct vop_win_phy rk3288_win23_data = { 553 .data_formats = formats_win_lite, 554 .nformats = ARRAY_SIZE(formats_win_lite), 555 .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4), 556 .gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0), 557 .format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1), 558 .rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12), 559 .dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0), 560 .dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0), 561 .yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0), 562 .yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0), 563 .src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0), 564 .dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0), 565 }; 566 567 static const struct vop_modeset rk3288_modeset = { 568 .htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 569 .hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0), 570 .vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 571 .vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0), 572 .hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0), 573 .vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0), 574 }; 575 576 static const struct vop_output rk3288_output = { 577 .pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4), 578 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), 579 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), 580 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), 581 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), 582 }; 583 584 static const struct vop_common rk3288_common = { 585 .standby = VOP_REG_SYNC(RK3288_SYS_CTRL, 0x1, 22), 586 .gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23), 587 .mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20), 588 .pre_dither_down = VOP_REG(RK3288_DSP_CTRL1, 0x1, 1), 589 .dither_down = VOP_REG(RK3288_DSP_CTRL1, 0xf, 1), 590 .dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6), 591 .data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19), 592 .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18), 593 .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0), 594 .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), 595 }; 596 597 /* 598 * Note: rk3288 has a dedicated 'cursor' window, however, that window requires 599 * special support to get alpha blending working. For now, just use overlay 600 * window 3 for the drm cursor. 601 * 602 */ 603 static const struct vop_win_data rk3288_vop_win_data[] = { 604 { .base = 0x00, .phy = &rk3288_win01_data, 605 .type = DRM_PLANE_TYPE_PRIMARY }, 606 { .base = 0x40, .phy = &rk3288_win01_data, 607 .type = DRM_PLANE_TYPE_OVERLAY }, 608 { .base = 0x00, .phy = &rk3288_win23_data, 609 .type = DRM_PLANE_TYPE_OVERLAY }, 610 { .base = 0x50, .phy = &rk3288_win23_data, 611 .type = DRM_PLANE_TYPE_CURSOR }, 612 }; 613 614 static const int rk3288_vop_intrs[] = { 615 DSP_HOLD_VALID_INTR, 616 FS_INTR, 617 LINE_FLAG_INTR, 618 BUS_ERROR_INTR, 619 }; 620 621 static const struct vop_intr rk3288_vop_intr = { 622 .intrs = rk3288_vop_intrs, 623 .nintrs = ARRAY_SIZE(rk3288_vop_intrs), 624 .line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12), 625 .status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0), 626 .enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4), 627 .clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8), 628 }; 629 630 static const struct vop_data rk3288_vop = { 631 .version = VOP_VERSION(3, 1), 632 .feature = VOP_FEATURE_OUTPUT_RGB10, 633 .intr = &rk3288_vop_intr, 634 .common = &rk3288_common, 635 .modeset = &rk3288_modeset, 636 .output = &rk3288_output, 637 .win = rk3288_vop_win_data, 638 .win_size = ARRAY_SIZE(rk3288_vop_win_data), 639 }; 640 641 static const int rk3368_vop_intrs[] = { 642 FS_INTR, 643 0, 0, 644 LINE_FLAG_INTR, 645 0, 646 BUS_ERROR_INTR, 647 0, 0, 0, 0, 0, 0, 0, 648 DSP_HOLD_VALID_INTR, 649 }; 650 651 static const struct vop_intr rk3368_vop_intr = { 652 .intrs = rk3368_vop_intrs, 653 .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 654 .line_flag_num[0] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 0), 655 .line_flag_num[1] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 16), 656 .status = VOP_REG_MASK_SYNC(RK3368_INTR_STATUS, 0x3fff, 0), 657 .enable = VOP_REG_MASK_SYNC(RK3368_INTR_EN, 0x3fff, 0), 658 .clear = VOP_REG_MASK_SYNC(RK3368_INTR_CLEAR, 0x3fff, 0), 659 }; 660 661 static const struct vop_win_phy rk3368_win01_data = { 662 .scl = &rk3288_win_full_scl, 663 .data_formats = formats_win_full, 664 .nformats = ARRAY_SIZE(formats_win_full), 665 .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0), 666 .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1), 667 .rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12), 668 .x_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 21), 669 .y_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 22), 670 .act_info = VOP_REG(RK3368_WIN0_ACT_INFO, 0x1fff1fff, 0), 671 .dsp_info = VOP_REG(RK3368_WIN0_DSP_INFO, 0x0fff0fff, 0), 672 .dsp_st = VOP_REG(RK3368_WIN0_DSP_ST, 0x1fff1fff, 0), 673 .yrgb_mst = VOP_REG(RK3368_WIN0_YRGB_MST, 0xffffffff, 0), 674 .uv_mst = VOP_REG(RK3368_WIN0_CBR_MST, 0xffffffff, 0), 675 .yrgb_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 0), 676 .uv_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 16), 677 .src_alpha_ctl = VOP_REG(RK3368_WIN0_SRC_ALPHA_CTRL, 0xff, 0), 678 .dst_alpha_ctl = VOP_REG(RK3368_WIN0_DST_ALPHA_CTRL, 0xff, 0), 679 .channel = VOP_REG(RK3368_WIN0_CTRL2, 0xff, 0), 680 }; 681 682 static const struct vop_win_phy rk3368_win23_data = { 683 .data_formats = formats_win_lite, 684 .nformats = ARRAY_SIZE(formats_win_lite), 685 .gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0), 686 .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4), 687 .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5), 688 .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20), 689 .y_mir_en = VOP_REG(RK3368_WIN2_CTRL1, 0x1, 15), 690 .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0), 691 .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0), 692 .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0), 693 .yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0), 694 .src_alpha_ctl = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 0), 695 .dst_alpha_ctl = VOP_REG(RK3368_WIN2_DST_ALPHA_CTRL, 0xff, 0), 696 }; 697 698 static const struct vop_win_data rk3368_vop_win_data[] = { 699 { .base = 0x00, .phy = &rk3368_win01_data, 700 .type = DRM_PLANE_TYPE_PRIMARY }, 701 { .base = 0x40, .phy = &rk3368_win01_data, 702 .type = DRM_PLANE_TYPE_OVERLAY }, 703 { .base = 0x00, .phy = &rk3368_win23_data, 704 .type = DRM_PLANE_TYPE_OVERLAY }, 705 { .base = 0x50, .phy = &rk3368_win23_data, 706 .type = DRM_PLANE_TYPE_CURSOR }, 707 }; 708 709 static const struct vop_output rk3368_output = { 710 .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16), 711 .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20), 712 .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24), 713 .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28), 714 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), 715 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), 716 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), 717 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), 718 }; 719 720 static const struct vop_misc rk3368_misc = { 721 .global_regdone_en = VOP_REG(RK3368_SYS_CTRL, 0x1, 11), 722 }; 723 724 static const struct vop_data rk3368_vop = { 725 .version = VOP_VERSION(3, 2), 726 .intr = &rk3368_vop_intr, 727 .common = &rk3288_common, 728 .modeset = &rk3288_modeset, 729 .output = &rk3368_output, 730 .misc = &rk3368_misc, 731 .win = rk3368_vop_win_data, 732 .win_size = ARRAY_SIZE(rk3368_vop_win_data), 733 }; 734 735 static const struct vop_intr rk3366_vop_intr = { 736 .intrs = rk3368_vop_intrs, 737 .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 738 .line_flag_num[0] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 0), 739 .line_flag_num[1] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 16), 740 .status = VOP_REG_MASK_SYNC(RK3366_INTR_STATUS0, 0xffff, 0), 741 .enable = VOP_REG_MASK_SYNC(RK3366_INTR_EN0, 0xffff, 0), 742 .clear = VOP_REG_MASK_SYNC(RK3366_INTR_CLEAR0, 0xffff, 0), 743 }; 744 745 static const struct vop_data rk3366_vop = { 746 .version = VOP_VERSION(3, 4), 747 .intr = &rk3366_vop_intr, 748 .common = &rk3288_common, 749 .modeset = &rk3288_modeset, 750 .output = &rk3368_output, 751 .misc = &rk3368_misc, 752 .win = rk3368_vop_win_data, 753 .win_size = ARRAY_SIZE(rk3368_vop_win_data), 754 }; 755 756 static const struct vop_output rk3399_output = { 757 .dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16), 758 .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16), 759 .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20), 760 .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24), 761 .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28), 762 .dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11), 763 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), 764 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), 765 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), 766 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), 767 .mipi_dual_channel_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 3), 768 }; 769 770 static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win01_data = { 771 .y2r_coefficients = { 772 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 0), 773 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 16), 774 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 0), 775 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 16), 776 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 0), 777 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 16), 778 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 0), 779 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 16), 780 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 16, 0xffff, 0), 781 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 20, 0xffffffff, 0), 782 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 24, 0xffffffff, 0), 783 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 28, 0xffffffff, 0), 784 }, 785 }; 786 787 static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win23_data = { }; 788 789 static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = { 790 { .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data, 791 .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1) }, 792 { .base = 0x60, .phy = &rk3399_yuv2yuv_win01_data, 793 .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 9) }, 794 { .base = 0xC0, .phy = &rk3399_yuv2yuv_win23_data }, 795 { .base = 0x120, .phy = &rk3399_yuv2yuv_win23_data }, 796 }; 797 798 static const struct vop_data rk3399_vop_big = { 799 .version = VOP_VERSION(3, 5), 800 .feature = VOP_FEATURE_OUTPUT_RGB10, 801 .intr = &rk3366_vop_intr, 802 .common = &rk3288_common, 803 .modeset = &rk3288_modeset, 804 .output = &rk3399_output, 805 .misc = &rk3368_misc, 806 .win = rk3368_vop_win_data, 807 .win_size = ARRAY_SIZE(rk3368_vop_win_data), 808 .win_yuv2yuv = rk3399_vop_big_win_yuv2yuv_data, 809 }; 810 811 static const struct vop_win_data rk3399_vop_lit_win_data[] = { 812 { .base = 0x00, .phy = &rk3368_win01_data, 813 .type = DRM_PLANE_TYPE_PRIMARY }, 814 { .base = 0x00, .phy = &rk3368_win23_data, 815 .type = DRM_PLANE_TYPE_CURSOR}, 816 }; 817 818 static const struct vop_win_yuv2yuv_data rk3399_vop_lit_win_yuv2yuv_data[] = { 819 { .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data, 820 .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1)}, 821 { .base = 0x60, .phy = &rk3399_yuv2yuv_win23_data }, 822 }; 823 824 static const struct vop_data rk3399_vop_lit = { 825 .version = VOP_VERSION(3, 6), 826 .intr = &rk3366_vop_intr, 827 .common = &rk3288_common, 828 .modeset = &rk3288_modeset, 829 .output = &rk3399_output, 830 .misc = &rk3368_misc, 831 .win = rk3399_vop_lit_win_data, 832 .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data), 833 .win_yuv2yuv = rk3399_vop_lit_win_yuv2yuv_data, 834 }; 835 836 static const struct vop_win_data rk3228_vop_win_data[] = { 837 { .base = 0x00, .phy = &rk3288_win01_data, 838 .type = DRM_PLANE_TYPE_PRIMARY }, 839 { .base = 0x40, .phy = &rk3288_win01_data, 840 .type = DRM_PLANE_TYPE_CURSOR }, 841 }; 842 843 static const struct vop_data rk3228_vop = { 844 .version = VOP_VERSION(3, 7), 845 .feature = VOP_FEATURE_OUTPUT_RGB10, 846 .intr = &rk3366_vop_intr, 847 .common = &rk3288_common, 848 .modeset = &rk3288_modeset, 849 .output = &rk3399_output, 850 .misc = &rk3368_misc, 851 .win = rk3228_vop_win_data, 852 .win_size = ARRAY_SIZE(rk3228_vop_win_data), 853 }; 854 855 static const struct vop_modeset rk3328_modeset = { 856 .htotal_pw = VOP_REG(RK3328_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 857 .hact_st_end = VOP_REG(RK3328_DSP_HACT_ST_END, 0x1fff1fff, 0), 858 .vtotal_pw = VOP_REG(RK3328_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 859 .vact_st_end = VOP_REG(RK3328_DSP_VACT_ST_END, 0x1fff1fff, 0), 860 .hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0), 861 .vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0), 862 }; 863 864 static const struct vop_output rk3328_output = { 865 .rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12), 866 .hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13), 867 .edp_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 14), 868 .mipi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 15), 869 .rgb_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 16), 870 .hdmi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 20), 871 .edp_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 24), 872 .mipi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 28), 873 }; 874 875 static const struct vop_misc rk3328_misc = { 876 .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11), 877 }; 878 879 static const struct vop_common rk3328_common = { 880 .standby = VOP_REG_SYNC(RK3328_SYS_CTRL, 0x1, 22), 881 .dither_down = VOP_REG(RK3328_DSP_CTRL1, 0xf, 1), 882 .dither_up = VOP_REG(RK3328_DSP_CTRL1, 0x1, 6), 883 .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18), 884 .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0), 885 .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), 886 }; 887 888 static const struct vop_intr rk3328_vop_intr = { 889 .intrs = rk3368_vop_intrs, 890 .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 891 .line_flag_num[0] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 0), 892 .line_flag_num[1] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 16), 893 .status = VOP_REG_MASK_SYNC(RK3328_INTR_STATUS0, 0xffff, 0), 894 .enable = VOP_REG_MASK_SYNC(RK3328_INTR_EN0, 0xffff, 0), 895 .clear = VOP_REG_MASK_SYNC(RK3328_INTR_CLEAR0, 0xffff, 0), 896 }; 897 898 static const struct vop_win_data rk3328_vop_win_data[] = { 899 { .base = 0xd0, .phy = &rk3368_win01_data, 900 .type = DRM_PLANE_TYPE_PRIMARY }, 901 { .base = 0x1d0, .phy = &rk3368_win01_data, 902 .type = DRM_PLANE_TYPE_OVERLAY }, 903 { .base = 0x2d0, .phy = &rk3368_win01_data, 904 .type = DRM_PLANE_TYPE_CURSOR }, 905 }; 906 907 static const struct vop_data rk3328_vop = { 908 .version = VOP_VERSION(3, 8), 909 .feature = VOP_FEATURE_OUTPUT_RGB10, 910 .intr = &rk3328_vop_intr, 911 .common = &rk3328_common, 912 .modeset = &rk3328_modeset, 913 .output = &rk3328_output, 914 .misc = &rk3328_misc, 915 .win = rk3328_vop_win_data, 916 .win_size = ARRAY_SIZE(rk3328_vop_win_data), 917 }; 918 919 static const struct of_device_id vop_driver_dt_match[] = { 920 { .compatible = "rockchip,rk3036-vop", 921 .data = &rk3036_vop }, 922 { .compatible = "rockchip,rk3126-vop", 923 .data = &rk3126_vop }, 924 { .compatible = "rockchip,px30-vop-big", 925 .data = &px30_vop_big }, 926 { .compatible = "rockchip,px30-vop-lit", 927 .data = &px30_vop_lit }, 928 { .compatible = "rockchip,rk3066-vop", 929 .data = &rk3066_vop }, 930 { .compatible = "rockchip,rk3188-vop", 931 .data = &rk3188_vop }, 932 { .compatible = "rockchip,rk3288-vop", 933 .data = &rk3288_vop }, 934 { .compatible = "rockchip,rk3368-vop", 935 .data = &rk3368_vop }, 936 { .compatible = "rockchip,rk3366-vop", 937 .data = &rk3366_vop }, 938 { .compatible = "rockchip,rk3399-vop-big", 939 .data = &rk3399_vop_big }, 940 { .compatible = "rockchip,rk3399-vop-lit", 941 .data = &rk3399_vop_lit }, 942 { .compatible = "rockchip,rk3228-vop", 943 .data = &rk3228_vop }, 944 { .compatible = "rockchip,rk3328-vop", 945 .data = &rk3328_vop }, 946 {}, 947 }; 948 MODULE_DEVICE_TABLE(of, vop_driver_dt_match); 949 950 static int vop_probe(struct platform_device *pdev) 951 { 952 struct device *dev = &pdev->dev; 953 954 if (!dev->of_node) { 955 DRM_DEV_ERROR(dev, "can't find vop devices\n"); 956 return -ENODEV; 957 } 958 959 return component_add(dev, &vop_component_ops); 960 } 961 962 static int vop_remove(struct platform_device *pdev) 963 { 964 component_del(&pdev->dev, &vop_component_ops); 965 966 return 0; 967 } 968 969 struct platform_driver vop_platform_driver = { 970 .probe = vop_probe, 971 .remove = vop_remove, 972 .driver = { 973 .name = "rockchip-vop", 974 .of_match_table = of_match_ptr(vop_driver_dt_match), 975 }, 976 }; 977