Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2009 Nokia Corporation
0004  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
0005  *
0006  * Some code and ideas taken from drivers/video/omap/ driver
0007  * by Imre Deak.
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     /* detach old manager */
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 }