linux/drivers/video/omap2/dss/overlay-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 "OVERLAY"
  22
  23#include <linux/module.h>
  24#include <linux/err.h>
  25#include <linux/sysfs.h>
  26#include <linux/kobject.h>
  27#include <linux/platform_device.h>
  28
  29#include <video/omapdss.h>
  30
  31#include "dss.h"
  32#include "dss_features.h"
  33
  34static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
  35{
  36        return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
  37}
  38
  39static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
  40{
  41        return snprintf(buf, PAGE_SIZE, "%s\n",
  42                        ovl->manager ? ovl->manager->name : "<none>");
  43}
  44
  45static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
  46                size_t size)
  47{
  48        int i, r;
  49        struct omap_overlay_manager *mgr = NULL;
  50        struct omap_overlay_manager *old_mgr;
  51        int len = size;
  52
  53        if (buf[size-1] == '\n')
  54                --len;
  55
  56        if (len > 0) {
  57                for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
  58                        mgr = omap_dss_get_overlay_manager(i);
  59
  60                        if (sysfs_streq(buf, mgr->name))
  61                                break;
  62
  63                        mgr = NULL;
  64                }
  65        }
  66
  67        if (len > 0 && mgr == NULL)
  68                return -EINVAL;
  69
  70        if (mgr)
  71                DSSDBG("manager %s found\n", mgr->name);
  72
  73        if (mgr == ovl->manager)
  74                return size;
  75
  76        old_mgr = ovl->manager;
  77
  78        r = dispc_runtime_get();
  79        if (r)
  80                return r;
  81
  82        /* detach old manager */
  83        if (old_mgr) {
  84                r = ovl->unset_manager(ovl);
  85                if (r) {
  86                        DSSERR("detach failed\n");
  87                        goto err;
  88                }
  89
  90                r = old_mgr->apply(old_mgr);
  91                if (r)
  92                        goto err;
  93        }
  94
  95        if (mgr) {
  96                r = ovl->set_manager(ovl, mgr);
  97                if (r) {
  98                        DSSERR("Failed to attach overlay\n");
  99                        goto err;
 100                }
 101
 102                r = mgr->apply(mgr);
 103                if (r)
 104                        goto err;
 105        }
 106
 107        dispc_runtime_put();
 108
 109        return size;
 110
 111err:
 112        dispc_runtime_put();
 113        return r;
 114}
 115
 116static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
 117{
 118        struct omap_overlay_info info;
 119
 120        ovl->get_overlay_info(ovl, &info);
 121
 122        return snprintf(buf, PAGE_SIZE, "%d,%d\n",
 123                        info.width, info.height);
 124}
 125
 126static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
 127{
 128        struct omap_overlay_info info;
 129
 130        ovl->get_overlay_info(ovl, &info);
 131
 132        return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
 133}
 134
 135static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
 136{
 137        struct omap_overlay_info info;
 138
 139        ovl->get_overlay_info(ovl, &info);
 140
 141        return snprintf(buf, PAGE_SIZE, "%d,%d\n",
 142                        info.pos_x, info.pos_y);
 143}
 144
 145static ssize_t overlay_position_store(struct omap_overlay *ovl,
 146                const char *buf, size_t size)
 147{
 148        int r;
 149        char *last;
 150        struct omap_overlay_info info;
 151
 152        ovl->get_overlay_info(ovl, &info);
 153
 154        info.pos_x = simple_strtoul(buf, &last, 10);
 155        ++last;
 156        if (last - buf >= size)
 157                return -EINVAL;
 158
 159        info.pos_y = simple_strtoul(last, &last, 10);
 160
 161        r = ovl->set_overlay_info(ovl, &info);
 162        if (r)
 163                return r;
 164
 165        if (ovl->manager) {
 166                r = ovl->manager->apply(ovl->manager);
 167                if (r)
 168                        return r;
 169        }
 170
 171        return size;
 172}
 173
 174static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
 175{
 176        struct omap_overlay_info info;
 177
 178        ovl->get_overlay_info(ovl, &info);
 179
 180        return snprintf(buf, PAGE_SIZE, "%d,%d\n",
 181                        info.out_width, info.out_height);
 182}
 183
 184static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
 185                const char *buf, size_t size)
 186{
 187        int r;
 188        char *last;
 189        struct omap_overlay_info info;
 190
 191        ovl->get_overlay_info(ovl, &info);
 192
 193        info.out_width = simple_strtoul(buf, &last, 10);
 194        ++last;
 195        if (last - buf >= size)
 196                return -EINVAL;
 197
 198        info.out_height = simple_strtoul(last, &last, 10);
 199
 200        r = ovl->set_overlay_info(ovl, &info);
 201        if (r)
 202                return r;
 203
 204        if (ovl->manager) {
 205                r = ovl->manager->apply(ovl->manager);
 206                if (r)
 207                        return r;
 208        }
 209
 210        return size;
 211}
 212
 213static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
 214{
 215        return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
 216}
 217
 218static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
 219                size_t size)
 220{
 221        int r;
 222        bool enable;
 223
 224        r = strtobool(buf, &enable);
 225        if (r)
 226                return r;
 227
 228        if (enable)
 229                r = ovl->enable(ovl);
 230        else
 231                r = ovl->disable(ovl);
 232
 233        if (r)
 234                return r;
 235
 236        return size;
 237}
 238
 239static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
 240{
 241        struct omap_overlay_info info;
 242
 243        ovl->get_overlay_info(ovl, &info);
 244
 245        return snprintf(buf, PAGE_SIZE, "%d\n",
 246                        info.global_alpha);
 247}
 248
 249static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
 250                const char *buf, size_t size)
 251{
 252        int r;
 253        u8 alpha;
 254        struct omap_overlay_info info;
 255
 256        if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
 257                return -ENODEV;
 258
 259        r = kstrtou8(buf, 0, &alpha);
 260        if (r)
 261                return r;
 262
 263        ovl->get_overlay_info(ovl, &info);
 264
 265        info.global_alpha = alpha;
 266
 267        r = ovl->set_overlay_info(ovl, &info);
 268        if (r)
 269                return r;
 270
 271        if (ovl->manager) {
 272                r = ovl->manager->apply(ovl->manager);
 273                if (r)
 274                        return r;
 275        }
 276
 277        return size;
 278}
 279
 280static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
 281                char *buf)
 282{
 283        struct omap_overlay_info info;
 284
 285        ovl->get_overlay_info(ovl, &info);
 286
 287        return snprintf(buf, PAGE_SIZE, "%d\n",
 288                        info.pre_mult_alpha);
 289}
 290
 291static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
 292                const char *buf, size_t size)
 293{
 294        int r;
 295        u8 alpha;
 296        struct omap_overlay_info info;
 297
 298        if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
 299                return -ENODEV;
 300
 301        r = kstrtou8(buf, 0, &alpha);
 302        if (r)
 303                return r;
 304
 305        ovl->get_overlay_info(ovl, &info);
 306
 307        info.pre_mult_alpha = alpha;
 308
 309        r = ovl->set_overlay_info(ovl, &info);
 310        if (r)
 311                return r;
 312
 313        if (ovl->manager) {
 314                r = ovl->manager->apply(ovl->manager);
 315                if (r)
 316                        return r;
 317        }
 318
 319        return size;
 320}
 321
 322static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
 323{
 324        struct omap_overlay_info info;
 325
 326        ovl->get_overlay_info(ovl, &info);
 327
 328        return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
 329}
 330
 331static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
 332                const char *buf, size_t size)
 333{
 334        int r;
 335        u8 zorder;
 336        struct omap_overlay_info info;
 337
 338        if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
 339                return -ENODEV;
 340
 341        r = kstrtou8(buf, 0, &zorder);
 342        if (r)
 343                return r;
 344
 345        ovl->get_overlay_info(ovl, &info);
 346
 347        info.zorder = zorder;
 348
 349        r = ovl->set_overlay_info(ovl, &info);
 350        if (r)
 351                return r;
 352
 353        if (ovl->manager) {
 354                r = ovl->manager->apply(ovl->manager);
 355                if (r)
 356                        return r;
 357        }
 358
 359        return size;
 360}
 361
 362struct overlay_attribute {
 363        struct attribute attr;
 364        ssize_t (*show)(struct omap_overlay *, char *);
 365        ssize_t (*store)(struct omap_overlay *, const char *, size_t);
 366};
 367
 368#define OVERLAY_ATTR(_name, _mode, _show, _store) \
 369        struct overlay_attribute overlay_attr_##_name = \
 370        __ATTR(_name, _mode, _show, _store)
 371
 372static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
 373static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
 374                overlay_manager_show, overlay_manager_store);
 375static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
 376static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
 377static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
 378                overlay_position_show, overlay_position_store);
 379static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
 380                overlay_output_size_show, overlay_output_size_store);
 381static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
 382                overlay_enabled_show, overlay_enabled_store);
 383static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
 384                overlay_global_alpha_show, overlay_global_alpha_store);
 385static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
 386                overlay_pre_mult_alpha_show,
 387                overlay_pre_mult_alpha_store);
 388static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
 389                overlay_zorder_show, overlay_zorder_store);
 390
 391static struct attribute *overlay_sysfs_attrs[] = {
 392        &overlay_attr_name.attr,
 393        &overlay_attr_manager.attr,
 394        &overlay_attr_input_size.attr,
 395        &overlay_attr_screen_width.attr,
 396        &overlay_attr_position.attr,
 397        &overlay_attr_output_size.attr,
 398        &overlay_attr_enabled.attr,
 399        &overlay_attr_global_alpha.attr,
 400        &overlay_attr_pre_mult_alpha.attr,
 401        &overlay_attr_zorder.attr,
 402        NULL
 403};
 404
 405static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
 406                char *buf)
 407{
 408        struct omap_overlay *overlay;
 409        struct overlay_attribute *overlay_attr;
 410
 411        overlay = container_of(kobj, struct omap_overlay, kobj);
 412        overlay_attr = container_of(attr, struct overlay_attribute, attr);
 413
 414        if (!overlay_attr->show)
 415                return -ENOENT;
 416
 417        return overlay_attr->show(overlay, buf);
 418}
 419
 420static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
 421                const char *buf, size_t size)
 422{
 423        struct omap_overlay *overlay;
 424        struct overlay_attribute *overlay_attr;
 425
 426        overlay = container_of(kobj, struct omap_overlay, kobj);
 427        overlay_attr = container_of(attr, struct overlay_attribute, attr);
 428
 429        if (!overlay_attr->store)
 430                return -ENOENT;
 431
 432        return overlay_attr->store(overlay, buf, size);
 433}
 434
 435static const struct sysfs_ops overlay_sysfs_ops = {
 436        .show = overlay_attr_show,
 437        .store = overlay_attr_store,
 438};
 439
 440static struct kobj_type overlay_ktype = {
 441        .sysfs_ops = &overlay_sysfs_ops,
 442        .default_attrs = overlay_sysfs_attrs,
 443};
 444
 445int dss_overlay_kobj_init(struct omap_overlay *ovl,
 446                struct platform_device *pdev)
 447{
 448        return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
 449                        &pdev->dev.kobj, "overlay%d", ovl->id);
 450}
 451
 452void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
 453{
 454        kobject_del(&ovl->kobj);
 455        kobject_put(&ovl->kobj);
 456}
 457