1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2019-2022 Bootlin 4 * Author: Paul Kocialkowski <paul.kocialkowski@bootlin.com> 5 */ 6 7 #include <linux/bitfield.h> 8 #include <linux/clk.h> 9 #include <linux/mfd/syscon.h> 10 #include <linux/module.h> 11 #include <linux/of.h> 12 #include <linux/of_address.h> 13 #include <linux/of_reserved_mem.h> 14 #include <linux/platform_device.h> 15 #include <linux/regmap.h> 16 #include <linux/types.h> 17 18 #include <drm/drm_atomic_helper.h> 19 #include <drm/drm_client_setup.h> 20 #include <drm/drm_drv.h> 21 #include <drm/drm_fbdev_dma.h> 22 #include <drm/drm_fourcc.h> 23 #include <drm/drm_gem_dma_helper.h> 24 #include <drm/drm_print.h> 25 26 #include "logicvc_crtc.h" 27 #include "logicvc_drm.h" 28 #include "logicvc_interface.h" 29 #include "logicvc_mode.h" 30 #include "logicvc_layer.h" 31 #include "logicvc_of.h" 32 #include "logicvc_regs.h" 33 34 DEFINE_DRM_GEM_DMA_FOPS(logicvc_drm_fops); 35 36 static int logicvc_drm_gem_dma_dumb_create(struct drm_file *file_priv, 37 struct drm_device *drm_dev, 38 struct drm_mode_create_dumb *args) 39 { 40 struct logicvc_drm *logicvc = logicvc_drm(drm_dev); 41 42 /* Stride is always fixed to its configuration value. */ 43 args->pitch = logicvc->config.row_stride * DIV_ROUND_UP(args->bpp, 8); 44 45 return drm_gem_dma_dumb_create_internal(file_priv, drm_dev, args); 46 } 47 48 static struct drm_driver logicvc_drm_driver = { 49 .driver_features = DRIVER_GEM | DRIVER_MODESET | 50 DRIVER_ATOMIC, 51 52 .fops = &logicvc_drm_fops, 53 .name = "logicvc-drm", 54 .desc = "Xylon LogiCVC DRM driver", 55 .date = "20200403", 56 .major = 1, 57 .minor = 0, 58 59 DRM_GEM_DMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(logicvc_drm_gem_dma_dumb_create), 60 DRM_FBDEV_DMA_DRIVER_OPS, 61 }; 62 63 static struct regmap_config logicvc_drm_regmap_config = { 64 .reg_bits = 32, 65 .val_bits = 32, 66 .reg_stride = 4, 67 .name = "logicvc-drm", 68 }; 69 70 static irqreturn_t logicvc_drm_irq_handler(int irq, void *data) 71 { 72 struct logicvc_drm *logicvc = data; 73 irqreturn_t ret = IRQ_NONE; 74 u32 stat = 0; 75 76 /* Get pending interrupt sources. */ 77 regmap_read(logicvc->regmap, LOGICVC_INT_STAT_REG, &stat); 78 79 /* Clear all pending interrupt sources. */ 80 regmap_write(logicvc->regmap, LOGICVC_INT_STAT_REG, stat); 81 82 if (stat & LOGICVC_INT_STAT_V_SYNC) { 83 logicvc_crtc_vblank_handler(logicvc); 84 ret = IRQ_HANDLED; 85 } 86 87 return ret; 88 } 89 90 static int logicvc_drm_config_parse(struct logicvc_drm *logicvc) 91 { 92 struct drm_device *drm_dev = &logicvc->drm_dev; 93 struct device *dev = drm_dev->dev; 94 struct device_node *of_node = dev->of_node; 95 struct logicvc_drm_config *config = &logicvc->config; 96 struct device_node *layers_node; 97 int ret; 98 99 logicvc_of_property_parse_bool(of_node, LOGICVC_OF_PROPERTY_DITHERING, 100 &config->dithering); 101 logicvc_of_property_parse_bool(of_node, 102 LOGICVC_OF_PROPERTY_BACKGROUND_LAYER, 103 &config->background_layer); 104 logicvc_of_property_parse_bool(of_node, 105 LOGICVC_OF_PROPERTY_LAYERS_CONFIGURABLE, 106 &config->layers_configurable); 107 108 ret = logicvc_of_property_parse_u32(of_node, 109 LOGICVC_OF_PROPERTY_DISPLAY_INTERFACE, 110 &config->display_interface); 111 if (ret) 112 return ret; 113 114 ret = logicvc_of_property_parse_u32(of_node, 115 LOGICVC_OF_PROPERTY_DISPLAY_COLORSPACE, 116 &config->display_colorspace); 117 if (ret) 118 return ret; 119 120 ret = logicvc_of_property_parse_u32(of_node, 121 LOGICVC_OF_PROPERTY_DISPLAY_DEPTH, 122 &config->display_depth); 123 if (ret) 124 return ret; 125 126 ret = logicvc_of_property_parse_u32(of_node, 127 LOGICVC_OF_PROPERTY_ROW_STRIDE, 128 &config->row_stride); 129 if (ret) 130 return ret; 131 132 layers_node = of_get_child_by_name(of_node, "layers"); 133 if (!layers_node) { 134 drm_err(drm_dev, "Missing non-optional layers node\n"); 135 return -EINVAL; 136 } 137 138 config->layers_count = of_get_child_count(layers_node); 139 if (!config->layers_count) { 140 drm_err(drm_dev, 141 "Missing a non-optional layers children node\n"); 142 return -EINVAL; 143 } 144 145 return 0; 146 } 147 148 static int logicvc_clocks_prepare(struct logicvc_drm *logicvc) 149 { 150 struct drm_device *drm_dev = &logicvc->drm_dev; 151 struct device *dev = drm_dev->dev; 152 153 struct { 154 struct clk **clk; 155 char *name; 156 bool optional; 157 } clocks_map[] = { 158 { 159 .clk = &logicvc->vclk, 160 .name = "vclk", 161 .optional = false, 162 }, 163 { 164 .clk = &logicvc->vclk2, 165 .name = "vclk2", 166 .optional = true, 167 }, 168 { 169 .clk = &logicvc->lvdsclk, 170 .name = "lvdsclk", 171 .optional = true, 172 }, 173 { 174 .clk = &logicvc->lvdsclkn, 175 .name = "lvdsclkn", 176 .optional = true, 177 }, 178 }; 179 unsigned int i; 180 int ret; 181 182 for (i = 0; i < ARRAY_SIZE(clocks_map); i++) { 183 struct clk *clk; 184 185 clk = devm_clk_get(dev, clocks_map[i].name); 186 if (IS_ERR(clk)) { 187 if (PTR_ERR(clk) == -ENOENT && clocks_map[i].optional) 188 continue; 189 190 drm_err(drm_dev, "Missing non-optional clock %s\n", 191 clocks_map[i].name); 192 193 ret = PTR_ERR(clk); 194 goto error; 195 } 196 197 ret = clk_prepare_enable(clk); 198 if (ret) { 199 drm_err(drm_dev, 200 "Failed to prepare and enable clock %s\n", 201 clocks_map[i].name); 202 goto error; 203 } 204 205 *clocks_map[i].clk = clk; 206 } 207 208 return 0; 209 210 error: 211 for (i = 0; i < ARRAY_SIZE(clocks_map); i++) { 212 if (!*clocks_map[i].clk) 213 continue; 214 215 clk_disable_unprepare(*clocks_map[i].clk); 216 *clocks_map[i].clk = NULL; 217 } 218 219 return ret; 220 } 221 222 static int logicvc_clocks_unprepare(struct logicvc_drm *logicvc) 223 { 224 struct clk **clocks[] = { 225 &logicvc->vclk, 226 &logicvc->vclk2, 227 &logicvc->lvdsclk, 228 &logicvc->lvdsclkn, 229 }; 230 unsigned int i; 231 232 for (i = 0; i < ARRAY_SIZE(clocks); i++) { 233 if (!*clocks[i]) 234 continue; 235 236 clk_disable_unprepare(*clocks[i]); 237 *clocks[i] = NULL; 238 } 239 240 return 0; 241 } 242 243 static const struct logicvc_drm_caps logicvc_drm_caps[] = { 244 { 245 .major = 3, 246 .layer_address = false, 247 }, 248 { 249 .major = 4, 250 .layer_address = true, 251 }, 252 { 253 .major = 5, 254 .layer_address = true, 255 }, 256 }; 257 258 static const struct logicvc_drm_caps * 259 logicvc_drm_caps_match(struct logicvc_drm *logicvc) 260 { 261 struct drm_device *drm_dev = &logicvc->drm_dev; 262 const struct logicvc_drm_caps *caps = NULL; 263 unsigned int major, minor; 264 char level; 265 unsigned int i; 266 u32 version; 267 268 regmap_read(logicvc->regmap, LOGICVC_IP_VERSION_REG, &version); 269 270 major = FIELD_GET(LOGICVC_IP_VERSION_MAJOR_MASK, version); 271 minor = FIELD_GET(LOGICVC_IP_VERSION_MINOR_MASK, version); 272 level = FIELD_GET(LOGICVC_IP_VERSION_LEVEL_MASK, version) + 'a'; 273 274 for (i = 0; i < ARRAY_SIZE(logicvc_drm_caps); i++) { 275 if (logicvc_drm_caps[i].major && 276 logicvc_drm_caps[i].major != major) 277 continue; 278 279 if (logicvc_drm_caps[i].minor && 280 logicvc_drm_caps[i].minor != minor) 281 continue; 282 283 if (logicvc_drm_caps[i].level && 284 logicvc_drm_caps[i].level != level) 285 continue; 286 287 caps = &logicvc_drm_caps[i]; 288 } 289 290 drm_info(drm_dev, "LogiCVC version %d.%02d.%c\n", major, minor, level); 291 292 return caps; 293 } 294 295 static int logicvc_drm_probe(struct platform_device *pdev) 296 { 297 struct device_node *of_node = pdev->dev.of_node; 298 struct device_node *reserved_mem_node; 299 struct reserved_mem *reserved_mem = NULL; 300 const struct logicvc_drm_caps *caps; 301 struct logicvc_drm *logicvc; 302 struct device *dev = &pdev->dev; 303 struct drm_device *drm_dev; 304 struct regmap *regmap = NULL; 305 struct resource res; 306 void __iomem *base; 307 int irq; 308 int ret; 309 310 ret = of_reserved_mem_device_init(dev); 311 if (ret && ret != -ENODEV) { 312 dev_err(dev, "Failed to init memory region\n"); 313 goto error_early; 314 } 315 316 reserved_mem_node = of_parse_phandle(of_node, "memory-region", 0); 317 if (reserved_mem_node) { 318 reserved_mem = of_reserved_mem_lookup(reserved_mem_node); 319 of_node_put(reserved_mem_node); 320 } 321 322 /* Get regmap from parent if available. */ 323 if (of_node->parent) 324 regmap = syscon_node_to_regmap(of_node->parent); 325 326 /* Register our own regmap otherwise. */ 327 if (IS_ERR_OR_NULL(regmap)) { 328 ret = of_address_to_resource(of_node, 0, &res); 329 if (ret) { 330 dev_err(dev, "Failed to get resource from address\n"); 331 goto error_reserved_mem; 332 } 333 334 base = devm_ioremap_resource(dev, &res); 335 if (IS_ERR(base)) { 336 dev_err(dev, "Failed to map I/O base\n"); 337 ret = PTR_ERR(base); 338 goto error_reserved_mem; 339 } 340 341 logicvc_drm_regmap_config.max_register = resource_size(&res) - 342 4; 343 344 regmap = devm_regmap_init_mmio(dev, base, 345 &logicvc_drm_regmap_config); 346 if (IS_ERR(regmap)) { 347 dev_err(dev, "Failed to create regmap for I/O\n"); 348 ret = PTR_ERR(regmap); 349 goto error_reserved_mem; 350 } 351 } 352 353 irq = platform_get_irq(pdev, 0); 354 if (irq < 0) { 355 ret = -ENODEV; 356 goto error_reserved_mem; 357 } 358 359 logicvc = devm_drm_dev_alloc(dev, &logicvc_drm_driver, 360 struct logicvc_drm, drm_dev); 361 if (IS_ERR(logicvc)) { 362 ret = PTR_ERR(logicvc); 363 goto error_reserved_mem; 364 } 365 366 platform_set_drvdata(pdev, logicvc); 367 drm_dev = &logicvc->drm_dev; 368 369 logicvc->regmap = regmap; 370 INIT_LIST_HEAD(&logicvc->layers_list); 371 372 caps = logicvc_drm_caps_match(logicvc); 373 if (!caps) { 374 ret = -EINVAL; 375 goto error_reserved_mem; 376 } 377 378 logicvc->caps = caps; 379 380 if (reserved_mem) 381 logicvc->reserved_mem_base = reserved_mem->base; 382 383 ret = logicvc_clocks_prepare(logicvc); 384 if (ret) { 385 drm_err(drm_dev, "Failed to prepare clocks\n"); 386 goto error_reserved_mem; 387 } 388 389 ret = devm_request_irq(dev, irq, logicvc_drm_irq_handler, 0, 390 dev_name(dev), logicvc); 391 if (ret) { 392 drm_err(drm_dev, "Failed to request IRQ\n"); 393 goto error_clocks; 394 } 395 396 ret = logicvc_drm_config_parse(logicvc); 397 if (ret && ret != -ENODEV) { 398 drm_err(drm_dev, "Failed to parse config\n"); 399 goto error_clocks; 400 } 401 402 ret = drmm_mode_config_init(drm_dev); 403 if (ret) { 404 drm_err(drm_dev, "Failed to init mode config\n"); 405 goto error_clocks; 406 } 407 408 ret = logicvc_layers_init(logicvc); 409 if (ret) { 410 drm_err(drm_dev, "Failed to initialize layers\n"); 411 goto error_clocks; 412 } 413 414 ret = logicvc_crtc_init(logicvc); 415 if (ret) { 416 drm_err(drm_dev, "Failed to initialize CRTC\n"); 417 goto error_clocks; 418 } 419 420 logicvc_layers_attach_crtc(logicvc); 421 422 ret = logicvc_interface_init(logicvc); 423 if (ret) { 424 if (ret != -EPROBE_DEFER) 425 drm_err(drm_dev, "Failed to initialize interface\n"); 426 427 goto error_clocks; 428 } 429 430 logicvc_interface_attach_crtc(logicvc); 431 432 ret = logicvc_mode_init(logicvc); 433 if (ret) { 434 drm_err(drm_dev, "Failed to initialize KMS\n"); 435 goto error_clocks; 436 } 437 438 ret = drm_dev_register(drm_dev, 0); 439 if (ret) { 440 drm_err(drm_dev, "Failed to register DRM device\n"); 441 goto error_mode; 442 } 443 444 drm_client_setup(drm_dev, NULL); 445 446 return 0; 447 448 error_mode: 449 logicvc_mode_fini(logicvc); 450 451 error_clocks: 452 logicvc_clocks_unprepare(logicvc); 453 454 error_reserved_mem: 455 of_reserved_mem_device_release(dev); 456 457 error_early: 458 return ret; 459 } 460 461 static void logicvc_drm_remove(struct platform_device *pdev) 462 { 463 struct logicvc_drm *logicvc = platform_get_drvdata(pdev); 464 struct device *dev = &pdev->dev; 465 struct drm_device *drm_dev = &logicvc->drm_dev; 466 467 drm_dev_unregister(drm_dev); 468 drm_atomic_helper_shutdown(drm_dev); 469 470 logicvc_mode_fini(logicvc); 471 472 logicvc_clocks_unprepare(logicvc); 473 474 of_reserved_mem_device_release(dev); 475 } 476 477 static void logicvc_drm_shutdown(struct platform_device *pdev) 478 { 479 struct logicvc_drm *logicvc = platform_get_drvdata(pdev); 480 struct drm_device *drm_dev = &logicvc->drm_dev; 481 482 drm_atomic_helper_shutdown(drm_dev); 483 } 484 485 static const struct of_device_id logicvc_drm_of_table[] = { 486 { .compatible = "xylon,logicvc-3.02.a-display" }, 487 { .compatible = "xylon,logicvc-4.01.a-display" }, 488 {}, 489 }; 490 MODULE_DEVICE_TABLE(of, logicvc_drm_of_table); 491 492 static struct platform_driver logicvc_drm_platform_driver = { 493 .probe = logicvc_drm_probe, 494 .remove_new = logicvc_drm_remove, 495 .shutdown = logicvc_drm_shutdown, 496 .driver = { 497 .name = "logicvc-drm", 498 .of_match_table = logicvc_drm_of_table, 499 }, 500 }; 501 502 module_platform_driver(logicvc_drm_platform_driver); 503 504 MODULE_AUTHOR("Paul Kocialkowski <paul.kocialkowski@bootlin.com>"); 505 MODULE_DESCRIPTION("Xylon LogiCVC DRM driver"); 506 MODULE_LICENSE("GPL"); 507