exynos_drm_drv.c 12.3 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
2 3 4 5 6 7 8 9
/*
 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
 * Authors:
 *	Inki Dae <inki.dae@samsung.com>
 *	Joonyoung Shim <jy0922.shim@samsung.com>
 *	Seung-Woo Kim <sw0312.kim@samsung.com>
 */

S
Sam Ravnborg 已提交
10
#include <linux/component.h>
11
#include <linux/pm_runtime.h>
S
Sam Ravnborg 已提交
12

13 14
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
15
#include <drm/drm_fb_helper.h>
16
#include <drm/drm_probe_helper.h>
17 18 19 20
#include <drm/exynos_drm.h>

#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
S
Sam Ravnborg 已提交
21 22
#include "exynos_drm_fbdev.h"
#include "exynos_drm_g2d.h"
23
#include "exynos_drm_gem.h"
24
#include "exynos_drm_ipp.h"
S
Sam Ravnborg 已提交
25
#include "exynos_drm_plane.h"
26
#include "exynos_drm_vidi.h"
27

I
Inki Dae 已提交
28
#define DRIVER_NAME	"exynos"
29
#define DRIVER_DESC	"Samsung SoC DRM"
30 31 32 33 34 35 36 37
#define DRIVER_DATE	"20180330"

/*
 * Interface history:
 *
 * 1.0 - Original version
 * 1.1 - Upgrade IPP driver to version 2.0
 */
38
#define DRIVER_MAJOR	1
39
#define DRIVER_MINOR	1
40

41 42
static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
{
J
Joonyoung Shim 已提交
43
	struct drm_exynos_file_private *file_priv;
44
	int ret;
J
Joonyoung Shim 已提交
45 46 47 48 49 50

	file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
	if (!file_priv)
		return -ENOMEM;

	file->driver_priv = file_priv;
51
	ret = g2d_open(dev, file);
52
	if (ret)
53
		goto err_file_priv_free;
54

55
	return ret;
56 57

err_file_priv_free:
58 59
	kfree(file_priv);
	file->driver_priv = NULL;
60
	return ret;
61 62
}

63
static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
I
Inki Dae 已提交
64
{
65
	g2d_close(dev, file);
66 67 68 69
	kfree(file->driver_priv);
	file->driver_priv = NULL;
}

70
static const struct vm_operations_struct exynos_drm_gem_vm_ops = {
71 72 73 74 75
	.fault = exynos_drm_gem_fault,
	.open = drm_gem_vm_open,
	.close = drm_gem_vm_close,
};

R
Rob Clark 已提交
76
static const struct drm_ioctl_desc exynos_ioctls[] = {
77
	DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl,
78
			DRM_AUTH | DRM_RENDER_ALLOW),
79 80
	DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP, exynos_drm_gem_map_ioctl,
			DRM_AUTH | DRM_RENDER_ALLOW),
81
	DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET, exynos_drm_gem_get_ioctl,
82
			DRM_RENDER_ALLOW),
83
	DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION, vidi_connection_ioctl,
84
			DRM_AUTH),
85
	DRM_IOCTL_DEF_DRV(EXYNOS_G2D_GET_VER, exynos_g2d_get_ver_ioctl,
86
			DRM_AUTH | DRM_RENDER_ALLOW),
87
	DRM_IOCTL_DEF_DRV(EXYNOS_G2D_SET_CMDLIST, exynos_g2d_set_cmdlist_ioctl,
88
			DRM_AUTH | DRM_RENDER_ALLOW),
89
	DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC, exynos_g2d_exec_ioctl,
90
			DRM_AUTH | DRM_RENDER_ALLOW),
91 92 93 94 95 96 97 98 99 100
	DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_RESOURCES,
			exynos_drm_ipp_get_res_ioctl,
			DRM_AUTH | DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_CAPS, exynos_drm_ipp_get_caps_ioctl,
			DRM_AUTH | DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_LIMITS,
			exynos_drm_ipp_get_limits_ioctl,
			DRM_AUTH | DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(EXYNOS_IPP_COMMIT, exynos_drm_ipp_commit_ioctl,
			DRM_AUTH | DRM_RENDER_ALLOW),
101 102
};

J
Joonyoung Shim 已提交
103 104 105 106 107 108 109
static const struct file_operations exynos_drm_driver_fops = {
	.owner		= THIS_MODULE,
	.open		= drm_open,
	.mmap		= exynos_drm_gem_mmap,
	.poll		= drm_poll,
	.read		= drm_read,
	.unlocked_ioctl	= drm_ioctl,
110
	.compat_ioctl = drm_compat_ioctl,
J
Joonyoung Shim 已提交
111 112 113
	.release	= drm_release,
};

