summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/omapdrm/dss/overlay-sysfs.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-18 22:58:31 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-18 22:58:31 +0300
commitd43fb9f3c5dff281dd72bea5cd2e91386fdc33a8 (patch)
tree4f3f2b00629b2df1ce4f02684689ccaa4b434854 /drivers/gpu/drm/omapdrm/dss/overlay-sysfs.c
parent5807fcaa9bf7dd87241df739161c119cf78a6bc4 (diff)
parent6f6abd360603aff043352db90c28748c8c46560e (diff)
downloadlinux-d43fb9f3c5dff281dd72bea5cd2e91386fdc33a8.tar.xz
Merge tag 'fbdev-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux
Pull fbdev updates from Tomi Valkeinen: "Summary: - pxafb: device-tree support - An unsafe kernel parameter 'lockless_register_fb' for debugging problems happening while inside the console lock - Small miscellaneous fixes & cleanups - omapdss: add writeback support functions - Separation of omapfb and omapdrm (see below) About the separation of omapfb and omapdrm, see http://permalink.gmane.org/gmane.comp.video.dri.devel/143151 for longer story. The short version: omapfb and omapdrm have shared low level drivers (omapdss and panel drivers), making further development of omapdrm difficult. After these patches omapfb and omapdrm have their own versions of the drivers, which are more or less direct copies for now but will diverge soon. This also means that omapfb (everything under drivers/video/fbdev/omap2/) is now in maintenance mode, and all new development will be done for omapdrm (drivers/gpu/drm/omapdrm/)" * tag 'fbdev-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux: (49 commits) video: fbdev: pxafb: fix out of memory error path drm/omap: make omapdrm select OMAP2_DSS drm/omap: move omapdss & displays under omapdrm omapfb: move vrfb into omapfb omapfb: take omapfb's private omapdss into use omapfb/displays: change CONFIG_DISPLAY_* to CONFIG_FB_OMAP2_* omapfb/dss: change CONFIG_OMAP* to CONFIG_FB_OMAP* omapdss: remove CONFIG_OMAP2_DSS_VENC from omapdss.h omapfb: copy omapdss & displays for omapfb omapfb: allow compilation only if DRM_OMAP is disabled fbdev: omap2: panel-dpi: simplify gpio setting fbdev: omap2: panel-dpi: in .disable first disable backlight then display OMAPDSS: DSS: fix a warning message video: omapdss: delete unneeded of_node_put OMAPDSS: DISPC: Remove boolean comparisons OMAPDSS: DSI: cleanup DSI_IRQ_ERROR_MASK define OMAPDSS: remove extra out == NULL checks OMAPDSS: change internal dispc functions to static OMAPDSS: make a two dss feat funcs internal to omapdss OMAPDSS: remove extra EXPORT_SYMBOLs ...
Diffstat (limited to 'drivers/gpu/drm/omapdrm/dss/overlay-sysfs.c')
-rw-r--r--drivers/gpu/drm/omapdrm/dss/overlay-sysfs.c456
1 files changed, 456 insertions, 0 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/overlay-sysfs.c b/drivers/gpu/drm/omapdrm/dss/overlay-sysfs.c
new file mode 100644
index 000000000000..4cc5ddebfb34
--- /dev/null
+++ b/drivers/gpu/drm/omapdrm/dss/overlay-sysfs.c
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "OVERLAY"
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/platform_device.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
+}
+
+static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ ovl->manager ? ovl->manager->name : "<none>");
+}
+
+static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
+ size_t size)
+{
+ int i, r;
+ struct omap_overlay_manager *mgr = NULL;
+ struct omap_overlay_manager *old_mgr;
+ int len = size;
+
+ if (buf[size-1] == '\n')
+ --len;
+
+ if (len > 0) {
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+ mgr = omap_dss_get_overlay_manager(i);
+
+ if (sysfs_streq(buf, mgr->name))
+ break;
+
+ mgr = NULL;
+ }
+ }
+
+ if (len > 0 && mgr == NULL)
+ return -EINVAL;
+
+ if (mgr)
+ DSSDBG("manager %s found\n", mgr->name);
+
+ if (mgr == ovl->manager)
+ return size;
+
+ old_mgr = ovl->manager;
+
+ r = dispc_runtime_get();
+ if (r)
+ return r;
+
+ /* detach old manager */
+ if (old_mgr) {
+ r = ovl->unset_manager(ovl);
+ if (r) {
+ DSSERR("detach failed\n");
+ goto err;
+ }
+
+ r = old_mgr->apply(old_mgr);
+ if (r)
+ goto err;
+ }
+
+ if (mgr) {
+ r = ovl->set_manager(ovl, mgr);
+ if (r) {
+ DSSERR("Failed to attach overlay\n");
+ goto err;
+ }
+
+ r = mgr->apply(mgr);
+ if (r)
+ goto err;
+ }
+
+ dispc_runtime_put();
+
+ return size;
+
+err:
+ dispc_runtime_put();
+ return r;
+}
+
+static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
+{
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+ info.width, info.height);
+}
+
+static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
+{
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
+}
+
+static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
+{
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+ info.pos_x, info.pos_y);
+}
+
+static ssize_t overlay_position_store(struct omap_overlay *ovl,
+ const char *buf, size_t size)
+{
+ int r;
+ char *last;
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ info.pos_x = simple_strtoul(buf, &last, 10);
+ ++last;
+ if (last - buf >= size)
+ return -EINVAL;
+
+ info.pos_y = simple_strtoul(last, &last, 10);
+
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r)
+ return r;
+
+ if (ovl->manager) {
+ r = ovl->manager->apply(ovl->manager);
+ if (r)
+ return r;
+ }
+
+ return size;
+}
+
+static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
+{
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+ info.out_width, info.out_height);
+}
+
+static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
+ const char *buf, size_t size)
+{
+ int r;
+ char *last;
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ info.out_width = simple_strtoul(buf, &last, 10);
+ ++last;
+ if (last - buf >= size)
+ return -EINVAL;
+
+ info.out_height = simple_strtoul(last, &last, 10);
+
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r)
+ return r;
+
+ if (ovl->manager) {
+ r = ovl->manager->apply(ovl->manager);
+ if (r)
+ return r;
+ }
+
+ return size;
+}
+
+static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
+}
+
+static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
+ size_t size)
+{
+ int r;
+ bool enable;
+
+ r = strtobool(buf, &enable);
+ if (r)
+ return r;
+
+ if (enable)
+ r = ovl->enable(ovl);
+ else
+ r = ovl->disable(ovl);
+
+ if (r)
+ return r;
+
+ return size;
+}
+
+static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
+{
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ info.global_alpha);
+}
+
+static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
+ const char *buf, size_t size)
+{
+ int r;
+ u8 alpha;
+ struct omap_overlay_info info;
+
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
+ return -ENODEV;
+
+ r = kstrtou8(buf, 0, &alpha);
+ if (r)
+ return r;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ info.global_alpha = alpha;
+
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r)
+ return r;
+
+ if (ovl->manager) {
+ r = ovl->manager->apply(ovl->manager);
+ if (r)
+ return r;
+ }
+
+ return size;
+}
+
+static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
+ char *buf)
+{
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ info.pre_mult_alpha);
+}
+
+static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
+ const char *buf, size_t size)
+{
+ int r;
+ u8 alpha;
+ struct omap_overlay_info info;
+
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
+ return -ENODEV;
+
+ r = kstrtou8(buf, 0, &alpha);
+ if (r)
+ return r;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ info.pre_mult_alpha = alpha;
+
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r)
+ return r;
+
+ if (ovl->manager) {
+ r = ovl->manager->apply(ovl->manager);
+ if (r)
+ return r;
+ }
+
+ return size;
+}
+
+static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
+{
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
+}
+
+static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
+ const char *buf, size_t size)
+{
+ int r;
+ u8 zorder;
+ struct omap_overlay_info info;
+
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
+ return -ENODEV;
+
+ r = kstrtou8(buf, 0, &zorder);
+ if (r)
+ return r;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ info.zorder = zorder;
+
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r)
+ return r;
+
+ if (ovl->manager) {
+ r = ovl->manager->apply(ovl->manager);
+ if (r)
+ return r;
+ }
+
+ return size;
+}
+
+struct overlay_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct omap_overlay *, char *);
+ ssize_t (*store)(struct omap_overlay *, const char *, size_t);
+};
+
+#define OVERLAY_ATTR(_name, _mode, _show, _store) \
+ struct overlay_attribute overlay_attr_##_name = \
+ __ATTR(_name, _mode, _show, _store)
+
+static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
+static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
+ overlay_manager_show, overlay_manager_store);
+static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
+static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
+static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
+ overlay_position_show, overlay_position_store);
+static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
+ overlay_output_size_show, overlay_output_size_store);
+static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
+ overlay_enabled_show, overlay_enabled_store);
+static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
+ overlay_global_alpha_show, overlay_global_alpha_store);
+static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
+ overlay_pre_mult_alpha_show,
+ overlay_pre_mult_alpha_store);
+static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
+ overlay_zorder_show, overlay_zorder_store);
+
+static struct attribute *overlay_sysfs_attrs[] = {
+ &overlay_attr_name.attr,
+ &overlay_attr_manager.attr,
+ &overlay_attr_input_size.attr,
+ &overlay_attr_screen_width.attr,
+ &overlay_attr_position.attr,
+ &overlay_attr_output_size.attr,
+ &overlay_attr_enabled.attr,
+ &overlay_attr_global_alpha.attr,
+ &overlay_attr_pre_mult_alpha.attr,
+ &overlay_attr_zorder.attr,
+ NULL
+};
+
+static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct omap_overlay *overlay;
+ struct overlay_attribute *overlay_attr;
+
+ overlay = container_of(kobj, struct omap_overlay, kobj);
+ overlay_attr = container_of(attr, struct overlay_attribute, attr);
+
+ if (!overlay_attr->show)
+ return -ENOENT;
+
+ return overlay_attr->show(overlay, buf);
+}
+
+static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t size)
+{
+ struct omap_overlay *overlay;
+ struct overlay_attribute *overlay_attr;
+
+ overlay = container_of(kobj, struct omap_overlay, kobj);
+ overlay_attr = container_of(attr, struct overlay_attribute, attr);
+
+ if (!overlay_attr->store)
+ return -ENOENT;
+
+ return overlay_attr->store(overlay, buf, size);
+}
+
+static const struct sysfs_ops overlay_sysfs_ops = {
+ .show = overlay_attr_show,
+ .store = overlay_attr_store,
+};
+
+static struct kobj_type overlay_ktype = {
+ .sysfs_ops = &overlay_sysfs_ops,
+ .default_attrs = overlay_sysfs_attrs,
+};
+
+int dss_overlay_kobj_init(struct omap_overlay *ovl,
+ struct platform_device *pdev)
+{
+ return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
+ &pdev->dev.kobj, "overlay%d", ovl->id);
+}
+
+void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
+{
+ kobject_del(&ovl->kobj);
+ kobject_put(&ovl->kobj);
+}