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 at 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 --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__ */
-- 
1.7.9.5

Reply via email to