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 <steve_longerbeam@xxxxxxxxxx> --- 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 -- 1.7.9.5 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel