diff mbox

[56/72] imx-drm: Implement custom ioctl to set gamma

Message ID 1414796095-10107-57-git-send-email-steve_longerbeam@mentor.com (mailing list archive)
State New, archived
Headers show

Commit Message

Steve Longerbeam Oct. 31, 2014, 10:54 p.m. UTC
Implement i.MX specific ioctl to set gamma directly using slope and
y-intercept values that define the piecewise linear gamma correction
curve.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
 drivers/staging/imx-drm/imx-drm-core.c |   40 +++++++++++++++++++++++++++++++-
 drivers/staging/imx-drm/imx-drm.h      |    3 +--
 drivers/staging/imx-drm/ipuv3-crtc.c   |    9 +++++++
 include/uapi/drm/imx_drm.h             |   30 ++++++++++++++++++++++++
 4 files changed, 79 insertions(+), 3 deletions(-)
 create mode 100644 include/uapi/drm/imx_drm.h
diff mbox

Patch

diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index 084ed53..4c85fd3 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -24,6 +24,7 @@ 
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/imx_drm.h>
 
 #include "imx-drm.h"
 
@@ -122,6 +123,18 @@  static struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
 	return NULL;
 }
 
+static struct imx_drm_crtc *imx_drm_find_crtc_by_id(struct drm_device *drm,
+						    u32 crtc_id)
+{
+	struct drm_crtc *crtc;
+
+	crtc = drm_crtc_find(drm, crtc_id);
+	if (!crtc)
+		return NULL;
+
+	return imx_drm_find_crtc(crtc);
+}
+
 int imx_drm_panel_format_pins(struct drm_encoder *encoder,
 		u32 interface_pix_fmt, int hsync_pin, int vsync_pin)
 {
@@ -537,8 +550,33 @@  int imx_drm_encoder_get_mux_id(struct device_node *node,
 }
 EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id);
 
+static int drm_imx_set_gamma_ioctl(struct drm_device *drm, void *data,
+				   struct drm_file *file_priv)
+{
+	struct drm_imx_gamma *g = data;
+	struct imx_drm_crtc_helper_funcs *helper;
+	struct imx_drm_crtc *imx_crtc;
+	int ret = -EINVAL;
+
+	if (!drm_core_check_feature(drm, DRIVER_MODESET))
+		return -ENODEV;
+
+	drm_modeset_lock_all(drm);
+
+	imx_crtc = imx_drm_find_crtc_by_id(drm, g->crtc_id);
+	if (!imx_crtc)
+		goto out_unlock;
+
+	helper = &imx_crtc->imx_drm_helper_funcs;
+	ret = helper->gamma_set(imx_crtc->crtc, g->enable, g->m, g->b);
+
+out_unlock:
+	drm_modeset_unlock_all(drm);
+	return ret;
+}
+
 static const struct drm_ioctl_desc imx_drm_ioctls[] = {
-	/* none so far */
+	DRM_IOCTL_DEF_DRV(IMX_SET_GAMMA, drm_imx_set_gamma_ioctl, DRM_AUTH),
 };
 
 static struct drm_driver imx_drm_driver = {
diff --git a/drivers/staging/imx-drm/imx-drm.h b/drivers/staging/imx-drm/imx-drm.h
index bf6b06b..0bb4735 100644
--- a/drivers/staging/imx-drm/imx-drm.h
+++ b/drivers/staging/imx-drm/imx-drm.h
@@ -21,6 +21,7 @@  struct imx_drm_crtc_helper_funcs {
 	void (*disable_vblank)(struct drm_crtc *crtc, int pipe);
 	int (*set_interface_pix_fmt)(struct drm_crtc *crtc, u32 encoder_type,
 			u32 pix_fmt, int hsync_pin, int vsync_pin);
+	int (*gamma_set)(struct drm_crtc *crtc, bool enable, u32 *m, u32 *b);
 	const struct drm_crtc_helper_funcs *crtc_helper_funcs;
 	const struct drm_crtc_funcs *crtc_funcs;
 };
@@ -52,6 +53,4 @@  int imx_drm_encoder_parse_of(struct drm_device *drm,
 void imx_drm_connector_destroy(struct drm_connector *connector);
 void imx_drm_encoder_destroy(struct drm_encoder *encoder);
 
-#define DRM_IMX_GAMMA_SIZE 16
-
 #endif /* _IMX_DRM_H_ */
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index 4f2ba40..8d7c998 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -29,6 +29,7 @@ 
 #include <linux/errno.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/imx_drm.h>
 
 #include <video/imx-ipu-v3.h>
 #include "imx-drm.h"
@@ -405,10 +406,18 @@  static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type,
 	return 0;
 }
 
+static int ipu_gamma_set(struct drm_crtc *crtc, bool enable, u32 *m, u32 *b)
+{
+	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
+
+	return ipu_plane_gamma_set(&ipu_crtc->plane[0], true, m, b);
+}
+
 static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = {
 	.enable_vblank = ipu_enable_vblank,
 	.disable_vblank = ipu_disable_vblank,
 	.set_interface_pix_fmt = ipu_set_interface_pix_fmt,
+	.gamma_set = ipu_gamma_set,
 	.crtc_funcs = &ipu_crtc_funcs,
 	.crtc_helper_funcs = &ipu_helper_funcs,
 };
diff --git a/include/uapi/drm/imx_drm.h b/include/uapi/drm/imx_drm.h
new file mode 100644
index 0000000..b0a03d6
--- /dev/null
+++ b/include/uapi/drm/imx_drm.h
@@ -0,0 +1,30 @@ 
+/*
+ * include/uapi/drm/imx_drm.h
+ *
+ * Copyright (C) 2013-2014 Mentor Graphics
+ *
+ * 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.
+ *
+ */
+
+#ifndef __IMX_DRM_H__
+#define __IMX_DRM_H__
+
+#include <drm/drm.h>
+
+#define DRM_IMX_GAMMA_SIZE         16
+struct drm_imx_gamma {
+	bool     enable;
+	uint32_t crtc_id;
+	uint32_t m[DRM_IMX_GAMMA_SIZE];
+	uint32_t b[DRM_IMX_GAMMA_SIZE];
+};
+
+#define DRM_IMX_SET_GAMMA    0x00
+
+#define DRM_IOCTL_IMX_SET_GAMMA                                         \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_IMX_SET_GAMMA, struct drm_imx_gamma)
+
+#endif /* __IMX_DRM_H__ */