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