1 /* 2 * Hisilicon Kirin SoCs drm master driver 3 * 4 * Copyright (c) 2016 Linaro Limited. 5 * Copyright (c) 2014-2016 Hisilicon Limited. 6 * 7 * Author: 8 * Xinliang Liu <z.liuxinliang@hisilicon.com> 9 * Xinliang Liu <xinliang.liu@linaro.org> 10 * Xinwei Kong <kong.kongxinwei@hisilicon.com> 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License version 2 as 14 * published by the Free Software Foundation. 15 * 16 */ 17 18 #include <linux/of_platform.h> 19 #include <linux/component.h> 20 #include <linux/of_graph.h> 21 22 #include <drm/drmP.h> 23 #include <drm/drm_gem_cma_helper.h> 24 #include <drm/drm_fb_cma_helper.h> 25 #include <drm/drm_atomic_helper.h> 26 #include <drm/drm_crtc_helper.h> 27 #include <drm/drm_of.h> 28 29 #include "kirin_drm_drv.h" 30 31 static struct kirin_dc_ops *dc_ops; 32 33 static int kirin_drm_kms_cleanup(struct drm_device *dev) 34 { 35 struct kirin_drm_private *priv = dev->dev_private; 36 37 #ifdef CONFIG_DRM_FBDEV_EMULATION 38 if (priv->fbdev) { 39 drm_fbdev_cma_fini(priv->fbdev); 40 priv->fbdev = NULL; 41 } 42 #endif 43 drm_kms_helper_poll_fini(dev); 44 drm_vblank_cleanup(dev); 45 dc_ops->cleanup(dev); 46 drm_mode_config_cleanup(dev); 47 devm_kfree(dev->dev, priv); 48 dev->dev_private = NULL; 49 50 return 0; 51 } 52 53 #ifdef CONFIG_DRM_FBDEV_EMULATION 54 static void kirin_fbdev_output_poll_changed(struct drm_device *dev) 55 { 56 struct kirin_drm_private *priv = dev->dev_private; 57 58 if (priv->fbdev) { 59 drm_fbdev_cma_hotplug_event(priv->fbdev); 60 } else { 61 priv->fbdev = drm_fbdev_cma_init(dev, 32, 62 dev->mode_config.num_crtc, 63 dev->mode_config.num_connector); 64 if (IS_ERR(priv->fbdev)) 65 priv->fbdev = NULL; 66 } 67 } 68 #endif 69 70 static const struct drm_mode_config_funcs kirin_drm_mode_config_funcs = { 71 .fb_create = drm_fb_cma_create, 72 #ifdef CONFIG_DRM_FBDEV_EMULATION 73 .output_poll_changed = kirin_fbdev_output_poll_changed, 74 #endif 75 .atomic_check = drm_atomic_helper_check, 76 .atomic_commit = drm_atomic_helper_commit, 77 }; 78 79 static void kirin_drm_mode_config_init(struct drm_device *dev) 80 { 81 dev->mode_config.min_width = 0; 82 dev->mode_config.min_height = 0; 83 84 dev->mode_config.max_width = 2048; 85 dev->mode_config.max_height = 2048; 86 87 dev->mode_config.funcs = &kirin_drm_mode_config_funcs; 88 } 89 90 static int kirin_drm_kms_init(struct drm_device *dev) 91 { 92 struct kirin_drm_private *priv; 93 int ret; 94 95 priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL); 96 if (!priv) 97 return -ENOMEM; 98 99 dev->dev_private = priv; 100 dev_set_drvdata(dev->dev, dev); 101 102 /* dev->mode_config initialization */ 103 drm_mode_config_init(dev); 104 kirin_drm_mode_config_init(dev); 105 106 /* display controller init */ 107 ret = dc_ops->init(dev); 108 if (ret) 109 goto err_mode_config_cleanup; 110 111 /* bind and init sub drivers */ 112 ret = component_bind_all(dev->dev, dev); 113 if (ret) { 114 DRM_ERROR("failed to bind all component.\n"); 115 goto err_dc_cleanup; 116 } 117 118 /* vblank init */ 119 ret = drm_vblank_init(dev, dev->mode_config.num_crtc); 120 if (ret) { 121 DRM_ERROR("failed to initialize vblank.\n"); 122 goto err_unbind_all; 123 } 124 /* with irq_enabled = true, we can use the vblank feature. */ 125 dev->irq_enabled = true; 126 127 /* reset all the states of crtc/plane/encoder/connector */ 128 drm_mode_config_reset(dev); 129 130 /* init kms poll for handling hpd */ 131 drm_kms_helper_poll_init(dev); 132 133 /* force detection after connectors init */ 134 (void)drm_helper_hpd_irq_event(dev); 135 136 return 0; 137 138 err_unbind_all: 139 component_unbind_all(dev->dev, dev); 140 err_dc_cleanup: 141 dc_ops->cleanup(dev); 142 err_mode_config_cleanup: 143 drm_mode_config_cleanup(dev); 144 devm_kfree(dev->dev, priv); 145 dev->dev_private = NULL; 146 147 return ret; 148 } 149 150 static const struct file_operations kirin_drm_fops = { 151 .owner = THIS_MODULE, 152 .open = drm_open, 153 .release = drm_release, 154 .unlocked_ioctl = drm_ioctl, 155 .compat_ioctl = drm_compat_ioctl, 156 .poll = drm_poll, 157 .read = drm_read, 158 .llseek = no_llseek, 159 .mmap = drm_gem_cma_mmap, 160 }; 161 162 static int kirin_gem_cma_dumb_create(struct drm_file *file, 163 struct drm_device *dev, 164 struct drm_mode_create_dumb *args) 165 { 166 return drm_gem_cma_dumb_create_internal(file, dev, args); 167 } 168 169 static struct drm_driver kirin_drm_driver = { 170 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | 171 DRIVER_ATOMIC, 172 .fops = &kirin_drm_fops, 173 174 .gem_free_object_unlocked = drm_gem_cma_free_object, 175 .gem_vm_ops = &drm_gem_cma_vm_ops, 176 .dumb_create = kirin_gem_cma_dumb_create, 177 .dumb_map_offset = drm_gem_cma_dumb_map_offset, 178 .dumb_destroy = drm_gem_dumb_destroy, 179 180 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 181 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 182 .gem_prime_export = drm_gem_prime_export, 183 .gem_prime_import = drm_gem_prime_import, 184 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, 185 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, 186 .gem_prime_vmap = drm_gem_cma_prime_vmap, 187 .gem_prime_vunmap = drm_gem_cma_prime_vunmap, 188 .gem_prime_mmap = drm_gem_cma_prime_mmap, 189 190 .name = "kirin", 191 .desc = "Hisilicon Kirin SoCs' DRM Driver", 192 .date = "20150718", 193 .major = 1, 194 .minor = 0, 195 }; 196 197 static int compare_of(struct device *dev, void *data) 198 { 199 return dev->of_node == data; 200 } 201 202 static int kirin_drm_bind(struct device *dev) 203 { 204 struct drm_driver *driver = &kirin_drm_driver; 205 struct drm_device *drm_dev; 206 int ret; 207 208 drm_dev = drm_dev_alloc(driver, dev); 209 if (IS_ERR(drm_dev)) 210 return PTR_ERR(drm_dev); 211 212 drm_dev->platformdev = to_platform_device(dev); 213 214 ret = kirin_drm_kms_init(drm_dev); 215 if (ret) 216 goto err_drm_dev_unref; 217 218 ret = drm_dev_register(drm_dev, 0); 219 if (ret) 220 goto err_kms_cleanup; 221 222 DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", 223 driver->name, driver->major, driver->minor, driver->patchlevel, 224 driver->date, drm_dev->primary->index); 225 226 return 0; 227 228 err_kms_cleanup: 229 kirin_drm_kms_cleanup(drm_dev); 230 err_drm_dev_unref: 231 drm_dev_unref(drm_dev); 232 233 return ret; 234 } 235 236 static void kirin_drm_unbind(struct device *dev) 237 { 238 struct drm_device *drm_dev = dev_get_drvdata(dev); 239 240 drm_dev_unregister(drm_dev); 241 kirin_drm_kms_cleanup(drm_dev); 242 drm_dev_unref(drm_dev); 243 } 244 245 static const struct component_master_ops kirin_drm_ops = { 246 .bind = kirin_drm_bind, 247 .unbind = kirin_drm_unbind, 248 }; 249 250 static struct device_node *kirin_get_remote_node(struct device_node *np) 251 { 252 struct device_node *endpoint, *remote; 253 254 /* get the first endpoint, in our case only one remote node 255 * is connected to display controller. 256 */ 257 endpoint = of_graph_get_next_endpoint(np, NULL); 258 if (!endpoint) { 259 DRM_ERROR("no valid endpoint node\n"); 260 return ERR_PTR(-ENODEV); 261 } 262 263 remote = of_graph_get_remote_port_parent(endpoint); 264 of_node_put(endpoint); 265 if (!remote) { 266 DRM_ERROR("no valid remote node\n"); 267 return ERR_PTR(-ENODEV); 268 } 269 270 if (!of_device_is_available(remote)) { 271 DRM_ERROR("not available for remote node\n"); 272 return ERR_PTR(-ENODEV); 273 } 274 275 return remote; 276 } 277 278 static int kirin_drm_platform_probe(struct platform_device *pdev) 279 { 280 struct device *dev = &pdev->dev; 281 struct device_node *np = dev->of_node; 282 struct component_match *match = NULL; 283 struct device_node *remote; 284 285 dc_ops = (struct kirin_dc_ops *)of_device_get_match_data(dev); 286 if (!dc_ops) { 287 DRM_ERROR("failed to get dt id data\n"); 288 return -EINVAL; 289 } 290 291 remote = kirin_get_remote_node(np); 292 if (IS_ERR(remote)) 293 return PTR_ERR(remote); 294 295 drm_of_component_match_add(dev, &match, compare_of, remote); 296 of_node_put(remote); 297 298 return component_master_add_with_match(dev, &kirin_drm_ops, match); 299 300 return 0; 301 } 302 303 static int kirin_drm_platform_remove(struct platform_device *pdev) 304 { 305 component_master_del(&pdev->dev, &kirin_drm_ops); 306 dc_ops = NULL; 307 return 0; 308 } 309 310 static const struct of_device_id kirin_drm_dt_ids[] = { 311 { .compatible = "hisilicon,hi6220-ade", 312 .data = &ade_dc_ops, 313 }, 314 { /* end node */ }, 315 }; 316 MODULE_DEVICE_TABLE(of, kirin_drm_dt_ids); 317 318 static struct platform_driver kirin_drm_platform_driver = { 319 .probe = kirin_drm_platform_probe, 320 .remove = kirin_drm_platform_remove, 321 .driver = { 322 .name = "kirin-drm", 323 .of_match_table = kirin_drm_dt_ids, 324 }, 325 }; 326 327 module_platform_driver(kirin_drm_platform_driver); 328 329 MODULE_AUTHOR("Xinliang Liu <xinliang.liu@linaro.org>"); 330 MODULE_AUTHOR("Xinliang Liu <z.liuxinliang@hisilicon.com>"); 331 MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>"); 332 MODULE_DESCRIPTION("hisilicon Kirin SoCs' DRM master driver"); 333 MODULE_LICENSE("GPL v2"); 334