0001
0002
0003
0004
0005
0006
0007
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 }