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