0001
0002
0003
0004
0005
0006
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 #include <linux/platform_device.h>
0010 #include <linux/slab.h>
0011 #include <linux/of.h>
0012
0013 #include <video/omapfb_dss.h>
0014
0015 #include "dss.h"
0016
0017 static LIST_HEAD(output_list);
0018 static DEFINE_MUTEX(output_lock);
0019
0020 int omapdss_output_set_device(struct omap_dss_device *out,
0021 struct omap_dss_device *dssdev)
0022 {
0023 int r;
0024
0025 mutex_lock(&output_lock);
0026
0027 if (out->dst) {
0028 DSSERR("output already has device %s connected to it\n",
0029 out->dst->name);
0030 r = -EINVAL;
0031 goto err;
0032 }
0033
0034 if (out->output_type != dssdev->type) {
0035 DSSERR("output type and display type don't match\n");
0036 r = -EINVAL;
0037 goto err;
0038 }
0039
0040 out->dst = dssdev;
0041 dssdev->src = out;
0042
0043 mutex_unlock(&output_lock);
0044
0045 return 0;
0046 err:
0047 mutex_unlock(&output_lock);
0048
0049 return r;
0050 }
0051 EXPORT_SYMBOL(omapdss_output_set_device);
0052
0053 int omapdss_output_unset_device(struct omap_dss_device *out)
0054 {
0055 int r;
0056
0057 mutex_lock(&output_lock);
0058
0059 if (!out->dst) {
0060 DSSERR("output doesn't have a device connected to it\n");
0061 r = -EINVAL;
0062 goto err;
0063 }
0064
0065 if (out->dst->state != OMAP_DSS_DISPLAY_DISABLED) {
0066 DSSERR("device %s is not disabled, cannot unset device\n",
0067 out->dst->name);
0068 r = -EINVAL;
0069 goto err;
0070 }
0071
0072 out->dst->src = NULL;
0073 out->dst = NULL;
0074
0075 mutex_unlock(&output_lock);
0076
0077 return 0;
0078 err:
0079 mutex_unlock(&output_lock);
0080
0081 return r;
0082 }
0083 EXPORT_SYMBOL(omapdss_output_unset_device);
0084
0085 int omapdss_register_output(struct omap_dss_device *out)
0086 {
0087 list_add_tail(&out->list, &output_list);
0088 return 0;
0089 }
0090 EXPORT_SYMBOL(omapdss_register_output);
0091
0092 void omapdss_unregister_output(struct omap_dss_device *out)
0093 {
0094 list_del(&out->list);
0095 }
0096 EXPORT_SYMBOL(omapdss_unregister_output);
0097
0098 struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id)
0099 {
0100 struct omap_dss_device *out;
0101
0102 list_for_each_entry(out, &output_list, list) {
0103 if (out->id == id)
0104 return out;
0105 }
0106
0107 return NULL;
0108 }
0109 EXPORT_SYMBOL(omap_dss_get_output);
0110
0111 struct omap_dss_device *omap_dss_find_output(const char *name)
0112 {
0113 struct omap_dss_device *out;
0114
0115 list_for_each_entry(out, &output_list, list) {
0116 if (strcmp(out->name, name) == 0)
0117 return omap_dss_get_device(out);
0118 }
0119
0120 return NULL;
0121 }
0122 EXPORT_SYMBOL(omap_dss_find_output);
0123
0124 struct omap_dss_device *omap_dss_find_output_by_port_node(struct device_node *port)
0125 {
0126 struct device_node *src_node;
0127 struct omap_dss_device *out;
0128 u32 reg;
0129
0130 src_node = dss_of_port_get_parent_device(port);
0131 if (!src_node)
0132 return NULL;
0133
0134 reg = dss_of_port_get_port_number(port);
0135
0136 list_for_each_entry(out, &output_list, list) {
0137 if (out->dev->of_node == src_node && out->port_num == reg) {
0138 of_node_put(src_node);
0139 return omap_dss_get_device(out);
0140 }
0141 }
0142
0143 of_node_put(src_node);
0144
0145 return NULL;
0146 }
0147 EXPORT_SYMBOL(omap_dss_find_output_by_port_node);
0148
0149 struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev)
0150 {
0151 while (dssdev->src)
0152 dssdev = dssdev->src;
0153
0154 if (dssdev->id != 0)
0155 return omap_dss_get_device(dssdev);
0156
0157 return NULL;
0158 }
0159 EXPORT_SYMBOL(omapdss_find_output_from_display);
0160
0161 struct omap_overlay_manager *omapdss_find_mgr_from_display(struct omap_dss_device *dssdev)
0162 {
0163 struct omap_dss_device *out;
0164 struct omap_overlay_manager *mgr;
0165
0166 out = omapdss_find_output_from_display(dssdev);
0167
0168 if (out == NULL)
0169 return NULL;
0170
0171 mgr = out->manager;
0172
0173 omap_dss_put_device(out);
0174
0175 return mgr;
0176 }
0177 EXPORT_SYMBOL(omapdss_find_mgr_from_display);
0178
0179 static const struct dss_mgr_ops *dss_mgr_ops;
0180
0181 int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops)
0182 {
0183 if (dss_mgr_ops)
0184 return -EBUSY;
0185
0186 dss_mgr_ops = mgr_ops;
0187
0188 return 0;
0189 }
0190 EXPORT_SYMBOL(dss_install_mgr_ops);
0191
0192 void dss_uninstall_mgr_ops(void)
0193 {
0194 dss_mgr_ops = NULL;
0195 }
0196 EXPORT_SYMBOL(dss_uninstall_mgr_ops);
0197
0198 int dss_mgr_connect(struct omap_overlay_manager *mgr,
0199 struct omap_dss_device *dst)
0200 {
0201 return dss_mgr_ops->connect(mgr, dst);
0202 }
0203 EXPORT_SYMBOL(dss_mgr_connect);
0204
0205 void dss_mgr_disconnect(struct omap_overlay_manager *mgr,
0206 struct omap_dss_device *dst)
0207 {
0208 dss_mgr_ops->disconnect(mgr, dst);
0209 }
0210 EXPORT_SYMBOL(dss_mgr_disconnect);
0211
0212 void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
0213 const struct omap_video_timings *timings)
0214 {
0215 dss_mgr_ops->set_timings(mgr, timings);
0216 }
0217 EXPORT_SYMBOL(dss_mgr_set_timings);
0218
0219 void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
0220 const struct dss_lcd_mgr_config *config)
0221 {
0222 dss_mgr_ops->set_lcd_config(mgr, config);
0223 }
0224 EXPORT_SYMBOL(dss_mgr_set_lcd_config);
0225
0226 int dss_mgr_enable(struct omap_overlay_manager *mgr)
0227 {
0228 return dss_mgr_ops->enable(mgr);
0229 }
0230 EXPORT_SYMBOL(dss_mgr_enable);
0231
0232 void dss_mgr_disable(struct omap_overlay_manager *mgr)
0233 {
0234 dss_mgr_ops->disable(mgr);
0235 }
0236 EXPORT_SYMBOL(dss_mgr_disable);
0237
0238 void dss_mgr_start_update(struct omap_overlay_manager *mgr)
0239 {
0240 dss_mgr_ops->start_update(mgr);
0241 }
0242 EXPORT_SYMBOL(dss_mgr_start_update);
0243
0244 int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
0245 void (*handler)(void *), void *data)
0246 {
0247 return dss_mgr_ops->register_framedone_handler(mgr, handler, data);
0248 }
0249 EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
0250
0251 void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
0252 void (*handler)(void *), void *data)
0253 {
0254 dss_mgr_ops->unregister_framedone_handler(mgr, handler, data);
0255 }
0256 EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);