diff options
author | Jason Chen <b02280@freescale.com> | 2009-11-24 18:53:24 +0800 |
---|---|---|
committer | Jason Chen <b02280@freescale.com> | 2009-11-24 18:53:24 +0800 |
commit | 7668c6f2527d862d78c8b45aa6d97cb15214a9ad (patch) | |
tree | 9456eede74165632dd72457316a3a96e29c9fce1 | |
parent | ba0e7753bfb874294f7776e76b52e19aa51e3505 (diff) |
ENGR00116313 ipuv3: DP gamma support
Support DP gamma by setting piecewise linear approximation,
application need set coefficient const[k] and slope[k]. The algorithm to
calculate these coefficient pls refer to unit test.
Signed-off-by: Jason Chen <b02280@freescale.com>
-rw-r--r-- | drivers/mxc/ipu3/ipu_disp.c | 58 | ||||
-rw-r--r-- | drivers/mxc/ipu3/ipu_regs.h | 4 | ||||
-rw-r--r-- | drivers/video/mxc/mxc_ipuv3_fb.c | 13 | ||||
-rw-r--r-- | include/linux/ipu.h | 2 | ||||
-rw-r--r-- | include/linux/mxcfb.h | 7 |
5 files changed, 84 insertions, 0 deletions
diff --git a/drivers/mxc/ipu3/ipu_disp.c b/drivers/mxc/ipu3/ipu_disp.c index e1f0ef7f8454..e459347dde68 100644 --- a/drivers/mxc/ipu3/ipu_disp.c +++ b/drivers/mxc/ipu3/ipu_disp.c @@ -1443,6 +1443,64 @@ int32_t ipu_disp_set_color_key(ipu_channel_t channel, bool enable, EXPORT_SYMBOL(ipu_disp_set_color_key); /*! + * This function sets the gamma correction for DP output. + * + * @param channel Input parameter for the logical channel ID. + * + * @param enable Boolean to enable or disable gamma correction. + * + * @param constk Gamma piecewise linear approximation constk coeff. + * + * @param slopek Gamma piecewise linear approximation slopek coeff. + * + * @return Returns 0 on success or negative error code on fail + */ +int32_t ipu_disp_set_gamma_correction(ipu_channel_t channel, bool enable, int constk[], int slopek[]) +{ + uint32_t reg, flow, i; + unsigned long lock_flags; + + if (channel == MEM_BG_SYNC || channel == MEM_FG_SYNC) + flow = DP_SYNC; + else if (channel == MEM_BG_ASYNC0 || channel == MEM_FG_ASYNC0) + flow = DP_ASYNC0; + else if (channel == MEM_BG_ASYNC1 || channel == MEM_FG_ASYNC1) + flow = DP_ASYNC1; + else + return -EINVAL; + + if (!g_ipu_clk_enabled) + clk_enable(g_ipu_clk); + spin_lock_irqsave(&ipu_lock, lock_flags); + + for (i = 0; i < 8; i++) + __raw_writel((constk[2*i] & 0x1ff) | ((constk[2*i+1] & 0x1ff) << 16), DP_GAMMA_C(flow, i)); + for (i = 0; i < 4; i++) + __raw_writel((slopek[4*i] & 0xff) | ((slopek[4*i+1] & 0xff) << 8) | + ((slopek[4*i+2] & 0xff) << 16) | ((slopek[4*i+3] & 0xff) << 24), DP_GAMMA_S(flow, i)); + + if (enable) { + reg = __raw_readl(DP_COM_CONF(flow)); + if ((bg_csc_type == RGB2YUV) || (bg_csc_type == YUV2YUV)) + reg |= DP_COM_CONF_GAMMA_YUV_EN; + else + reg &= ~DP_COM_CONF_GAMMA_YUV_EN; + __raw_writel(reg | DP_COM_CONF_GAMMA_EN, DP_COM_CONF(flow)); + } else + __raw_writel(reg & ~DP_COM_CONF_GAMMA_EN, DP_COM_CONF(flow)); + + reg = __raw_readl(IPU_SRM_PRI2) | 0x8; + __raw_writel(reg, IPU_SRM_PRI2); + + spin_unlock_irqrestore(&ipu_lock, lock_flags); + if (!g_ipu_clk_enabled) + clk_disable(g_ipu_clk); + + return 0; +} +EXPORT_SYMBOL(ipu_disp_set_gamma_correction); + +/*! * This function sets the window position of the foreground or background plane. * modes. * diff --git a/drivers/mxc/ipu3/ipu_regs.h b/drivers/mxc/ipu3/ipu_regs.h index 46b6c1101046..f31e181148bb 100644 --- a/drivers/mxc/ipu3/ipu_regs.h +++ b/drivers/mxc/ipu3/ipu_regs.h @@ -287,6 +287,8 @@ extern u32 *ipu_vdi_reg; #define DP_COM_CONF(flow) (ipu_dp_reg + flow/4) #define DP_GRAPH_WIND_CTRL(flow) (ipu_dp_reg + 0x0004/4 + flow/4) #define DP_FG_POS(flow) (ipu_dp_reg + 0x0008/4 + flow/4) +#define DP_GAMMA_C(flow, i) (ipu_dp_reg + 0x0014/4 + flow/4 + i) +#define DP_GAMMA_S(flow, i) (ipu_dp_reg + 0x0034/4 + flow/4 + i) #define DP_CSC_A_0(flow) (ipu_dp_reg + 0x0044/4 + flow/4) #define DP_CSC_A_1(flow) (ipu_dp_reg + 0x0048/4 + flow/4) #define DP_CSC_A_2(flow) (ipu_dp_reg + 0x004C/4 + flow/4) @@ -601,6 +603,8 @@ enum { DP_COM_CONF_CSC_DEF_FG = 0x00000300, DP_COM_CONF_CSC_DEF_BG = 0x00000200, DP_COM_CONF_CSC_DEF_BOTH = 0x00000100, + DP_COM_CONF_GAMMA_EN = 0x00001000, + DP_COM_CONF_GAMMA_YUV_EN = 0x00002000, DI_SER_CONF_LLA_SER_ACCESS = 0x00000020, DI_SER_CONF_SERIAL_CLK_POL = 0x00000010, diff --git a/drivers/video/mxc/mxc_ipuv3_fb.c b/drivers/video/mxc/mxc_ipuv3_fb.c index 27a6c32fbf21..279b9527b4a7 100644 --- a/drivers/video/mxc/mxc_ipuv3_fb.c +++ b/drivers/video/mxc/mxc_ipuv3_fb.c @@ -837,6 +837,19 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) key.color_key); break; } + case MXCFB_SET_GAMMA: + { + struct mxcfb_gamma gamma; + if (copy_from_user(&gamma, (void *)arg, sizeof(gamma))) { + retval = -EFAULT; + break; + } + retval = ipu_disp_set_gamma_correction(mxc_fbi->ipu_ch, + gamma.enable, + gamma.constk, + gamma.slopek); + break; + } case MXCFB_WAIT_FOR_VSYNC: { if (mxc_fbi->blank != FB_BLANK_UNBLANK) diff --git a/include/linux/ipu.h b/include/linux/ipu.h index 167abf1b900a..af2bb266244d 100644 --- a/include/linux/ipu.h +++ b/include/linux/ipu.h @@ -940,6 +940,8 @@ int32_t ipu_disp_set_global_alpha(ipu_channel_t channel, bool enable, uint8_t alpha); int32_t ipu_disp_set_color_key(ipu_channel_t channel, bool enable, uint32_t colorKey); +int32_t ipu_disp_set_gamma_correction(ipu_channel_t channel, bool enable, + int constk[], int slopek[]); int ipu_init_async_panel(int disp, int type, uint32_t cycle_time, uint32_t pixel_fmt, ipu_adc_sig_cfg_t sig); diff --git a/include/linux/mxcfb.h b/include/linux/mxcfb.h index 79c23c344dfa..f7d60a3377d3 100644 --- a/include/linux/mxcfb.h +++ b/include/linux/mxcfb.h @@ -51,6 +51,12 @@ struct mxcfb_pos { __u16 y; }; +struct mxcfb_gamma { + int enable; + int constk[16]; + int slopek[16]; +}; + #define MXCFB_WAIT_FOR_VSYNC _IOW('F', 0x20, u_int32_t) #define MXCFB_SET_GBL_ALPHA _IOW('F', 0x21, struct mxcfb_gbl_alpha) #define MXCFB_SET_CLR_KEY _IOW('F', 0x22, struct mxcfb_color_key) @@ -58,6 +64,7 @@ struct mxcfb_pos { #define MXCFB_GET_FB_IPU_CHAN _IOR('F', 0x25, u_int32_t) #define MXCFB_SET_LOC_ALPHA _IOWR('F', 0x26, struct mxcfb_loc_alpha) #define MXCFB_SET_LOC_ALP_BUF _IOW('F', 0x27, unsigned long) +#define MXCFB_SET_GAMMA _IOW('F', 0x28, struct mxcfb_gamma) #ifdef __KERNEL__ |