510 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) Rockchip Electronics Co.Ltd4 * Author: Andy Yan <andy.yan@rock-chips.com>5 */6 7#include <linux/kernel.h>8#include <linux/component.h>9#include <linux/mod_devicetable.h>10#include <linux/platform_device.h>11#include <linux/of.h>12#include <drm/drm_fourcc.h>13#include <drm/drm_plane.h>14#include <drm/drm_print.h>15 16#include "rockchip_drm_vop2.h"17 18static const uint32_t formats_cluster[] = {19 DRM_FORMAT_XRGB2101010,20 DRM_FORMAT_XBGR2101010,21 DRM_FORMAT_XRGB8888,22 DRM_FORMAT_ARGB8888,23 DRM_FORMAT_XBGR8888,24 DRM_FORMAT_ABGR8888,25 DRM_FORMAT_RGB888,26 DRM_FORMAT_BGR888,27 DRM_FORMAT_RGB565,28 DRM_FORMAT_BGR565,29 DRM_FORMAT_YUV420_8BIT, /* yuv420_8bit non-Linear mode only */30 DRM_FORMAT_YUV420_10BIT, /* yuv420_10bit non-Linear mode only */31 DRM_FORMAT_YUYV, /* yuv422_8bit non-Linear mode only*/32 DRM_FORMAT_Y210, /* yuv422_10bit non-Linear mode only */33};34 35static const uint32_t formats_esmart[] = {36 DRM_FORMAT_XRGB8888,37 DRM_FORMAT_ARGB8888,38 DRM_FORMAT_XBGR8888,39 DRM_FORMAT_ABGR8888,40 DRM_FORMAT_RGB888,41 DRM_FORMAT_BGR888,42 DRM_FORMAT_RGB565,43 DRM_FORMAT_BGR565,44 DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */45 DRM_FORMAT_NV21, /* yvu420_8bit linear mode, 2 plane */46 DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */47 DRM_FORMAT_NV61, /* yvu422_8bit linear mode, 2 plane */48 DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */49 DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */50 DRM_FORMAT_NV42, /* yvu444_8bit linear mode, 2 plane */51 DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */52 DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */53 DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */54 DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */55 DRM_FORMAT_YUYV, /* yuv422_8bit[YUYV] linear mode */56 DRM_FORMAT_UYVY, /* yuv422_8bit[UYVY] linear mode */57};58 59static const uint32_t formats_rk356x_esmart[] = {60 DRM_FORMAT_XRGB8888,61 DRM_FORMAT_ARGB8888,62 DRM_FORMAT_XBGR8888,63 DRM_FORMAT_ABGR8888,64 DRM_FORMAT_RGB888,65 DRM_FORMAT_BGR888,66 DRM_FORMAT_RGB565,67 DRM_FORMAT_BGR565,68 DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */69 DRM_FORMAT_NV21, /* yuv420_8bit linear mode, 2 plane */70 DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */71 DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */72 DRM_FORMAT_NV61, /* yuv422_8bit linear mode, 2 plane */73 DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */74 DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */75 DRM_FORMAT_NV42, /* yuv444_8bit linear mode, 2 plane */76 DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */77 DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */78 DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */79};80 81static const uint32_t formats_smart[] = {82 DRM_FORMAT_XRGB8888,83 DRM_FORMAT_ARGB8888,84 DRM_FORMAT_XBGR8888,85 DRM_FORMAT_ABGR8888,86 DRM_FORMAT_RGB888,87 DRM_FORMAT_BGR888,88 DRM_FORMAT_RGB565,89 DRM_FORMAT_BGR565,90};91 92static const uint64_t format_modifiers[] = {93 DRM_FORMAT_MOD_LINEAR,94 DRM_FORMAT_MOD_INVALID,95};96 97static const uint64_t format_modifiers_afbc[] = {98 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16),99 100 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |101 AFBC_FORMAT_MOD_SPARSE),102 103 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |104 AFBC_FORMAT_MOD_YTR),105 106 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |107 AFBC_FORMAT_MOD_CBR),108 109 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |110 AFBC_FORMAT_MOD_YTR |111 AFBC_FORMAT_MOD_SPARSE),112 113 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |114 AFBC_FORMAT_MOD_CBR |115 AFBC_FORMAT_MOD_SPARSE),116 117 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |118 AFBC_FORMAT_MOD_YTR |119 AFBC_FORMAT_MOD_CBR),120 121 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |122 AFBC_FORMAT_MOD_YTR |123 AFBC_FORMAT_MOD_CBR |124 AFBC_FORMAT_MOD_SPARSE),125 126 /* SPLIT mandates SPARSE, RGB modes mandates YTR */127 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |128 AFBC_FORMAT_MOD_YTR |129 AFBC_FORMAT_MOD_SPARSE |130 AFBC_FORMAT_MOD_SPLIT),131 DRM_FORMAT_MOD_INVALID,132};133 134static const struct vop2_video_port_data rk3568_vop_video_ports[] = {135 {136 .id = 0,137 .feature = VOP2_VP_FEATURE_OUTPUT_10BIT,138 .gamma_lut_len = 1024,139 .cubic_lut_len = 9 * 9 * 9,140 .max_output = { 4096, 2304 },141 .pre_scan_max_dly = { 69, 53, 53, 42 },142 .offset = 0xc00,143 }, {144 .id = 1,145 .gamma_lut_len = 1024,146 .max_output = { 2048, 1536 },147 .pre_scan_max_dly = { 40, 40, 40, 40 },148 .offset = 0xd00,149 }, {150 .id = 2,151 .gamma_lut_len = 1024,152 .max_output = { 1920, 1080 },153 .pre_scan_max_dly = { 40, 40, 40, 40 },154 .offset = 0xe00,155 },156};157 158/*159 * rk3568 vop with 2 cluster, 2 esmart win, 2 smart win.160 * Every cluster can work as 4K win or split into two win.161 * All win in cluster support AFBCD.162 *163 * Every esmart win and smart win support 4 Multi-region.164 *165 * Scale filter mode:166 *167 * * Cluster: bicubic for horizontal scale up, others use bilinear168 * * ESmart:169 * * nearest-neighbor/bilinear/bicubic for scale up170 * * nearest-neighbor/bilinear/average for scale down171 *172 *173 * @TODO describe the wind like cpu-map dt nodes;174 */175static const struct vop2_win_data rk3568_vop_win_data[] = {176 {177 .name = "Smart0-win0",178 .phys_id = ROCKCHIP_VOP2_SMART0,179 .base = 0x1c00,180 .formats = formats_smart,181 .nformats = ARRAY_SIZE(formats_smart),182 .format_modifiers = format_modifiers,183 .layer_sel_id = 3,184 .supported_rotations = DRM_MODE_REFLECT_Y,185 .type = DRM_PLANE_TYPE_PRIMARY,186 .max_upscale_factor = 8,187 .max_downscale_factor = 8,188 .dly = { 20, 47, 41 },189 }, {190 .name = "Smart1-win0",191 .phys_id = ROCKCHIP_VOP2_SMART1,192 .formats = formats_smart,193 .nformats = ARRAY_SIZE(formats_smart),194 .format_modifiers = format_modifiers,195 .base = 0x1e00,196 .layer_sel_id = 7,197 .supported_rotations = DRM_MODE_REFLECT_Y,198 .type = DRM_PLANE_TYPE_PRIMARY,199 .max_upscale_factor = 8,200 .max_downscale_factor = 8,201 .dly = { 20, 47, 41 },202 }, {203 .name = "Esmart1-win0",204 .phys_id = ROCKCHIP_VOP2_ESMART1,205 .formats = formats_rk356x_esmart,206 .nformats = ARRAY_SIZE(formats_rk356x_esmart),207 .format_modifiers = format_modifiers,208 .base = 0x1a00,209 .layer_sel_id = 6,210 .supported_rotations = DRM_MODE_REFLECT_Y,211 .type = DRM_PLANE_TYPE_PRIMARY,212 .max_upscale_factor = 8,213 .max_downscale_factor = 8,214 .dly = { 20, 47, 41 },215 }, {216 .name = "Esmart0-win0",217 .phys_id = ROCKCHIP_VOP2_ESMART0,218 .formats = formats_rk356x_esmart,219 .nformats = ARRAY_SIZE(formats_rk356x_esmart),220 .format_modifiers = format_modifiers,221 .base = 0x1800,222 .layer_sel_id = 2,223 .supported_rotations = DRM_MODE_REFLECT_Y,224 .type = DRM_PLANE_TYPE_PRIMARY,225 .max_upscale_factor = 8,226 .max_downscale_factor = 8,227 .dly = { 20, 47, 41 },228 }, {229 .name = "Cluster0-win0",230 .phys_id = ROCKCHIP_VOP2_CLUSTER0,231 .base = 0x1000,232 .formats = formats_cluster,233 .nformats = ARRAY_SIZE(formats_cluster),234 .format_modifiers = format_modifiers_afbc,235 .layer_sel_id = 0,236 .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |237 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,238 .max_upscale_factor = 4,239 .max_downscale_factor = 4,240 .dly = { 0, 27, 21 },241 .type = DRM_PLANE_TYPE_OVERLAY,242 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,243 }, {244 .name = "Cluster1-win0",245 .phys_id = ROCKCHIP_VOP2_CLUSTER1,246 .base = 0x1200,247 .formats = formats_cluster,248 .nformats = ARRAY_SIZE(formats_cluster),249 .format_modifiers = format_modifiers_afbc,250 .layer_sel_id = 1,251 .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |252 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,253 .type = DRM_PLANE_TYPE_OVERLAY,254 .max_upscale_factor = 4,255 .max_downscale_factor = 4,256 .dly = { 0, 27, 21 },257 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,258 },259};260 261static const struct vop2_video_port_data rk3588_vop_video_ports[] = {262 {263 .id = 0,264 .feature = VOP2_VP_FEATURE_OUTPUT_10BIT,265 .gamma_lut_len = 1024,266 .cubic_lut_len = 9 * 9 * 9, /* 9x9x9 */267 .max_output = { 4096, 2304 },268 /* hdr2sdr sdr2hdr hdr2hdr sdr2sdr */269 .pre_scan_max_dly = { 76, 65, 65, 54 },270 .offset = 0xc00,271 }, {272 .id = 1,273 .feature = VOP2_VP_FEATURE_OUTPUT_10BIT,274 .gamma_lut_len = 1024,275 .cubic_lut_len = 729, /* 9x9x9 */276 .max_output = { 4096, 2304 },277 .pre_scan_max_dly = { 76, 65, 65, 54 },278 .offset = 0xd00,279 }, {280 .id = 2,281 .feature = VOP2_VP_FEATURE_OUTPUT_10BIT,282 .gamma_lut_len = 1024,283 .cubic_lut_len = 17 * 17 * 17, /* 17x17x17 */284 .max_output = { 4096, 2304 },285 .pre_scan_max_dly = { 52, 52, 52, 52 },286 .offset = 0xe00,287 }, {288 .id = 3,289 .gamma_lut_len = 1024,290 .max_output = { 2048, 1536 },291 .pre_scan_max_dly = { 52, 52, 52, 52 },292 .offset = 0xf00,293 },294};295 296/*297 * rk3588 vop with 4 cluster, 4 esmart win.298 * Every cluster can work as 4K win or split into two win.299 * All win in cluster support AFBCD.300 *301 * Every esmart win and smart win support 4 Multi-region.302 *303 * Scale filter mode:304 *305 * * Cluster: bicubic for horizontal scale up, others use bilinear306 * * ESmart:307 * * nearest-neighbor/bilinear/bicubic for scale up308 * * nearest-neighbor/bilinear/average for scale down309 *310 * AXI Read ID assignment:311 * Two AXI bus:312 * AXI0 is a read/write bus with a higher performance.313 * AXI1 is a read only bus.314 *315 * Every window on a AXI bus must assigned two unique316 * read id(yrgb_id/uv_id, valid id are 0x1~0xe).317 *318 * AXI0:319 * Cluster0/1, Esmart0/1, WriteBack320 *321 * AXI 1:322 * Cluster2/3, Esmart2/3323 *324 */325static const struct vop2_win_data rk3588_vop_win_data[] = {326 {327 .name = "Cluster0-win0",328 .phys_id = ROCKCHIP_VOP2_CLUSTER0,329 .base = 0x1000,330 .formats = formats_cluster,331 .nformats = ARRAY_SIZE(formats_cluster),332 .format_modifiers = format_modifiers_afbc,333 .layer_sel_id = 0,334 .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |335 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,336 .max_upscale_factor = 4,337 .max_downscale_factor = 4,338 .dly = { 4, 26, 29 },339 .type = DRM_PLANE_TYPE_PRIMARY,340 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,341 }, {342 .name = "Cluster1-win0",343 .phys_id = ROCKCHIP_VOP2_CLUSTER1,344 .base = 0x1200,345 .formats = formats_cluster,346 .nformats = ARRAY_SIZE(formats_cluster),347 .format_modifiers = format_modifiers_afbc,348 .layer_sel_id = 1,349 .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |350 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,351 .type = DRM_PLANE_TYPE_PRIMARY,352 .max_upscale_factor = 4,353 .max_downscale_factor = 4,354 .dly = { 4, 26, 29 },355 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,356 }, {357 .name = "Cluster2-win0",358 .phys_id = ROCKCHIP_VOP2_CLUSTER2,359 .base = 0x1400,360 .formats = formats_cluster,361 .nformats = ARRAY_SIZE(formats_cluster),362 .format_modifiers = format_modifiers_afbc,363 .layer_sel_id = 4,364 .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |365 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,366 .type = DRM_PLANE_TYPE_PRIMARY,367 .max_upscale_factor = 4,368 .max_downscale_factor = 4,369 .dly = { 4, 26, 29 },370 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,371 }, {372 .name = "Cluster3-win0",373 .phys_id = ROCKCHIP_VOP2_CLUSTER3,374 .base = 0x1600,375 .formats = formats_cluster,376 .nformats = ARRAY_SIZE(formats_cluster),377 .format_modifiers = format_modifiers_afbc,378 .layer_sel_id = 5,379 .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |380 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,381 .type = DRM_PLANE_TYPE_PRIMARY,382 .max_upscale_factor = 4,383 .max_downscale_factor = 4,384 .dly = { 4, 26, 29 },385 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,386 }, {387 .name = "Esmart0-win0",388 .phys_id = ROCKCHIP_VOP2_ESMART0,389 .formats = formats_esmart,390 .nformats = ARRAY_SIZE(formats_esmart),391 .format_modifiers = format_modifiers,392 .base = 0x1800,393 .layer_sel_id = 2,394 .supported_rotations = DRM_MODE_REFLECT_Y,395 .type = DRM_PLANE_TYPE_OVERLAY,396 .max_upscale_factor = 8,397 .max_downscale_factor = 8,398 .dly = { 23, 45, 48 },399 }, {400 .name = "Esmart1-win0",401 .phys_id = ROCKCHIP_VOP2_ESMART1,402 .formats = formats_esmart,403 .nformats = ARRAY_SIZE(formats_esmart),404 .format_modifiers = format_modifiers,405 .base = 0x1a00,406 .layer_sel_id = 3,407 .supported_rotations = DRM_MODE_REFLECT_Y,408 .type = DRM_PLANE_TYPE_OVERLAY,409 .max_upscale_factor = 8,410 .max_downscale_factor = 8,411 .dly = { 23, 45, 48 },412 }, {413 .name = "Esmart2-win0",414 .phys_id = ROCKCHIP_VOP2_ESMART2,415 .base = 0x1c00,416 .formats = formats_esmart,417 .nformats = ARRAY_SIZE(formats_esmart),418 .format_modifiers = format_modifiers,419 .layer_sel_id = 6,420 .supported_rotations = DRM_MODE_REFLECT_Y,421 .type = DRM_PLANE_TYPE_OVERLAY,422 .max_upscale_factor = 8,423 .max_downscale_factor = 8,424 .dly = { 23, 45, 48 },425 }, {426 .name = "Esmart3-win0",427 .phys_id = ROCKCHIP_VOP2_ESMART3,428 .formats = formats_esmart,429 .nformats = ARRAY_SIZE(formats_esmart),430 .format_modifiers = format_modifiers,431 .base = 0x1e00,432 .layer_sel_id = 7,433 .supported_rotations = DRM_MODE_REFLECT_Y,434 .type = DRM_PLANE_TYPE_OVERLAY,435 .max_upscale_factor = 8,436 .max_downscale_factor = 8,437 .dly = { 23, 45, 48 },438 },439};440 441static const struct vop2_data rk3566_vop = {442 .feature = VOP2_FEATURE_HAS_SYS_GRF,443 .nr_vps = 3,444 .max_input = { 4096, 2304 },445 .max_output = { 4096, 2304 },446 .vp = rk3568_vop_video_ports,447 .win = rk3568_vop_win_data,448 .win_size = ARRAY_SIZE(rk3568_vop_win_data),449 .soc_id = 3566,450};451 452static const struct vop2_data rk3568_vop = {453 .feature = VOP2_FEATURE_HAS_SYS_GRF,454 .nr_vps = 3,455 .max_input = { 4096, 2304 },456 .max_output = { 4096, 2304 },457 .vp = rk3568_vop_video_ports,458 .win = rk3568_vop_win_data,459 .win_size = ARRAY_SIZE(rk3568_vop_win_data),460 .soc_id = 3568,461};462 463static const struct vop2_data rk3588_vop = {464 .feature = VOP2_FEATURE_HAS_SYS_GRF | VOP2_FEATURE_HAS_VO1_GRF |465 VOP2_FEATURE_HAS_VOP_GRF | VOP2_FEATURE_HAS_SYS_PMU,466 .nr_vps = 4,467 .max_input = { 4096, 4320 },468 .max_output = { 4096, 4320 },469 .vp = rk3588_vop_video_ports,470 .win = rk3588_vop_win_data,471 .win_size = ARRAY_SIZE(rk3588_vop_win_data),472 .soc_id = 3588,473};474 475static const struct of_device_id vop2_dt_match[] = {476 {477 .compatible = "rockchip,rk3566-vop",478 .data = &rk3566_vop,479 }, {480 .compatible = "rockchip,rk3568-vop",481 .data = &rk3568_vop,482 }, {483 .compatible = "rockchip,rk3588-vop",484 .data = &rk3588_vop485 }, {486 },487};488MODULE_DEVICE_TABLE(of, vop2_dt_match);489 490static int vop2_probe(struct platform_device *pdev)491{492 struct device *dev = &pdev->dev;493 494 return component_add(dev, &vop2_component_ops);495}496 497static void vop2_remove(struct platform_device *pdev)498{499 component_del(&pdev->dev, &vop2_component_ops);500}501 502struct platform_driver vop2_platform_driver = {503 .probe = vop2_probe,504 .remove_new = vop2_remove,505 .driver = {506 .name = "rockchip-vop2",507 .of_match_table = vop2_dt_match,508 },509};510