Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.17 215 lines 5.3 kB view raw
1/* 2 * Copyright 2016 Linaro Ltd. 3 * Copyright 2016 ZTE Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 */ 10 11#include <linux/clk.h> 12#include <linux/component.h> 13#include <linux/list.h> 14#include <linux/module.h> 15#include <linux/of_graph.h> 16#include <linux/of_platform.h> 17#include <linux/spinlock.h> 18 19#include <drm/drm_atomic_helper.h> 20#include <drm/drm_crtc.h> 21#include <drm/drm_crtc_helper.h> 22#include <drm/drm_fb_cma_helper.h> 23#include <drm/drm_fb_helper.h> 24#include <drm/drm_gem_cma_helper.h> 25#include <drm/drm_gem_framebuffer_helper.h> 26#include <drm/drm_of.h> 27#include <drm/drmP.h> 28 29#include "zx_drm_drv.h" 30#include "zx_vou.h" 31 32static const struct drm_mode_config_funcs zx_drm_mode_config_funcs = { 33 .fb_create = drm_gem_fb_create, 34 .output_poll_changed = drm_fb_helper_output_poll_changed, 35 .atomic_check = drm_atomic_helper_check, 36 .atomic_commit = drm_atomic_helper_commit, 37}; 38 39DEFINE_DRM_GEM_CMA_FOPS(zx_drm_fops); 40 41static struct drm_driver zx_drm_driver = { 42 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | 43 DRIVER_ATOMIC, 44 .lastclose = drm_fb_helper_lastclose, 45 .gem_free_object_unlocked = drm_gem_cma_free_object, 46 .gem_vm_ops = &drm_gem_cma_vm_ops, 47 .dumb_create = drm_gem_cma_dumb_create, 48 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 49 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 50 .gem_prime_export = drm_gem_prime_export, 51 .gem_prime_import = drm_gem_prime_import, 52 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, 53 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, 54 .gem_prime_vmap = drm_gem_cma_prime_vmap, 55 .gem_prime_vunmap = drm_gem_cma_prime_vunmap, 56 .gem_prime_mmap = drm_gem_cma_prime_mmap, 57 .fops = &zx_drm_fops, 58 .name = "zx-vou", 59 .desc = "ZTE VOU Controller DRM", 60 .date = "20160811", 61 .major = 1, 62 .minor = 0, 63}; 64 65static int zx_drm_bind(struct device *dev) 66{ 67 struct drm_device *drm; 68 int ret; 69 70 drm = drm_dev_alloc(&zx_drm_driver, dev); 71 if (IS_ERR(drm)) 72 return PTR_ERR(drm); 73 74 dev_set_drvdata(dev, drm); 75 76 drm_mode_config_init(drm); 77 drm->mode_config.min_width = 16; 78 drm->mode_config.min_height = 16; 79 drm->mode_config.max_width = 4096; 80 drm->mode_config.max_height = 4096; 81 drm->mode_config.funcs = &zx_drm_mode_config_funcs; 82 83 ret = component_bind_all(dev, drm); 84 if (ret) { 85 DRM_DEV_ERROR(dev, "failed to bind all components: %d\n", ret); 86 goto out_unregister; 87 } 88 89 ret = drm_vblank_init(drm, drm->mode_config.num_crtc); 90 if (ret < 0) { 91 DRM_DEV_ERROR(dev, "failed to init vblank: %d\n", ret); 92 goto out_unbind; 93 } 94 95 /* 96 * We will manage irq handler on our own. In this case, irq_enabled 97 * need to be true for using vblank core support. 98 */ 99 drm->irq_enabled = true; 100 101 drm_mode_config_reset(drm); 102 drm_kms_helper_poll_init(drm); 103 104 ret = drm_fb_cma_fbdev_init(drm, 32, 0); 105 if (ret) { 106 DRM_DEV_ERROR(dev, "failed to init cma fbdev: %d\n", ret); 107 goto out_poll_fini; 108 } 109 110 ret = drm_dev_register(drm, 0); 111 if (ret) 112 goto out_fbdev_fini; 113 114 return 0; 115 116out_fbdev_fini: 117 drm_fb_cma_fbdev_fini(drm); 118out_poll_fini: 119 drm_kms_helper_poll_fini(drm); 120 drm_mode_config_cleanup(drm); 121out_unbind: 122 component_unbind_all(dev, drm); 123out_unregister: 124 dev_set_drvdata(dev, NULL); 125 drm_dev_unref(drm); 126 return ret; 127} 128 129static void zx_drm_unbind(struct device *dev) 130{ 131 struct drm_device *drm = dev_get_drvdata(dev); 132 133 drm_dev_unregister(drm); 134 drm_fb_cma_fbdev_fini(drm); 135 drm_kms_helper_poll_fini(drm); 136 drm_mode_config_cleanup(drm); 137 component_unbind_all(dev, drm); 138 dev_set_drvdata(dev, NULL); 139 drm_dev_unref(drm); 140} 141 142static const struct component_master_ops zx_drm_master_ops = { 143 .bind = zx_drm_bind, 144 .unbind = zx_drm_unbind, 145}; 146 147static int compare_of(struct device *dev, void *data) 148{ 149 return dev->of_node == data; 150} 151 152static int zx_drm_probe(struct platform_device *pdev) 153{ 154 struct device *dev = &pdev->dev; 155 struct device_node *parent = dev->of_node; 156 struct device_node *child; 157 struct component_match *match = NULL; 158 int ret; 159 160 ret = devm_of_platform_populate(dev); 161 if (ret) 162 return ret; 163 164 for_each_available_child_of_node(parent, child) { 165 component_match_add(dev, &match, compare_of, child); 166 of_node_put(child); 167 } 168 169 return component_master_add_with_match(dev, &zx_drm_master_ops, match); 170} 171 172static int zx_drm_remove(struct platform_device *pdev) 173{ 174 component_master_del(&pdev->dev, &zx_drm_master_ops); 175 return 0; 176} 177 178static const struct of_device_id zx_drm_of_match[] = { 179 { .compatible = "zte,zx296718-vou", }, 180 { /* end */ }, 181}; 182MODULE_DEVICE_TABLE(of, zx_drm_of_match); 183 184static struct platform_driver zx_drm_platform_driver = { 185 .probe = zx_drm_probe, 186 .remove = zx_drm_remove, 187 .driver = { 188 .name = "zx-drm", 189 .of_match_table = zx_drm_of_match, 190 }, 191}; 192 193static struct platform_driver *drivers[] = { 194 &zx_crtc_driver, 195 &zx_hdmi_driver, 196 &zx_tvenc_driver, 197 &zx_vga_driver, 198 &zx_drm_platform_driver, 199}; 200 201static int zx_drm_init(void) 202{ 203 return platform_register_drivers(drivers, ARRAY_SIZE(drivers)); 204} 205module_init(zx_drm_init); 206 207static void zx_drm_exit(void) 208{ 209 platform_unregister_drivers(drivers, ARRAY_SIZE(drivers)); 210} 211module_exit(zx_drm_exit); 212 213MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>"); 214MODULE_DESCRIPTION("ZTE ZX VOU DRM driver"); 215MODULE_LICENSE("GPL v2");