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 "MANAGER"
0011 
0012 #include <linux/kernel.h>
0013 #include <linux/slab.h>
0014 #include <linux/module.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/jiffies.h>
0017 
0018 #include <video/omapfb_dss.h>
0019 
0020 #include "dss.h"
0021 #include "dss_features.h"
0022 
0023 static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
0024 {
0025     return sysfs_emit(buf, "%s\n", mgr->name);
0026 }
0027 
0028 static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
0029 {
0030     struct omap_dss_device *dssdev = mgr->get_device(mgr);
0031 
0032     return sysfs_emit(buf, "%s\n", dssdev ?
0033             dssdev->name : "<none>");
0034 }
0035 
0036 static int manager_display_match(struct omap_dss_device *dssdev, void *data)
0037 {
0038     const char *str = data;
0039 
0040     return sysfs_streq(dssdev->name, str);
0041 }
0042 
0043 static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
0044         const char *buf, size_t size)
0045 {
0046     int r = 0;
0047     size_t len = size;
0048     struct omap_dss_device *dssdev = NULL;
0049     struct omap_dss_device *old_dssdev;
0050 
0051     if (buf[size-1] == '\n')
0052         --len;
0053 
0054     if (len > 0)
0055         dssdev = omap_dss_find_device((void *)buf,
0056             manager_display_match);
0057 
0058     if (len > 0 && dssdev == NULL)
0059         return -EINVAL;
0060 
0061     if (dssdev) {
0062         DSSDBG("display %s found\n", dssdev->name);
0063 
0064         if (omapdss_device_is_connected(dssdev)) {
0065             DSSERR("new display is already connected\n");
0066             r = -EINVAL;
0067             goto put_device;
0068         }
0069 
0070         if (omapdss_device_is_enabled(dssdev)) {
0071             DSSERR("new display is not disabled\n");
0072             r = -EINVAL;
0073             goto put_device;
0074         }
0075     }
0076 
0077     old_dssdev = mgr->get_device(mgr);
0078     if (old_dssdev) {
0079         if (omapdss_device_is_enabled(old_dssdev)) {
0080             DSSERR("old display is not disabled\n");
0081             r = -EINVAL;
0082             goto put_device;
0083         }
0084 
0085         old_dssdev->driver->disconnect(old_dssdev);
0086     }
0087 
0088     if (dssdev) {
0089         r = dssdev->driver->connect(dssdev);
0090         if (r) {
0091             DSSERR("failed to connect new device\n");
0092             goto put_device;
0093         }
0094 
0095         old_dssdev = mgr->get_device(mgr);
0096         if (old_dssdev != dssdev) {
0097             DSSERR("failed to connect device to this manager\n");
0098             dssdev->driver->disconnect(dssdev);
0099             goto put_device;
0100         }
0101 
0102         r = mgr->apply(mgr);
0103         if (r) {
0104             DSSERR("failed to apply dispc config\n");
0105             goto put_device;
0106         }
0107     }
0108 
0109 put_device:
0110     if (dssdev)
0111         omap_dss_put_device(dssdev);
0112 
0113     return r ? r : size;
0114 }
0115 
0116 static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
0117                       char *buf)
0118 {
0119     struct omap_overlay_manager_info info;
0120 
0121     mgr->get_manager_info(mgr, &info);
0122 
0123     return sysfs_emit(buf, "%#x\n", info.default_color);
0124 }
0125 
0126 static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
0127                        const char *buf, size_t size)
0128 {
0129     struct omap_overlay_manager_info info;
0130     u32 color;
0131     int r;
0132 
0133     r = kstrtouint(buf, 0, &color);
0134     if (r)
0135         return r;
0136 
0137     mgr->get_manager_info(mgr, &info);
0138 
0139     info.default_color = color;
0140 
0141     r = mgr->set_manager_info(mgr, &info);
0142     if (r)
0143         return r;
0144 
0145     r = mgr->apply(mgr);
0146     if (r)
0147         return r;
0148 
0149     return size;
0150 }
0151 
0152 static const char *trans_key_type_str[] = {
0153     "gfx-destination",
0154     "video-source",
0155 };
0156 
0157 static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
0158                        char *buf)
0159 {
0160     enum omap_dss_trans_key_type key_type;
0161     struct omap_overlay_manager_info info;
0162 
0163     mgr->get_manager_info(mgr, &info);
0164 
0165     key_type = info.trans_key_type;
0166     BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
0167 
0168     return sysfs_emit(buf, "%s\n", trans_key_type_str[key_type]);
0169 }
0170 
0171 static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
0172                         const char *buf, size_t size)
0173 {
0174     struct omap_overlay_manager_info info;
0175     int r;
0176 
0177     r = sysfs_match_string(trans_key_type_str, buf);
0178     if (r < 0)
0179         return r;
0180 
0181     mgr->get_manager_info(mgr, &info);
0182 
0183     info.trans_key_type = r;
0184 
0185     r = mgr->set_manager_info(mgr, &info);
0186     if (r)
0187         return r;
0188 
0189     r = mgr->apply(mgr);
0190     if (r)
0191         return r;
0192 
0193     return size;
0194 }
0195 
0196 static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
0197                         char *buf)
0198 {
0199     struct omap_overlay_manager_info info;
0200 
0201     mgr->get_manager_info(mgr, &info);
0202 
0203     return sysfs_emit(buf, "%#x\n", info.trans_key);
0204 }
0205 
0206 static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
0207                          const char *buf, size_t size)
0208 {
0209     struct omap_overlay_manager_info info;
0210     u32 key_value;
0211     int r;
0212 
0213     r = kstrtouint(buf, 0, &key_value);
0214     if (r)
0215         return r;
0216 
0217     mgr->get_manager_info(mgr, &info);
0218 
0219     info.trans_key = key_value;
0220 
0221     r = mgr->set_manager_info(mgr, &info);
0222     if (r)
0223         return r;
0224 
0225     r = mgr->apply(mgr);
0226     if (r)
0227         return r;
0228 
0229     return size;
0230 }
0231 
0232 static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
0233                           char *buf)
0234 {
0235     struct omap_overlay_manager_info info;
0236 
0237     mgr->get_manager_info(mgr, &info);
0238 
0239     return sysfs_emit(buf, "%d\n", info.trans_enabled);
0240 }
0241 
0242 static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
0243                            const char *buf, size_t size)
0244 {
0245     struct omap_overlay_manager_info info;
0246     bool enable;
0247     int r;
0248 
0249     r = strtobool(buf, &enable);
0250     if (r)
0251         return r;
0252 
0253     mgr->get_manager_info(mgr, &info);
0254 
0255     info.trans_enabled = enable;
0256 
0257     r = mgr->set_manager_info(mgr, &info);
0258     if (r)
0259         return r;
0260 
0261     r = mgr->apply(mgr);
0262     if (r)
0263         return r;
0264 
0265     return size;
0266 }
0267 
0268 static ssize_t manager_alpha_blending_enabled_show(
0269         struct omap_overlay_manager *mgr, char *buf)
0270 {
0271     struct omap_overlay_manager_info info;
0272 
0273     if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
0274         return -ENODEV;
0275 
0276     mgr->get_manager_info(mgr, &info);
0277 
0278     return sysfs_emit(buf, "%d\n",
0279         info.partial_alpha_enabled);
0280 }
0281 
0282 static ssize_t manager_alpha_blending_enabled_store(
0283         struct omap_overlay_manager *mgr,
0284         const char *buf, size_t size)
0285 {
0286     struct omap_overlay_manager_info info;
0287     bool enable;
0288     int r;
0289 
0290     if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
0291         return -ENODEV;
0292 
0293     r = strtobool(buf, &enable);
0294     if (r)
0295         return r;
0296 
0297     mgr->get_manager_info(mgr, &info);
0298 
0299     info.partial_alpha_enabled = enable;
0300 
0301     r = mgr->set_manager_info(mgr, &info);
0302     if (r)
0303         return r;
0304 
0305     r = mgr->apply(mgr);
0306     if (r)
0307         return r;
0308 
0309     return size;
0310 }
0311 
0312 static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
0313         char *buf)
0314 {
0315     struct omap_overlay_manager_info info;
0316 
0317     mgr->get_manager_info(mgr, &info);
0318 
0319     return sysfs_emit(buf, "%d\n", info.cpr_enable);
0320 }
0321 
0322 static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
0323         const char *buf, size_t size)
0324 {
0325     struct omap_overlay_manager_info info;
0326     int r;
0327     bool enable;
0328 
0329     if (!dss_has_feature(FEAT_CPR))
0330         return -ENODEV;
0331 
0332     r = strtobool(buf, &enable);
0333     if (r)
0334         return r;
0335 
0336     mgr->get_manager_info(mgr, &info);
0337 
0338     if (info.cpr_enable == enable)
0339         return size;
0340 
0341     info.cpr_enable = enable;
0342 
0343     r = mgr->set_manager_info(mgr, &info);
0344     if (r)
0345         return r;
0346 
0347     r = mgr->apply(mgr);
0348     if (r)
0349         return r;
0350 
0351     return size;
0352 }
0353 
0354 static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
0355         char *buf)
0356 {
0357     struct omap_overlay_manager_info info;
0358 
0359     mgr->get_manager_info(mgr, &info);
0360 
0361     return sysfs_emit(buf,
0362             "%d %d %d %d %d %d %d %d %d\n",
0363             info.cpr_coefs.rr,
0364             info.cpr_coefs.rg,
0365             info.cpr_coefs.rb,
0366             info.cpr_coefs.gr,
0367             info.cpr_coefs.gg,
0368             info.cpr_coefs.gb,
0369             info.cpr_coefs.br,
0370             info.cpr_coefs.bg,
0371             info.cpr_coefs.bb);
0372 }
0373 
0374 static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
0375         const char *buf, size_t size)
0376 {
0377     struct omap_overlay_manager_info info;
0378     struct omap_dss_cpr_coefs coefs;
0379     int r, i;
0380     s16 *arr;
0381 
0382     if (!dss_has_feature(FEAT_CPR))
0383         return -ENODEV;
0384 
0385     if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
0386                 &coefs.rr, &coefs.rg, &coefs.rb,
0387                 &coefs.gr, &coefs.gg, &coefs.gb,
0388                 &coefs.br, &coefs.bg, &coefs.bb) != 9)
0389         return -EINVAL;
0390 
0391     arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
0392         coefs.gr, coefs.gg, coefs.gb,
0393         coefs.br, coefs.bg, coefs.bb };
0394 
0395     for (i = 0; i < 9; ++i) {
0396         if (arr[i] < -512 || arr[i] > 511)
0397             return -EINVAL;
0398     }
0399 
0400     mgr->get_manager_info(mgr, &info);
0401 
0402     info.cpr_coefs = coefs;
0403 
0404     r = mgr->set_manager_info(mgr, &info);
0405     if (r)
0406         return r;
0407 
0408     r = mgr->apply(mgr);
0409     if (r)
0410         return r;
0411 
0412     return size;
0413 }
0414 
0415 struct manager_attribute {
0416     struct attribute attr;
0417     ssize_t (*show)(struct omap_overlay_manager *, char *);
0418     ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
0419 };
0420 
0421 #define MANAGER_ATTR(_name, _mode, _show, _store) \
0422     struct manager_attribute manager_attr_##_name = \
0423     __ATTR(_name, _mode, _show, _store)
0424 
0425 static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
0426 static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
0427         manager_display_show, manager_display_store);
0428 static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
0429         manager_default_color_show, manager_default_color_store);
0430 static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
0431         manager_trans_key_type_show, manager_trans_key_type_store);
0432 static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
0433         manager_trans_key_value_show, manager_trans_key_value_store);
0434 static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
0435         manager_trans_key_enabled_show,
0436         manager_trans_key_enabled_store);
0437 static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
0438         manager_alpha_blending_enabled_show,
0439         manager_alpha_blending_enabled_store);
0440 static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
0441         manager_cpr_enable_show,
0442         manager_cpr_enable_store);
0443 static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
0444         manager_cpr_coef_show,
0445         manager_cpr_coef_store);
0446 
0447 
0448 static struct attribute *manager_sysfs_attrs[] = {
0449     &manager_attr_name.attr,
0450     &manager_attr_display.attr,
0451     &manager_attr_default_color.attr,
0452     &manager_attr_trans_key_type.attr,
0453     &manager_attr_trans_key_value.attr,
0454     &manager_attr_trans_key_enabled.attr,
0455     &manager_attr_alpha_blending_enabled.attr,
0456     &manager_attr_cpr_enable.attr,
0457     &manager_attr_cpr_coef.attr,
0458     NULL
0459 };
0460 ATTRIBUTE_GROUPS(manager_sysfs);
0461 
0462 static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
0463         char *buf)
0464 {
0465     struct omap_overlay_manager *manager;
0466     struct manager_attribute *manager_attr;
0467 
0468     manager = container_of(kobj, struct omap_overlay_manager, kobj);
0469     manager_attr = container_of(attr, struct manager_attribute, attr);
0470 
0471     if (!manager_attr->show)
0472         return -ENOENT;
0473 
0474     return manager_attr->show(manager, buf);
0475 }
0476 
0477 static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
0478         const char *buf, size_t size)
0479 {
0480     struct omap_overlay_manager *manager;
0481     struct manager_attribute *manager_attr;
0482 
0483     manager = container_of(kobj, struct omap_overlay_manager, kobj);
0484     manager_attr = container_of(attr, struct manager_attribute, attr);
0485 
0486     if (!manager_attr->store)
0487         return -ENOENT;
0488 
0489     return manager_attr->store(manager, buf, size);
0490 }
0491 
0492 static const struct sysfs_ops manager_sysfs_ops = {
0493     .show = manager_attr_show,
0494     .store = manager_attr_store,
0495 };
0496 
0497 static struct kobj_type manager_ktype = {
0498     .sysfs_ops = &manager_sysfs_ops,
0499     .default_groups = manager_sysfs_groups,
0500 };
0501 
0502 int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
0503         struct platform_device *pdev)
0504 {
0505     return kobject_init_and_add(&mgr->kobj, &manager_ktype,
0506             &pdev->dev.kobj, "manager%d", mgr->id);
0507 }
0508 
0509 void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
0510 {
0511     kobject_del(&mgr->kobj);
0512     kobject_put(&mgr->kobj);
0513 
0514     memset(&mgr->kobj, 0, sizeof(mgr->kobj));
0515 }