cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

omapfb-sysfs.c (11536B)


      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
     26static 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 sysfs_emit(buf, "%d\n", ofbi->rotation_type);
     33}
     34
     35static 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	 */
     71put_region:
     72	omapfb_put_mem_region(rg);
     73out:
     74	unlock_fb_info(fbi);
     75
     76	return r ? r : count;
     77}
     78
     79
     80static 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 sysfs_emit(buf, "%d\n", ofbi->mirror);
     87}
     88
     89static 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;
    122out:
    123	omapfb_put_mem_region(ofbi->region);
    124
    125	unlock_fb_info(fbi);
    126
    127	return r;
    128}
    129
    130static 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 += scnprintf(buf + l, PAGE_SIZE - l, "%s%d",
    151				t == 0 ? "" : ",", ovlnum);
    152	}
    153
    154	l += scnprintf(buf + l, PAGE_SIZE - l, "\n");
    155
    156	omapfb_unlock(fbdev);
    157	unlock_fb_info(fbi);
    158
    159	return l;
    160}
    161
    162static 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
    179static 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;
    313out:
    314	omapfb_unlock(fbdev);
    315	unlock_fb_info(fbi);
    316
    317	return r;
    318}
    319
    320static 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 += scnprintf(buf + l, PAGE_SIZE - l, "%s%d",
    332				t == 0 ? "" : ",", ofbi->rotation[t]);
    333	}
    334
    335	l += scnprintf(buf + l, PAGE_SIZE - l, "\n");
    336
    337	unlock_fb_info(fbi);
    338
    339	return l;
    340}
    341
    342static 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;
    406out:
    407	unlock_fb_info(fbi);
    408
    409	return r;
    410}
    411
    412static 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 sysfs_emit(buf, "%lu\n", ofbi->region->size);
    419}
    420
    421static 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;
    480out:
    481	atomic_dec(&rg->lock_count);
    482	up_write(&rg->lock);
    483
    484	unlock_fb_info(fbi);
    485
    486	return r;
    487}
    488
    489static 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 sysfs_emit(buf, "%0x\n", ofbi->region->paddr);
    496}
    497
    498static 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 sysfs_emit(buf, "%p\n", ofbi->region->vaddr);
    505}
    506
    507static 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 sysfs_emit(buf, "%u\n", (unsigned int)mode);
    520}
    521
    522static 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
    540static 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
    553int 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
    576void 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