114
static struct drm_driver exynos_drm_driver = {
115
	.driver_features	= DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME
116
				  | DRIVER_ATOMIC | DRIVER_RENDER,
117
	.open			= exynos_drm_open,
118
	.lastclose		= drm_fb_helper_lastclose,
119
	.postclose		= exynos_drm_postclose,
120
	.gem_free_object_unlocked = exynos_drm_gem_free_object,
121 122
	.gem_vm_ops		= &exynos_drm_gem_vm_ops,
	.dumb_create		= exynos_drm_gem_dumb_create,
I
Inki Dae 已提交
123 124
	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
J
Joonyoung Shim 已提交
125
	.gem_prime_export	= drm_gem_prime_export,
M
Marek Szyprowski 已提交
126
	.gem_prime_import	= exynos_drm_gem_prime_import,
J
Joonyoung Shim 已提交
127 128 129 130
	.gem_prime_get_sg_table	= exynos_drm_gem_prime_get_sg_table,
	.gem_prime_import_sg_table	= exynos_drm_gem_prime_import_sg_table,
	.gem_prime_vmap		= exynos_drm_gem_prime_vmap,
	.gem_prime_vunmap	= exynos_drm_gem_prime_vunmap,
131
	.gem_prime_mmap		= exynos_drm_gem_prime_mmap,
132
	.ioctls			= exynos_ioctls,
R
Rob Clark 已提交
133
	.num_ioctls		= ARRAY_SIZE(exynos_ioctls),
J
Joonyoung Shim 已提交
134
	.fops			= &exynos_drm_driver_fops,
135 136 137 138 139 140 141
	.name	= DRIVER_NAME,
	.desc	= DRIVER_DESC,
	.date	= DRIVER_DATE,
	.major	= DRIVER_MAJOR,
	.minor	= DRIVER_MINOR,
};

A
Andrzej Hajda 已提交
142
static int exynos_drm_suspend(struct device *dev)
143 144 145
{
	struct drm_device *drm_dev = dev_get_drvdata(dev);

146
	return  drm_mode_config_helper_suspend(drm_dev);
147 148
}

149
static void exynos_drm_resume(struct device *dev)
150 151 152
{
	struct drm_device *drm_dev = dev_get_drvdata(dev);

153
	drm_mode_config_helper_resume(drm_dev);
154 155 156
}

static const struct dev_pm_ops exynos_drm_pm_ops = {
157 158
	.prepare = exynos_drm_suspend,
	.complete = exynos_drm_resume,
159 160
};

161 162
/* forward declaration */
static struct platform_driver exynos_drm_platform_driver;
163

164 165 166 167 168 169 170
struct exynos_drm_driver_info {
	struct platform_driver *driver;
	unsigned int flags;
};

#define DRM_COMPONENT_DRIVER	BIT(0)	/* supports component framework */
#define DRM_VIRTUAL_DEVICE	BIT(1)	/* create virtual platform device */
A
Andrzej Hajda 已提交
171
#define DRM_FIMC_DEVICE		BIT(2)	/* devices shared with V4L2 subsystem */
172 173 174

#define DRV_PTR(drv, cond) (IS_ENABLED(cond) ? &drv : NULL)

175 176 177 178
/*
 * Connector drivers should not be placed before associated crtc drivers,
 * because connector requires pipe number of its crtc during initialization.
 */
179 180 181
static struct exynos_drm_driver_info exynos_drm_drivers[] = {
	{
		DRV_PTR(fimd_driver, CONFIG_DRM_EXYNOS_FIMD),
A
Andrzej Hajda 已提交
182
		DRM_COMPONENT_DRIVER
183 184
	}, {
		DRV_PTR(exynos5433_decon_driver, CONFIG_DRM_EXYNOS5433_DECON),
A
Andrzej Hajda 已提交
185
		DRM_COMPONENT_DRIVER
186 187
	}, {
		DRV_PTR(decon_driver, CONFIG_DRM_EXYNOS7_DECON),
A
Andrzej Hajda 已提交
188
		DRM_COMPONENT_DRIVER
189 190
	}, {
		DRV_PTR(mixer_driver, CONFIG_DRM_EXYNOS_MIXER),
A
Andrzej Hajda 已提交
191
		DRM_COMPONENT_DRIVER
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
	}, {
		DRV_PTR(mic_driver, CONFIG_DRM_EXYNOS_MIC),
		DRM_COMPONENT_DRIVER
	}, {
		DRV_PTR(dp_driver, CONFIG_DRM_EXYNOS_DP),
		DRM_COMPONENT_DRIVER
	}, {
		DRV_PTR(dsi_driver, CONFIG_DRM_EXYNOS_DSI),
		DRM_COMPONENT_DRIVER
	}, {
		DRV_PTR(hdmi_driver, CONFIG_DRM_EXYNOS_HDMI),
		DRM_COMPONENT_DRIVER
	}, {
		DRV_PTR(vidi_driver, CONFIG_DRM_EXYNOS_VIDI),
		DRM_COMPONENT_DRIVER | DRM_VIRTUAL_DEVICE
	}, {
		DRV_PTR(g2d_driver, CONFIG_DRM_EXYNOS_G2D),
209
		DRM_COMPONENT_DRIVER
210 211
	}, {
		DRV_PTR(fimc_driver, CONFIG_DRM_EXYNOS_FIMC),
212
		DRM_COMPONENT_DRIVER | DRM_FIMC_DEVICE,
213 214
	}, {
		DRV_PTR(rotator_driver, CONFIG_DRM_EXYNOS_ROTATOR),
215
		DRM_COMPONENT_DRIVER
216 217 218
	}, {
		DRV_PTR(scaler_driver, CONFIG_DRM_EXYNOS_SCALER),
		DRM_COMPONENT_DRIVER
219 220
	}, {
		DRV_PTR(gsc_driver, CONFIG_DRM_EXYNOS_GSC),
221
		DRM_COMPONENT_DRIVER
222 223 224 225
	}, {
		&exynos_drm_platform_driver,
		DRM_VIRTUAL_DEVICE
	}
226
};
227

