0001
0002
0003
0004
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
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
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
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 };