Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2012 Texas Instruments
0004  * Author: Rob Clark <robdclark@gmail.com>
0005  */
0006 
0007 /* LCDC DRM driver, based on da8xx-fb */
0008 
0009 #include <linux/component.h>
0010 #include <linux/mod_devicetable.h>
0011 #include <linux/module.h>
0012 #include <linux/pinctrl/consumer.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/pm_runtime.h>
0015 
0016 #include <drm/drm_atomic_helper.h>
0017 #include <drm/drm_debugfs.h>
0018 #include <drm/drm_drv.h>
0019 #include <drm/drm_fb_helper.h>
0020 #include <drm/drm_fourcc.h>
0021 #include <drm/drm_gem_cma_helper.h>
0022 #include <drm/drm_gem_framebuffer_helper.h>
0023 #include <drm/drm_mm.h>
0024 #include <drm/drm_probe_helper.h>
0025 #include <drm/drm_vblank.h>
0026 
0027 
0028 #include "tilcdc_drv.h"
0029 #include "tilcdc_external.h"
0030 #include "tilcdc_panel.h"
0031 #include "tilcdc_regs.h"
0032 
0033 static LIST_HEAD(module_list);
0034 
0035 static const u32 tilcdc_rev1_formats[] = { DRM_FORMAT_RGB565 };
0036 
0037 static const u32 tilcdc_straight_formats[] = { DRM_FORMAT_RGB565,
0038                            DRM_FORMAT_BGR888,
0039                            DRM_FORMAT_XBGR8888 };
0040 
0041 static const u32 tilcdc_crossed_formats[] = { DRM_FORMAT_BGR565,
0042                           DRM_FORMAT_RGB888,
0043                           DRM_FORMAT_XRGB8888 };
0044 
0045 static const u32 tilcdc_legacy_formats[] = { DRM_FORMAT_RGB565,
0046                          DRM_FORMAT_RGB888,
0047                          DRM_FORMAT_XRGB8888 };
0048 
0049 void tilcdc_module_init(struct tilcdc_module *mod, const char *name,
0050         const struct tilcdc_module_ops *funcs)
0051 {
0052     mod->name = name;
0053     mod->funcs = funcs;
0054     INIT_LIST_HEAD(&mod->list);
0055     list_add(&mod->list, &module_list);
0056 }
0057 
0058 void tilcdc_module_cleanup(struct tilcdc_module *mod)
0059 {
0060     list_del(&mod->list);
0061 }
0062 
0063 static int tilcdc_atomic_check(struct drm_device *dev,
0064                    struct drm_atomic_state *state)
0065 {
0066     int ret;
0067 
0068     ret = drm_atomic_helper_check_modeset(dev, state);
0069     if (ret)
0070         return ret;
0071 
0072     ret = drm_atomic_helper_check_planes(dev, state);
0073     if (ret)
0074         return ret;
0075 
0076     /*
0077      * tilcdc ->atomic_check can update ->mode_changed if pixel format
0078      * changes, hence will we check modeset changes again.
0079      */
0080     ret = drm_atomic_helper_check_modeset(dev, state);
0081     if (ret)
0082         return ret;
0083 
0084     return ret;
0085 }
0086 
0087 static const struct drm_mode_config_funcs mode_config_funcs = {
0088     .fb_create = drm_gem_fb_create,
0089     .atomic_check = tilcdc_atomic_check,
0090     .atomic_commit = drm_atomic_helper_commit,
0091 };
0092 
0093 static void modeset_init(struct drm_device *dev)
0094 {
0095     struct tilcdc_drm_private *priv = dev->dev_private;
0096     struct tilcdc_module *mod;
0097 
0098     list_for_each_entry(mod, &module_list, list) {
0099         DBG("loading module: %s", mod->name);
0100         mod->funcs->modeset_init(mod, dev);
0101     }
0102 
0103     dev->mode_config.min_width = 0;
0104     dev->mode_config.min_height = 0;
0105     dev->mode_config.max_width = priv->max_width;
0106     dev->mode_config.max_height = 2048;
0107     dev->mode_config.funcs = &mode_config_funcs;
0108 }
0109 
0110 #ifdef CONFIG_CPU_FREQ
0111 static int cpufreq_transition(struct notifier_block *nb,
0112                      unsigned long val, void *data)
0113 {
0114     struct tilcdc_drm_private *priv = container_of(nb,
0115             struct tilcdc_drm_private, freq_transition);
0116 
0117     if (val == CPUFREQ_POSTCHANGE)
0118         tilcdc_crtc_update_clk(priv->crtc);
0119 
0120     return 0;
0121 }
0122 #endif
0123 
0124 static irqreturn_t tilcdc_irq(int irq, void *arg)
0125 {
0126     struct drm_device *dev = arg;
0127     struct tilcdc_drm_private *priv = dev->dev_private;
0128 
0129     return tilcdc_crtc_irq(priv->crtc);
0130 }
0131 
0132 static int tilcdc_irq_install(struct drm_device *dev, unsigned int irq)
0133 {
0134     struct tilcdc_drm_private *priv = dev->dev_private;
0135     int ret;
0136 
0137     ret = request_irq(irq, tilcdc_irq, 0, dev->driver->name, dev);
0138     if (ret)
0139         return ret;
0140 
0141     priv->irq_enabled = false;
0142 
0143     return 0;
0144 }
0145 
0146 static void tilcdc_irq_uninstall(struct drm_device *dev)
0147 {
0148     struct tilcdc_drm_private *priv = dev->dev_private;
0149 
0150     if (!priv->irq_enabled)
0151         return;
0152 
0153     free_irq(priv->irq, dev);
0154     priv->irq_enabled = false;
0155 }
0156 
0157 /*
0158  * DRM operations:
0159  */
0160 
0161 static void tilcdc_fini(struct drm_device *dev)
0162 {
0163     struct tilcdc_drm_private *priv = dev->dev_private;
0164 
0165 #ifdef CONFIG_CPU_FREQ
0166     if (priv->freq_transition.notifier_call)
0167         cpufreq_unregister_notifier(&priv->freq_transition,
0168                         CPUFREQ_TRANSITION_NOTIFIER);
0169 #endif
0170 
0171     if (priv->crtc)
0172         tilcdc_crtc_shutdown(priv->crtc);
0173 
0174     if (priv->is_registered)
0175         drm_dev_unregister(dev);
0176 
0177     drm_kms_helper_poll_fini(dev);
0178     tilcdc_irq_uninstall(dev);
0179     drm_mode_config_cleanup(dev);
0180 
0181     if (priv->clk)
0182         clk_put(priv->clk);
0183 
0184     if (priv->mmio)
0185         iounmap(priv->mmio);
0186 
0187     if (priv->wq)
0188         destroy_workqueue(priv->wq);
0189 
0190     dev->dev_private = NULL;
0191 
0192     pm_runtime_disable(dev->dev);
0193 
0194     drm_dev_put(dev);
0195 }
0196 
0197 static int tilcdc_init(const struct drm_driver *ddrv, struct device *dev)
0198 {
0199     struct drm_device *ddev;
0200     struct platform_device *pdev = to_platform_device(dev);
0201     struct device_node *node = dev->of_node;
0202     struct tilcdc_drm_private *priv;
0203     struct resource *res;
0204     u32 bpp = 0;
0205     int ret;
0206 
0207     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0208     if (!priv)
0209         return -ENOMEM;
0210 
0211     ddev = drm_dev_alloc(ddrv, dev);
0212     if (IS_ERR(ddev))
0213         return PTR_ERR(ddev);
0214 
0215     ddev->dev_private = priv;
0216     platform_set_drvdata(pdev, ddev);
0217     drm_mode_config_init(ddev);
0218 
0219     priv->is_componentized =
0220         tilcdc_get_external_components(dev, NULL) > 0;
0221 
0222     priv->wq = alloc_ordered_workqueue("tilcdc", 0);
0223     if (!priv->wq) {
0224         ret = -ENOMEM;
0225         goto init_failed;
0226     }
0227 
0228     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0229     if (!res) {
0230         dev_err(dev, "failed to get memory resource\n");
0231         ret = -EINVAL;
0232         goto init_failed;
0233     }
0234 
0235     priv->mmio = ioremap(res->start, resource_size(res));
0236     if (!priv->mmio) {
0237         dev_err(dev, "failed to ioremap\n");
0238         ret = -ENOMEM;
0239         goto init_failed;
0240     }
0241 
0242     priv->clk = clk_get(dev, "fck");
0243     if (IS_ERR(priv->clk)) {
0244         dev_err(dev, "failed to get functional clock\n");
0245         ret = -ENODEV;
0246         goto init_failed;
0247     }
0248 
0249     pm_runtime_enable(dev);
0250 
0251     /* Determine LCD IP Version */
0252     pm_runtime_get_sync(dev);
0253     switch (tilcdc_read(ddev, LCDC_PID_REG)) {
0254     case 0x4c100102:
0255         priv->rev = 1;
0256         break;
0257     case 0x4f200800:
0258     case 0x4f201000:
0259         priv->rev = 2;
0260         break;
0261     default:
0262         dev_warn(dev, "Unknown PID Reg value 0x%08x, "
0263             "defaulting to LCD revision 1\n",
0264             tilcdc_read(ddev, LCDC_PID_REG));
0265         priv->rev = 1;
0266         break;
0267     }
0268 
0269     pm_runtime_put_sync(dev);
0270 
0271     if (priv->rev == 1) {
0272         DBG("Revision 1 LCDC supports only RGB565 format");
0273         priv->pixelformats = tilcdc_rev1_formats;
0274         priv->num_pixelformats = ARRAY_SIZE(tilcdc_rev1_formats);
0275         bpp = 16;
0276     } else {
0277         const char *str = "\0";
0278 
0279         of_property_read_string(node, "blue-and-red-wiring", &str);
0280         if (0 == strcmp(str, "crossed")) {
0281             DBG("Configured for crossed blue and red wires");
0282             priv->pixelformats = tilcdc_crossed_formats;
0283             priv->num_pixelformats =
0284                 ARRAY_SIZE(tilcdc_crossed_formats);
0285             bpp = 32; /* Choose bpp with RGB support for fbdef */
0286         } else if (0 == strcmp(str, "straight")) {
0287             DBG("Configured for straight blue and red wires");
0288             priv->pixelformats = tilcdc_straight_formats;
0289             priv->num_pixelformats =
0290                 ARRAY_SIZE(tilcdc_straight_formats);
0291             bpp = 16; /* Choose bpp with RGB support for fbdef */
0292         } else {
0293             DBG("Blue and red wiring '%s' unknown, use legacy mode",
0294                 str);
0295             priv->pixelformats = tilcdc_legacy_formats;
0296             priv->num_pixelformats =
0297                 ARRAY_SIZE(tilcdc_legacy_formats);
0298             bpp = 16; /* This is just a guess */
0299         }
0300     }
0301 
0302     if (of_property_read_u32(node, "max-bandwidth", &priv->max_bandwidth))
0303         priv->max_bandwidth = TILCDC_DEFAULT_MAX_BANDWIDTH;
0304 
0305     DBG("Maximum Bandwidth Value %d", priv->max_bandwidth);
0306 
0307     if (of_property_read_u32(node, "max-width", &priv->max_width)) {
0308         if (priv->rev == 1)
0309             priv->max_width = TILCDC_DEFAULT_MAX_WIDTH_V1;
0310         else
0311             priv->max_width = TILCDC_DEFAULT_MAX_WIDTH_V2;
0312     }
0313 
0314     DBG("Maximum Horizontal Pixel Width Value %dpixels", priv->max_width);
0315 
0316     if (of_property_read_u32(node, "max-pixelclock",
0317                  &priv->max_pixelclock))
0318         priv->max_pixelclock = TILCDC_DEFAULT_MAX_PIXELCLOCK;
0319 
0320     DBG("Maximum Pixel Clock Value %dKHz", priv->max_pixelclock);
0321 
0322     ret = tilcdc_crtc_create(ddev);
0323     if (ret < 0) {
0324         dev_err(dev, "failed to create crtc\n");
0325         goto init_failed;
0326     }
0327     modeset_init(ddev);
0328 
0329 #ifdef CONFIG_CPU_FREQ
0330     priv->freq_transition.notifier_call = cpufreq_transition;
0331     ret = cpufreq_register_notifier(&priv->freq_transition,
0332             CPUFREQ_TRANSITION_NOTIFIER);
0333     if (ret) {
0334         dev_err(dev, "failed to register cpufreq notifier\n");
0335         priv->freq_transition.notifier_call = NULL;
0336         goto init_failed;
0337     }
0338 #endif
0339 
0340     if (priv->is_componentized) {
0341         ret = component_bind_all(dev, ddev);
0342         if (ret < 0)
0343             goto init_failed;
0344 
0345         ret = tilcdc_add_component_encoder(ddev);
0346         if (ret < 0)
0347             goto init_failed;
0348     } else {
0349         ret = tilcdc_attach_external_device(ddev);
0350         if (ret)
0351             goto init_failed;
0352     }
0353 
0354     if (!priv->external_connector &&
0355         ((priv->num_encoders == 0) || (priv->num_connectors == 0))) {
0356         dev_err(dev, "no encoders/connectors found\n");
0357         ret = -EPROBE_DEFER;
0358         goto init_failed;
0359     }
0360 
0361     ret = drm_vblank_init(ddev, 1);
0362     if (ret < 0) {
0363         dev_err(dev, "failed to initialize vblank\n");
0364         goto init_failed;
0365     }
0366 
0367     ret = platform_get_irq(pdev, 0);
0368     if (ret < 0)
0369         goto init_failed;
0370     priv->irq = ret;
0371 
0372     ret = tilcdc_irq_install(ddev, priv->irq);
0373     if (ret < 0) {
0374         dev_err(dev, "failed to install IRQ handler\n");
0375         goto init_failed;
0376     }
0377 
0378     drm_mode_config_reset(ddev);
0379 
0380     drm_kms_helper_poll_init(ddev);
0381 
0382     ret = drm_dev_register(ddev, 0);
0383     if (ret)
0384         goto init_failed;
0385     priv->is_registered = true;
0386 
0387     drm_fbdev_generic_setup(ddev, bpp);
0388     return 0;
0389 
0390 init_failed:
0391     tilcdc_fini(ddev);
0392 
0393     return ret;
0394 }
0395 
0396 #if defined(CONFIG_DEBUG_FS)
0397 static const struct {
0398     const char *name;
0399     uint8_t  rev;
0400     uint8_t  save;
0401     uint32_t reg;
0402 } registers[] =     {
0403 #define REG(rev, save, reg) { #reg, rev, save, reg }
0404         /* exists in revision 1: */
0405         REG(1, false, LCDC_PID_REG),
0406         REG(1, true,  LCDC_CTRL_REG),
0407         REG(1, false, LCDC_STAT_REG),
0408         REG(1, true,  LCDC_RASTER_CTRL_REG),
0409         REG(1, true,  LCDC_RASTER_TIMING_0_REG),
0410         REG(1, true,  LCDC_RASTER_TIMING_1_REG),
0411         REG(1, true,  LCDC_RASTER_TIMING_2_REG),
0412         REG(1, true,  LCDC_DMA_CTRL_REG),
0413         REG(1, true,  LCDC_DMA_FB_BASE_ADDR_0_REG),
0414         REG(1, true,  LCDC_DMA_FB_CEILING_ADDR_0_REG),
0415         REG(1, true,  LCDC_DMA_FB_BASE_ADDR_1_REG),
0416         REG(1, true,  LCDC_DMA_FB_CEILING_ADDR_1_REG),
0417         /* new in revision 2: */
0418         REG(2, false, LCDC_RAW_STAT_REG),
0419         REG(2, false, LCDC_MASKED_STAT_REG),
0420         REG(2, true, LCDC_INT_ENABLE_SET_REG),
0421         REG(2, false, LCDC_INT_ENABLE_CLR_REG),
0422         REG(2, false, LCDC_END_OF_INT_IND_REG),
0423         REG(2, true,  LCDC_CLK_ENABLE_REG),
0424 #undef REG
0425 };
0426 
0427 #endif
0428 
0429 #ifdef CONFIG_DEBUG_FS
0430 static int tilcdc_regs_show(struct seq_file *m, void *arg)
0431 {
0432     struct drm_info_node *node = (struct drm_info_node *) m->private;
0433     struct drm_device *dev = node->minor->dev;
0434     struct tilcdc_drm_private *priv = dev->dev_private;
0435     unsigned i;
0436 
0437     pm_runtime_get_sync(dev->dev);
0438 
0439     seq_printf(m, "revision: %d\n", priv->rev);
0440 
0441     for (i = 0; i < ARRAY_SIZE(registers); i++)
0442         if (priv->rev >= registers[i].rev)
0443             seq_printf(m, "%s:\t %08x\n", registers[i].name,
0444                     tilcdc_read(dev, registers[i].reg));
0445 
0446     pm_runtime_put_sync(dev->dev);
0447 
0448     return 0;
0449 }
0450 
0451 static int tilcdc_mm_show(struct seq_file *m, void *arg)
0452 {
0453     struct drm_info_node *node = (struct drm_info_node *) m->private;
0454     struct drm_device *dev = node->minor->dev;
0455     struct drm_printer p = drm_seq_file_printer(m);
0456     drm_mm_print(&dev->vma_offset_manager->vm_addr_space_mm, &p);
0457     return 0;
0458 }
0459 
0460 static struct drm_info_list tilcdc_debugfs_list[] = {
0461         { "regs", tilcdc_regs_show, 0, NULL },
0462         { "mm",   tilcdc_mm_show,   0, NULL },
0463 };
0464 
0465 static void tilcdc_debugfs_init(struct drm_minor *minor)
0466 {
0467     struct tilcdc_module *mod;
0468 
0469     drm_debugfs_create_files(tilcdc_debugfs_list,
0470                  ARRAY_SIZE(tilcdc_debugfs_list),
0471                  minor->debugfs_root, minor);
0472 
0473     list_for_each_entry(mod, &module_list, list)
0474         if (mod->funcs->debugfs_init)
0475             mod->funcs->debugfs_init(mod, minor);
0476 }
0477 #endif
0478 
0479 DEFINE_DRM_GEM_CMA_FOPS(fops);
0480 
0481 static const struct drm_driver tilcdc_driver = {
0482     .driver_features    = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
0483     DRM_GEM_CMA_DRIVER_OPS,
0484 #ifdef CONFIG_DEBUG_FS
0485     .debugfs_init       = tilcdc_debugfs_init,
0486 #endif
0487     .fops               = &fops,
0488     .name               = "tilcdc",
0489     .desc               = "TI LCD Controller DRM",
0490     .date               = "20121205",
0491     .major              = 1,
0492     .minor              = 0,
0493 };
0494 
0495 /*
0496  * Power management:
0497  */
0498 
0499 #ifdef CONFIG_PM_SLEEP
0500 static int tilcdc_pm_suspend(struct device *dev)
0501 {
0502     struct drm_device *ddev = dev_get_drvdata(dev);
0503     int ret = 0;
0504 
0505     ret = drm_mode_config_helper_suspend(ddev);
0506 
0507     /* Select sleep pin state */
0508     pinctrl_pm_select_sleep_state(dev);
0509 
0510     return ret;
0511 }
0512 
0513 static int tilcdc_pm_resume(struct device *dev)
0514 {
0515     struct drm_device *ddev = dev_get_drvdata(dev);
0516 
0517     /* Select default pin state */
0518     pinctrl_pm_select_default_state(dev);
0519     return  drm_mode_config_helper_resume(ddev);
0520 }
0521 #endif
0522 
0523 static const struct dev_pm_ops tilcdc_pm_ops = {
0524     SET_SYSTEM_SLEEP_PM_OPS(tilcdc_pm_suspend, tilcdc_pm_resume)
0525 };
0526 
0527 /*
0528  * Platform driver:
0529  */
0530 static int tilcdc_bind(struct device *dev)
0531 {
0532     return tilcdc_init(&tilcdc_driver, dev);
0533 }
0534 
0535 static void tilcdc_unbind(struct device *dev)
0536 {
0537     struct drm_device *ddev = dev_get_drvdata(dev);
0538 
0539     /* Check if a subcomponent has already triggered the unloading. */
0540     if (!ddev->dev_private)
0541         return;
0542 
0543     tilcdc_fini(dev_get_drvdata(dev));
0544 }
0545 
0546 static const struct component_master_ops tilcdc_comp_ops = {
0547     .bind = tilcdc_bind,
0548     .unbind = tilcdc_unbind,
0549 };
0550 
0551 static int tilcdc_pdev_probe(struct platform_device *pdev)
0552 {
0553     struct component_match *match = NULL;
0554     int ret;
0555 
0556     /* bail out early if no DT data: */
0557     if (!pdev->dev.of_node) {
0558         dev_err(&pdev->dev, "device-tree data is missing\n");
0559         return -ENXIO;
0560     }
0561 
0562     ret = tilcdc_get_external_components(&pdev->dev, &match);
0563     if (ret < 0)
0564         return ret;
0565     else if (ret == 0)
0566         return tilcdc_init(&tilcdc_driver, &pdev->dev);
0567     else
0568         return component_master_add_with_match(&pdev->dev,
0569                                &tilcdc_comp_ops,
0570                                match);
0571 }
0572 
0573 static int tilcdc_pdev_remove(struct platform_device *pdev)
0574 {
0575     int ret;
0576 
0577     ret = tilcdc_get_external_components(&pdev->dev, NULL);
0578     if (ret < 0)
0579         return ret;
0580     else if (ret == 0)
0581         tilcdc_fini(platform_get_drvdata(pdev));
0582     else
0583         component_master_del(&pdev->dev, &tilcdc_comp_ops);
0584 
0585     return 0;
0586 }
0587 
0588 static const struct of_device_id tilcdc_of_match[] = {
0589         { .compatible = "ti,am33xx-tilcdc", },
0590         { .compatible = "ti,da850-tilcdc", },
0591         { },
0592 };
0593 MODULE_DEVICE_TABLE(of, tilcdc_of_match);
0594 
0595 static struct platform_driver tilcdc_platform_driver = {
0596     .probe      = tilcdc_pdev_probe,
0597     .remove     = tilcdc_pdev_remove,
0598     .driver     = {
0599         .name   = "tilcdc",
0600         .pm     = &tilcdc_pm_ops,
0601         .of_match_table = tilcdc_of_match,
0602     },
0603 };
0604 
0605 static int __init tilcdc_drm_init(void)
0606 {
0607     if (drm_firmware_drivers_only())
0608         return -ENODEV;
0609 
0610     DBG("init");
0611     tilcdc_panel_init();
0612     return platform_driver_register(&tilcdc_platform_driver);
0613 }
0614 
0615 static void __exit tilcdc_drm_fini(void)
0616 {
0617     DBG("fini");
0618     platform_driver_unregister(&tilcdc_platform_driver);
0619     tilcdc_panel_fini();
0620 }
0621 
0622 module_init(tilcdc_drm_init);
0623 module_exit(tilcdc_drm_fini);
0624 
0625 MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
0626 MODULE_DESCRIPTION("TI LCD Controller DRM Driver");
0627 MODULE_LICENSE("GPL");