228
static int compare_dev(struct device *dev, void *data)
229 230 231 232
{
	return dev == (struct device *)data;
}

233
static struct component_match *exynos_drm_match_add(struct device *dev)
234
{
235
	struct component_match *match = NULL;
236
	int i;
237

238 239
	for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
		struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
240
		struct device *p = NULL, *d;
241

242 243 244
		if (!info->driver || !(info->flags & DRM_COMPONENT_DRIVER))
			continue;

245
		while ((d = platform_find_device_by_driver(p, &info->driver->driver))) {
246
			put_device(p);
247 248 249 250 251

			if (!(info->flags & DRM_FIMC_DEVICE) ||
			    exynos_drm_check_fimc_device(d) == 0)
				component_match_add(dev, &match,
						    compare_dev, d);
252
			p = d;
253
		}
254
		put_device(p);
255 256
	}

257
	return match ?: ERR_PTR(-ENODEV);
258 259 260 261
}

static int exynos_drm_bind(struct device *dev)
{
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
	struct exynos_drm_private *private;
	struct drm_encoder *encoder;
	struct drm_device *drm;
	unsigned int clone_mask;
	int cnt, ret;

	drm = drm_dev_alloc(&exynos_drm_driver, dev);
	if (IS_ERR(drm))
		return PTR_ERR(drm);

	private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
	if (!private) {
		ret = -ENOMEM;
		goto err_free_drm;
	}

	init_waitqueue_head(&private->wait);
	spin_lock_init(&private->lock);

	dev_set_drvdata(dev, drm);
	drm->dev_private = (void *)private;

	drm_mode_config_init(drm);

	exynos_drm_mode_config_init(drm);

	/* setup possible_clones. */
	cnt = 0;
	clone_mask = 0;
	list_for_each_entry(encoder, &drm->mode_config.encoder_list, head)
		clone_mask |= (1 << (cnt++));

	list_for_each_entry(encoder, &drm->mode_config.encoder_list, head)
		encoder->possible_clones = clone_mask;

	/* Try to bind all sub drivers. */
	ret = component_bind_all(drm->dev, drm);
	if (ret)
		goto err_mode_config_cleanup;

	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
	if (ret)
		goto err_unbind_all;

	drm_mode_config_reset(drm);

	/*
	 * enable drm irq mode.
	 * - with irq_enabled = true, we can use the vblank feature.
	 *
	 * P.S. note that we wouldn't use drm irq handler but
	 *	just specific driver own one instead because
	 *	drm framework supports only one irq handler.
	 */
	drm->irq_enabled = true;

	/* init kms poll for handling hpd */
	drm_kms_helper_poll_init(drm);

321 322 323
	ret = exynos_drm_fbdev_init(drm);
	if (ret)
		goto err_cleanup_poll;
324 325 326 327 328 329 330 331 332 333

	/* register the DRM device */
	ret = drm_dev_register(drm, 0);
	if (ret < 0)
		goto err_cleanup_fbdev;

	return 0;

err_cleanup_fbdev:
	exynos_drm_fbdev_fini(drm);
334
err_cleanup_poll:
335 336 337 338 339
	drm_kms_helper_poll_fini(drm);
err_unbind_all:
	component_unbind_all(drm->dev, drm);
err_mode_config_cleanup:
	drm_mode_config_cleanup(drm);
340
	exynos_drm_cleanup_dma(drm);
341 342
	kfree(private);
err_free_drm:
343
	drm_dev_put(drm);
344 345

	return ret;
346 347 348 349
}

