0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define DSS_SUBSYS_NAME "OVERLAY"
0011
0012 #include <linux/module.h>
0013 #include <linux/err.h>
0014 #include <linux/sysfs.h>
0015 #include <linux/kobject.h>
0016 #include <linux/platform_device.h>
0017
0018 #include <video/omapfb_dss.h>
0019
0020 #include "dss.h"
0021 #include "dss_features.h"
0022
0023 static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
0024 {
0025 return sysfs_emit(buf, "%s\n", ovl->name);
0026 }
0027
0028 static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
0029 {
0030 return sysfs_emit(buf, "%s\n",
0031 ovl->manager ? ovl->manager->name : "<none>");
0032 }
0033
0034 static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
0035 size_t size)
0036 {
0037 int i, r;
0038 struct omap_overlay_manager *mgr = NULL;
0039 struct omap_overlay_manager *old_mgr;
0040 int len = size;
0041
0042 if (buf[size-1] == '\n')
0043 --len;
0044
0045 if (len > 0) {
0046 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
0047 mgr = omap_dss_get_overlay_manager(i);
0048
0049 if (sysfs_streq(buf, mgr->name))
0050 break;
0051
0052 mgr = NULL;
0053 }
0054 }
0055
0056 if (len > 0 && mgr == NULL)
0057 return -EINVAL;
0058
0059 if (mgr)
0060 DSSDBG("manager %s found\n", mgr->name);
0061
0062 if (mgr == ovl->manager)
0063 return size;
0064
0065 old_mgr = ovl->manager;
0066
0067 r = dispc_runtime_get();
0068 if (r)
0069 return r;
0070
0071
0072 if (old_mgr) {
0073 r = ovl->unset_manager(ovl);
0074 if (r) {
0075 DSSERR("detach failed\n");
0076 goto err;
0077 }
0078
0079 r = old_mgr->apply(old_mgr);
0080 if (r)
0081 goto err;
0082 }
0083
0084 if (mgr) {
0085 r = ovl->set_manager(ovl, mgr);
0086 if (r) {
0087 DSSERR("Failed to attach overlay\n");
0088 goto err;
0089 }
0090
0091 r = mgr->apply(mgr);
0092 if (r)
0093 goto err;
0094 }
0095
0096 dispc_runtime_put();
0097
0098 return size;
0099
0100 err:
0101 dispc_runtime_put();
0102 return r;
0103 }
0104
0105 static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
0106 {
0107 struct omap_overlay_info info;
0108
0109 ovl->get_overlay_info(ovl, &info);
0110
0111 return sysfs_emit(buf, "%d,%d\n",
0112 info.width, info.height);
0113 }
0114
0115 static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
0116 {
0117 struct omap_overlay_info info;
0118
0119 ovl->get_overlay_info(ovl, &info);
0120
0121 return sysfs_emit(buf, "%d\n", info.screen_width);
0122 }
0123
0124 static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
0125 {
0126 struct omap_overlay_info info;
0127
0128 ovl->get_overlay_info(ovl, &info);
0129
0130 return sysfs_emit(buf, "%d,%d\n",
0131 info.pos_x, info.pos_y);
0132 }
0133
0134 static ssize_t overlay_position_store(struct omap_overlay *ovl,
0135 const char *buf, size_t size)
0136 {
0137 int r;
0138 char *last;
0139 struct omap_overlay_info info;
0140
0141 ovl->get_overlay_info(ovl, &info);
0142
0143 info.pos_x = simple_strtoul(buf, &last, 10);
0144 ++last;
0145 if (last - buf >= size)
0146 return -EINVAL;
0147
0148 info.pos_y = simple_strtoul(last, &last, 10);
0149
0150 r = ovl->set_overlay_info(ovl, &info);
0151 if (r)
0152 return r;
0153
0154 if (ovl->manager) {
0155 r = ovl->manager->apply(ovl->manager);
0156 if (r)
0157 return r;
0158 }
0159
0160 return size;
0161 }
0162
0163 static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
0164 {
0165 struct omap_overlay_info info;
0166
0167 ovl->get_overlay_info(ovl, &info);
0168
0169 return sysfs_emit(buf, "%d,%d\n",
0170 info.out_width, info.out_height);
0171 }
0172
0173 static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
0174 const char *buf, size_t size)
0175 {
0176 int r;
0177 char *last;
0178 struct omap_overlay_info info;
0179
0180 ovl->get_overlay_info(ovl, &info);
0181
0182 info.out_width = simple_strtoul(buf, &last, 10);
0183 ++last;
0184 if (last - buf >= size)
0185 return -EINVAL;
0186
0187 info.out_height = simple_strtoul(last, &last, 10);
0188
0189 r = ovl->set_overlay_info(ovl, &info);
0190 if (r)
0191 return r;
0192
0193 if (ovl->manager) {
0194 r = ovl->manager->apply(ovl->manager);
0195 if (r)
0196 return r;
0197 }
0198
0199 return size;
0200 }
0201
0202 static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
0203 {
0204 return sysfs_emit(buf, "%d\n", ovl->is_enabled(ovl));
0205 }
0206
0207 static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
0208 size_t size)
0209 {
0210 int r;
0211 bool enable;
0212
0213 r = strtobool(buf, &enable);
0214 if (r)
0215 return r;
0216
0217 if (enable)
0218 r = ovl->enable(ovl);
0219 else
0220 r = ovl->disable(ovl);
0221
0222 if (r)
0223 return r;
0224
0225 return size;
0226 }
0227
0228 static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
0229 {
0230 struct omap_overlay_info info;
0231
0232 ovl->get_overlay_info(ovl, &info);
0233
0234 return sysfs_emit(buf, "%d\n",
0235 info.global_alpha);
0236 }
0237
0238 static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
0239 const char *buf, size_t size)
0240 {
0241 int r;
0242 u8 alpha;
0243 struct omap_overlay_info info;
0244
0245 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
0246 return -ENODEV;
0247
0248 r = kstrtou8(buf, 0, &alpha);
0249 if (r)
0250 return r;
0251
0252 ovl->get_overlay_info(ovl, &info);
0253
0254 info.global_alpha = alpha;
0255
0256 r = ovl->set_overlay_info(ovl, &info);
0257 if (r)
0258 return r;
0259
0260 if (ovl->manager) {
0261 r = ovl->manager->apply(ovl->manager);
0262 if (r)
0263 return r;
0264 }
0265
0266 return size;
0267 }
0268
0269 static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
0270 char *buf)
0271 {
0272 struct omap_overlay_info info;
0273
0274 ovl->get_overlay_info(ovl, &info);
0275
0276 return sysfs_emit(buf, "%d\n",
0277 info.pre_mult_alpha);
0278 }
0279
0280 static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
0281 const char *buf, size_t size)
0282 {
0283 int r;
0284 u8 alpha;
0285 struct omap_overlay_info info;
0286
0287 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
0288 return -ENODEV;
0289
0290 r = kstrtou8(buf, 0, &alpha);
0291 if (r)
0292 return r;
0293
0294 ovl->get_overlay_info(ovl, &info);
0295
0296 info.pre_mult_alpha = alpha;
0297
0298 r = ovl->set_overlay_info(ovl, &info);
0299 if (r)
0300 return r;
0301
0302 if (ovl->manager) {
0303 r = ovl->manager->apply(ovl->manager);
0304 if (r)
0305 return r;
0306 }
0307
0308 return size;
0309 }
0310
0311 static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
0312 {
0313 struct omap_overlay_info info;
0314
0315 ovl->get_overlay_info(ovl, &info);
0316
0317 return sysfs_emit(buf, "%d\n", info.zorder);
0318 }
0319
0320 static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
0321 const char *buf, size_t size)
0322 {
0323 int r;
0324 u8 zorder;
0325 struct omap_overlay_info info;
0326
0327 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
0328 return -ENODEV;
0329
0330 r = kstrtou8(buf, 0, &zorder);
0331 if (r)
0332 return r;
0333
0334 ovl->get_overlay_info(ovl, &info);
0335
0336 info.zorder = zorder;
0337
0338 r = ovl->set_overlay_info(ovl, &info);
0339 if (r)
0340 return r;
0341
0342 if (ovl->manager) {
0343 r = ovl->manager->apply(ovl->manager);
0344 if (r)
0345 return r;
0346 }
0347
0348 return size;
0349 }
0350
0351 struct overlay_attribute {
0352 struct attribute attr;
0353 ssize_t (*show)(struct omap_overlay *, char *);
0354 ssize_t (*store)(struct omap_overlay *, const char *, size_t);
0355 };
0356
0357 #define OVERLAY_ATTR(_name, _mode, _show, _store) \
0358 struct overlay_attribute overlay_attr_##_name = \
0359 __ATTR(_name, _mode, _show, _store)
0360
0361 static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
0362 static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
0363 overlay_manager_show, overlay_manager_store);
0364 static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
0365 static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
0366 static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
0367 overlay_position_show, overlay_position_store);
0368 static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
0369 overlay_output_size_show, overlay_output_size_store);
0370 static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
0371 overlay_enabled_show, overlay_enabled_store);
0372 static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
0373 overlay_global_alpha_show, overlay_global_alpha_store);
0374 static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
0375 overlay_pre_mult_alpha_show,
0376 overlay_pre_mult_alpha_store);
0377 static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
0378 overlay_zorder_show, overlay_zorder_store);
0379
0380 static struct attribute *overlay_sysfs_attrs[] = {
0381 &overlay_attr_name.attr,
0382 &overlay_attr_manager.attr,
0383 &overlay_attr_input_size.attr,
0384 &overlay_attr_screen_width.attr,
0385 &overlay_attr_position.attr,
0386 &overlay_attr_output_size.attr,
0387 &overlay_attr_enabled.attr,
0388 &overlay_attr_global_alpha.attr,
0389 &overlay_attr_pre_mult_alpha.attr,
0390 &overlay_attr_zorder.attr,
0391 NULL
0392 };
0393 ATTRIBUTE_GROUPS(overlay_sysfs);
0394
0395 static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
0396 char *buf)
0397 {
0398 struct omap_overlay *overlay;
0399 struct overlay_attribute *overlay_attr;
0400
0401 overlay = container_of(kobj, struct omap_overlay, kobj);
0402 overlay_attr = container_of(attr, struct overlay_attribute, attr);
0403
0404 if (!overlay_attr->show)
0405 return -ENOENT;
0406
0407 return overlay_attr->show(overlay, buf);
0408 }
0409
0410 static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
0411 const char *buf, size_t size)
0412 {
0413 struct omap_overlay *overlay;
0414 struct overlay_attribute *overlay_attr;
0415
0416 overlay = container_of(kobj, struct omap_overlay, kobj);
0417 overlay_attr = container_of(attr, struct overlay_attribute, attr);
0418
0419 if (!overlay_attr->store)
0420 return -ENOENT;
0421
0422 return overlay_attr->store(overlay, buf, size);
0423 }
0424
0425 static const struct sysfs_ops overlay_sysfs_ops = {
0426 .show = overlay_attr_show,
0427 .store = overlay_attr_store,
0428 };
0429
0430 static struct kobj_type overlay_ktype = {
0431 .sysfs_ops = &overlay_sysfs_ops,
0432 .default_groups = overlay_sysfs_groups,
0433 };
0434
0435 int dss_overlay_kobj_init(struct omap_overlay *ovl,
0436 struct platform_device *pdev)
0437 {
0438 return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
0439 &pdev->dev.kobj, "overlay%d", ovl->id);
0440 }
0441
0442 void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
0443 {
0444 kobject_del(&ovl->kobj);
0445 kobject_put(&ovl->kobj);
0446 }