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