static void exynos_drm_unbind(struct device *dev)
{
350 351 352 353 354 355 356 357 358
	struct drm_device *drm = dev_get_drvdata(dev);

	drm_dev_unregister(drm);

	exynos_drm_fbdev_fini(drm);
	drm_kms_helper_poll_fini(drm);

	component_unbind_all(drm->dev, drm);
	drm_mode_config_cleanup(drm);
359
	exynos_drm_cleanup_dma(drm);
360 361 362

	kfree(drm->dev_private);
	drm->dev_private = NULL;
363
	dev_set_drvdata(dev, NULL);
364

365
	drm_dev_put(drm);
366 367 368 369 370
}

static const struct component_master_ops exynos_drm_ops = {
	.bind		= exynos_drm_bind,
	.unbind		= exynos_drm_unbind,
371 372
};

373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
static int exynos_drm_platform_probe(struct platform_device *pdev)
{
	struct component_match *match;

	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);

	match = exynos_drm_match_add(&pdev->dev);
	if (IS_ERR(match))
		return PTR_ERR(match);

	return component_master_add_with_match(&pdev->dev, &exynos_drm_ops,
					       match);
}

static int exynos_drm_platform_remove(struct platform_device *pdev)
{
	component_master_del(&pdev->dev, &exynos_drm_ops);
	return 0;
}

static struct platform_driver exynos_drm_platform_driver = {
	.probe	= exynos_drm_platform_probe,
	.remove	= exynos_drm_platform_remove,
	.driver	= {
		.name	= "exynos-drm",
		.pm	= &exynos_drm_pm_ops,
	},
};

static void exynos_drm_unregister_devices(void)
403
{
404 405 406 407 408
	int i;

	for (i = ARRAY_SIZE(exynos_drm_drivers) - 1; i >= 0; --i) {
		struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
		struct device *dev;
409

410 411 412
		if (!info->driver || !(info->flags & DRM_VIRTUAL_DEVICE))
			continue;

413 414
		while ((dev = platform_find_device_by_driver(NULL,
						&info->driver->driver))) {
415 416 417
			put_device(dev);
			platform_device_unregister(to_platform_device(dev));
		}
418 419
	}
}
A
Andrzej Hajda 已提交
420

421 422
static int exynos_drm_register_devices(void)
{
423
	struct platform_device *pdev;
424 425
	int i;

426 427
	for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
		struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
428

429
		if (!info->driver || !(info->flags & DRM_VIRTUAL_DEVICE))
430 431
			continue;

432 433 434 435
		pdev = platform_device_register_simple(
					info->driver->driver.name, -1, NULL, 0);
		if (IS_ERR(pdev))
			goto fail;
436
	}
437

438
	return 0;
439 440 441
fail:
	exynos_drm_unregister_devices();
	return PTR_ERR(pdev);
442 443
}

444
static void exynos_drm_unregister_drivers(void)
445
{
446
	int i;
447

448 449
	for (i = ARRAY_SIZE(exynos_drm_drivers) - 1; i >= 0; --i) {
		struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
450

451
		if (!info->driver)
452 453
			continue;

454
		platform_driver_unregister(info->driver);
455
	}
456 457
}

458
static int exynos_drm_register_drivers(void)
459
{
460
	int i, ret;
461

462 463
	for (i = 0; i < ARRAY_SIZE(exynos_drm_drivers); ++i) {
		struct exynos_drm_driver_info *info = &exynos_drm_drivers[i];
464

465 466
		if (!info->driver)
			continue;
467

468 469 470 471 472 473 474 475
		ret = platform_driver_register(info->driver);
		if (ret)
			goto fail;
	}
	return 0;
fail:
	exynos_drm_unregister_drivers();
	return ret;
476 477
}

478 479
static int exynos_drm_init(void)
{
480
	int ret;
481

482 483 484
	ret = exynos_drm_register_devices();
	if (ret)
		return ret;
485

486
	ret = exynos_drm_register_drivers();
487 488
	if (ret)
		goto err_unregister_pdevs;
489 490 491

	return 0;

492 493
err_unregister_pdevs:
	exynos_drm_unregister_devices();
494 495 496 497 498 499

	return ret;
}

static void exynos_drm_exit(void)
{
500
	exynos_drm_unregister_drivers();
501
	exynos_drm_unregister_devices();
502 503 504 505 506 507 508 509 510 511
}

module_init(exynos_drm_init);
module_exit(exynos_drm_exit);

MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
MODULE_DESCRIPTION("Samsung SoC DRM Driver");
MODULE_LICENSE("GPL");