0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/component.h>
0010 #include <linux/kernel.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/timer.h>
0013
0014 #include <drm/drm_atomic_helper.h>
0015 #include <drm/drm_edid.h>
0016 #include <drm/drm_framebuffer.h>
0017 #include <drm/drm_probe_helper.h>
0018 #include <drm/drm_simple_kms_helper.h>
0019 #include <drm/drm_vblank.h>
0020 #include <drm/exynos_drm.h>
0021
0022 #include "exynos_drm_crtc.h"
0023 #include "exynos_drm_drv.h"
0024 #include "exynos_drm_fb.h"
0025 #include "exynos_drm_plane.h"
0026 #include "exynos_drm_vidi.h"
0027
0028
0029 #define VIDI_REFRESH_TIME (1000 / 50)
0030
0031
0032 #define WINDOWS_NR 3
0033
0034 #define ctx_from_connector(c) container_of(c, struct vidi_context, \
0035 connector)
0036
0037 struct vidi_context {
0038 struct drm_encoder encoder;
0039 struct drm_device *drm_dev;
0040 struct device *dev;
0041 struct exynos_drm_crtc *crtc;
0042 struct drm_connector connector;
0043 struct exynos_drm_plane planes[WINDOWS_NR];
0044 struct edid *raw_edid;
0045 unsigned int clkdiv;
0046 unsigned int connected;
0047 bool suspended;
0048 struct timer_list timer;
0049 struct mutex lock;
0050 };
0051
0052 static inline struct vidi_context *encoder_to_vidi(struct drm_encoder *e)
0053 {
0054 return container_of(e, struct vidi_context, encoder);
0055 }
0056
0057 static const char fake_edid_info[] = {
0058 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x05, 0x05,
0059 0x00, 0x00, 0x00, 0x00, 0x30, 0x12, 0x01, 0x03, 0x80, 0x10, 0x09, 0x78,
0060 0x0a, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, 0xbd,
0061 0xee, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0062 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x66, 0x21, 0x50, 0xb0, 0x51, 0x00,
0063 0x1b, 0x30, 0x40, 0x70, 0x36, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e,
0064 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
0065 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18,
0066 0x4b, 0x1a, 0x44, 0x17, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0067 0x00, 0x00, 0x00, 0xfc, 0x00, 0x53, 0x41, 0x4d, 0x53, 0x55, 0x4e, 0x47,
0068 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xbc, 0x02, 0x03, 0x1e, 0xf1,
0069 0x46, 0x84, 0x05, 0x03, 0x10, 0x20, 0x22, 0x23, 0x09, 0x07, 0x07, 0x83,
0070 0x01, 0x00, 0x00, 0xe2, 0x00, 0x0f, 0x67, 0x03, 0x0c, 0x00, 0x10, 0x00,
0071 0xb8, 0x2d, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c,
0072 0x25, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x9e, 0x8c, 0x0a, 0xd0, 0x8a,
0073 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xa0, 0x5a, 0x00, 0x00,
0074 0x00, 0x18, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
0075 0x45, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
0076 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0077 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0078 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0079 0x00, 0x00, 0x00, 0x06
0080 };
0081
0082 static const uint32_t formats[] = {
0083 DRM_FORMAT_XRGB8888,
0084 DRM_FORMAT_ARGB8888,
0085 DRM_FORMAT_NV12,
0086 };
0087
0088 static const enum drm_plane_type vidi_win_types[WINDOWS_NR] = {
0089 DRM_PLANE_TYPE_PRIMARY,
0090 DRM_PLANE_TYPE_OVERLAY,
0091 DRM_PLANE_TYPE_CURSOR,
0092 };
0093
0094 static int vidi_enable_vblank(struct exynos_drm_crtc *crtc)
0095 {
0096 struct vidi_context *ctx = crtc->ctx;
0097
0098 if (ctx->suspended)
0099 return -EPERM;
0100
0101 mod_timer(&ctx->timer,
0102 jiffies + msecs_to_jiffies(VIDI_REFRESH_TIME) - 1);
0103
0104 return 0;
0105 }
0106
0107 static void vidi_disable_vblank(struct exynos_drm_crtc *crtc)
0108 {
0109 }
0110
0111 static void vidi_update_plane(struct exynos_drm_crtc *crtc,
0112 struct exynos_drm_plane *plane)
0113 {
0114 struct drm_plane_state *state = plane->base.state;
0115 struct vidi_context *ctx = crtc->ctx;
0116 dma_addr_t addr;
0117
0118 if (ctx->suspended)
0119 return;
0120
0121 addr = exynos_drm_fb_dma_addr(state->fb, 0);
0122 DRM_DEV_DEBUG_KMS(ctx->dev, "dma_addr = %pad\n", &addr);
0123 }
0124
0125 static void vidi_atomic_enable(struct exynos_drm_crtc *crtc)
0126 {
0127 struct vidi_context *ctx = crtc->ctx;
0128
0129 mutex_lock(&ctx->lock);
0130
0131 ctx->suspended = false;
0132
0133 mutex_unlock(&ctx->lock);
0134
0135 drm_crtc_vblank_on(&crtc->base);
0136 }
0137
0138 static void vidi_atomic_disable(struct exynos_drm_crtc *crtc)
0139 {
0140 struct vidi_context *ctx = crtc->ctx;
0141
0142 drm_crtc_vblank_off(&crtc->base);
0143
0144 mutex_lock(&ctx->lock);
0145
0146 ctx->suspended = true;
0147
0148 mutex_unlock(&ctx->lock);
0149 }
0150
0151 static const struct exynos_drm_crtc_ops vidi_crtc_ops = {
0152 .atomic_enable = vidi_atomic_enable,
0153 .atomic_disable = vidi_atomic_disable,
0154 .enable_vblank = vidi_enable_vblank,
0155 .disable_vblank = vidi_disable_vblank,
0156 .update_plane = vidi_update_plane,
0157 .atomic_flush = exynos_crtc_handle_event,
0158 };
0159
0160 static void vidi_fake_vblank_timer(struct timer_list *t)
0161 {
0162 struct vidi_context *ctx = from_timer(ctx, t, timer);
0163
0164 if (drm_crtc_handle_vblank(&ctx->crtc->base))
0165 mod_timer(&ctx->timer,
0166 jiffies + msecs_to_jiffies(VIDI_REFRESH_TIME) - 1);
0167 }
0168
0169 static ssize_t vidi_show_connection(struct device *dev,
0170 struct device_attribute *attr, char *buf)
0171 {
0172 struct vidi_context *ctx = dev_get_drvdata(dev);
0173 int rc;
0174
0175 mutex_lock(&ctx->lock);
0176
0177 rc = sprintf(buf, "%d\n", ctx->connected);
0178
0179 mutex_unlock(&ctx->lock);
0180
0181 return rc;
0182 }
0183
0184 static ssize_t vidi_store_connection(struct device *dev,
0185 struct device_attribute *attr,
0186 const char *buf, size_t len)
0187 {
0188 struct vidi_context *ctx = dev_get_drvdata(dev);
0189 int ret;
0190
0191 ret = kstrtoint(buf, 0, &ctx->connected);
0192 if (ret)
0193 return ret;
0194
0195 if (ctx->connected > 1)
0196 return -EINVAL;
0197
0198
0199 if (!ctx->raw_edid)
0200 ctx->raw_edid = (struct edid *)fake_edid_info;
0201
0202
0203 if (ctx->raw_edid != (struct edid *)fake_edid_info) {
0204 DRM_DEV_DEBUG_KMS(dev, "edid data is not fake data.\n");
0205 return -EINVAL;
0206 }
0207
0208 DRM_DEV_DEBUG_KMS(dev, "requested connection.\n");
0209
0210 drm_helper_hpd_irq_event(ctx->drm_dev);
0211
0212 return len;
0213 }
0214
0215 static DEVICE_ATTR(connection, 0644, vidi_show_connection,
0216 vidi_store_connection);
0217
0218 static struct attribute *vidi_attrs[] = {
0219 &dev_attr_connection.attr,
0220 NULL,
0221 };
0222 ATTRIBUTE_GROUPS(vidi);
0223
0224 int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
0225 struct drm_file *file_priv)
0226 {
0227 struct vidi_context *ctx = dev_get_drvdata(drm_dev->dev);
0228 struct drm_exynos_vidi_connection *vidi = data;
0229
0230 if (!vidi) {
0231 DRM_DEV_DEBUG_KMS(ctx->dev,
0232 "user data for vidi is null.\n");
0233 return -EINVAL;
0234 }
0235
0236 if (vidi->connection > 1) {
0237 DRM_DEV_DEBUG_KMS(ctx->dev,
0238 "connection should be 0 or 1.\n");
0239 return -EINVAL;
0240 }
0241
0242 if (ctx->connected == vidi->connection) {
0243 DRM_DEV_DEBUG_KMS(ctx->dev,
0244 "same connection request.\n");
0245 return -EINVAL;
0246 }
0247
0248 if (vidi->connection) {
0249 struct edid *raw_edid;
0250
0251 raw_edid = (struct edid *)(unsigned long)vidi->edid;
0252 if (!drm_edid_is_valid(raw_edid)) {
0253 DRM_DEV_DEBUG_KMS(ctx->dev,
0254 "edid data is invalid.\n");
0255 return -EINVAL;
0256 }
0257 ctx->raw_edid = drm_edid_duplicate(raw_edid);
0258 if (!ctx->raw_edid) {
0259 DRM_DEV_DEBUG_KMS(ctx->dev,
0260 "failed to allocate raw_edid.\n");
0261 return -ENOMEM;
0262 }
0263 } else {
0264
0265
0266
0267
0268 if (ctx->raw_edid && ctx->raw_edid !=
0269 (struct edid *)fake_edid_info) {
0270 kfree(ctx->raw_edid);
0271 ctx->raw_edid = NULL;
0272 }
0273 }
0274
0275 ctx->connected = vidi->connection;
0276 drm_helper_hpd_irq_event(ctx->drm_dev);
0277
0278 return 0;
0279 }
0280
0281 static enum drm_connector_status vidi_detect(struct drm_connector *connector,
0282 bool force)
0283 {
0284 struct vidi_context *ctx = ctx_from_connector(connector);
0285
0286
0287
0288
0289
0290 return ctx->connected ? connector_status_connected :
0291 connector_status_disconnected;
0292 }
0293
0294 static void vidi_connector_destroy(struct drm_connector *connector)
0295 {
0296 }
0297
0298 static const struct drm_connector_funcs vidi_connector_funcs = {
0299 .fill_modes = drm_helper_probe_single_connector_modes,
0300 .detect = vidi_detect,
0301 .destroy = vidi_connector_destroy,
0302 .reset = drm_atomic_helper_connector_reset,
0303 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
0304 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
0305 };
0306
0307 static int vidi_get_modes(struct drm_connector *connector)
0308 {
0309 struct vidi_context *ctx = ctx_from_connector(connector);
0310 struct edid *edid;
0311 int edid_len;
0312
0313
0314
0315
0316
0317 if (!ctx->raw_edid) {
0318 DRM_DEV_DEBUG_KMS(ctx->dev, "raw_edid is null.\n");
0319 return -EFAULT;
0320 }
0321
0322 edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
0323 edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
0324 if (!edid) {
0325 DRM_DEV_DEBUG_KMS(ctx->dev, "failed to allocate edid\n");
0326 return -ENOMEM;
0327 }
0328
0329 drm_connector_update_edid_property(connector, edid);
0330
0331 return drm_add_edid_modes(connector, edid);
0332 }
0333
0334 static const struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
0335 .get_modes = vidi_get_modes,
0336 };
0337
0338 static int vidi_create_connector(struct drm_encoder *encoder)
0339 {
0340 struct vidi_context *ctx = encoder_to_vidi(encoder);
0341 struct drm_connector *connector = &ctx->connector;
0342 int ret;
0343
0344 connector->polled = DRM_CONNECTOR_POLL_HPD;
0345
0346 ret = drm_connector_init(ctx->drm_dev, connector,
0347 &vidi_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
0348 if (ret) {
0349 DRM_DEV_ERROR(ctx->dev,
0350 "Failed to initialize connector with drm\n");
0351 return ret;
0352 }
0353
0354 drm_connector_helper_add(connector, &vidi_connector_helper_funcs);
0355 drm_connector_attach_encoder(connector, encoder);
0356
0357 return 0;
0358 }
0359
0360 static void exynos_vidi_mode_set(struct drm_encoder *encoder,
0361 struct drm_display_mode *mode,
0362 struct drm_display_mode *adjusted_mode)
0363 {
0364 }
0365
0366 static void exynos_vidi_enable(struct drm_encoder *encoder)
0367 {
0368 }
0369
0370 static void exynos_vidi_disable(struct drm_encoder *encoder)
0371 {
0372 }
0373
0374 static const struct drm_encoder_helper_funcs exynos_vidi_encoder_helper_funcs = {
0375 .mode_set = exynos_vidi_mode_set,
0376 .enable = exynos_vidi_enable,
0377 .disable = exynos_vidi_disable,
0378 };
0379
0380 static int vidi_bind(struct device *dev, struct device *master, void *data)
0381 {
0382 struct vidi_context *ctx = dev_get_drvdata(dev);
0383 struct drm_device *drm_dev = data;
0384 struct drm_encoder *encoder = &ctx->encoder;
0385 struct exynos_drm_plane *exynos_plane;
0386 struct exynos_drm_plane_config plane_config = { 0 };
0387 unsigned int i;
0388 int ret;
0389
0390 ctx->drm_dev = drm_dev;
0391
0392 plane_config.pixel_formats = formats;
0393 plane_config.num_pixel_formats = ARRAY_SIZE(formats);
0394
0395 for (i = 0; i < WINDOWS_NR; i++) {
0396 plane_config.zpos = i;
0397 plane_config.type = vidi_win_types[i];
0398
0399 ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
0400 &plane_config);
0401 if (ret)
0402 return ret;
0403 }
0404
0405 exynos_plane = &ctx->planes[DEFAULT_WIN];
0406 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
0407 EXYNOS_DISPLAY_TYPE_VIDI, &vidi_crtc_ops, ctx);
0408 if (IS_ERR(ctx->crtc)) {
0409 DRM_DEV_ERROR(dev, "failed to create crtc.\n");
0410 return PTR_ERR(ctx->crtc);
0411 }
0412
0413 drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
0414
0415 drm_encoder_helper_add(encoder, &exynos_vidi_encoder_helper_funcs);
0416
0417 ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_VIDI);
0418 if (ret < 0)
0419 return ret;
0420
0421 ret = vidi_create_connector(encoder);
0422 if (ret) {
0423 DRM_DEV_ERROR(dev, "failed to create connector ret = %d\n",
0424 ret);
0425 drm_encoder_cleanup(encoder);
0426 return ret;
0427 }
0428
0429 return 0;
0430 }
0431
0432
0433 static void vidi_unbind(struct device *dev, struct device *master, void *data)
0434 {
0435 struct vidi_context *ctx = dev_get_drvdata(dev);
0436
0437 del_timer_sync(&ctx->timer);
0438 }
0439
0440 static const struct component_ops vidi_component_ops = {
0441 .bind = vidi_bind,
0442 .unbind = vidi_unbind,
0443 };
0444
0445 static int vidi_probe(struct platform_device *pdev)
0446 {
0447 struct vidi_context *ctx;
0448 struct device *dev = &pdev->dev;
0449
0450 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
0451 if (!ctx)
0452 return -ENOMEM;
0453
0454 ctx->dev = dev;
0455
0456 timer_setup(&ctx->timer, vidi_fake_vblank_timer, 0);
0457
0458 mutex_init(&ctx->lock);
0459
0460 platform_set_drvdata(pdev, ctx);
0461
0462 return component_add(dev, &vidi_component_ops);
0463 }
0464
0465 static int vidi_remove(struct platform_device *pdev)
0466 {
0467 struct vidi_context *ctx = platform_get_drvdata(pdev);
0468
0469 if (ctx->raw_edid != (struct edid *)fake_edid_info) {
0470 kfree(ctx->raw_edid);
0471 ctx->raw_edid = NULL;
0472
0473 return -EINVAL;
0474 }
0475
0476 component_del(&pdev->dev, &vidi_component_ops);
0477
0478 return 0;
0479 }
0480
0481 struct platform_driver vidi_driver = {
0482 .probe = vidi_probe,
0483 .remove = vidi_remove,
0484 .driver = {
0485 .name = "exynos-drm-vidi",
0486 .owner = THIS_MODULE,
0487 .dev_groups = vidi_groups,
0488 },
0489 };