1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Hisilicon Kirin SoCs drm master driver 4 * 5 * Copyright (c) 2016 Linaro Limited. 6 * Copyright (c) 2014-2016 Hisilicon Limited. 7 * 8 * Author: 9 * Xinliang Liu <z.liuxinliang@hisilicon.com> 10 * Xinliang Liu <xinliang.liu@linaro.org> 11 * Xinwei Kong <kong.kongxinwei@hisilicon.com> 12 */ 13 14 #include <linux/of_platform.h> 15 #include <linux/component.h> 16 #include <linux/module.h> 17 #include <linux/of_graph.h> 18 #include <linux/platform_device.h> 19 20 #include <drm/drm_atomic_helper.h> 21 #include <drm/drm_drv.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/drm_probe_helper.h> 28 #include <drm/drm_vblank.h> 29 30 #include "kirin_drm_drv.h" 31 32 #define KIRIN_MAX_PLANE 2 33 34 struct kirin_drm_private { 35 struct kirin_crtc crtc; 36 struct kirin_plane planes[KIRIN_MAX_PLANE]; 37 void *hw_ctx; 38 }; 39 40 static int kirin_drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, 41 struct drm_plane *plane, 42 const struct kirin_drm_data *driver_data) 43 { 44 struct device_node *port; 45 int ret; 46 47 /* set crtc port so that 48 * drm_of_find_possible_crtcs call works 49 */ 50 port = of_get_child_by_name(dev->dev->of_node, "port"); 51 if (!port) { 52 DRM_ERROR("no port node found in %pOF\n", dev->dev->of_node); 53 return -EINVAL; 54 } 55 of_node_put(port); 56 crtc->port = port; 57 58 ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, 59 driver_data->crtc_funcs, NULL); 60 if (ret) { 61 DRM_ERROR("failed to init crtc.\n"); 62 return ret; 63 } 64 65 drm_crtc_helper_add(crtc, driver_data->crtc_helper_funcs); 66 67 return 0; 68 } 69 70 static int kirin_drm_plane_init(struct drm_device *dev, struct drm_plane *plane, 71 enum drm_plane_type type, 72 const struct kirin_drm_data *data) 73 { 74 int ret = 0; 75 76 ret = drm_universal_plane_init(dev, plane, 1, data->plane_funcs, 77 data->channel_formats, 78 data->channel_formats_cnt, 79 NULL, type, NULL); 80 if (ret) { 81 DRM_ERROR("fail to init plane, ch=%d\n", 0); 82 return ret; 83 } 84 85 drm_plane_helper_add(plane, data->plane_helper_funcs); 86 87 return 0; 88 } 89 90 static void kirin_drm_private_cleanup(struct drm_device *dev) 91 { 92 struct kirin_drm_private *kirin_priv = dev->dev_private; 93 struct kirin_drm_data *data; 94 95 data = (struct kirin_drm_data *)of_device_get_match_data(dev->dev); 96 if (data->cleanup_hw_ctx) 97 data->cleanup_hw_ctx(kirin_priv->hw_ctx); 98 99 devm_kfree(dev->dev, kirin_priv); 100 dev->dev_private = NULL; 101 } 102 103 static int kirin_drm_private_init(struct drm_device *dev, 104 const struct kirin_drm_data *driver_data) 105 { 106 struct platform_device *pdev = to_platform_device(dev->dev); 107 struct kirin_drm_private *kirin_priv; 108 struct drm_plane *prim_plane; 109 enum drm_plane_type type; 110 void *ctx; 111 int ret; 112 u32 ch; 113 114 kirin_priv = devm_kzalloc(dev->dev, sizeof(*kirin_priv), GFP_KERNEL); 115 if (!kirin_priv) { 116 DRM_ERROR("failed to alloc kirin_drm_private\n"); 117 return -ENOMEM; 118 } 119 120 ctx = driver_data->alloc_hw_ctx(pdev, &kirin_priv->crtc.base); 121 if (IS_ERR(ctx)) { 122 DRM_ERROR("failed to initialize kirin_priv hw ctx\n"); 123 return -EINVAL; 124 } 125 kirin_priv->hw_ctx = ctx; 126 127 /* 128 * plane init 129 * TODO: Now only support primary plane, overlay planes 130 * need to do. 131 */ 132 for (ch = 0; ch < driver_data->num_planes; ch++) { 133 if (ch == driver_data->prim_plane) 134 type = DRM_PLANE_TYPE_PRIMARY; 135 else 136 type = DRM_PLANE_TYPE_OVERLAY; 137 ret = kirin_drm_plane_init(dev, &kirin_priv->planes[ch].base, 138 type, driver_data); 139 if (ret) 140 return ret; 141 kirin_priv->planes[ch].ch = ch; 142 kirin_priv->planes[ch].hw_ctx = ctx; 143 } 144 145 /* crtc init */ 146 prim_plane = &kirin_priv->planes[driver_data->prim_plane].base; 147 ret = kirin_drm_crtc_init(dev, &kirin_priv->crtc.base, 148 prim_plane, driver_data); 149 if (ret) 150 return ret; 151 kirin_priv->crtc.hw_ctx = ctx; 152 dev->dev_private = kirin_priv; 153 154 return 0; 155 } 156 157 static int kirin_drm_kms_init(struct drm_device *dev, 158 const struct kirin_drm_data *driver_data) 159 { 160 int ret; 161 162 /* dev->mode_config initialization */ 163 drm_mode_config_init(dev); 164 dev->mode_config.min_width = 0; 165 dev->mode_config.min_height = 0; 166 dev->mode_config.max_width = driver_data->config_max_width; 167 dev->mode_config.max_height = driver_data->config_max_width; 168 dev->mode_config.funcs = driver_data->mode_config_funcs; 169 170 /* display controller init */ 171 ret = kirin_drm_private_init(dev, driver_data); 172 if (ret) 173 goto err_mode_config_cleanup; 174 175 /* bind and init sub drivers */ 176 ret = component_bind_all(dev->dev, dev); 177 if (ret) { 178 DRM_ERROR("failed to bind all component.\n"); 179 goto err_private_cleanup; 180 } 181 182 /* vblank init */ 183 ret = drm_vblank_init(dev, dev->mode_config.num_crtc); 184 if (ret) { 185 DRM_ERROR("failed to initialize vblank.\n"); 186 goto err_unbind_all; 187 } 188 /* with irq_enabled = true, we can use the vblank feature. */ 189 dev->irq_enabled = true; 190 191 /* reset all the states of crtc/plane/encoder/connector */ 192 drm_mode_config_reset(dev); 193 194 /* init kms poll for handling hpd */ 195 drm_kms_helper_poll_init(dev); 196 197 return 0; 198 199 err_unbind_all: 200 component_unbind_all(dev->dev, dev); 201 err_private_cleanup: 202 kirin_drm_private_cleanup(dev); 203 err_mode_config_cleanup: 204 drm_mode_config_cleanup(dev); 205 return ret; 206 } 207 208 static int compare_of(struct device *dev, void *data) 209 { 210 return dev->of_node == data; 211 } 212 213 static int kirin_drm_kms_cleanup(struct drm_device *dev) 214 { 215 drm_kms_helper_poll_fini(dev); 216 kirin_drm_private_cleanup(dev); 217 drm_mode_config_cleanup(dev); 218 219 return 0; 220 } 221 222 static int kirin_drm_connectors_register(struct drm_device *dev) 223 { 224 struct drm_connector *connector; 225 struct drm_connector *failed_connector; 226 struct drm_connector_list_iter conn_iter; 227 int ret; 228 229 mutex_lock(&dev->mode_config.mutex); 230 drm_connector_list_iter_begin(dev, &conn_iter); 231 drm_for_each_connector_iter(connector, &conn_iter) { 232 ret = drm_connector_register(connector); 233 if (ret) { 234 failed_connector = connector; 235 goto err; 236 } 237 } 238 drm_connector_list_iter_end(&conn_iter); 239 mutex_unlock(&dev->mode_config.mutex); 240 241 return 0; 242 243 err: 244 drm_connector_list_iter_begin(dev, &conn_iter); 245 drm_for_each_connector_iter(connector, &conn_iter) { 246 if (failed_connector == connector) 247 break; 248 drm_connector_unregister(connector); 249 } 250 drm_connector_list_iter_end(&conn_iter); 251 mutex_unlock(&dev->mode_config.mutex); 252 253 return ret; 254 } 255 256 static int kirin_drm_bind(struct device *dev) 257 { 258 struct kirin_drm_data *driver_data; 259 struct drm_device *drm_dev; 260 int ret; 261 262 driver_data = (struct kirin_drm_data *)of_device_get_match_data(dev); 263 if (!driver_data) 264 return -EINVAL; 265 266 drm_dev = drm_dev_alloc(driver_data->driver, dev); 267 if (IS_ERR(drm_dev)) 268 return PTR_ERR(drm_dev); 269 dev_set_drvdata(dev, drm_dev); 270 271 /* display controller init */ 272 ret = kirin_drm_kms_init(drm_dev, driver_data); 273 if (ret) 274 goto err_drm_dev_put; 275 276 ret = drm_dev_register(drm_dev, 0); 277 if (ret) 278 goto err_kms_cleanup; 279 280 drm_fbdev_generic_setup(drm_dev, 32); 281 282 /* connectors should be registered after drm device register */ 283 if (driver_data->register_connects) { 284 ret = kirin_drm_connectors_register(drm_dev); 285 if (ret) 286 goto err_drm_dev_unregister; 287 } 288 289 return 0; 290 291 err_drm_dev_unregister: 292 drm_dev_unregister(drm_dev); 293 err_kms_cleanup: 294 kirin_drm_kms_cleanup(drm_dev); 295 err_drm_dev_put: 296 drm_dev_put(drm_dev); 297 298 return ret; 299 } 300 301 static void kirin_drm_unbind(struct device *dev) 302 { 303 struct drm_device *drm_dev = dev_get_drvdata(dev); 304 305 drm_dev_unregister(drm_dev); 306 kirin_drm_kms_cleanup(drm_dev); 307 drm_dev_put(drm_dev); 308 } 309 310 static const struct component_master_ops kirin_drm_ops = { 311 .bind = kirin_drm_bind, 312 .unbind = kirin_drm_unbind, 313 }; 314 315 static int kirin_drm_platform_probe(struct platform_device *pdev) 316 { 317 struct device *dev = &pdev->dev; 318 struct device_node *np = dev->of_node; 319 struct component_match *match = NULL; 320 struct device_node *remote; 321 322 remote = of_graph_get_remote_node(np, 0, 0); 323 if (!remote) 324 return -ENODEV; 325 326 drm_of_component_match_add(dev, &match, compare_of, remote); 327 of_node_put(remote); 328 329 return component_master_add_with_match(dev, &kirin_drm_ops, match); 330 } 331 332 static int kirin_drm_platform_remove(struct platform_device *pdev) 333 { 334 component_master_del(&pdev->dev, &kirin_drm_ops); 335 return 0; 336 } 337 338 static const struct of_device_id kirin_drm_dt_ids[] = { 339 { .compatible = "hisilicon,hi6220-ade", 340 .data = &ade_driver_data, 341 }, 342 { /* end node */ }, 343 }; 344 MODULE_DEVICE_TABLE(of, kirin_drm_dt_ids); 345 346 static struct platform_driver kirin_drm_platform_driver = { 347 .probe = kirin_drm_platform_probe, 348 .remove = kirin_drm_platform_remove, 349 .driver = { 350 .name = "kirin-drm", 351 .of_match_table = kirin_drm_dt_ids, 352 }, 353 }; 354 355 module_platform_driver(kirin_drm_platform_driver); 356 357 MODULE_AUTHOR("Xinliang Liu <xinliang.liu@linaro.org>"); 358 MODULE_AUTHOR("Xinliang Liu <z.liuxinliang@hisilicon.com>"); 359 MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>"); 360 MODULE_DESCRIPTION("hisilicon Kirin SoCs' DRM master driver"); 361 MODULE_LICENSE("GPL v2"); 362