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 rk3188_win_scl = { 303 .scale_yrgb_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), 304 .scale_yrgb_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), 305 .scale_cbcr_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), 306 .scale_cbcr_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 16), 307 }; 308 309 static const struct vop_win_phy rk3188_win0_data = { 310 .scl = &rk3188_win_scl, 311 .data_formats = formats_win_full, 312 .nformats = ARRAY_SIZE(formats_win_full), 313 .enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 0), 314 .format = VOP_REG(RK3188_SYS_CTRL, 0x7, 3), 315 .rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 15), 316 .act_info = VOP_REG(RK3188_WIN0_ACT_INFO, 0x1fff1fff, 0), 317 .dsp_info = VOP_REG(RK3188_WIN0_DSP_INFO, 0x0fff0fff, 0), 318 .dsp_st = VOP_REG(RK3188_WIN0_DSP_ST, 0x1fff1fff, 0), 319 .yrgb_mst = VOP_REG(RK3188_WIN0_YRGB_MST0, 0xffffffff, 0), 320 .uv_mst = VOP_REG(RK3188_WIN0_CBR_MST0, 0xffffffff, 0), 321 .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 0), 322 }; 323 324 static const struct vop_win_phy rk3188_win1_data = { 325 .data_formats = formats_win_lite, 326 .nformats = ARRAY_SIZE(formats_win_lite), 327 .enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 1), 328 .format = VOP_REG(RK3188_SYS_CTRL, 0x7, 6), 329 .rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 19), 330 /* no act_info on window1 */ 331 .dsp_info = VOP_REG(RK3188_WIN1_DSP_INFO, 0x07ff07ff, 0), 332 .dsp_st = VOP_REG(RK3188_WIN1_DSP_ST, 0x0fff0fff, 0), 333 .yrgb_mst = VOP_REG(RK3188_WIN1_MST, 0xffffffff, 0), 334 .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 16), 335 }; 336 337 static const struct vop_modeset rk3188_modeset = { 338 .htotal_pw = VOP_REG(RK3188_DSP_HTOTAL_HS_END, 0x0fff0fff, 0), 339 .hact_st_end = VOP_REG(RK3188_DSP_HACT_ST_END, 0x0fff0fff, 0), 340 .vtotal_pw = VOP_REG(RK3188_DSP_VTOTAL_VS_END, 0x0fff0fff, 0), 341 .vact_st_end = VOP_REG(RK3188_DSP_VACT_ST_END, 0x0fff0fff, 0), 342 }; 343 344 static const struct vop_output rk3188_output = { 345 .pin_pol = VOP_REG(RK3188_DSP_CTRL0, 0xf, 4), 346 }; 347 348 static const struct vop_common rk3188_common = { 349 .gate_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 31), 350 .standby = VOP_REG(RK3188_SYS_CTRL, 0x1, 30), 351 .out_mode = VOP_REG(RK3188_DSP_CTRL0, 0xf, 0), 352 .cfg_done = VOP_REG(RK3188_REG_CFG_DONE, 0x1, 0), 353 .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x3, 24), 354 }; 355 356 static const struct vop_win_data rk3188_vop_win_data[] = { 357 { .base = 0x00, .phy = &rk3188_win0_data, 358 .type = DRM_PLANE_TYPE_PRIMARY }, 359 { .base = 0x00, .phy = &rk3188_win1_data, 360 .type = DRM_PLANE_TYPE_CURSOR }, 361 }; 362 363 static const int rk3188_vop_intrs[] = { 364 0, 365 FS_INTR, 366 LINE_FLAG_INTR, 367 BUS_ERROR_INTR, 368 }; 369 370 static const struct vop_intr rk3188_vop_intr = { 371 .intrs = rk3188_vop_intrs, 372 .nintrs = ARRAY_SIZE(rk3188_vop_intrs), 373 .line_flag_num[0] = VOP_REG(RK3188_INT_STATUS, 0xfff, 12), 374 .status = VOP_REG(RK3188_INT_STATUS, 0xf, 0), 375 .enable = VOP_REG(RK3188_INT_STATUS, 0xf, 4), 376 .clear = VOP_REG(RK3188_INT_STATUS, 0xf, 8), 377 }; 378 379 static const struct vop_data rk3188_vop = { 380 .intr = &rk3188_vop_intr, 381 .common = &rk3188_common, 382 .modeset = &rk3188_modeset, 383 .output = &rk3188_output, 384 .win = rk3188_vop_win_data, 385 .win_size = ARRAY_SIZE(rk3188_vop_win_data), 386 .feature = VOP_FEATURE_INTERNAL_RGB, 387 }; 388 389 static const struct vop_scl_extension rk3288_win_full_scl_ext = { 390 .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31), 391 .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30), 392 .cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28), 393 .cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26), 394 .cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24), 395 .yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23), 396 .yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22), 397 .yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20), 398 .yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18), 399 .yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16), 400 .line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15), 401 .cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12), 402 .yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8), 403 .vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7), 404 .vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6), 405 .vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5), 406 .vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4), 407 .bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2), 408 .cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1), 409 .yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0), 410 .lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5), 411 }; 412 413 static const struct vop_scl_regs rk3288_win_full_scl = { 414 .ext = &rk3288_win_full_scl_ext, 415 .scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), 416 .scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), 417 .scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), 418 .scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16), 419 }; 420 421 static const struct vop_win_phy rk3288_win01_data = { 422 .scl = &rk3288_win_full_scl, 423 .data_formats = formats_win_full, 424 .nformats = ARRAY_SIZE(formats_win_full), 425 .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), 426 .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), 427 .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), 428 .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), 429 .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), 430 .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0), 431 .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0), 432 .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0), 433 .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0), 434 .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), 435 .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), 436 .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), 437 .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0), 438 }; 439 440 static const struct vop_win_phy rk3288_win23_data = { 441 .data_formats = formats_win_lite, 442 .nformats = ARRAY_SIZE(formats_win_lite), 443 .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4), 444 .gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0), 445 .format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1), 446 .rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12), 447 .dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0), 448 .dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0), 449 .yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0), 450 .yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0), 451 .src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0), 452 .dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0), 453 }; 454 455 static const struct vop_modeset rk3288_modeset = { 456 .htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 457 .hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0), 458 .vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 459 .vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0), 460 .hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0), 461 .vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0), 462 }; 463 464 static const struct vop_output rk3288_output = { 465 .pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4), 466 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), 467 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), 468 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), 469 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), 470 }; 471 472 static const struct vop_common rk3288_common = { 473 .standby = VOP_REG_SYNC(RK3288_SYS_CTRL, 0x1, 22), 474 .gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23), 475 .mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20), 476 .pre_dither_down = VOP_REG(RK3288_DSP_CTRL1, 0x1, 1), 477 .dither_down = VOP_REG(RK3288_DSP_CTRL1, 0xf, 1), 478 .dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6), 479 .data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19), 480 .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18), 481 .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0), 482 .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), 483 }; 484 485 /* 486 * Note: rk3288 has a dedicated 'cursor' window, however, that window requires 487 * special support to get alpha blending working. For now, just use overlay 488 * window 3 for the drm cursor. 489 * 490 */ 491 static const struct vop_win_data rk3288_vop_win_data[] = { 492 { .base = 0x00, .phy = &rk3288_win01_data, 493 .type = DRM_PLANE_TYPE_PRIMARY }, 494 { .base = 0x40, .phy = &rk3288_win01_data, 495 .type = DRM_PLANE_TYPE_OVERLAY }, 496 { .base = 0x00, .phy = &rk3288_win23_data, 497 .type = DRM_PLANE_TYPE_OVERLAY }, 498 { .base = 0x50, .phy = &rk3288_win23_data, 499 .type = DRM_PLANE_TYPE_CURSOR }, 500 }; 501 502 static const int rk3288_vop_intrs[] = { 503 DSP_HOLD_VALID_INTR, 504 FS_INTR, 505 LINE_FLAG_INTR, 506 BUS_ERROR_INTR, 507 }; 508 509 static const struct vop_intr rk3288_vop_intr = { 510 .intrs = rk3288_vop_intrs, 511 .nintrs = ARRAY_SIZE(rk3288_vop_intrs), 512 .line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12), 513 .status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0), 514 .enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4), 515 .clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8), 516 }; 517 518 static const struct vop_data rk3288_vop = { 519 .version = VOP_VERSION(3, 1), 520 .feature = VOP_FEATURE_OUTPUT_RGB10, 521 .intr = &rk3288_vop_intr, 522 .common = &rk3288_common, 523 .modeset = &rk3288_modeset, 524 .output = &rk3288_output, 525 .win = rk3288_vop_win_data, 526 .win_size = ARRAY_SIZE(rk3288_vop_win_data), 527 }; 528 529 static const int rk3368_vop_intrs[] = { 530 FS_INTR, 531 0, 0, 532 LINE_FLAG_INTR, 533 0, 534 BUS_ERROR_INTR, 535 0, 0, 0, 0, 0, 0, 0, 536 DSP_HOLD_VALID_INTR, 537 }; 538 539 static const struct vop_intr rk3368_vop_intr = { 540 .intrs = rk3368_vop_intrs, 541 .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 542 .line_flag_num[0] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 0), 543 .line_flag_num[1] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 16), 544 .status = VOP_REG_MASK_SYNC(RK3368_INTR_STATUS, 0x3fff, 0), 545 .enable = VOP_REG_MASK_SYNC(RK3368_INTR_EN, 0x3fff, 0), 546 .clear = VOP_REG_MASK_SYNC(RK3368_INTR_CLEAR, 0x3fff, 0), 547 }; 548 549 static const struct vop_win_phy rk3368_win23_data = { 550 .data_formats = formats_win_lite, 551 .nformats = ARRAY_SIZE(formats_win_lite), 552 .gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0), 553 .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4), 554 .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5), 555 .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20), 556 .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0), 557 .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0), 558 .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0), 559 .yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0), 560 .src_alpha_ctl = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 0), 561 .dst_alpha_ctl = VOP_REG(RK3368_WIN2_DST_ALPHA_CTRL, 0xff, 0), 562 }; 563 564 static const struct vop_win_data rk3368_vop_win_data[] = { 565 { .base = 0x00, .phy = &rk3288_win01_data, 566 .type = DRM_PLANE_TYPE_PRIMARY }, 567 { .base = 0x40, .phy = &rk3288_win01_data, 568 .type = DRM_PLANE_TYPE_OVERLAY }, 569 { .base = 0x00, .phy = &rk3368_win23_data, 570 .type = DRM_PLANE_TYPE_OVERLAY }, 571 { .base = 0x50, .phy = &rk3368_win23_data, 572 .type = DRM_PLANE_TYPE_CURSOR }, 573 }; 574 575 static const struct vop_output rk3368_output = { 576 .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16), 577 .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20), 578 .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24), 579 .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28), 580 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), 581 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), 582 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), 583 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), 584 }; 585 586 static const struct vop_misc rk3368_misc = { 587 .global_regdone_en = VOP_REG(RK3368_SYS_CTRL, 0x1, 11), 588 }; 589 590 static const struct vop_data rk3368_vop = { 591 .version = VOP_VERSION(3, 2), 592 .intr = &rk3368_vop_intr, 593 .common = &rk3288_common, 594 .modeset = &rk3288_modeset, 595 .output = &rk3368_output, 596 .misc = &rk3368_misc, 597 .win = rk3368_vop_win_data, 598 .win_size = ARRAY_SIZE(rk3368_vop_win_data), 599 }; 600 601 static const struct vop_intr rk3366_vop_intr = { 602 .intrs = rk3368_vop_intrs, 603 .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 604 .line_flag_num[0] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 0), 605 .line_flag_num[1] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 16), 606 .status = VOP_REG_MASK_SYNC(RK3366_INTR_STATUS0, 0xffff, 0), 607 .enable = VOP_REG_MASK_SYNC(RK3366_INTR_EN0, 0xffff, 0), 608 .clear = VOP_REG_MASK_SYNC(RK3366_INTR_CLEAR0, 0xffff, 0), 609 }; 610 611 static const struct vop_data rk3366_vop = { 612 .version = VOP_VERSION(3, 4), 613 .intr = &rk3366_vop_intr, 614 .common = &rk3288_common, 615 .modeset = &rk3288_modeset, 616 .output = &rk3368_output, 617 .misc = &rk3368_misc, 618 .win = rk3368_vop_win_data, 619 .win_size = ARRAY_SIZE(rk3368_vop_win_data), 620 }; 621 622 static const struct vop_output rk3399_output = { 623 .dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16), 624 .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16), 625 .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20), 626 .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24), 627 .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28), 628 .dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11), 629 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), 630 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), 631 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), 632 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), 633 }; 634 635 static const struct vop_data rk3399_vop_big = { 636 .version = VOP_VERSION(3, 5), 637 .feature = VOP_FEATURE_OUTPUT_RGB10, 638 .intr = &rk3366_vop_intr, 639 .common = &rk3288_common, 640 .modeset = &rk3288_modeset, 641 .output = &rk3399_output, 642 .misc = &rk3368_misc, 643 .win = rk3368_vop_win_data, 644 .win_size = ARRAY_SIZE(rk3368_vop_win_data), 645 }; 646 647 static const struct vop_win_data rk3399_vop_lit_win_data[] = { 648 { .base = 0x00, .phy = &rk3288_win01_data, 649 .type = DRM_PLANE_TYPE_PRIMARY }, 650 { .base = 0x00, .phy = &rk3368_win23_data, 651 .type = DRM_PLANE_TYPE_CURSOR}, 652 }; 653 654 static const struct vop_data rk3399_vop_lit = { 655 .version = VOP_VERSION(3, 6), 656 .intr = &rk3366_vop_intr, 657 .common = &rk3288_common, 658 .modeset = &rk3288_modeset, 659 .output = &rk3399_output, 660 .misc = &rk3368_misc, 661 .win = rk3399_vop_lit_win_data, 662 .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data), 663 }; 664 665 static const struct vop_win_data rk3228_vop_win_data[] = { 666 { .base = 0x00, .phy = &rk3288_win01_data, 667 .type = DRM_PLANE_TYPE_PRIMARY }, 668 { .base = 0x40, .phy = &rk3288_win01_data, 669 .type = DRM_PLANE_TYPE_CURSOR }, 670 }; 671 672 static const struct vop_data rk3228_vop = { 673 .version = VOP_VERSION(3, 7), 674 .feature = VOP_FEATURE_OUTPUT_RGB10, 675 .intr = &rk3366_vop_intr, 676 .common = &rk3288_common, 677 .modeset = &rk3288_modeset, 678 .output = &rk3399_output, 679 .misc = &rk3368_misc, 680 .win = rk3228_vop_win_data, 681 .win_size = ARRAY_SIZE(rk3228_vop_win_data), 682 }; 683 684 static const struct vop_modeset rk3328_modeset = { 685 .htotal_pw = VOP_REG(RK3328_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 686 .hact_st_end = VOP_REG(RK3328_DSP_HACT_ST_END, 0x1fff1fff, 0), 687 .vtotal_pw = VOP_REG(RK3328_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 688 .vact_st_end = VOP_REG(RK3328_DSP_VACT_ST_END, 0x1fff1fff, 0), 689 .hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0), 690 .vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0), 691 }; 692 693 static const struct vop_output rk3328_output = { 694 .rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12), 695 .hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13), 696 .edp_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 14), 697 .mipi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 15), 698 .rgb_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 16), 699 .hdmi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 20), 700 .edp_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 24), 701 .mipi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 28), 702 }; 703 704 static const struct vop_misc rk3328_misc = { 705 .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11), 706 }; 707 708 static const struct vop_common rk3328_common = { 709 .standby = VOP_REG_SYNC(RK3328_SYS_CTRL, 0x1, 22), 710 .dither_down = VOP_REG(RK3328_DSP_CTRL1, 0xf, 1), 711 .dither_up = VOP_REG(RK3328_DSP_CTRL1, 0x1, 6), 712 .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18), 713 .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0), 714 .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), 715 }; 716 717 static const struct vop_intr rk3328_vop_intr = { 718 .intrs = rk3368_vop_intrs, 719 .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 720 .line_flag_num[0] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 0), 721 .line_flag_num[1] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 16), 722 .status = VOP_REG_MASK_SYNC(RK3328_INTR_STATUS0, 0xffff, 0), 723 .enable = VOP_REG_MASK_SYNC(RK3328_INTR_EN0, 0xffff, 0), 724 .clear = VOP_REG_MASK_SYNC(RK3328_INTR_CLEAR0, 0xffff, 0), 725 }; 726 727 static const struct vop_win_data rk3328_vop_win_data[] = { 728 { .base = 0xd0, .phy = &rk3288_win01_data, 729 .type = DRM_PLANE_TYPE_PRIMARY }, 730 { .base = 0x1d0, .phy = &rk3288_win01_data, 731 .type = DRM_PLANE_TYPE_OVERLAY }, 732 { .base = 0x2d0, .phy = &rk3288_win01_data, 733 .type = DRM_PLANE_TYPE_CURSOR }, 734 }; 735 736 static const struct vop_data rk3328_vop = { 737 .version = VOP_VERSION(3, 8), 738 .feature = VOP_FEATURE_OUTPUT_RGB10, 739 .intr = &rk3328_vop_intr, 740 .common = &rk3328_common, 741 .modeset = &rk3328_modeset, 742 .output = &rk3328_output, 743 .misc = &rk3328_misc, 744 .win = rk3328_vop_win_data, 745 .win_size = ARRAY_SIZE(rk3328_vop_win_data), 746 }; 747 748 static const struct of_device_id vop_driver_dt_match[] = { 749 { .compatible = "rockchip,rk3036-vop", 750 .data = &rk3036_vop }, 751 { .compatible = "rockchip,rk3126-vop", 752 .data = &rk3126_vop }, 753 { .compatible = "rockchip,px30-vop-big", 754 .data = &px30_vop_big }, 755 { .compatible = "rockchip,px30-vop-lit", 756 .data = &px30_vop_lit }, 757 { .compatible = "rockchip,rk3188-vop", 758 .data = &rk3188_vop }, 759 { .compatible = "rockchip,rk3288-vop", 760 .data = &rk3288_vop }, 761 { .compatible = "rockchip,rk3368-vop", 762 .data = &rk3368_vop }, 763 { .compatible = "rockchip,rk3366-vop", 764 .data = &rk3366_vop }, 765 { .compatible = "rockchip,rk3399-vop-big", 766 .data = &rk3399_vop_big }, 767 { .compatible = "rockchip,rk3399-vop-lit", 768 .data = &rk3399_vop_lit }, 769 { .compatible = "rockchip,rk3228-vop", 770 .data = &rk3228_vop }, 771 { .compatible = "rockchip,rk3328-vop", 772 .data = &rk3328_vop }, 773 {}, 774 }; 775 MODULE_DEVICE_TABLE(of, vop_driver_dt_match); 776 777 static int vop_probe(struct platform_device *pdev) 778 { 779 struct device *dev = &pdev->dev; 780 781 if (!dev->of_node) { 782 DRM_DEV_ERROR(dev, "can't find vop devices\n"); 783 return -ENODEV; 784 } 785 786 return component_add(dev, &vop_component_ops); 787 } 788 789 static int vop_remove(struct platform_device *pdev) 790 { 791 component_del(&pdev->dev, &vop_component_ops); 792 793 return 0; 794 } 795 796 struct platform_driver vop_platform_driver = { 797 .probe = vop_probe, 798 .remove = vop_remove, 799 .driver = { 800 .name = "rockchip-vop", 801 .of_match_table = of_match_ptr(vop_driver_dt_match), 802 }, 803 }; 804