1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 29960aa7cSTomi Valkeinen /* 3bb5cdf8dSAndrew F. Davis * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ 49960aa7cSTomi Valkeinen * Author: Archit Taneja <archit@ti.com> 59960aa7cSTomi Valkeinen */ 69960aa7cSTomi Valkeinen 7*8090f7ebSLaurent Pinchart #include <linux/bitops.h> 89960aa7cSTomi Valkeinen #include <linux/kernel.h> 99960aa7cSTomi Valkeinen #include <linux/module.h> 109960aa7cSTomi Valkeinen #include <linux/platform_device.h> 119960aa7cSTomi Valkeinen #include <linux/slab.h> 129960aa7cSTomi Valkeinen #include <linux/of.h> 1379107f27SLaurent Pinchart #include <linux/of_graph.h> 149960aa7cSTomi Valkeinen 1530b71761SLaurent Pinchart #include <drm/drm_panel.h> 1630b71761SLaurent Pinchart 17845417b3SLaurent Pinchart #include "dss.h" 1832043da7SPeter Ujfalusi #include "omapdss.h" 199960aa7cSTomi Valkeinen 20d17eb453SLaurent Pinchart int omapdss_device_init_output(struct omap_dss_device *out) 219960aa7cSTomi Valkeinen { 2279107f27SLaurent Pinchart struct device_node *remote_node; 2379107f27SLaurent Pinchart 24*8090f7ebSLaurent Pinchart remote_node = of_graph_get_remote_node(out->dev->of_node, 25*8090f7ebSLaurent Pinchart ffs(out->of_ports) - 1, 0); 2679107f27SLaurent Pinchart if (!remote_node) { 2779107f27SLaurent Pinchart dev_dbg(out->dev, "failed to find video sink\n"); 2879107f27SLaurent Pinchart return 0; 29d17eb453SLaurent Pinchart } 30d17eb453SLaurent Pinchart 3179107f27SLaurent Pinchart out->next = omapdss_find_device_by_node(remote_node); 3279107f27SLaurent Pinchart out->bridge = of_drm_find_bridge(remote_node); 3330b71761SLaurent Pinchart out->panel = of_drm_find_panel(remote_node); 3430b71761SLaurent Pinchart if (IS_ERR(out->panel)) 3530b71761SLaurent Pinchart out->panel = NULL; 3679107f27SLaurent Pinchart 3779107f27SLaurent Pinchart of_node_put(remote_node); 3879107f27SLaurent Pinchart 390dbfc396SLaurent Pinchart if (out->next && out->type != out->next->type) { 4039637e10STomi Valkeinen dev_err(out->dev, "output type and display type don't match\n"); 4179107f27SLaurent Pinchart omapdss_device_put(out->next); 4279107f27SLaurent Pinchart out->next = NULL; 4371316556SLaurent Pinchart return -EINVAL; 449960aa7cSTomi Valkeinen } 459960aa7cSTomi Valkeinen 4630b71761SLaurent Pinchart return out->next || out->bridge || out->panel ? 0 : -EPROBE_DEFER; 479960aa7cSTomi Valkeinen } 48d17eb453SLaurent Pinchart EXPORT_SYMBOL(omapdss_device_init_output); 49d17eb453SLaurent Pinchart 50d17eb453SLaurent Pinchart void omapdss_device_cleanup_output(struct omap_dss_device *out) 51d17eb453SLaurent Pinchart { 52d17eb453SLaurent Pinchart if (out->next) 53d17eb453SLaurent Pinchart omapdss_device_put(out->next); 54d17eb453SLaurent Pinchart } 55d17eb453SLaurent Pinchart EXPORT_SYMBOL(omapdss_device_cleanup_output); 569960aa7cSTomi Valkeinen 57845417b3SLaurent Pinchart int dss_install_mgr_ops(struct dss_device *dss, 58845417b3SLaurent Pinchart const struct dss_mgr_ops *mgr_ops, 5964cb8179SLaurent Pinchart struct omap_drm_private *priv) 609960aa7cSTomi Valkeinen { 61845417b3SLaurent Pinchart if (dss->mgr_ops) 629960aa7cSTomi Valkeinen return -EBUSY; 639960aa7cSTomi Valkeinen 64845417b3SLaurent Pinchart dss->mgr_ops = mgr_ops; 65845417b3SLaurent Pinchart dss->mgr_ops_priv = priv; 669960aa7cSTomi Valkeinen 679960aa7cSTomi Valkeinen return 0; 689960aa7cSTomi Valkeinen } 699960aa7cSTomi Valkeinen EXPORT_SYMBOL(dss_install_mgr_ops); 709960aa7cSTomi Valkeinen 71845417b3SLaurent Pinchart void dss_uninstall_mgr_ops(struct dss_device *dss) 729960aa7cSTomi Valkeinen { 73845417b3SLaurent Pinchart dss->mgr_ops = NULL; 74845417b3SLaurent Pinchart dss->mgr_ops_priv = NULL; 759960aa7cSTomi Valkeinen } 769960aa7cSTomi Valkeinen EXPORT_SYMBOL(dss_uninstall_mgr_ops); 779960aa7cSTomi Valkeinen 7828d79f3eSLaurent Pinchart void dss_mgr_set_timings(struct omap_dss_device *dssdev, 7928d79f3eSLaurent Pinchart const struct videomode *vm) 809960aa7cSTomi Valkeinen { 81845417b3SLaurent Pinchart dssdev->dss->mgr_ops->set_timings(dssdev->dss->mgr_ops_priv, 82845417b3SLaurent Pinchart dssdev->dispc_channel, vm); 839960aa7cSTomi Valkeinen } 849960aa7cSTomi Valkeinen EXPORT_SYMBOL(dss_mgr_set_timings); 859960aa7cSTomi Valkeinen 8628d79f3eSLaurent Pinchart void dss_mgr_set_lcd_config(struct omap_dss_device *dssdev, 879960aa7cSTomi Valkeinen const struct dss_lcd_mgr_config *config) 889960aa7cSTomi Valkeinen { 89845417b3SLaurent Pinchart dssdev->dss->mgr_ops->set_lcd_config(dssdev->dss->mgr_ops_priv, 9064cb8179SLaurent Pinchart dssdev->dispc_channel, config); 919960aa7cSTomi Valkeinen } 929960aa7cSTomi Valkeinen EXPORT_SYMBOL(dss_mgr_set_lcd_config); 939960aa7cSTomi Valkeinen 9428d79f3eSLaurent Pinchart int dss_mgr_enable(struct omap_dss_device *dssdev) 959960aa7cSTomi Valkeinen { 96845417b3SLaurent Pinchart return dssdev->dss->mgr_ops->enable(dssdev->dss->mgr_ops_priv, 97845417b3SLaurent Pinchart dssdev->dispc_channel); 989960aa7cSTomi Valkeinen } 999960aa7cSTomi Valkeinen EXPORT_SYMBOL(dss_mgr_enable); 1009960aa7cSTomi Valkeinen 10128d79f3eSLaurent Pinchart void dss_mgr_disable(struct omap_dss_device *dssdev) 1029960aa7cSTomi Valkeinen { 103845417b3SLaurent Pinchart dssdev->dss->mgr_ops->disable(dssdev->dss->mgr_ops_priv, 104845417b3SLaurent Pinchart dssdev->dispc_channel); 1059960aa7cSTomi Valkeinen } 1069960aa7cSTomi Valkeinen EXPORT_SYMBOL(dss_mgr_disable); 1079960aa7cSTomi Valkeinen 10828d79f3eSLaurent Pinchart void dss_mgr_start_update(struct omap_dss_device *dssdev) 1099960aa7cSTomi Valkeinen { 110845417b3SLaurent Pinchart dssdev->dss->mgr_ops->start_update(dssdev->dss->mgr_ops_priv, 111845417b3SLaurent Pinchart dssdev->dispc_channel); 1129960aa7cSTomi Valkeinen } 1139960aa7cSTomi Valkeinen EXPORT_SYMBOL(dss_mgr_start_update); 1149960aa7cSTomi Valkeinen 11528d79f3eSLaurent Pinchart int dss_mgr_register_framedone_handler(struct omap_dss_device *dssdev, 1169960aa7cSTomi Valkeinen void (*handler)(void *), void *data) 1179960aa7cSTomi Valkeinen { 118845417b3SLaurent Pinchart struct dss_device *dss = dssdev->dss; 119845417b3SLaurent Pinchart 120845417b3SLaurent Pinchart return dss->mgr_ops->register_framedone_handler(dss->mgr_ops_priv, 12164cb8179SLaurent Pinchart dssdev->dispc_channel, 12228d79f3eSLaurent Pinchart handler, data); 1239960aa7cSTomi Valkeinen } 1249960aa7cSTomi Valkeinen EXPORT_SYMBOL(dss_mgr_register_framedone_handler); 1259960aa7cSTomi Valkeinen 12628d79f3eSLaurent Pinchart void dss_mgr_unregister_framedone_handler(struct omap_dss_device *dssdev, 1279960aa7cSTomi Valkeinen void (*handler)(void *), void *data) 1289960aa7cSTomi Valkeinen { 129845417b3SLaurent Pinchart struct dss_device *dss = dssdev->dss; 130845417b3SLaurent Pinchart 131845417b3SLaurent Pinchart dss->mgr_ops->unregister_framedone_handler(dss->mgr_ops_priv, 13264cb8179SLaurent Pinchart dssdev->dispc_channel, 13328d79f3eSLaurent Pinchart handler, data); 1349960aa7cSTomi Valkeinen } 1359960aa7cSTomi Valkeinen EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler); 136