Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) Rockchip Electronics Co.Ltd
0004  * Author: Andy Yan <andy.yan@rock-chips.com>
0005  */
0006 
0007 #include <linux/kernel.h>
0008 #include <linux/component.h>
0009 #include <linux/mod_devicetable.h>
0010 #include <linux/platform_device.h>
0011 #include <linux/of.h>
0012 #include <drm/drm_fourcc.h>
0013 #include <drm/drm_plane.h>
0014 #include <drm/drm_print.h>
0015 
0016 #include "rockchip_drm_vop2.h"
0017 
0018 static const uint32_t formats_win_full_10bit[] = {
0019     DRM_FORMAT_XRGB8888,
0020     DRM_FORMAT_ARGB8888,
0021     DRM_FORMAT_XBGR8888,
0022     DRM_FORMAT_ABGR8888,
0023     DRM_FORMAT_RGB888,
0024     DRM_FORMAT_BGR888,
0025     DRM_FORMAT_RGB565,
0026     DRM_FORMAT_BGR565,
0027     DRM_FORMAT_NV12,
0028     DRM_FORMAT_NV16,
0029     DRM_FORMAT_NV24,
0030 };
0031 
0032 static const uint32_t formats_win_full_10bit_yuyv[] = {
0033     DRM_FORMAT_XRGB8888,
0034     DRM_FORMAT_ARGB8888,
0035     DRM_FORMAT_XBGR8888,
0036     DRM_FORMAT_ABGR8888,
0037     DRM_FORMAT_RGB888,
0038     DRM_FORMAT_BGR888,
0039     DRM_FORMAT_RGB565,
0040     DRM_FORMAT_BGR565,
0041     DRM_FORMAT_NV12,
0042     DRM_FORMAT_NV16,
0043     DRM_FORMAT_NV24,
0044     DRM_FORMAT_YVYU,
0045     DRM_FORMAT_VYUY,
0046 };
0047 
0048 static const uint32_t formats_win_lite[] = {
0049     DRM_FORMAT_XRGB8888,
0050     DRM_FORMAT_ARGB8888,
0051     DRM_FORMAT_XBGR8888,
0052     DRM_FORMAT_ABGR8888,
0053     DRM_FORMAT_RGB888,
0054     DRM_FORMAT_BGR888,
0055     DRM_FORMAT_RGB565,
0056     DRM_FORMAT_BGR565,
0057 };
0058 
0059 static const uint64_t format_modifiers[] = {
0060     DRM_FORMAT_MOD_LINEAR,
0061     DRM_FORMAT_MOD_INVALID,
0062 };
0063 
0064 static const uint64_t format_modifiers_afbc[] = {
0065     DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16),
0066 
0067     DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
0068                 AFBC_FORMAT_MOD_SPARSE),
0069 
0070     DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
0071                 AFBC_FORMAT_MOD_YTR),
0072 
0073     DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
0074                 AFBC_FORMAT_MOD_CBR),
0075 
0076     DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
0077                 AFBC_FORMAT_MOD_YTR |
0078                 AFBC_FORMAT_MOD_SPARSE),
0079 
0080     DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
0081                 AFBC_FORMAT_MOD_CBR |
0082                 AFBC_FORMAT_MOD_SPARSE),
0083 
0084     DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
0085                 AFBC_FORMAT_MOD_YTR |
0086                 AFBC_FORMAT_MOD_CBR),
0087 
0088     DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
0089                 AFBC_FORMAT_MOD_YTR |
0090                 AFBC_FORMAT_MOD_CBR |
0091                 AFBC_FORMAT_MOD_SPARSE),
0092 
0093     /* SPLIT mandates SPARSE, RGB modes mandates YTR */
0094     DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
0095                 AFBC_FORMAT_MOD_YTR |
0096                 AFBC_FORMAT_MOD_SPARSE |
0097                 AFBC_FORMAT_MOD_SPLIT),
0098     DRM_FORMAT_MOD_INVALID,
0099 };
0100 
0101 static const struct vop2_video_port_data rk3568_vop_video_ports[] = {
0102     {
0103         .id = 0,
0104         .feature = VOP_FEATURE_OUTPUT_10BIT,
0105         .gamma_lut_len = 1024,
0106         .cubic_lut_len = 9 * 9 * 9,
0107         .max_output = { 4096, 2304 },
0108         .pre_scan_max_dly = { 69, 53, 53, 42 },
0109         .offset = 0xc00,
0110     }, {
0111         .id = 1,
0112         .gamma_lut_len = 1024,
0113         .max_output = { 2048, 1536 },
0114         .pre_scan_max_dly = { 40, 40, 40, 40 },
0115         .offset = 0xd00,
0116     }, {
0117         .id = 2,
0118         .gamma_lut_len = 1024,
0119         .max_output = { 1920, 1080 },
0120         .pre_scan_max_dly = { 40, 40, 40, 40 },
0121         .offset = 0xe00,
0122     },
0123 };
0124 
0125 /*
0126  * rk3568 vop with 2 cluster, 2 esmart win, 2 smart win.
0127  * Every cluster can work as 4K win or split into two win.
0128  * All win in cluster support AFBCD.
0129  *
0130  * Every esmart win and smart win support 4 Multi-region.
0131  *
0132  * Scale filter mode:
0133  *
0134  * * Cluster:  bicubic for horizontal scale up, others use bilinear
0135  * * ESmart:
0136  *    * nearest-neighbor/bilinear/bicubic for scale up
0137  *    * nearest-neighbor/bilinear/average for scale down
0138  *
0139  *
0140  * @TODO describe the wind like cpu-map dt nodes;
0141  */
0142 static const struct vop2_win_data rk3568_vop_win_data[] = {
0143     {
0144         .name = "Smart0-win0",
0145         .phys_id = ROCKCHIP_VOP2_SMART0,
0146         .base = 0x1c00,
0147         .formats = formats_win_lite,
0148         .nformats = ARRAY_SIZE(formats_win_lite),
0149         .format_modifiers = format_modifiers,
0150         .layer_sel_id = 3,
0151         .supported_rotations = DRM_MODE_REFLECT_Y,
0152         .type = DRM_PLANE_TYPE_PRIMARY,
0153         .max_upscale_factor = 8,
0154         .max_downscale_factor = 8,
0155         .dly = { 20, 47, 41 },
0156     }, {
0157         .name = "Smart1-win0",
0158         .phys_id = ROCKCHIP_VOP2_SMART1,
0159         .formats = formats_win_lite,
0160         .nformats = ARRAY_SIZE(formats_win_lite),
0161         .format_modifiers = format_modifiers,
0162         .base = 0x1e00,
0163         .layer_sel_id = 7,
0164         .supported_rotations = DRM_MODE_REFLECT_Y,
0165         .type = DRM_PLANE_TYPE_PRIMARY,
0166         .max_upscale_factor = 8,
0167         .max_downscale_factor = 8,
0168         .dly = { 20, 47, 41 },
0169     }, {
0170         .name = "Esmart1-win0",
0171         .phys_id = ROCKCHIP_VOP2_ESMART1,
0172         .formats = formats_win_full_10bit_yuyv,
0173         .nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv),
0174         .format_modifiers = format_modifiers,
0175         .base = 0x1a00,
0176         .layer_sel_id = 6,
0177         .supported_rotations = DRM_MODE_REFLECT_Y,
0178         .type = DRM_PLANE_TYPE_PRIMARY,
0179         .max_upscale_factor = 8,
0180         .max_downscale_factor = 8,
0181         .dly = { 20, 47, 41 },
0182     }, {
0183         .name = "Esmart0-win0",
0184         .phys_id = ROCKCHIP_VOP2_ESMART0,
0185         .formats = formats_win_full_10bit_yuyv,
0186         .nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv),
0187         .format_modifiers = format_modifiers,
0188         .base = 0x1800,
0189         .layer_sel_id = 2,
0190         .supported_rotations = DRM_MODE_REFLECT_Y,
0191         .type = DRM_PLANE_TYPE_OVERLAY,
0192         .max_upscale_factor = 8,
0193         .max_downscale_factor = 8,
0194         .dly = { 20, 47, 41 },
0195     }, {
0196         .name = "Cluster0-win0",
0197         .phys_id = ROCKCHIP_VOP2_CLUSTER0,
0198         .base = 0x1000,
0199         .formats = formats_win_full_10bit,
0200         .nformats = ARRAY_SIZE(formats_win_full_10bit),
0201         .format_modifiers = format_modifiers_afbc,
0202         .layer_sel_id = 0,
0203         .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
0204                     DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
0205         .max_upscale_factor = 4,
0206         .max_downscale_factor = 4,
0207         .dly = { 0, 27, 21 },
0208         .type = DRM_PLANE_TYPE_OVERLAY,
0209         .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
0210     }, {
0211         .name = "Cluster1-win0",
0212         .phys_id = ROCKCHIP_VOP2_CLUSTER1,
0213         .base = 0x1200,
0214         .formats = formats_win_full_10bit,
0215         .nformats = ARRAY_SIZE(formats_win_full_10bit),
0216         .format_modifiers = format_modifiers_afbc,
0217         .layer_sel_id = 1,
0218         .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
0219                     DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
0220         .type = DRM_PLANE_TYPE_OVERLAY,
0221         .max_upscale_factor = 4,
0222         .max_downscale_factor = 4,
0223         .dly = { 0, 27, 21 },
0224         .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
0225     },
0226 };
0227 
0228 static const struct vop2_data rk3566_vop = {
0229     .nr_vps = 3,
0230     .max_input = { 4096, 2304 },
0231     .max_output = { 4096, 2304 },
0232     .vp = rk3568_vop_video_ports,
0233     .win = rk3568_vop_win_data,
0234     .win_size = ARRAY_SIZE(rk3568_vop_win_data),
0235     .soc_id = 3566,
0236 };
0237 
0238 static const struct vop2_data rk3568_vop = {
0239     .nr_vps = 3,
0240     .max_input = { 4096, 2304 },
0241     .max_output = { 4096, 2304 },
0242     .vp = rk3568_vop_video_ports,
0243     .win = rk3568_vop_win_data,
0244     .win_size = ARRAY_SIZE(rk3568_vop_win_data),
0245     .soc_id = 3568,
0246 };
0247 
0248 static const struct of_device_id vop2_dt_match[] = {
0249     {
0250         .compatible = "rockchip,rk3566-vop",
0251         .data = &rk3566_vop,
0252     }, {
0253         .compatible = "rockchip,rk3568-vop",
0254         .data = &rk3568_vop,
0255     }, {
0256     },
0257 };
0258 MODULE_DEVICE_TABLE(of, vop2_dt_match);
0259 
0260 static int vop2_probe(struct platform_device *pdev)
0261 {
0262     struct device *dev = &pdev->dev;
0263 
0264     return component_add(dev, &vop2_component_ops);
0265 }
0266 
0267 static int vop2_remove(struct platform_device *pdev)
0268 {
0269     component_del(&pdev->dev, &vop2_component_ops);
0270 
0271     return 0;
0272 }
0273 
0274 struct platform_driver vop2_platform_driver = {
0275     .probe = vop2_probe,
0276     .remove = vop2_remove,
0277     .driver = {
0278         .name = "rockchip-vop2",
0279         .of_match_table = of_match_ptr(vop2_dt_match),
0280     },
0281 };