linux/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
<<
>>
Prefs
   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 snprintf(buf, PAGE_SIZE, "%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 snprintf(buf, PAGE_SIZE, "%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 snprintf(buf, PAGE_SIZE, "%#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 snprintf(buf, PAGE_SIZE, "%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 snprintf(buf, PAGE_SIZE, "%#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 snprintf(buf, PAGE_SIZE, "%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 snprintf(buf, PAGE_SIZE, "%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 snprintf(buf, PAGE_SIZE, "%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 snprintf(buf, PAGE_SIZE,
 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};
 460
 461static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
 462                char *buf)
 463{
 464        struct omap_overlay_manager *manager;
 465        struct manager_attribute *manager_attr;
 466
 467        manager = container_of(kobj, struct omap_overlay_manager, kobj);
 468        manager_attr = container_of(attr, struct manager_attribute, attr);
 469
 470        if (!manager_attr->show)
 471                return -ENOENT;
 472
 473        return manager_attr->show(manager, buf);
 474}
 475
 476static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
 477                const char *buf, size_t size)
 478{
 479        struct omap_overlay_manager *manager;
 480        struct manager_attribute *manager_attr;
 481
 482        manager = container_of(kobj, struct omap_overlay_manager, kobj);
 483        manager_attr = container_of(attr, struct manager_attribute, attr);
 484
 485        if (!manager_attr->store)
 486                return -ENOENT;
 487
 488        return manager_attr->store(manager, buf, size);
 489}
 490
 491static const struct sysfs_ops manager_sysfs_ops = {
 492        .show = manager_attr_show,
 493        .store = manager_attr_store,
 494};
 495
 496static struct kobj_type manager_ktype = {
 497        .sysfs_ops = &manager_sysfs_ops,
 498        .default_attrs = manager_sysfs_attrs,
 499};
 500
 501int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
 502                struct platform_device *pdev)
 503{
 504        return kobject_init_and_add(&mgr->kobj, &manager_ktype,
 505                        &pdev->dev.kobj, "manager%d", mgr->id);
 506}
 507
 508void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
 509{
 510        kobject_del(&mgr->kobj);
 511        kobject_put(&mgr->kobj);
 512
 513        memset(&mgr->kobj, 0, sizeof(mgr->kobj));
 514}
 515