root/drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. show_rotate_type
  2. store_rotate_type
  3. show_mirror
  4. store_mirror
  5. show_overlays
  6. get_overlay_fb
  7. store_overlays
  8. show_overlays_rotate
  9. store_overlays_rotate
  10. show_size
  11. store_size
  12. show_phys
  13. show_virt
  14. show_upd_mode
  15. store_upd_mode
  16. omapfb_create_sysfs
  17. omapfb_remove_sysfs

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * linux/drivers/video/omap2/omapfb-sysfs.c
   4  *
   5  * Copyright (C) 2008 Nokia Corporation
   6  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
   7  *
   8  * Some code and ideas taken from drivers/video/omap/ driver
   9  * by Imre Deak.
  10  */
  11 
  12 #include <linux/fb.h>
  13 #include <linux/sysfs.h>
  14 #include <linux/device.h>
  15 #include <linux/uaccess.h>
  16 #include <linux/platform_device.h>
  17 #include <linux/kernel.h>
  18 #include <linux/mm.h>
  19 #include <linux/omapfb.h>
  20 
  21 #include <video/omapfb_dss.h>
  22 #include <video/omapvrfb.h>
  23 
  24 #include "omapfb.h"
  25 
  26 static ssize_t show_rotate_type(struct device *dev,
  27                 struct device_attribute *attr, char *buf)
  28 {
  29         struct fb_info *fbi = dev_get_drvdata(dev);
  30         struct omapfb_info *ofbi = FB2OFB(fbi);
  31 
  32         return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type);
  33 }
  34 
  35 static ssize_t store_rotate_type(struct device *dev,
  36                 struct device_attribute *attr,
  37                 const char *buf, size_t count)
  38 {
  39         struct fb_info *fbi = dev_get_drvdata(dev);
  40         struct omapfb_info *ofbi = FB2OFB(fbi);
  41         struct omapfb2_mem_region *rg;
  42         int rot_type;
  43         int r;
  44 
  45         r = kstrtoint(buf, 0, &rot_type);
  46         if (r)
  47                 return r;
  48 
  49         if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
  50                 return -EINVAL;
  51 
  52         lock_fb_info(fbi);
  53 
  54         r = 0;
  55         if (rot_type == ofbi->rotation_type)
  56                 goto out;
  57 
  58         rg = omapfb_get_mem_region(ofbi->region);
  59 
  60         if (rg->size) {
  61                 r = -EBUSY;
  62                 goto put_region;
  63         }
  64 
  65         ofbi->rotation_type = rot_type;
  66 
  67         /*
  68          * Since the VRAM for this FB is not allocated at the moment we don't
  69          * need to do any further parameter checking at this point.
  70          */
  71 put_region:
  72         omapfb_put_mem_region(rg);
  73 out:
  74         unlock_fb_info(fbi);
  75 
  76         return r ? r : count;
  77 }
  78 
  79 
  80 static ssize_t show_mirror(struct device *dev,
  81                 struct device_attribute *attr, char *buf)
  82 {
  83         struct fb_info *fbi = dev_get_drvdata(dev);
  84         struct omapfb_info *ofbi = FB2OFB(fbi);
  85 
  86         return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror);
  87 }
  88 
  89 static ssize_t store_mirror(struct device *dev,
  90                 struct device_attribute *attr,
  91                 const char *buf, size_t count)
  92 {
  93         struct fb_info *fbi = dev_get_drvdata(dev);
  94         struct omapfb_info *ofbi = FB2OFB(fbi);
  95         bool mirror;
  96         int r;
  97         struct fb_var_screeninfo new_var;
  98 
  99         r = strtobool(buf, &mirror);
 100         if (r)
 101                 return r;
 102 
 103         lock_fb_info(fbi);
 104 
 105         ofbi->mirror = mirror;
 106 
 107         omapfb_get_mem_region(ofbi->region);
 108 
 109         memcpy(&new_var, &fbi->var, sizeof(new_var));
 110         r = check_fb_var(fbi, &new_var);
 111         if (r)
 112                 goto out;
 113         memcpy(&fbi->var, &new_var, sizeof(fbi->var));
 114 
 115         set_fb_fix(fbi);
 116 
 117         r = omapfb_apply_changes(fbi, 0);
 118         if (r)
 119                 goto out;
 120 
 121         r = count;
 122 out:
 123         omapfb_put_mem_region(ofbi->region);
 124 
 125         unlock_fb_info(fbi);
 126 
 127         return r;
 128 }
 129 
 130 static ssize_t show_overlays(struct device *dev,
 131                 struct device_attribute *attr, char *buf)
 132 {
 133         struct fb_info *fbi = dev_get_drvdata(dev);
 134         struct omapfb_info *ofbi = FB2OFB(fbi);
 135         struct omapfb2_device *fbdev = ofbi->fbdev;
 136         ssize_t l = 0;
 137         int t;
 138 
 139         lock_fb_info(fbi);
 140         omapfb_lock(fbdev);
 141 
 142         for (t = 0; t < ofbi->num_overlays; t++) {
 143                 struct omap_overlay *ovl = ofbi->overlays[t];
 144                 int ovlnum;
 145 
 146                 for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum)
 147                         if (ovl == fbdev->overlays[ovlnum])
 148                                 break;
 149 
 150                 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
 151                                 t == 0 ? "" : ",", ovlnum);
 152         }
 153 
 154         l += snprintf(buf + l, PAGE_SIZE - l, "\n");
 155 
 156         omapfb_unlock(fbdev);
 157         unlock_fb_info(fbi);
 158 
 159         return l;
 160 }
 161 
 162 static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev,
 163                 struct omap_overlay *ovl)
 164 {
 165         int i, t;
 166 
 167         for (i = 0; i < fbdev->num_fbs; i++) {
 168                 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
 169 
 170                 for (t = 0; t < ofbi->num_overlays; t++) {
 171                         if (ofbi->overlays[t] == ovl)
 172                                 return ofbi;
 173                 }
 174         }
 175 
 176         return NULL;
 177 }
 178 
 179 static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
 180                 const char *buf, size_t count)
 181 {
 182         struct fb_info *fbi = dev_get_drvdata(dev);
 183         struct omapfb_info *ofbi = FB2OFB(fbi);
 184         struct omapfb2_device *fbdev = ofbi->fbdev;
 185         struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB];
 186         struct omap_overlay *ovl;
 187         int num_ovls, r, i;
 188         int len;
 189         bool added = false;
 190 
 191         num_ovls = 0;
 192 
 193         len = strlen(buf);
 194         if (buf[len - 1] == '\n')
 195                 len = len - 1;
 196 
 197         lock_fb_info(fbi);
 198         omapfb_lock(fbdev);
 199 
 200         if (len > 0) {
 201                 char *p = (char *)buf;
 202                 int ovlnum;
 203 
 204                 while (p < buf + len) {
 205                         int found;
 206                         if (num_ovls == OMAPFB_MAX_OVL_PER_FB) {
 207                                 r = -EINVAL;
 208                                 goto out;
 209                         }
 210 
 211                         ovlnum = simple_strtoul(p, &p, 0);
 212                         if (ovlnum > fbdev->num_overlays) {
 213                                 r = -EINVAL;
 214                                 goto out;
 215                         }
 216 
 217                         found = 0;
 218                         for (i = 0; i < num_ovls; ++i) {
 219                                 if (ovls[i] == fbdev->overlays[ovlnum]) {
 220                                         found = 1;
 221                                         break;
 222                                 }
 223                         }
 224 
 225                         if (!found)
 226                                 ovls[num_ovls++] = fbdev->overlays[ovlnum];
 227 
 228                         p++;
 229                 }
 230         }
 231 
 232         for (i = 0; i < num_ovls; ++i) {
 233                 struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]);
 234                 if (ofbi2 && ofbi2 != ofbi) {
 235                         dev_err(fbdev->dev, "overlay already in use\n");
 236                         r = -EINVAL;
 237                         goto out;
 238                 }
 239         }
 240 
 241         /* detach unused overlays */
 242         for (i = 0; i < ofbi->num_overlays; ++i) {
 243                 int t, found;
 244 
 245                 ovl = ofbi->overlays[i];
 246 
 247                 found = 0;
 248 
 249                 for (t = 0; t < num_ovls; ++t) {
 250                         if (ovl == ovls[t]) {
 251                                 found = 1;
 252                                 break;
 253                         }
 254                 }
 255 
 256                 if (found)
 257                         continue;
 258 
 259                 DBG("detaching %d\n", ofbi->overlays[i]->id);
 260 
 261                 omapfb_get_mem_region(ofbi->region);
 262 
 263                 omapfb_overlay_enable(ovl, 0);
 264 
 265                 if (ovl->manager)
 266                         ovl->manager->apply(ovl->manager);
 267 
 268                 omapfb_put_mem_region(ofbi->region);
 269 
 270                 for (t = i + 1; t < ofbi->num_overlays; t++) {
 271                         ofbi->rotation[t-1] = ofbi->rotation[t];
 272                         ofbi->overlays[t-1] = ofbi->overlays[t];
 273                 }
 274 
 275                 ofbi->num_overlays--;
 276                 i--;
 277         }
 278 
 279         for (i = 0; i < num_ovls; ++i) {
 280                 int t, found;
 281 
 282                 ovl = ovls[i];
 283 
 284                 found = 0;
 285 
 286                 for (t = 0; t < ofbi->num_overlays; ++t) {
 287                         if (ovl == ofbi->overlays[t]) {
 288                                 found = 1;
 289                                 break;
 290                         }
 291                 }
 292 
 293                 if (found)
 294                         continue;
 295                 ofbi->rotation[ofbi->num_overlays] = 0;
 296                 ofbi->overlays[ofbi->num_overlays++] = ovl;
 297 
 298                 added = true;
 299         }
 300 
 301         if (added) {
 302                 omapfb_get_mem_region(ofbi->region);
 303 
 304                 r = omapfb_apply_changes(fbi, 0);
 305 
 306                 omapfb_put_mem_region(ofbi->region);
 307 
 308                 if (r)
 309                         goto out;
 310         }
 311 
 312         r = count;
 313 out:
 314         omapfb_unlock(fbdev);
 315         unlock_fb_info(fbi);
 316 
 317         return r;
 318 }
 319 
 320 static ssize_t show_overlays_rotate(struct device *dev,
 321                 struct device_attribute *attr, char *buf)
 322 {
 323         struct fb_info *fbi = dev_get_drvdata(dev);
 324         struct omapfb_info *ofbi = FB2OFB(fbi);
 325         ssize_t l = 0;
 326         int t;
 327 
 328         lock_fb_info(fbi);
 329 
 330         for (t = 0; t < ofbi->num_overlays; t++) {
 331                 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
 332                                 t == 0 ? "" : ",", ofbi->rotation[t]);
 333         }
 334 
 335         l += snprintf(buf + l, PAGE_SIZE - l, "\n");
 336 
 337         unlock_fb_info(fbi);
 338 
 339         return l;
 340 }
 341 
 342 static ssize_t store_overlays_rotate(struct device *dev,
 343                 struct device_attribute *attr, const char *buf, size_t count)
 344 {
 345         struct fb_info *fbi = dev_get_drvdata(dev);
 346         struct omapfb_info *ofbi = FB2OFB(fbi);
 347         int num_ovls = 0, r, i;
 348         int len;
 349         bool changed = false;
 350         u8 rotation[OMAPFB_MAX_OVL_PER_FB];
 351 
 352         len = strlen(buf);
 353         if (buf[len - 1] == '\n')
 354                 len = len - 1;
 355 
 356         lock_fb_info(fbi);
 357 
 358         if (len > 0) {
 359                 char *p = (char *)buf;
 360 
 361                 while (p < buf + len) {
 362                         int rot;
 363 
 364                         if (num_ovls == ofbi->num_overlays) {
 365                                 r = -EINVAL;
 366                                 goto out;
 367                         }
 368 
 369                         rot = simple_strtoul(p, &p, 0);
 370                         if (rot < 0 || rot > 3) {
 371                                 r = -EINVAL;
 372                                 goto out;
 373                         }
 374 
 375                         if (ofbi->rotation[num_ovls] != rot)
 376                                 changed = true;
 377 
 378                         rotation[num_ovls++] = rot;
 379 
 380                         p++;
 381                 }
 382         }
 383 
 384         if (num_ovls != ofbi->num_overlays) {
 385                 r = -EINVAL;
 386                 goto out;
 387         }
 388 
 389         if (changed) {
 390                 for (i = 0; i < num_ovls; ++i)
 391                         ofbi->rotation[i] = rotation[i];
 392 
 393                 omapfb_get_mem_region(ofbi->region);
 394 
 395                 r = omapfb_apply_changes(fbi, 0);
 396 
 397                 omapfb_put_mem_region(ofbi->region);
 398 
 399                 if (r)
 400                         goto out;
 401 
 402                 /* FIXME error handling? */
 403         }
 404 
 405         r = count;
 406 out:
 407         unlock_fb_info(fbi);
 408 
 409         return r;
 410 }
 411 
 412 static ssize_t show_size(struct device *dev,
 413                 struct device_attribute *attr, char *buf)
 414 {
 415         struct fb_info *fbi = dev_get_drvdata(dev);
 416         struct omapfb_info *ofbi = FB2OFB(fbi);
 417 
 418         return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size);
 419 }
 420 
 421 static ssize_t store_size(struct device *dev, struct device_attribute *attr,
 422                 const char *buf, size_t count)
 423 {
 424         struct fb_info *fbi = dev_get_drvdata(dev);
 425         struct omapfb_info *ofbi = FB2OFB(fbi);
 426         struct omapfb2_device *fbdev = ofbi->fbdev;
 427         struct omap_dss_device *display = fb2display(fbi);
 428         struct omapfb2_mem_region *rg;
 429         unsigned long size;
 430         int r;
 431         int i;
 432 
 433         r = kstrtoul(buf, 0, &size);
 434         if (r)
 435                 return r;
 436 
 437         size = PAGE_ALIGN(size);
 438 
 439         lock_fb_info(fbi);
 440 
 441         if (display && display->driver->sync)
 442                 display->driver->sync(display);
 443 
 444         rg = ofbi->region;
 445 
 446         down_write_nested(&rg->lock, rg->id);
 447         atomic_inc(&rg->lock_count);
 448 
 449         if (atomic_read(&rg->map_count)) {
 450                 r = -EBUSY;
 451                 goto out;
 452         }
 453 
 454         for (i = 0; i < fbdev->num_fbs; i++) {
 455                 struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
 456                 int j;
 457 
 458                 if (ofbi2->region != rg)
 459                         continue;
 460 
 461                 for (j = 0; j < ofbi2->num_overlays; j++) {
 462                         struct omap_overlay *ovl;
 463                         ovl = ofbi2->overlays[j];
 464                         if (ovl->is_enabled(ovl)) {
 465                                 r = -EBUSY;
 466                                 goto out;
 467                         }
 468                 }
 469         }
 470 
 471         if (size != ofbi->region->size) {
 472                 r = omapfb_realloc_fbmem(fbi, size, ofbi->region->type);
 473                 if (r) {
 474                         dev_err(dev, "realloc fbmem failed\n");
 475                         goto out;
 476                 }
 477         }
 478 
 479         r = count;
 480 out:
 481         atomic_dec(&rg->lock_count);
 482         up_write(&rg->lock);
 483 
 484         unlock_fb_info(fbi);
 485 
 486         return r;
 487 }
 488 
 489 static ssize_t show_phys(struct device *dev,
 490                 struct device_attribute *attr, char *buf)
 491 {
 492         struct fb_info *fbi = dev_get_drvdata(dev);
 493         struct omapfb_info *ofbi = FB2OFB(fbi);
 494 
 495         return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr);
 496 }
 497 
 498 static ssize_t show_virt(struct device *dev,
 499                 struct device_attribute *attr, char *buf)
 500 {
 501         struct fb_info *fbi = dev_get_drvdata(dev);
 502         struct omapfb_info *ofbi = FB2OFB(fbi);
 503 
 504         return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
 505 }
 506 
 507 static ssize_t show_upd_mode(struct device *dev,
 508                 struct device_attribute *attr, char *buf)
 509 {
 510         struct fb_info *fbi = dev_get_drvdata(dev);
 511         enum omapfb_update_mode mode;
 512         int r;
 513 
 514         r = omapfb_get_update_mode(fbi, &mode);
 515 
 516         if (r)
 517                 return r;
 518 
 519         return snprintf(buf, PAGE_SIZE, "%u\n", (unsigned)mode);
 520 }
 521 
 522 static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr,
 523                 const char *buf, size_t count)
 524 {
 525         struct fb_info *fbi = dev_get_drvdata(dev);
 526         unsigned mode;
 527         int r;
 528 
 529         r = kstrtouint(buf, 0, &mode);
 530         if (r)
 531                 return r;
 532 
 533         r = omapfb_set_update_mode(fbi, mode);
 534         if (r)
 535                 return r;
 536 
 537         return count;
 538 }
 539 
 540 static struct device_attribute omapfb_attrs[] = {
 541         __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
 542                         store_rotate_type),
 543         __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
 544         __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
 545         __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
 546         __ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate,
 547                         store_overlays_rotate),
 548         __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
 549         __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
 550         __ATTR(update_mode, S_IRUGO | S_IWUSR, show_upd_mode, store_upd_mode),
 551 };
 552 
 553 int omapfb_create_sysfs(struct omapfb2_device *fbdev)
 554 {
 555         int i;
 556         int r;
 557 
 558         DBG("create sysfs for fbs\n");
 559         for (i = 0; i < fbdev->num_fbs; i++) {
 560                 int t;
 561                 for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) {
 562                         r = device_create_file(fbdev->fbs[i]->dev,
 563                                         &omapfb_attrs[t]);
 564 
 565                         if (r) {
 566                                 dev_err(fbdev->dev, "failed to create sysfs "
 567                                                 "file\n");
 568                                 return r;
 569                         }
 570                 }
 571         }
 572 
 573         return 0;
 574 }
 575 
 576 void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
 577 {
 578         int i, t;
 579 
 580         DBG("remove sysfs for fbs\n");
 581         for (i = 0; i < fbdev->num_fbs; i++) {
 582                 for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++)
 583                         device_remove_file(fbdev->fbs[i]->dev,
 584                                         &omapfb_attrs[t]);
 585         }
 586 }
 587 

/* [<][>][^][v][top][bottom][index][help] */