18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * rcar_du_drv.c -- R-Car Display Unit DRM driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2013-2015 Renesas Electronics Corporation 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/clk.h> 118c2ecf20Sopenharmony_ci#include <linux/io.h> 128c2ecf20Sopenharmony_ci#include <linux/mm.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/of_device.h> 158c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 168c2ecf20Sopenharmony_ci#include <linux/pm.h> 178c2ecf20Sopenharmony_ci#include <linux/slab.h> 188c2ecf20Sopenharmony_ci#include <linux/wait.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include <drm/drm_atomic_helper.h> 218c2ecf20Sopenharmony_ci#include <drm/drm_fb_cma_helper.h> 228c2ecf20Sopenharmony_ci#include <drm/drm_fb_helper.h> 238c2ecf20Sopenharmony_ci#include <drm/drm_drv.h> 248c2ecf20Sopenharmony_ci#include <drm/drm_gem_cma_helper.h> 258c2ecf20Sopenharmony_ci#include <drm/drm_probe_helper.h> 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#include "rcar_du_drv.h" 288c2ecf20Sopenharmony_ci#include "rcar_du_kms.h" 298c2ecf20Sopenharmony_ci#include "rcar_du_of.h" 308c2ecf20Sopenharmony_ci#include "rcar_du_regs.h" 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------- 338c2ecf20Sopenharmony_ci * Device Information 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rzg1_du_r8a7743_info = { 378c2ecf20Sopenharmony_ci .gen = 2, 388c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 398c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_INTERLACED 408c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 418c2ecf20Sopenharmony_ci .channels_mask = BIT(1) | BIT(0), 428c2ecf20Sopenharmony_ci .routes = { 438c2ecf20Sopenharmony_ci /* 448c2ecf20Sopenharmony_ci * R8A774[34] has one RGB output and one LVDS output 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 478c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1) | BIT(0), 488c2ecf20Sopenharmony_ci .port = 0, 498c2ecf20Sopenharmony_ci }, 508c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS0] = { 518c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 528c2ecf20Sopenharmony_ci .port = 1, 538c2ecf20Sopenharmony_ci }, 548c2ecf20Sopenharmony_ci }, 558c2ecf20Sopenharmony_ci .num_lvds = 1, 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rzg1_du_r8a7745_info = { 598c2ecf20Sopenharmony_ci .gen = 2, 608c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 618c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_INTERLACED 628c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 638c2ecf20Sopenharmony_ci .channels_mask = BIT(1) | BIT(0), 648c2ecf20Sopenharmony_ci .routes = { 658c2ecf20Sopenharmony_ci /* 668c2ecf20Sopenharmony_ci * R8A7745 has two RGB outputs 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 698c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 708c2ecf20Sopenharmony_ci .port = 0, 718c2ecf20Sopenharmony_ci }, 728c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD1] = { 738c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1), 748c2ecf20Sopenharmony_ci .port = 1, 758c2ecf20Sopenharmony_ci }, 768c2ecf20Sopenharmony_ci }, 778c2ecf20Sopenharmony_ci}; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rzg1_du_r8a77470_info = { 808c2ecf20Sopenharmony_ci .gen = 2, 818c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 828c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_INTERLACED 838c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 848c2ecf20Sopenharmony_ci .channels_mask = BIT(1) | BIT(0), 858c2ecf20Sopenharmony_ci .routes = { 868c2ecf20Sopenharmony_ci /* 878c2ecf20Sopenharmony_ci * R8A77470 has two RGB outputs, one LVDS output, and 888c2ecf20Sopenharmony_ci * one (currently unsupported) analog video output 898c2ecf20Sopenharmony_ci */ 908c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 918c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 928c2ecf20Sopenharmony_ci .port = 0, 938c2ecf20Sopenharmony_ci }, 948c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD1] = { 958c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1), 968c2ecf20Sopenharmony_ci .port = 1, 978c2ecf20Sopenharmony_ci }, 988c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS0] = { 998c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0) | BIT(1), 1008c2ecf20Sopenharmony_ci .port = 2, 1018c2ecf20Sopenharmony_ci }, 1028c2ecf20Sopenharmony_ci }, 1038c2ecf20Sopenharmony_ci}; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rcar_du_r8a774a1_info = { 1068c2ecf20Sopenharmony_ci .gen = 3, 1078c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 1088c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_VSP1_SOURCE 1098c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_INTERLACED 1108c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 1118c2ecf20Sopenharmony_ci .channels_mask = BIT(2) | BIT(1) | BIT(0), 1128c2ecf20Sopenharmony_ci .routes = { 1138c2ecf20Sopenharmony_ci /* 1148c2ecf20Sopenharmony_ci * R8A774A1 has one RGB output, one LVDS output and one HDMI 1158c2ecf20Sopenharmony_ci * output. 1168c2ecf20Sopenharmony_ci */ 1178c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 1188c2ecf20Sopenharmony_ci .possible_crtcs = BIT(2), 1198c2ecf20Sopenharmony_ci .port = 0, 1208c2ecf20Sopenharmony_ci }, 1218c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_HDMI0] = { 1228c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1), 1238c2ecf20Sopenharmony_ci .port = 1, 1248c2ecf20Sopenharmony_ci }, 1258c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS0] = { 1268c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 1278c2ecf20Sopenharmony_ci .port = 2, 1288c2ecf20Sopenharmony_ci }, 1298c2ecf20Sopenharmony_ci }, 1308c2ecf20Sopenharmony_ci .num_lvds = 1, 1318c2ecf20Sopenharmony_ci .dpll_mask = BIT(1), 1328c2ecf20Sopenharmony_ci}; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rcar_du_r8a774b1_info = { 1358c2ecf20Sopenharmony_ci .gen = 3, 1368c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 1378c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_VSP1_SOURCE 1388c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_INTERLACED 1398c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 1408c2ecf20Sopenharmony_ci .channels_mask = BIT(3) | BIT(1) | BIT(0), 1418c2ecf20Sopenharmony_ci .routes = { 1428c2ecf20Sopenharmony_ci /* 1438c2ecf20Sopenharmony_ci * R8A774B1 has one RGB output, one LVDS output and one HDMI 1448c2ecf20Sopenharmony_ci * output. 1458c2ecf20Sopenharmony_ci */ 1468c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 1478c2ecf20Sopenharmony_ci .possible_crtcs = BIT(2), 1488c2ecf20Sopenharmony_ci .port = 0, 1498c2ecf20Sopenharmony_ci }, 1508c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_HDMI0] = { 1518c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1), 1528c2ecf20Sopenharmony_ci .port = 1, 1538c2ecf20Sopenharmony_ci }, 1548c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS0] = { 1558c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 1568c2ecf20Sopenharmony_ci .port = 2, 1578c2ecf20Sopenharmony_ci }, 1588c2ecf20Sopenharmony_ci }, 1598c2ecf20Sopenharmony_ci .num_lvds = 1, 1608c2ecf20Sopenharmony_ci .dpll_mask = BIT(1), 1618c2ecf20Sopenharmony_ci}; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rcar_du_r8a774c0_info = { 1648c2ecf20Sopenharmony_ci .gen = 3, 1658c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 1668c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_VSP1_SOURCE, 1678c2ecf20Sopenharmony_ci .channels_mask = BIT(1) | BIT(0), 1688c2ecf20Sopenharmony_ci .routes = { 1698c2ecf20Sopenharmony_ci /* 1708c2ecf20Sopenharmony_ci * R8A774C0 has one RGB output and two LVDS outputs 1718c2ecf20Sopenharmony_ci */ 1728c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 1738c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0) | BIT(1), 1748c2ecf20Sopenharmony_ci .port = 0, 1758c2ecf20Sopenharmony_ci }, 1768c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS0] = { 1778c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 1788c2ecf20Sopenharmony_ci .port = 1, 1798c2ecf20Sopenharmony_ci }, 1808c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS1] = { 1818c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1), 1828c2ecf20Sopenharmony_ci .port = 2, 1838c2ecf20Sopenharmony_ci }, 1848c2ecf20Sopenharmony_ci }, 1858c2ecf20Sopenharmony_ci .num_lvds = 2, 1868c2ecf20Sopenharmony_ci .lvds_clk_mask = BIT(1) | BIT(0), 1878c2ecf20Sopenharmony_ci}; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rcar_du_r8a774e1_info = { 1908c2ecf20Sopenharmony_ci .gen = 3, 1918c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 1928c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_VSP1_SOURCE 1938c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_INTERLACED 1948c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 1958c2ecf20Sopenharmony_ci .channels_mask = BIT(3) | BIT(1) | BIT(0), 1968c2ecf20Sopenharmony_ci .routes = { 1978c2ecf20Sopenharmony_ci /* 1988c2ecf20Sopenharmony_ci * R8A774E1 has one RGB output, one LVDS output and one HDMI 1998c2ecf20Sopenharmony_ci * output. 2008c2ecf20Sopenharmony_ci */ 2018c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 2028c2ecf20Sopenharmony_ci .possible_crtcs = BIT(2), 2038c2ecf20Sopenharmony_ci .port = 0, 2048c2ecf20Sopenharmony_ci }, 2058c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_HDMI0] = { 2068c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1), 2078c2ecf20Sopenharmony_ci .port = 1, 2088c2ecf20Sopenharmony_ci }, 2098c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS0] = { 2108c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 2118c2ecf20Sopenharmony_ci .port = 2, 2128c2ecf20Sopenharmony_ci }, 2138c2ecf20Sopenharmony_ci }, 2148c2ecf20Sopenharmony_ci .num_lvds = 1, 2158c2ecf20Sopenharmony_ci .dpll_mask = BIT(1), 2168c2ecf20Sopenharmony_ci}; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rcar_du_r8a7779_info = { 2198c2ecf20Sopenharmony_ci .gen = 1, 2208c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_INTERLACED 2218c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 2228c2ecf20Sopenharmony_ci .channels_mask = BIT(1) | BIT(0), 2238c2ecf20Sopenharmony_ci .routes = { 2248c2ecf20Sopenharmony_ci /* 2258c2ecf20Sopenharmony_ci * R8A7779 has two RGB outputs and one (currently unsupported) 2268c2ecf20Sopenharmony_ci * TCON output. 2278c2ecf20Sopenharmony_ci */ 2288c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 2298c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 2308c2ecf20Sopenharmony_ci .port = 0, 2318c2ecf20Sopenharmony_ci }, 2328c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD1] = { 2338c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1) | BIT(0), 2348c2ecf20Sopenharmony_ci .port = 1, 2358c2ecf20Sopenharmony_ci }, 2368c2ecf20Sopenharmony_ci }, 2378c2ecf20Sopenharmony_ci}; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rcar_du_r8a7790_info = { 2408c2ecf20Sopenharmony_ci .gen = 2, 2418c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 2428c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_INTERLACED 2438c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 2448c2ecf20Sopenharmony_ci .quirks = RCAR_DU_QUIRK_ALIGN_128B, 2458c2ecf20Sopenharmony_ci .channels_mask = BIT(2) | BIT(1) | BIT(0), 2468c2ecf20Sopenharmony_ci .routes = { 2478c2ecf20Sopenharmony_ci /* 2488c2ecf20Sopenharmony_ci * R8A7742 and R8A7790 each have one RGB output and two LVDS 2498c2ecf20Sopenharmony_ci * outputs. Additionally R8A7790 supports one TCON output 2508c2ecf20Sopenharmony_ci * (currently unsupported by the driver). 2518c2ecf20Sopenharmony_ci */ 2528c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 2538c2ecf20Sopenharmony_ci .possible_crtcs = BIT(2) | BIT(1) | BIT(0), 2548c2ecf20Sopenharmony_ci .port = 0, 2558c2ecf20Sopenharmony_ci }, 2568c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS0] = { 2578c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 2588c2ecf20Sopenharmony_ci .port = 1, 2598c2ecf20Sopenharmony_ci }, 2608c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS1] = { 2618c2ecf20Sopenharmony_ci .possible_crtcs = BIT(2) | BIT(1), 2628c2ecf20Sopenharmony_ci .port = 2, 2638c2ecf20Sopenharmony_ci }, 2648c2ecf20Sopenharmony_ci }, 2658c2ecf20Sopenharmony_ci .num_lvds = 2, 2668c2ecf20Sopenharmony_ci}; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci/* M2-W (r8a7791) and M2-N (r8a7793) are identical */ 2698c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rcar_du_r8a7791_info = { 2708c2ecf20Sopenharmony_ci .gen = 2, 2718c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 2728c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_INTERLACED 2738c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 2748c2ecf20Sopenharmony_ci .channels_mask = BIT(1) | BIT(0), 2758c2ecf20Sopenharmony_ci .routes = { 2768c2ecf20Sopenharmony_ci /* 2778c2ecf20Sopenharmony_ci * R8A779[13] has one RGB output, one LVDS output and one 2788c2ecf20Sopenharmony_ci * (currently unsupported) TCON output. 2798c2ecf20Sopenharmony_ci */ 2808c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 2818c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1) | BIT(0), 2828c2ecf20Sopenharmony_ci .port = 0, 2838c2ecf20Sopenharmony_ci }, 2848c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS0] = { 2858c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 2868c2ecf20Sopenharmony_ci .port = 1, 2878c2ecf20Sopenharmony_ci }, 2888c2ecf20Sopenharmony_ci }, 2898c2ecf20Sopenharmony_ci .num_lvds = 1, 2908c2ecf20Sopenharmony_ci}; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rcar_du_r8a7792_info = { 2938c2ecf20Sopenharmony_ci .gen = 2, 2948c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 2958c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_INTERLACED 2968c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 2978c2ecf20Sopenharmony_ci .channels_mask = BIT(1) | BIT(0), 2988c2ecf20Sopenharmony_ci .routes = { 2998c2ecf20Sopenharmony_ci /* R8A7792 has two RGB outputs. */ 3008c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 3018c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 3028c2ecf20Sopenharmony_ci .port = 0, 3038c2ecf20Sopenharmony_ci }, 3048c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD1] = { 3058c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1), 3068c2ecf20Sopenharmony_ci .port = 1, 3078c2ecf20Sopenharmony_ci }, 3088c2ecf20Sopenharmony_ci }, 3098c2ecf20Sopenharmony_ci}; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rcar_du_r8a7794_info = { 3128c2ecf20Sopenharmony_ci .gen = 2, 3138c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 3148c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_INTERLACED 3158c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 3168c2ecf20Sopenharmony_ci .channels_mask = BIT(1) | BIT(0), 3178c2ecf20Sopenharmony_ci .routes = { 3188c2ecf20Sopenharmony_ci /* 3198c2ecf20Sopenharmony_ci * R8A7794 has two RGB outputs and one (currently unsupported) 3208c2ecf20Sopenharmony_ci * TCON output. 3218c2ecf20Sopenharmony_ci */ 3228c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 3238c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 3248c2ecf20Sopenharmony_ci .port = 0, 3258c2ecf20Sopenharmony_ci }, 3268c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD1] = { 3278c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1), 3288c2ecf20Sopenharmony_ci .port = 1, 3298c2ecf20Sopenharmony_ci }, 3308c2ecf20Sopenharmony_ci }, 3318c2ecf20Sopenharmony_ci}; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rcar_du_r8a7795_info = { 3348c2ecf20Sopenharmony_ci .gen = 3, 3358c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 3368c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_VSP1_SOURCE 3378c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_INTERLACED 3388c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 3398c2ecf20Sopenharmony_ci .channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0), 3408c2ecf20Sopenharmony_ci .routes = { 3418c2ecf20Sopenharmony_ci /* 3428c2ecf20Sopenharmony_ci * R8A7795 has one RGB output, two HDMI outputs and one 3438c2ecf20Sopenharmony_ci * LVDS output. 3448c2ecf20Sopenharmony_ci */ 3458c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 3468c2ecf20Sopenharmony_ci .possible_crtcs = BIT(3), 3478c2ecf20Sopenharmony_ci .port = 0, 3488c2ecf20Sopenharmony_ci }, 3498c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_HDMI0] = { 3508c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1), 3518c2ecf20Sopenharmony_ci .port = 1, 3528c2ecf20Sopenharmony_ci }, 3538c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_HDMI1] = { 3548c2ecf20Sopenharmony_ci .possible_crtcs = BIT(2), 3558c2ecf20Sopenharmony_ci .port = 2, 3568c2ecf20Sopenharmony_ci }, 3578c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS0] = { 3588c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 3598c2ecf20Sopenharmony_ci .port = 3, 3608c2ecf20Sopenharmony_ci }, 3618c2ecf20Sopenharmony_ci }, 3628c2ecf20Sopenharmony_ci .num_lvds = 1, 3638c2ecf20Sopenharmony_ci .dpll_mask = BIT(2) | BIT(1), 3648c2ecf20Sopenharmony_ci}; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rcar_du_r8a7796_info = { 3678c2ecf20Sopenharmony_ci .gen = 3, 3688c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 3698c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_VSP1_SOURCE 3708c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_INTERLACED 3718c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 3728c2ecf20Sopenharmony_ci .channels_mask = BIT(2) | BIT(1) | BIT(0), 3738c2ecf20Sopenharmony_ci .routes = { 3748c2ecf20Sopenharmony_ci /* 3758c2ecf20Sopenharmony_ci * R8A7796 has one RGB output, one LVDS output and one HDMI 3768c2ecf20Sopenharmony_ci * output. 3778c2ecf20Sopenharmony_ci */ 3788c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 3798c2ecf20Sopenharmony_ci .possible_crtcs = BIT(2), 3808c2ecf20Sopenharmony_ci .port = 0, 3818c2ecf20Sopenharmony_ci }, 3828c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_HDMI0] = { 3838c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1), 3848c2ecf20Sopenharmony_ci .port = 1, 3858c2ecf20Sopenharmony_ci }, 3868c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS0] = { 3878c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 3888c2ecf20Sopenharmony_ci .port = 2, 3898c2ecf20Sopenharmony_ci }, 3908c2ecf20Sopenharmony_ci }, 3918c2ecf20Sopenharmony_ci .num_lvds = 1, 3928c2ecf20Sopenharmony_ci .dpll_mask = BIT(1), 3938c2ecf20Sopenharmony_ci}; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rcar_du_r8a77965_info = { 3968c2ecf20Sopenharmony_ci .gen = 3, 3978c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 3988c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_VSP1_SOURCE 3998c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_INTERLACED 4008c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 4018c2ecf20Sopenharmony_ci .channels_mask = BIT(3) | BIT(1) | BIT(0), 4028c2ecf20Sopenharmony_ci .routes = { 4038c2ecf20Sopenharmony_ci /* 4048c2ecf20Sopenharmony_ci * R8A77965 has one RGB output, one LVDS output and one HDMI 4058c2ecf20Sopenharmony_ci * output. 4068c2ecf20Sopenharmony_ci */ 4078c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 4088c2ecf20Sopenharmony_ci .possible_crtcs = BIT(2), 4098c2ecf20Sopenharmony_ci .port = 0, 4108c2ecf20Sopenharmony_ci }, 4118c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_HDMI0] = { 4128c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1), 4138c2ecf20Sopenharmony_ci .port = 1, 4148c2ecf20Sopenharmony_ci }, 4158c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS0] = { 4168c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 4178c2ecf20Sopenharmony_ci .port = 2, 4188c2ecf20Sopenharmony_ci }, 4198c2ecf20Sopenharmony_ci }, 4208c2ecf20Sopenharmony_ci .num_lvds = 1, 4218c2ecf20Sopenharmony_ci .dpll_mask = BIT(1), 4228c2ecf20Sopenharmony_ci}; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rcar_du_r8a77970_info = { 4258c2ecf20Sopenharmony_ci .gen = 3, 4268c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 4278c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_VSP1_SOURCE 4288c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_INTERLACED 4298c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_TVM_SYNC, 4308c2ecf20Sopenharmony_ci .channels_mask = BIT(0), 4318c2ecf20Sopenharmony_ci .routes = { 4328c2ecf20Sopenharmony_ci /* 4338c2ecf20Sopenharmony_ci * R8A77970 and R8A77980 have one RGB output and one LVDS 4348c2ecf20Sopenharmony_ci * output. 4358c2ecf20Sopenharmony_ci */ 4368c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 4378c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 4388c2ecf20Sopenharmony_ci .port = 0, 4398c2ecf20Sopenharmony_ci }, 4408c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS0] = { 4418c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 4428c2ecf20Sopenharmony_ci .port = 1, 4438c2ecf20Sopenharmony_ci }, 4448c2ecf20Sopenharmony_ci }, 4458c2ecf20Sopenharmony_ci .num_lvds = 1, 4468c2ecf20Sopenharmony_ci}; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_cistatic const struct rcar_du_device_info rcar_du_r8a7799x_info = { 4498c2ecf20Sopenharmony_ci .gen = 3, 4508c2ecf20Sopenharmony_ci .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 4518c2ecf20Sopenharmony_ci | RCAR_DU_FEATURE_VSP1_SOURCE, 4528c2ecf20Sopenharmony_ci .channels_mask = BIT(1) | BIT(0), 4538c2ecf20Sopenharmony_ci .routes = { 4548c2ecf20Sopenharmony_ci /* 4558c2ecf20Sopenharmony_ci * R8A77990 and R8A77995 have one RGB output and two LVDS 4568c2ecf20Sopenharmony_ci * outputs. 4578c2ecf20Sopenharmony_ci */ 4588c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_DPAD0] = { 4598c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0) | BIT(1), 4608c2ecf20Sopenharmony_ci .port = 0, 4618c2ecf20Sopenharmony_ci }, 4628c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS0] = { 4638c2ecf20Sopenharmony_ci .possible_crtcs = BIT(0), 4648c2ecf20Sopenharmony_ci .port = 1, 4658c2ecf20Sopenharmony_ci }, 4668c2ecf20Sopenharmony_ci [RCAR_DU_OUTPUT_LVDS1] = { 4678c2ecf20Sopenharmony_ci .possible_crtcs = BIT(1), 4688c2ecf20Sopenharmony_ci .port = 2, 4698c2ecf20Sopenharmony_ci }, 4708c2ecf20Sopenharmony_ci }, 4718c2ecf20Sopenharmony_ci .num_lvds = 2, 4728c2ecf20Sopenharmony_ci .lvds_clk_mask = BIT(1) | BIT(0), 4738c2ecf20Sopenharmony_ci}; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic const struct of_device_id rcar_du_of_table[] = { 4768c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a7742", .data = &rcar_du_r8a7790_info }, 4778c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a7743", .data = &rzg1_du_r8a7743_info }, 4788c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a7744", .data = &rzg1_du_r8a7743_info }, 4798c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a7745", .data = &rzg1_du_r8a7745_info }, 4808c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a77470", .data = &rzg1_du_r8a77470_info }, 4818c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a774a1", .data = &rcar_du_r8a774a1_info }, 4828c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a774b1", .data = &rcar_du_r8a774b1_info }, 4838c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a774c0", .data = &rcar_du_r8a774c0_info }, 4848c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a774e1", .data = &rcar_du_r8a774e1_info }, 4858c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info }, 4868c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info }, 4878c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info }, 4888c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a7792", .data = &rcar_du_r8a7792_info }, 4898c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info }, 4908c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info }, 4918c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info }, 4928c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info }, 4938c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a77961", .data = &rcar_du_r8a7796_info }, 4948c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info }, 4958c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info }, 4968c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a77980", .data = &rcar_du_r8a77970_info }, 4978c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a77990", .data = &rcar_du_r8a7799x_info }, 4988c2ecf20Sopenharmony_ci { .compatible = "renesas,du-r8a77995", .data = &rcar_du_r8a7799x_info }, 4998c2ecf20Sopenharmony_ci { } 5008c2ecf20Sopenharmony_ci}; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, rcar_du_of_table); 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------- 5058c2ecf20Sopenharmony_ci * DRM operations 5068c2ecf20Sopenharmony_ci */ 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ciDEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops); 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_cistatic struct drm_driver rcar_du_driver = { 5118c2ecf20Sopenharmony_ci .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, 5128c2ecf20Sopenharmony_ci DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(rcar_du_dumb_create), 5138c2ecf20Sopenharmony_ci .fops = &rcar_du_fops, 5148c2ecf20Sopenharmony_ci .name = "rcar-du", 5158c2ecf20Sopenharmony_ci .desc = "Renesas R-Car Display Unit", 5168c2ecf20Sopenharmony_ci .date = "20130110", 5178c2ecf20Sopenharmony_ci .major = 1, 5188c2ecf20Sopenharmony_ci .minor = 0, 5198c2ecf20Sopenharmony_ci}; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------- 5228c2ecf20Sopenharmony_ci * Power management 5238c2ecf20Sopenharmony_ci */ 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 5268c2ecf20Sopenharmony_cistatic int rcar_du_pm_suspend(struct device *dev) 5278c2ecf20Sopenharmony_ci{ 5288c2ecf20Sopenharmony_ci struct rcar_du_device *rcdu = dev_get_drvdata(dev); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci return drm_mode_config_helper_suspend(rcdu->ddev); 5318c2ecf20Sopenharmony_ci} 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_cistatic int rcar_du_pm_resume(struct device *dev) 5348c2ecf20Sopenharmony_ci{ 5358c2ecf20Sopenharmony_ci struct rcar_du_device *rcdu = dev_get_drvdata(dev); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci return drm_mode_config_helper_resume(rcdu->ddev); 5388c2ecf20Sopenharmony_ci} 5398c2ecf20Sopenharmony_ci#endif 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_cistatic const struct dev_pm_ops rcar_du_pm_ops = { 5428c2ecf20Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(rcar_du_pm_suspend, rcar_du_pm_resume) 5438c2ecf20Sopenharmony_ci}; 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------- 5468c2ecf20Sopenharmony_ci * Platform driver 5478c2ecf20Sopenharmony_ci */ 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_cistatic int rcar_du_remove(struct platform_device *pdev) 5508c2ecf20Sopenharmony_ci{ 5518c2ecf20Sopenharmony_ci struct rcar_du_device *rcdu = platform_get_drvdata(pdev); 5528c2ecf20Sopenharmony_ci struct drm_device *ddev = rcdu->ddev; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci drm_dev_unregister(ddev); 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci drm_kms_helper_poll_fini(ddev); 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci drm_dev_put(ddev); 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci return 0; 5618c2ecf20Sopenharmony_ci} 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_cistatic int rcar_du_probe(struct platform_device *pdev) 5648c2ecf20Sopenharmony_ci{ 5658c2ecf20Sopenharmony_ci struct rcar_du_device *rcdu; 5668c2ecf20Sopenharmony_ci struct drm_device *ddev; 5678c2ecf20Sopenharmony_ci struct resource *mem; 5688c2ecf20Sopenharmony_ci int ret; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci /* Allocate and initialize the R-Car device structure. */ 5718c2ecf20Sopenharmony_ci rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL); 5728c2ecf20Sopenharmony_ci if (rcdu == NULL) 5738c2ecf20Sopenharmony_ci return -ENOMEM; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci rcdu->dev = &pdev->dev; 5768c2ecf20Sopenharmony_ci rcdu->info = of_device_get_match_data(rcdu->dev); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, rcdu); 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci /* I/O resources */ 5818c2ecf20Sopenharmony_ci mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 5828c2ecf20Sopenharmony_ci rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem); 5838c2ecf20Sopenharmony_ci if (IS_ERR(rcdu->mmio)) 5848c2ecf20Sopenharmony_ci return PTR_ERR(rcdu->mmio); 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci /* DRM/KMS objects */ 5878c2ecf20Sopenharmony_ci ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev); 5888c2ecf20Sopenharmony_ci if (IS_ERR(ddev)) 5898c2ecf20Sopenharmony_ci return PTR_ERR(ddev); 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci rcdu->ddev = ddev; 5928c2ecf20Sopenharmony_ci ddev->dev_private = rcdu; 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci ret = rcar_du_modeset_init(rcdu); 5958c2ecf20Sopenharmony_ci if (ret < 0) { 5968c2ecf20Sopenharmony_ci if (ret != -EPROBE_DEFER) 5978c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 5988c2ecf20Sopenharmony_ci "failed to initialize DRM/KMS (%d)\n", ret); 5998c2ecf20Sopenharmony_ci goto error; 6008c2ecf20Sopenharmony_ci } 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci ddev->irq_enabled = 1; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci /* 6058c2ecf20Sopenharmony_ci * Register the DRM device with the core and the connectors with 6068c2ecf20Sopenharmony_ci * sysfs. 6078c2ecf20Sopenharmony_ci */ 6088c2ecf20Sopenharmony_ci ret = drm_dev_register(ddev, 0); 6098c2ecf20Sopenharmony_ci if (ret) 6108c2ecf20Sopenharmony_ci goto error; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci DRM_INFO("Device %s probed\n", dev_name(&pdev->dev)); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci drm_fbdev_generic_setup(ddev, 32); 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci return 0; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_cierror: 6198c2ecf20Sopenharmony_ci rcar_du_remove(pdev); 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci return ret; 6228c2ecf20Sopenharmony_ci} 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_cistatic struct platform_driver rcar_du_platform_driver = { 6258c2ecf20Sopenharmony_ci .probe = rcar_du_probe, 6268c2ecf20Sopenharmony_ci .remove = rcar_du_remove, 6278c2ecf20Sopenharmony_ci .driver = { 6288c2ecf20Sopenharmony_ci .name = "rcar-du", 6298c2ecf20Sopenharmony_ci .pm = &rcar_du_pm_ops, 6308c2ecf20Sopenharmony_ci .of_match_table = rcar_du_of_table, 6318c2ecf20Sopenharmony_ci }, 6328c2ecf20Sopenharmony_ci}; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_cistatic int __init rcar_du_init(void) 6358c2ecf20Sopenharmony_ci{ 6368c2ecf20Sopenharmony_ci rcar_du_of_init(rcar_du_of_table); 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci return platform_driver_register(&rcar_du_platform_driver); 6398c2ecf20Sopenharmony_ci} 6408c2ecf20Sopenharmony_cimodule_init(rcar_du_init); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_cistatic void __exit rcar_du_exit(void) 6438c2ecf20Sopenharmony_ci{ 6448c2ecf20Sopenharmony_ci platform_driver_unregister(&rcar_du_platform_driver); 6458c2ecf20Sopenharmony_ci} 6468c2ecf20Sopenharmony_cimodule_exit(rcar_du_exit); 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ciMODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); 6498c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Renesas R-Car Display Unit DRM Driver"); 6508c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 651