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