output.c (5344B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2012 Texas Instruments Ltd 4 * Author: Archit Taneja <archit@ti.com> 5 */ 6 7#include <linux/kernel.h> 8#include <linux/module.h> 9#include <linux/platform_device.h> 10#include <linux/slab.h> 11#include <linux/of.h> 12 13#include <video/omapfb_dss.h> 14 15#include "dss.h" 16 17static LIST_HEAD(output_list); 18static DEFINE_MUTEX(output_lock); 19 20int omapdss_output_set_device(struct omap_dss_device *out, 21 struct omap_dss_device *dssdev) 22{ 23 int r; 24 25 mutex_lock(&output_lock); 26 27 if (out->dst) { 28 DSSERR("output already has device %s connected to it\n", 29 out->dst->name); 30 r = -EINVAL; 31 goto err; 32 } 33 34 if (out->output_type != dssdev->type) { 35 DSSERR("output type and display type don't match\n"); 36 r = -EINVAL; 37 goto err; 38 } 39 40 out->dst = dssdev; 41 dssdev->src = out; 42 43 mutex_unlock(&output_lock); 44 45 return 0; 46err: 47 mutex_unlock(&output_lock); 48 49 return r; 50} 51EXPORT_SYMBOL(omapdss_output_set_device); 52 53int omapdss_output_unset_device(struct omap_dss_device *out) 54{ 55 int r; 56 57 mutex_lock(&output_lock); 58 59 if (!out->dst) { 60 DSSERR("output doesn't have a device connected to it\n"); 61 r = -EINVAL; 62 goto err; 63 } 64 65 if (out->dst->state != OMAP_DSS_DISPLAY_DISABLED) { 66 DSSERR("device %s is not disabled, cannot unset device\n", 67 out->dst->name); 68 r = -EINVAL; 69 goto err; 70 } 71 72 out->dst->src = NULL; 73 out->dst = NULL; 74 75 mutex_unlock(&output_lock); 76 77 return 0; 78err: 79 mutex_unlock(&output_lock); 80 81 return r; 82} 83EXPORT_SYMBOL(omapdss_output_unset_device); 84 85int omapdss_register_output(struct omap_dss_device *out) 86{ 87 list_add_tail(&out->list, &output_list); 88 return 0; 89} 90EXPORT_SYMBOL(omapdss_register_output); 91 92void omapdss_unregister_output(struct omap_dss_device *out) 93{ 94 list_del(&out->list); 95} 96EXPORT_SYMBOL(omapdss_unregister_output); 97 98struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id) 99{ 100 struct omap_dss_device *out; 101 102 list_for_each_entry(out, &output_list, list) { 103 if (out->id == id) 104 return out; 105 } 106 107 return NULL; 108} 109EXPORT_SYMBOL(omap_dss_get_output); 110 111struct omap_dss_device *omap_dss_find_output(const char *name) 112{ 113 struct omap_dss_device *out; 114 115 list_for_each_entry(out, &output_list, list) { 116 if (strcmp(out->name, name) == 0) 117 return omap_dss_get_device(out); 118 } 119 120 return NULL; 121} 122EXPORT_SYMBOL(omap_dss_find_output); 123 124struct omap_dss_device *omap_dss_find_output_by_port_node(struct device_node *port) 125{ 126 struct device_node *src_node; 127 struct omap_dss_device *out; 128 u32 reg; 129 130 src_node = dss_of_port_get_parent_device(port); 131 if (!src_node) 132 return NULL; 133 134 reg = dss_of_port_get_port_number(port); 135 136 list_for_each_entry(out, &output_list, list) { 137 if (out->dev->of_node == src_node && out->port_num == reg) { 138 of_node_put(src_node); 139 return omap_dss_get_device(out); 140 } 141 } 142 143 of_node_put(src_node); 144 145 return NULL; 146} 147EXPORT_SYMBOL(omap_dss_find_output_by_port_node); 148 149struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev) 150{ 151 while (dssdev->src) 152 dssdev = dssdev->src; 153 154 if (dssdev->id != 0) 155 return omap_dss_get_device(dssdev); 156 157 return NULL; 158} 159EXPORT_SYMBOL(omapdss_find_output_from_display); 160 161struct omap_overlay_manager *omapdss_find_mgr_from_display(struct omap_dss_device *dssdev) 162{ 163 struct omap_dss_device *out; 164 struct omap_overlay_manager *mgr; 165 166 out = omapdss_find_output_from_display(dssdev); 167 168 if (out == NULL) 169 return NULL; 170 171 mgr = out->manager; 172 173 omap_dss_put_device(out); 174 175 return mgr; 176} 177EXPORT_SYMBOL(omapdss_find_mgr_from_display); 178 179static const struct dss_mgr_ops *dss_mgr_ops; 180 181int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops) 182{ 183 if (dss_mgr_ops) 184 return -EBUSY; 185 186 dss_mgr_ops = mgr_ops; 187 188 return 0; 189} 190EXPORT_SYMBOL(dss_install_mgr_ops); 191 192void dss_uninstall_mgr_ops(void) 193{ 194 dss_mgr_ops = NULL; 195} 196EXPORT_SYMBOL(dss_uninstall_mgr_ops); 197 198int dss_mgr_connect(struct omap_overlay_manager *mgr, 199 struct omap_dss_device *dst) 200{ 201 return dss_mgr_ops->connect(mgr, dst); 202} 203EXPORT_SYMBOL(dss_mgr_connect); 204 205void dss_mgr_disconnect(struct omap_overlay_manager *mgr, 206 struct omap_dss_device *dst) 207{ 208 dss_mgr_ops->disconnect(mgr, dst); 209} 210EXPORT_SYMBOL(dss_mgr_disconnect); 211 212void dss_mgr_set_timings(struct omap_overlay_manager *mgr, 213 const struct omap_video_timings *timings) 214{ 215 dss_mgr_ops->set_timings(mgr, timings); 216} 217EXPORT_SYMBOL(dss_mgr_set_timings); 218 219void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr, 220 const struct dss_lcd_mgr_config *config) 221{ 222 dss_mgr_ops->set_lcd_config(mgr, config); 223} 224EXPORT_SYMBOL(dss_mgr_set_lcd_config); 225 226int dss_mgr_enable(struct omap_overlay_manager *mgr) 227{ 228 return dss_mgr_ops->enable(mgr); 229} 230EXPORT_SYMBOL(dss_mgr_enable); 231 232void dss_mgr_disable(struct omap_overlay_manager *mgr) 233{ 234 dss_mgr_ops->disable(mgr); 235} 236EXPORT_SYMBOL(dss_mgr_disable); 237 238void dss_mgr_start_update(struct omap_overlay_manager *mgr) 239{ 240 dss_mgr_ops->start_update(mgr); 241} 242EXPORT_SYMBOL(dss_mgr_start_update); 243 244int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr, 245 void (*handler)(void *), void *data) 246{ 247 return dss_mgr_ops->register_framedone_handler(mgr, handler, data); 248} 249EXPORT_SYMBOL(dss_mgr_register_framedone_handler); 250 251void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr, 252 void (*handler)(void *), void *data) 253{ 254 dss_mgr_ops->unregister_framedone_handler(mgr, handler, data); 255} 256EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);