manager-sysfs.c (11205B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2009 Nokia Corporation 4 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> 5 * 6 * Some code and ideas taken from drivers/video/omap/ driver 7 * by Imre Deak. 8 */ 9 10#define DSS_SUBSYS_NAME "MANAGER" 11 12#include <linux/kernel.h> 13#include <linux/slab.h> 14#include <linux/module.h> 15#include <linux/platform_device.h> 16#include <linux/jiffies.h> 17 18#include <video/omapfb_dss.h> 19 20#include "dss.h" 21#include "dss_features.h" 22 23static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) 24{ 25 return sysfs_emit(buf, "%s\n", mgr->name); 26} 27 28static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf) 29{ 30 struct omap_dss_device *dssdev = mgr->get_device(mgr); 31 32 return sysfs_emit(buf, "%s\n", dssdev ? 33 dssdev->name : "<none>"); 34} 35 36static int manager_display_match(struct omap_dss_device *dssdev, void *data) 37{ 38 const char *str = data; 39 40 return sysfs_streq(dssdev->name, str); 41} 42 43static ssize_t manager_display_store(struct omap_overlay_manager *mgr, 44 const char *buf, size_t size) 45{ 46 int r = 0; 47 size_t len = size; 48 struct omap_dss_device *dssdev = NULL; 49 struct omap_dss_device *old_dssdev; 50 51 if (buf[size-1] == '\n') 52 --len; 53 54 if (len > 0) 55 dssdev = omap_dss_find_device((void *)buf, 56 manager_display_match); 57 58 if (len > 0 && dssdev == NULL) 59 return -EINVAL; 60 61 if (dssdev) { 62 DSSDBG("display %s found\n", dssdev->name); 63 64 if (omapdss_device_is_connected(dssdev)) { 65 DSSERR("new display is already connected\n"); 66 r = -EINVAL; 67 goto put_device; 68 } 69 70 if (omapdss_device_is_enabled(dssdev)) { 71 DSSERR("new display is not disabled\n"); 72 r = -EINVAL; 73 goto put_device; 74 } 75 } 76 77 old_dssdev = mgr->get_device(mgr); 78 if (old_dssdev) { 79 if (omapdss_device_is_enabled(old_dssdev)) { 80 DSSERR("old display is not disabled\n"); 81 r = -EINVAL; 82 goto put_device; 83 } 84 85 old_dssdev->driver->disconnect(old_dssdev); 86 } 87 88 if (dssdev) { 89 r = dssdev->driver->connect(dssdev); 90 if (r) { 91 DSSERR("failed to connect new device\n"); 92 goto put_device; 93 } 94 95 old_dssdev = mgr->get_device(mgr); 96 if (old_dssdev != dssdev) { 97 DSSERR("failed to connect device to this manager\n"); 98 dssdev->driver->disconnect(dssdev); 99 goto put_device; 100 } 101 102 r = mgr->apply(mgr); 103 if (r) { 104 DSSERR("failed to apply dispc config\n"); 105 goto put_device; 106 } 107 } 108 109put_device: 110 if (dssdev) 111 omap_dss_put_device(dssdev); 112 113 return r ? r : size; 114} 115 116static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr, 117 char *buf) 118{ 119 struct omap_overlay_manager_info info; 120 121 mgr->get_manager_info(mgr, &info); 122 123 return sysfs_emit(buf, "%#x\n", info.default_color); 124} 125 126static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, 127 const char *buf, size_t size) 128{ 129 struct omap_overlay_manager_info info; 130 u32 color; 131 int r; 132 133 r = kstrtouint(buf, 0, &color); 134 if (r) 135 return r; 136 137 mgr->get_manager_info(mgr, &info); 138 139 info.default_color = color; 140 141 r = mgr->set_manager_info(mgr, &info); 142 if (r) 143 return r; 144 145 r = mgr->apply(mgr); 146 if (r) 147 return r; 148 149 return size; 150} 151 152static const char *trans_key_type_str[] = { 153 "gfx-destination", 154 "video-source", 155}; 156 157static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr, 158 char *buf) 159{ 160 enum omap_dss_trans_key_type key_type; 161 struct omap_overlay_manager_info info; 162 163 mgr->get_manager_info(mgr, &info); 164 165 key_type = info.trans_key_type; 166 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str)); 167 168 return sysfs_emit(buf, "%s\n", trans_key_type_str[key_type]); 169} 170 171static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr, 172 const char *buf, size_t size) 173{ 174 struct omap_overlay_manager_info info; 175 int r; 176 177 r = sysfs_match_string(trans_key_type_str, buf); 178 if (r < 0) 179 return r; 180 181 mgr->get_manager_info(mgr, &info); 182 183 info.trans_key_type = r; 184 185 r = mgr->set_manager_info(mgr, &info); 186 if (r) 187 return r; 188 189 r = mgr->apply(mgr); 190 if (r) 191 return r; 192 193 return size; 194} 195 196static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr, 197 char *buf) 198{ 199 struct omap_overlay_manager_info info; 200 201 mgr->get_manager_info(mgr, &info); 202 203 return sysfs_emit(buf, "%#x\n", info.trans_key); 204} 205 206static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, 207 const char *buf, size_t size) 208{ 209 struct omap_overlay_manager_info info; 210 u32 key_value; 211 int r; 212 213 r = kstrtouint(buf, 0, &key_value); 214 if (r) 215 return r; 216 217 mgr->get_manager_info(mgr, &info); 218 219 info.trans_key = key_value; 220 221 r = mgr->set_manager_info(mgr, &info); 222 if (r) 223 return r; 224 225 r = mgr->apply(mgr); 226 if (r) 227 return r; 228 229 return size; 230} 231 232static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr, 233 char *buf) 234{ 235 struct omap_overlay_manager_info info; 236 237 mgr->get_manager_info(mgr, &info); 238 239 return sysfs_emit(buf, "%d\n", info.trans_enabled); 240} 241 242static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr, 243 const char *buf, size_t size) 244{ 245 struct omap_overlay_manager_info info; 246 bool enable; 247 int r; 248 249 r = strtobool(buf, &enable); 250 if (r) 251 return r; 252 253 mgr->get_manager_info(mgr, &info); 254 255 info.trans_enabled = enable; 256 257 r = mgr->set_manager_info(mgr, &info); 258 if (r) 259 return r; 260 261 r = mgr->apply(mgr); 262 if (r) 263 return r; 264 265 return size; 266} 267 268static ssize_t manager_alpha_blending_enabled_show( 269 struct omap_overlay_manager *mgr, char *buf) 270{ 271 struct omap_overlay_manager_info info; 272 273 if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) 274 return -ENODEV; 275 276 mgr->get_manager_info(mgr, &info); 277 278 return sysfs_emit(buf, "%d\n", 279 info.partial_alpha_enabled); 280} 281 282static ssize_t manager_alpha_blending_enabled_store( 283 struct omap_overlay_manager *mgr, 284 const char *buf, size_t size) 285{ 286 struct omap_overlay_manager_info info; 287 bool enable; 288 int r; 289 290 if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) 291 return -ENODEV; 292 293 r = strtobool(buf, &enable); 294 if (r) 295 return r; 296 297 mgr->get_manager_info(mgr, &info); 298 299 info.partial_alpha_enabled = enable; 300 301 r = mgr->set_manager_info(mgr, &info); 302 if (r) 303 return r; 304 305 r = mgr->apply(mgr); 306 if (r) 307 return r; 308 309 return size; 310} 311 312static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr, 313 char *buf) 314{ 315 struct omap_overlay_manager_info info; 316 317 mgr->get_manager_info(mgr, &info); 318 319 return sysfs_emit(buf, "%d\n", info.cpr_enable); 320} 321 322static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr, 323 const char *buf, size_t size) 324{ 325 struct omap_overlay_manager_info info; 326 int r; 327 bool enable; 328 329 if (!dss_has_feature(FEAT_CPR)) 330 return -ENODEV; 331 332 r = strtobool(buf, &enable); 333 if (r) 334 return r; 335 336 mgr->get_manager_info(mgr, &info); 337 338 if (info.cpr_enable == enable) 339 return size; 340 341 info.cpr_enable = enable; 342 343 r = mgr->set_manager_info(mgr, &info); 344 if (r) 345 return r; 346 347 r = mgr->apply(mgr); 348 if (r) 349 return r; 350 351 return size; 352} 353 354static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr, 355 char *buf) 356{ 357 struct omap_overlay_manager_info info; 358 359 mgr->get_manager_info(mgr, &info); 360 361 return sysfs_emit(buf, 362 "%d %d %d %d %d %d %d %d %d\n", 363 info.cpr_coefs.rr, 364 info.cpr_coefs.rg, 365 info.cpr_coefs.rb, 366 info.cpr_coefs.gr, 367 info.cpr_coefs.gg, 368 info.cpr_coefs.gb, 369 info.cpr_coefs.br, 370 info.cpr_coefs.bg, 371 info.cpr_coefs.bb); 372} 373 374static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr, 375 const char *buf, size_t size) 376{ 377 struct omap_overlay_manager_info info; 378 struct omap_dss_cpr_coefs coefs; 379 int r, i; 380 s16 *arr; 381 382 if (!dss_has_feature(FEAT_CPR)) 383 return -ENODEV; 384 385 if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd", 386 &coefs.rr, &coefs.rg, &coefs.rb, 387 &coefs.gr, &coefs.gg, &coefs.gb, 388 &coefs.br, &coefs.bg, &coefs.bb) != 9) 389 return -EINVAL; 390 391 arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb, 392 coefs.gr, coefs.gg, coefs.gb, 393 coefs.br, coefs.bg, coefs.bb }; 394 395 for (i = 0; i < 9; ++i) { 396 if (arr[i] < -512 || arr[i] > 511) 397 return -EINVAL; 398 } 399 400 mgr->get_manager_info(mgr, &info); 401 402 info.cpr_coefs = coefs; 403 404 r = mgr->set_manager_info(mgr, &info); 405 if (r) 406 return r; 407 408 r = mgr->apply(mgr); 409 if (r) 410 return r; 411 412 return size; 413} 414 415struct manager_attribute { 416 struct attribute attr; 417 ssize_t (*show)(struct omap_overlay_manager *, char *); 418 ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t); 419}; 420 421#define MANAGER_ATTR(_name, _mode, _show, _store) \ 422 struct manager_attribute manager_attr_##_name = \ 423 __ATTR(_name, _mode, _show, _store) 424 425static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL); 426static MANAGER_ATTR(display, S_IRUGO|S_IWUSR, 427 manager_display_show, manager_display_store); 428static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR, 429 manager_default_color_show, manager_default_color_store); 430static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR, 431 manager_trans_key_type_show, manager_trans_key_type_store); 432static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR, 433 manager_trans_key_value_show, manager_trans_key_value_store); 434static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR, 435 manager_trans_key_enabled_show, 436 manager_trans_key_enabled_store); 437static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR, 438 manager_alpha_blending_enabled_show, 439 manager_alpha_blending_enabled_store); 440static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR, 441 manager_cpr_enable_show, 442 manager_cpr_enable_store); 443static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR, 444 manager_cpr_coef_show, 445 manager_cpr_coef_store); 446 447 448static struct attribute *manager_sysfs_attrs[] = { 449 &manager_attr_name.attr, 450 &manager_attr_display.attr, 451 &manager_attr_default_color.attr, 452 &manager_attr_trans_key_type.attr, 453 &manager_attr_trans_key_value.attr, 454 &manager_attr_trans_key_enabled.attr, 455 &manager_attr_alpha_blending_enabled.attr, 456 &manager_attr_cpr_enable.attr, 457 &manager_attr_cpr_coef.attr, 458 NULL 459}; 460ATTRIBUTE_GROUPS(manager_sysfs); 461 462static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr, 463 char *buf) 464{ 465 struct omap_overlay_manager *manager; 466 struct manager_attribute *manager_attr; 467 468 manager = container_of(kobj, struct omap_overlay_manager, kobj); 469 manager_attr = container_of(attr, struct manager_attribute, attr); 470 471 if (!manager_attr->show) 472 return -ENOENT; 473 474 return manager_attr->show(manager, buf); 475} 476 477static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr, 478 const char *buf, size_t size) 479{ 480 struct omap_overlay_manager *manager; 481 struct manager_attribute *manager_attr; 482 483 manager = container_of(kobj, struct omap_overlay_manager, kobj); 484 manager_attr = container_of(attr, struct manager_attribute, attr); 485 486 if (!manager_attr->store) 487 return -ENOENT; 488 489 return manager_attr->store(manager, buf, size); 490} 491 492static const struct sysfs_ops manager_sysfs_ops = { 493 .show = manager_attr_show, 494 .store = manager_attr_store, 495}; 496 497static struct kobj_type manager_ktype = { 498 .sysfs_ops = &manager_sysfs_ops, 499 .default_groups = manager_sysfs_groups, 500}; 501 502int dss_manager_kobj_init(struct omap_overlay_manager *mgr, 503 struct platform_device *pdev) 504{ 505 return kobject_init_and_add(&mgr->kobj, &manager_ktype, 506 &pdev->dev.kobj, "manager%d", mgr->id); 507} 508 509void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr) 510{ 511 kobject_del(&mgr->kobj); 512 kobject_put(&mgr->kobj); 513 514 memset(&mgr->kobj, 0, sizeof(mgr->kobj)); 515}