--- zzzz-none-000/linux-3.10.107/drivers/gpu/drm/tilcdc/tilcdc_drv.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/gpu/drm/tilcdc/tilcdc_drv.c 2021-02-04 17:41:59.000000000 +0000 @@ -17,11 +17,13 @@ /* LCDC DRM driver, based on da8xx-fb */ +#include + #include "tilcdc_drv.h" #include "tilcdc_regs.h" #include "tilcdc_tfp410.h" -#include "tilcdc_slave.h" #include "tilcdc_panel.h" +#include "tilcdc_external.h" #include "drm_fb_helper.h" @@ -52,8 +54,7 @@ static void tilcdc_fb_output_poll_changed(struct drm_device *dev) { struct tilcdc_drm_private *priv = dev->dev_private; - if (priv->fbdev) - drm_fbdev_cma_hotplug_event(priv->fbdev); + drm_fbdev_cma_hotplug_event(priv->fbdev); } static const struct drm_mode_config_funcs mode_config_funcs = { @@ -75,13 +76,6 @@ mod->funcs->modeset_init(mod, dev); } - if ((priv->num_encoders == 0) || (priv->num_connectors == 0)) { - /* oh nos! */ - dev_err(dev->dev, "no encoders/connectors found\n"); - drm_mode_config_cleanup(dev); - return -ENXIO; - } - dev->mode_config.min_width = 0; dev->mode_config.min_height = 0; dev->mode_config.max_width = tilcdc_crtc_max_width(priv->crtc); @@ -115,7 +109,8 @@ static int tilcdc_unload(struct drm_device *dev) { struct tilcdc_drm_private *priv = dev->dev_private; - struct tilcdc_module *mod, *cur; + + tilcdc_remove_external_encoders(dev); drm_fbdev_cma_fini(priv->fbdev); drm_kms_helper_poll_fini(dev); @@ -144,11 +139,6 @@ pm_runtime_disable(dev->dev); - list_for_each_entry_safe(mod, cur, &module_list, list) { - DBG("destroying module: %s", mod->name); - mod->funcs->destroy(mod); - } - kfree(priv); return 0; @@ -159,7 +149,9 @@ struct platform_device *pdev = dev->platformdev; struct device_node *node = pdev->dev.of_node; struct tilcdc_drm_private *priv; + struct tilcdc_module *mod; struct resource *res; + u32 bpp = 0; int ret; priv = kzalloc(sizeof(*priv), GFP_KERNEL); @@ -170,6 +162,9 @@ dev->dev_private = priv; + priv->is_componentized = + tilcdc_get_external_components(dev->dev, NULL) > 0; + priv->wq = alloc_ordered_workqueue("tilcdc", 0); if (!priv->wq) { ret = -ENOMEM; @@ -216,9 +211,23 @@ #endif if (of_property_read_u32(node, "max-bandwidth", &priv->max_bandwidth)) - priv->max_bandwidth = 1280 * 1024 * 60; + priv->max_bandwidth = TILCDC_DEFAULT_MAX_BANDWIDTH; + + DBG("Maximum Bandwidth Value %d", priv->max_bandwidth); + + if (of_property_read_u32(node, "ti,max-width", &priv->max_width)) + priv->max_width = TILCDC_DEFAULT_MAX_WIDTH; + + DBG("Maximum Horizontal Pixel Width Value %dpixels", priv->max_width); + + if (of_property_read_u32(node, "ti,max-pixelclock", + &priv->max_pixelclock)) + priv->max_pixelclock = TILCDC_DEFAULT_MAX_PIXELCLOCK; + + DBG("Maximum Pixel Clock Value %dKHz", priv->max_pixelclock); pm_runtime_enable(dev->dev); + pm_runtime_irq_safe(dev->dev); /* Determine LCD IP Version */ pm_runtime_get_sync(dev->dev); @@ -246,23 +255,46 @@ goto fail_cpufreq_unregister; } + platform_set_drvdata(pdev, dev); + + if (priv->is_componentized) { + ret = component_bind_all(dev->dev, dev); + if (ret < 0) + goto fail_mode_config_cleanup; + + ret = tilcdc_add_external_encoders(dev, &bpp); + if (ret < 0) + goto fail_component_cleanup; + } + + if ((priv->num_encoders == 0) || (priv->num_connectors == 0)) { + dev_err(dev->dev, "no encoders/connectors found\n"); + ret = -ENXIO; + goto fail_external_cleanup; + } + ret = drm_vblank_init(dev, 1); if (ret < 0) { dev_err(dev->dev, "failed to initialize vblank\n"); - goto fail_mode_config_cleanup; + goto fail_external_cleanup; } pm_runtime_get_sync(dev->dev); - ret = drm_irq_install(dev); + ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0)); pm_runtime_put_sync(dev->dev); if (ret < 0) { dev_err(dev->dev, "failed to install IRQ handler\n"); goto fail_vblank_cleanup; } - platform_set_drvdata(pdev, dev); + list_for_each_entry(mod, &module_list, list) { + DBG("%s: preferred_bpp: %d", mod->name, mod->preferred_bpp); + bpp = mod->preferred_bpp; + if (bpp > 0) + break; + } - priv->fbdev = drm_fbdev_cma_init(dev, 16, + priv->fbdev = drm_fbdev_cma_init(dev, bpp, dev->mode_config.num_crtc, dev->mode_config.num_connector); if (IS_ERR(priv->fbdev)) { @@ -285,6 +317,13 @@ fail_mode_config_cleanup: drm_mode_config_cleanup(dev); +fail_component_cleanup: + if (priv->is_componentized) + component_unbind_all(dev->dev, dev); + +fail_external_cleanup: + tilcdc_remove_external_encoders(dev); + fail_cpufreq_unregister: pm_runtime_disable(dev->dev); #ifdef CONFIG_CPU_FREQ @@ -323,7 +362,7 @@ drm_fbdev_cma_restore_mode(priv->fbdev); } -static irqreturn_t tilcdc_irq(DRM_IRQ_ARGS) +static irqreturn_t tilcdc_irq(int irq, void *arg) { struct drm_device *dev = arg; struct tilcdc_drm_private *priv = dev->dev_private; @@ -386,13 +425,13 @@ tilcdc_clear(dev, reg, mask); } -static int tilcdc_enable_vblank(struct drm_device *dev, int crtc) +static int tilcdc_enable_vblank(struct drm_device *dev, unsigned int pipe) { enable_vblank(dev, true); return 0; } -static void tilcdc_disable_vblank(struct drm_device *dev, int crtc) +static void tilcdc_disable_vblank(struct drm_device *dev, unsigned int pipe) { enable_vblank(dev, false); } @@ -456,7 +495,7 @@ { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - return drm_mm_dump_table(m, dev->mm_private); + return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm); } static struct drm_info_list tilcdc_debugfs_list[] = { @@ -509,7 +548,6 @@ #endif .poll = drm_poll, .read = drm_read, - .fasync = drm_fasync, .llseek = no_llseek, .mmap = drm_gem_cma_mmap, }; @@ -520,18 +558,19 @@ .unload = tilcdc_unload, .preclose = tilcdc_preclose, .lastclose = tilcdc_lastclose, + .set_busid = drm_platform_set_busid, .irq_handler = tilcdc_irq, .irq_preinstall = tilcdc_irq_preinstall, .irq_postinstall = tilcdc_irq_postinstall, .irq_uninstall = tilcdc_irq_uninstall, - .get_vblank_counter = drm_vblank_count, + .get_vblank_counter = drm_vblank_no_hw_counter, .enable_vblank = tilcdc_enable_vblank, .disable_vblank = tilcdc_disable_vblank, .gem_free_object = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, .dumb_create = drm_gem_cma_dumb_create, .dumb_map_offset = drm_gem_cma_dumb_map_offset, - .dumb_destroy = drm_gem_cma_dumb_destroy, + .dumb_destroy = drm_gem_dumb_destroy, #ifdef CONFIG_DEBUG_FS .debugfs_init = tilcdc_debugfs_init, .debugfs_cleanup = tilcdc_debugfs_cleanup, @@ -590,20 +629,56 @@ * Platform driver: */ +static int tilcdc_bind(struct device *dev) +{ + return drm_platform_init(&tilcdc_driver, to_platform_device(dev)); +} + +static void tilcdc_unbind(struct device *dev) +{ + drm_put_dev(dev_get_drvdata(dev)); +} + +static const struct component_master_ops tilcdc_comp_ops = { + .bind = tilcdc_bind, + .unbind = tilcdc_unbind, +}; + static int tilcdc_pdev_probe(struct platform_device *pdev) { + struct component_match *match = NULL; + int ret; + /* bail out early if no DT data: */ if (!pdev->dev.of_node) { dev_err(&pdev->dev, "device-tree data is missing\n"); return -ENXIO; } - return drm_platform_init(&tilcdc_driver, pdev); + ret = tilcdc_get_external_components(&pdev->dev, &match); + if (ret < 0) + return ret; + else if (ret == 0) + return drm_platform_init(&tilcdc_driver, pdev); + else + return component_master_add_with_match(&pdev->dev, + &tilcdc_comp_ops, + match); } static int tilcdc_pdev_remove(struct platform_device *pdev) { - drm_platform_exit(&tilcdc_driver, pdev); + struct drm_device *ddev = dev_get_drvdata(&pdev->dev); + struct tilcdc_drm_private *priv = ddev->dev_private; + + /* Check if a subcomponent has already triggered the unloading. */ + if (!priv) + return 0; + + if (priv->is_componentized) + component_master_del(&pdev->dev, &tilcdc_comp_ops); + else + drm_put_dev(platform_get_drvdata(pdev)); return 0; } @@ -618,7 +693,6 @@ .probe = tilcdc_pdev_probe, .remove = tilcdc_pdev_remove, .driver = { - .owner = THIS_MODULE, .name = "tilcdc", .pm = &tilcdc_pm_ops, .of_match_table = tilcdc_of_match, @@ -629,7 +703,6 @@ { DBG("init"); tilcdc_tfp410_init(); - tilcdc_slave_init(); tilcdc_panel_init(); return platform_driver_register(&tilcdc_platform_driver); } @@ -639,11 +712,10 @@ DBG("fini"); platform_driver_unregister(&tilcdc_platform_driver); tilcdc_panel_fini(); - tilcdc_slave_fini(); tilcdc_tfp410_fini(); } -late_initcall(tilcdc_drm_init); +module_init(tilcdc_drm_init); module_exit(tilcdc_drm_fini); MODULE_AUTHOR("Rob Clark