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