summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Chen <b02280@freescale.com>2009-11-24 18:53:24 +0800
committerJason Chen <b02280@freescale.com>2009-11-24 18:53:24 +0800
commit7668c6f2527d862d78c8b45aa6d97cb15214a9ad (patch)
tree9456eede74165632dd72457316a3a96e29c9fce1
parentba0e7753bfb874294f7776e76b52e19aa51e3505 (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.c58
-rw-r--r--drivers/mxc/ipu3/ipu_regs.h4
-rw-r--r--drivers/video/mxc/mxc_ipuv3_fb.c13
-rw-r--r--include/linux/ipu.h2
-rw-r--r--include/linux/mxcfb.h7
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__