0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/slab.h>
0011 #include <linux/dma-mapping.h>
0012 #include <linux/export.h>
0013 #include <linux/module.h>
0014 #include <video/mmp_disp.h>
0015
0016 static struct mmp_overlay *path_get_overlay(struct mmp_path *path,
0017 int overlay_id)
0018 {
0019 if (path && overlay_id < path->overlay_num)
0020 return &path->overlays[overlay_id];
0021 return NULL;
0022 }
0023
0024 static int path_check_status(struct mmp_path *path)
0025 {
0026 int i;
0027 for (i = 0; i < path->overlay_num; i++)
0028 if (path->overlays[i].status)
0029 return 1;
0030
0031 return 0;
0032 }
0033
0034
0035
0036
0037
0038
0039
0040
0041 static int path_get_modelist(struct mmp_path *path,
0042 struct mmp_mode **modelist)
0043 {
0044 BUG_ON(!path || !modelist);
0045
0046 if (path->panel && path->panel->get_modelist)
0047 return path->panel->get_modelist(path->panel, modelist);
0048
0049 return 0;
0050 }
0051
0052
0053
0054
0055
0056
0057
0058
0059 static LIST_HEAD(panel_list);
0060 static LIST_HEAD(path_list);
0061 static DEFINE_MUTEX(disp_lock);
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 void mmp_register_panel(struct mmp_panel *panel)
0073 {
0074 struct mmp_path *path;
0075
0076 mutex_lock(&disp_lock);
0077
0078
0079 list_add_tail(&panel->node, &panel_list);
0080
0081
0082 list_for_each_entry(path, &path_list, node) {
0083 if (!strcmp(panel->plat_path_name, path->name)) {
0084 dev_info(panel->dev, "connect to path %s\n",
0085 path->name);
0086 path->panel = panel;
0087 break;
0088 }
0089 }
0090
0091 mutex_unlock(&disp_lock);
0092 }
0093 EXPORT_SYMBOL_GPL(mmp_register_panel);
0094
0095
0096
0097
0098
0099
0100
0101
0102 void mmp_unregister_panel(struct mmp_panel *panel)
0103 {
0104 struct mmp_path *path;
0105
0106 mutex_lock(&disp_lock);
0107 list_del(&panel->node);
0108
0109 list_for_each_entry(path, &path_list, node) {
0110 if (path->panel && path->panel == panel) {
0111 dev_info(panel->dev, "disconnect from path %s\n",
0112 path->name);
0113 path->panel = NULL;
0114 break;
0115 }
0116 }
0117 mutex_unlock(&disp_lock);
0118 }
0119 EXPORT_SYMBOL_GPL(mmp_unregister_panel);
0120
0121
0122
0123
0124
0125
0126
0127
0128 struct mmp_path *mmp_get_path(const char *name)
0129 {
0130 struct mmp_path *path = NULL, *iter;
0131
0132 mutex_lock(&disp_lock);
0133 list_for_each_entry(iter, &path_list, node) {
0134 if (!strcmp(name, iter->name)) {
0135 path = iter;
0136 break;
0137 }
0138 }
0139 mutex_unlock(&disp_lock);
0140
0141 return path;
0142 }
0143 EXPORT_SYMBOL_GPL(mmp_get_path);
0144
0145
0146
0147
0148
0149
0150
0151
0152 struct mmp_path *mmp_register_path(struct mmp_path_info *info)
0153 {
0154 int i;
0155 struct mmp_path *path = NULL;
0156 struct mmp_panel *panel;
0157
0158 path = kzalloc(struct_size(path, overlays, info->overlay_num),
0159 GFP_KERNEL);
0160 if (!path)
0161 return NULL;
0162
0163
0164 mutex_init(&path->access_ok);
0165 path->dev = info->dev;
0166 path->id = info->id;
0167 path->name = info->name;
0168 path->output_type = info->output_type;
0169 path->overlay_num = info->overlay_num;
0170 path->plat_data = info->plat_data;
0171 path->ops.set_mode = info->set_mode;
0172
0173 mutex_lock(&disp_lock);
0174
0175 list_for_each_entry(panel, &panel_list, node) {
0176 if (!strcmp(info->name, panel->plat_path_name)) {
0177 dev_info(path->dev, "get panel %s\n", panel->name);
0178 path->panel = panel;
0179 break;
0180 }
0181 }
0182
0183 dev_info(path->dev, "register %s, overlay_num %d\n",
0184 path->name, path->overlay_num);
0185
0186
0187 if (!path->ops.check_status)
0188 path->ops.check_status = path_check_status;
0189 if (!path->ops.get_overlay)
0190 path->ops.get_overlay = path_get_overlay;
0191 if (!path->ops.get_modelist)
0192 path->ops.get_modelist = path_get_modelist;
0193
0194
0195 for (i = 0; i < path->overlay_num; i++) {
0196 path->overlays[i].path = path;
0197 path->overlays[i].id = i;
0198 mutex_init(&path->overlays[i].access_ok);
0199 path->overlays[i].ops = info->overlay_ops;
0200 }
0201
0202
0203 list_add_tail(&path->node, &path_list);
0204
0205 mutex_unlock(&disp_lock);
0206 return path;
0207 }
0208 EXPORT_SYMBOL_GPL(mmp_register_path);
0209
0210
0211
0212
0213
0214
0215
0216 void mmp_unregister_path(struct mmp_path *path)
0217 {
0218 int i;
0219
0220 if (!path)
0221 return;
0222
0223 mutex_lock(&disp_lock);
0224
0225 list_del(&path->node);
0226
0227
0228 for (i = 0; i < path->overlay_num; i++)
0229 mutex_destroy(&path->overlays[i].access_ok);
0230
0231 mutex_destroy(&path->access_ok);
0232
0233 kfree(path);
0234 mutex_unlock(&disp_lock);
0235 }
0236 EXPORT_SYMBOL_GPL(mmp_unregister_path);
0237
0238 MODULE_AUTHOR("Zhou Zhu <zzhu3@marvell.com>");
0239 MODULE_DESCRIPTION("Marvell MMP display framework");
0240 MODULE_LICENSE("GPL");