From patchwork Fri Oct 31 22:54:38 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve Longerbeam X-Patchwork-Id: 5207641 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 1DA3DC11AC for ; Fri, 31 Oct 2014 23:57:21 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1686020176 for ; Fri, 31 Oct 2014 23:57:20 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id F140D20120 for ; Fri, 31 Oct 2014 23:57:18 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 785C36E88E; Fri, 31 Oct 2014 16:56:42 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-pd0-f182.google.com (mail-pd0-f182.google.com [209.85.192.182]) by gabe.freedesktop.org (Postfix) with ESMTP id E5F3B6E849 for ; Fri, 31 Oct 2014 15:57:33 -0700 (PDT) Received: by mail-pd0-f182.google.com with SMTP id fp1so8142914pdb.27 for ; Fri, 31 Oct 2014 15:57:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=yGp/aFBW+9Qzz4QaXvrsdWHwu2/t47pPf2kGIUuqi5c=; b=Erxf2MMZCaHi21VC0inmhpw+iuILPw2YIvqUfhzflwSfyHJD84WiW71ObswguKF+4Q paGSWoEufuRWgi7DayXJ1JRDOVZ/OGy7iobVeg3Q1HfAYmeU3J4rY/ZndRHEdkQLVFEO 4o9cXmJFZZUnUvLywVmkreLd/jexnm33mkimq9k6xBMZ2pLr3XJUfGSYVqY/Ai25bp82 Qq5XacWCic1fbbjXUta+wfYv2WfFwmwKILXZSseT8o0RdObQW08Bapsq1ZMRPqn8pbwh Bj1B32D6yVcB472wJzK43nqOicIlXqLPk4x/YOcSRi0t90ku9OVMTmabjRsTENybbVI2 gJBA== X-Received: by 10.68.92.66 with SMTP id ck2mr27712380pbb.72.1414796253801; Fri, 31 Oct 2014 15:57:33 -0700 (PDT) Received: from mothership.mgc.mentorg.com (c-50-152-159-227.hsd1.ca.comcast.net. [50.152.159.227]) by mx.google.com with ESMTPSA id ev8sm10870656pdb.28.2014.10.31.15.57.33 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 31 Oct 2014 15:57:33 -0700 (PDT) From: Steve Longerbeam X-Google-Original-From: Steve Longerbeam To: dri-devel@lists.freedesktop.org Subject: [PATCH 55/72] imx-drm: Implement DRM gamma set Date: Fri, 31 Oct 2014 15:54:38 -0700 Message-Id: <1414796095-10107-56-git-send-email-steve_longerbeam@mentor.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1414796095-10107-1-git-send-email-steve_longerbeam@mentor.com> References: <1414796095-10107-1-git-send-email-steve_longerbeam@mentor.com> X-Mailman-Approved-At: Fri, 31 Oct 2014 16:56:32 -0700 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Implement the DRM gamma set API. This API expects that the adapter will use a gamma-corrected CLUT, but the CLUT on i.MX6 is insufficient for that purpose. But the i.MX6 does support gamma correction via a set of registers that define a piecewise linear approximation to a luminance gamma correction curve, which is what this implementation uses. The input gamma-corrected luminance values to ipu_drm_gamma_set() must be in a specific format defined in the i.MX6 reference manual. Signed-off-by: Steve Longerbeam --- drivers/staging/imx-drm/imx-drm-core.c | 3 +- drivers/staging/imx-drm/imx-drm.h | 2 + drivers/staging/imx-drm/ipuv3-crtc.c | 85 ++++++++++++++++++++++++++++++++ drivers/staging/imx-drm/ipuv3-plane.c | 10 ++++ drivers/staging/imx-drm/ipuv3-plane.h | 3 ++ 5 files changed, 102 insertions(+), 1 deletion(-) diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index e0178d6..084ed53 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -387,7 +387,8 @@ int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc, *new_crtc = imx_drm_crtc; - ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256); + ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, + DRM_IMX_GAMMA_SIZE); if (ret) goto err_register; diff --git a/drivers/staging/imx-drm/imx-drm.h b/drivers/staging/imx-drm/imx-drm.h index ec084fe..bf6b06b 100644 --- a/drivers/staging/imx-drm/imx-drm.h +++ b/drivers/staging/imx-drm/imx-drm.h @@ -52,4 +52,6 @@ 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 3040f8e..4f2ba40 100644 --- a/drivers/staging/imx-drm/ipuv3-crtc.c +++ b/drivers/staging/imx-drm/ipuv3-crtc.c @@ -171,10 +171,95 @@ static int ipu_crtc_page_flip(struct drm_crtc *crtc, return ipu_plane_page_flip(crtc->primary, fb, event, page_flip_flags); } +/* + * Normally the DRM Gamma API is used to program a color LUT that contains + * gamma-corrected pixel values for red, green, and blue input pixel values + * (normally in the range 0 to 255). + * + * However the i.MX6 LUT is only 256 entries, so it only supports 8 bpp + * indexed pixel format. Therefore if the i.MX6 LUT were used to implement + * gamma correction, th DRM framebuffer would have to use 8 bpp indexed pixel + * format which is insufficient for most use cases. To support a gamma + * correcting LUT with full RGB24 or YUV444 pixel formats, there would have + * to be 3 separate 256-entry LUTs for each color component. + * + * But the i.MX6 does support gamma correction via a set of registers that + * define a piecewise linear approximation to a luminance gamma correction + * curve. This function uses this approach. + * + * The input pixel values to this function must be in a specific format + * according to the i.MX6 reference manual (see Table 37-28 in the + * Rev. 1 TRM, dated 04/2013). This info is reprinted here: + * + * "The required Gamma correction slope for a specific display should be + * provided by the display manufacture. This information can be provided + * in various forms, as graph or formula. The gamma correction input pixel + * level (Gin) should be normalized to a maximum of 383. The gamma correction + * output pixel level (Gout) should be normalized to a maximum of 255. Then + * the following data should be collected: + * + * Table 37-28. Gamma correction values + * Gin Gout + * --- ----- + * 0 Gout0 + * 2 Gout1 + * 4 Gout2 + * 8 Gout3 + * 16 Gout4 + * 32 Gout5 + * 64 Gout6 + * 96 Gout7 + * 128 Gout8 + * 160 Gout9 + * 192 Gout10 + * 224 Gout11 + * 256 Gout12 + * 288 Gout13 + * 320 Gout14 + * 352 Gout15" + * + * + * The 16 Gout values must be placed in the input lum[] array. The green + * and blue input arrays are ignored. + * + * The gamma register values are then computed according to Table 37-29 + * in the Rev. 1 TRM. + */ +static void ipu_crtc_gamma_set(struct drm_crtc *crtc, + u16 *lum, u16 *g_unused, u16 *b_unused, + uint32_t start, uint32_t size) +{ + struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); + u32 m[DRM_IMX_GAMMA_SIZE], b[DRM_IMX_GAMMA_SIZE]; + int i; + + if (size != DRM_IMX_GAMMA_SIZE) + return; + + for (i = 0; i < size; i++) { + if (i == 0) { + b[0] = lum[0]; + m[0] = 16 * (lum[1] - lum[0]); + } else if (i == 15) { + b[15] = lum[15]; + m[15] = 255 - lum[15]; + } else if (i < 5) { + b[i] = 2 * lum[i] - lum[i+1]; + m[i] = (lum[i+1] - lum[i]) << (5 - i); + } else { + b[i] = lum[i]; + m[i] = lum[i+1] - lum[i]; + } + } + + ipu_plane_gamma_set(&ipu_crtc->plane[0], true, m, b); +} + static const struct drm_crtc_funcs ipu_crtc_funcs = { .set_config = drm_crtc_helper_set_config, .destroy = drm_crtc_cleanup, .page_flip = ipu_crtc_page_flip, + .gamma_set = ipu_crtc_gamma_set, }; static int ipu_crtc_mode_set(struct drm_crtc *crtc, diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c index 3293e84..2912aa6 100644 --- a/drivers/staging/imx-drm/ipuv3-plane.c +++ b/drivers/staging/imx-drm/ipuv3-plane.c @@ -380,6 +380,16 @@ void ipu_plane_disable(struct ipu_plane *ipu_plane) ipu_dp_disable(ipu_plane->dp); } +int ipu_plane_gamma_set(struct ipu_plane *ipu_plane, + bool enable, u32 *m, u32 *b) +{ + if (!ipu_plane->dp) + return -EINVAL; + + return ipu_dp_set_gamma_correction(ipu_plane->dp, enable, m, b); +} + + /* * drm_plane API */ diff --git a/drivers/staging/imx-drm/ipuv3-plane.h b/drivers/staging/imx-drm/ipuv3-plane.h index 4d856e9..912902a 100644 --- a/drivers/staging/imx-drm/ipuv3-plane.h +++ b/drivers/staging/imx-drm/ipuv3-plane.h @@ -70,4 +70,7 @@ void ipu_plane_disable(struct ipu_plane *plane); int ipu_plane_get_resources(struct ipu_plane *plane); void ipu_plane_put_resources(struct ipu_plane *plane); +int ipu_plane_gamma_set(struct ipu_plane *ipu_plane, + bool enable, u32 *m, u32 *b); + #endif