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/omapfb_dss.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        struct omap_overlay_manager_info info;
 186        int r;
 187
 188        r = sysfs_match_string(trans_key_type_str, buf);
 189        if (r < 0)
 190                return r;
 191
 192        mgr->get_manager_info(mgr, &info);
 193
 194        info.trans_key_type = r;
 195
 196        r = mgr->set_manager_info(mgr, &info);
 197        if (r)
 198                return r;
 199
 200        r = mgr->apply(mgr);
 201        if (r)
 202                return r;
 203
 204        return size;
 205}
 206
 207static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
 208                                            char *buf)
 209{
 210        struct omap_overlay_manager_info info;
 211
 212        mgr->get_manager_info(mgr, &info);
 213
 214        return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
 215}
 216
 217static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
 218                                             const char *buf, size_t size)
 219{
 220        struct omap_overlay_manager_info info;
 221        u32 key_value;
 222        int r;
 223
 224        r = kstrtouint(buf, 0, &key_value);
 225        if (r)
 226                return r;
 227
 228        mgr->get_manager_info(mgr, &info);
 229
 230        info.trans_key = key_value;
 231
 232        r = mgr->set_manager_info(mgr, &info);
 233        if (r)
 234                return r;
 235
 236        r = mgr->apply(mgr);
 237        if (r)
 238                return r;
 239
 240        return size;
 241}
 242
 243static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
 244                                              char *buf)
 245{
 246        struct omap_overlay_manager_info info;
 247
 248        mgr->get_manager_info(mgr, &info);
 249
 250        return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
 251}
 252
 253static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
 254                                               const char *buf, size_t size)
 255{
 256        struct omap_overlay_manager_info info;
 257        bool enable;
 258        int r;
 259
 260        r = strtobool(buf, &enable);
 261        if (r)
 262                return r;
 263
 264        mgr->get_manager_info(mgr, &info);
 265
 266        info.trans_enabled = enable;
 267
 268        r = mgr->set_manager_info(mgr, &info);
 269        if (r)
 270                return r;
 271
 272        r = mgr->apply(mgr);
 273        if (r)
 274                return r;
 275
 276        return size;
 277}
 278
 279static ssize_t manager_alpha_blending_enabled_show(
 280                struct omap_overlay_manager *mgr, char *buf)
 281{
 282        struct omap_overlay_manager_info info;
 283
 284        if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
 285                return -ENODEV;
 286
 287        mgr->get_manager_info(mgr, &info);
 288
 289        return snprintf(buf, PAGE_SIZE, "%d\n",
 290                info.partial_alpha_enabled);
 291}
 292
 293static ssize_t manager_alpha_blending_enabled_store(
 294                struct omap_overlay_manager *mgr,
 295                const char *buf, size_t size)
 296{
 297        struct omap_overlay_manager_info info;
 298        bool enable;
 299        int r;
 300
 301        if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
 302                return -ENODEV;
 303
 304        r = strtobool(buf, &enable);
 305        if (r)
 306                return r;
 307
 308        mgr->get_manager_info(mgr, &info);
 309
 310        info.partial_alpha_enabled = enable;
 311
 312        r = mgr->set_manager_info(mgr, &info);
 313        if (r)
 314                return r;
 315
 316        r = mgr->apply(mgr);
 317        if (r)
 318                return r;
 319
 320        return size;
 321}
 322
 323static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
 324                char *buf)
 325{
 326        struct omap_overlay_manager_info info;
 327
 328        mgr->get_manager_info(mgr, &info);
 329
 330        return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
 331}
 332
 333static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
 334                const char *buf, size_t size)
 335{
 336        struct omap_overlay_manager_info info;
 337        int r;
 338        bool enable;
 339
 340        if (!dss_has_feature(FEAT_CPR))
 341                return -ENODEV;
 342
 343        r = strtobool(buf, &enable);
 344        if (r)
 345                return r;
 346
 347        mgr->get_manager_info(mgr, &info);
 348
 349        if (info.cpr_enable == enable)
 350                return size;
 351
 352        info.cpr_enable = enable;
 353
 354        r = mgr->set_manager_info(mgr, &info);
 355        if (r)
 356                return r;
 357
 358        r = mgr->apply(mgr);
 359        if (r)
 360                return r;
 361
 362        return size;
 363}
 364
 365static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
 366                char *buf)
 367{
 368        struct omap_overlay_manager_info info;
 369
 370        mgr->get_manager_info(mgr, &info);
 371
 372        return snprintf(buf, PAGE_SIZE,
 373                        "%d %d %d %d %d %d %d %d %d\n",
 374                        info.cpr_coefs.rr,
 375                        info.cpr_coefs.rg,
 376                        info.cpr_coefs.rb,
 377                        info.cpr_coefs.gr,
 378                        info.cpr_coefs.gg,
 379                        info.cpr_coefs.gb,
 380                        info.cpr_coefs.br,
 381                        info.cpr_coefs.bg,
 382                        info.cpr_coefs.bb);
 383}
 384
 385static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
 386                const char *buf, size_t size)
 387{
 388        struct omap_overlay_manager_info info;
 389        struct omap_dss_cpr_coefs coefs;
 390        int r, i;
 391        s16 *arr;
 392
 393        if (!dss_has_feature(FEAT_CPR))
 394                return -ENODEV;
 395
 396        if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
 397                                &coefs.rr, &coefs.rg, &coefs.rb,
 398                                &coefs.gr, &coefs.gg, &coefs.gb,
 399                                &coefs.br, &coefs.bg, &coefs.bb) != 9)
 400                return -EINVAL;
 401
 402        arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
 403                coefs.gr, coefs.gg, coefs.gb,
 404                coefs.br, coefs.bg, coefs.bb };
 405
 406        for (i = 0; i < 9; ++i) {
 407                if (arr[i] < -512 || arr[i] > 511)
 408                        return -EINVAL;
 409        }
 410
 411        mgr->get_manager_info(mgr, &info);
 412
 413        info.cpr_coefs = coefs;
 414
 415        r = mgr->set_manager_info(mgr, &info);
 416        if (r)
 417                return r;
 418
 419        r = mgr->apply(mgr);
 420        if (r)
 421                return r;
 422
 423        return size;
 424}
 425
 426struct manager_attribute {
 427        struct attribute attr;
 428        ssize_t (*show)(struct omap_overlay_manager *, char *);
 429        ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
 430};
 431
 432#define MANAGER_ATTR(_name, _mode, _show, _store) \
 433        struct manager_attribute manager_attr_##_name = \
 434        __ATTR(_name, _mode, _show, _store)
 435
 436static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
 437static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
 438                manager_display_show, manager_display_store);
 439static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
 440                manager_default_color_show, manager_default_color_store);
 441static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
 442                manager_trans_key_type_show, manager_trans_key_type_store);
 443static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
 444                manager_trans_key_value_show, manager_trans_key_value_store);
 445static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
 446                manager_trans_key_enabled_show,
 447                manager_trans_key_enabled_store);
 448static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
 449                manager_alpha_blending_enabled_show,
 450                manager_alpha_blending_enabled_store);
 451static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
 452                manager_cpr_enable_show,
 453                manager_cpr_enable_store);
 454static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
 455                manager_cpr_coef_show,
 456                manager_cpr_coef_store);
 457
 458
 459static struct attribute *manager_sysfs_attrs[] = {
 460        &manager_attr_name.attr,
 461        &manager_attr_display.attr,
 462        &manager_attr_default_color.attr,
 463        &manager_attr_trans_key_type.attr,
 464        &manager_attr_trans_key_value.attr,
 465        &manager_attr_trans_key_enabled.attr,
 466        &manager_attr_alpha_blending_enabled.attr,
 467        &manager_attr_cpr_enable.attr,
 468        &manager_attr_cpr_coef.attr,
 469        NULL
 470};
 471
 472static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
 473                char *buf)
 474{
 475        struct omap_overlay_manager *manager;
 476        struct manager_attribute *manager_attr;
 477
 478        manager = container_of(kobj, struct omap_overlay_manager, kobj);
 479        manager_attr = container_of(attr, struct manager_attribute, attr);
 480
 481        if (!manager_attr->show)
 482                return -ENOENT;
 483
 484        return manager_attr->show(manager, buf);
 485}
 486
 487static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
 488                const char *buf, size_t size)
 489{
 490        struct omap_overlay_manager *manager;
 491        struct manager_attribute *manager_attr;
 492
 493        manager = container_of(kobj, struct omap_overlay_manager, kobj);
 494        manager_attr = container_of(attr, struct manager_attribute, attr);
 495
 496        if (!manager_attr->store)
 497                return -ENOENT;
 498
 499        return manager_attr->store(manager, buf, size);
 500}
 501
 502static const struct sysfs_ops manager_sysfs_ops = {
 503        .show = manager_attr_show,
 504        .store = manager_attr_store,
 505};
 506
 507static struct kobj_type manager_ktype = {
 508        .sysfs_ops = &manager_sysfs_ops,
 509        .default_attrs = manager_sysfs_attrs,
 510};
 511
 512int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
 513                struct platform_device *pdev)
 514{
 515        return kobject_init_and_add(&mgr->kobj, &manager_ktype,
 516                        &pdev->dev.kobj, "manager%d", mgr->id);
 517}
 518
 519void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
 520{
 521        kobject_del(&mgr->kobj);
 522        kobject_put(&mgr->kobj);
 523
 524        memset(&mgr->kobj, 0, sizeof(mgr->kobj));
 525}
 526