summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Chen <b02280@freescale.com>2009-12-16 15:32:32 +0800
committerJustin Waters <justin.waters@timesys.com>2010-03-25 14:01:46 -0400
commit4b4cc7389a84a3e6c79586a7b65a218a5401d11a (patch)
treed98af9307e47a1c65bbf6e9877a9397ee167eb45
parentacc41cfb94eece13a5d2b9dca2543885f6211a8f (diff)
ENGR00119275 ipuv3: dmfc size control
add dmfc size control for dynamic change and _setup. DMFC_NORMAL: segment 0,1 for DC, 4,5 for DP-BG, 6,7 for DP-FG. DMFC_HIGH_RESOLUTION_DC: segment 0~3 for DC, 4,5 for DP-BG, 6,7 for DP-FG. DMFC_HIGH_RESOLUTION_DP: segment 0,1 for DC, 2~5 for DP-BG, 6,7 for DP-FG. DMFC_HIGH_RESOLUTION_ONLY_DP: segment 0~3 for DP-BG, 4~7 for DP-FG. IPU diplay driver will try to enlarge its related DMFC segment size when it meet high resolution condition, but if dmfc is already in high resolution setting, dmfc will not change.That said, first request wins. For cmdline setting, "dmfc=1" is DMFC_HIGH_RESOLUTION_DC, "dmfc=2" is DMFC_HIGH_RESOLUTION_DP, "dmfc=3" is DMFC_HIGH_RESOLUTION_ONLY_DP. NOTE: DMFC_HIGH_RESOLUTION_ONLY_DP only can be set by cmdline. Signed-off-by: Jason Chen <b02280@freescale.com>
-rw-r--r--drivers/mxc/ipu3/ipu_common.c5
-rw-r--r--drivers/mxc/ipu3/ipu_disp.c120
-rw-r--r--drivers/mxc/ipu3/ipu_prv.h10
3 files changed, 110 insertions, 25 deletions
diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c
index 56657b8f6ea1..16e7f01605fb 100644
--- a/drivers/mxc/ipu3/ipu_common.c
+++ b/drivers/mxc/ipu3/ipu_common.c
@@ -278,7 +278,6 @@ static int ipu_probe(struct platform_device *pdev)
struct resource *res;
struct mxc_ipu_config *plat_data = pdev->dev.platform_data;
unsigned long ipu_base;
- u32 reg;
spin_lock_init(&ipu_lock);
@@ -379,7 +378,7 @@ static int ipu_probe(struct platform_device *pdev)
__raw_writel(0xFFFFFFFF, IPU_INT_CTRL(10));
/* DMFC Init */
- _ipu_dmfc_init();
+ _ipu_dmfc_init(DMFC_NORMAL, 1);
/* Set sync refresh channels as high priority */
__raw_writel(0x18800000L, IDMAC_CHA_PRI(0));
@@ -2407,7 +2406,7 @@ static int ipu_resume(struct platform_device *pdev)
__raw_writel(idma_enable_reg[1], IDMAC_CHA_EN(32));
} else {
clk_enable(g_ipu_clk);
- _ipu_dmfc_init();
+ _ipu_dmfc_init(DMFC_NORMAL, 0);
_ipu_init_dc_mappings();
/* Set sync refresh channels as high priority */
diff --git a/drivers/mxc/ipu3/ipu_disp.c b/drivers/mxc/ipu3/ipu_disp.c
index 505d3f7d84d7..035d0c9e4519 100644
--- a/drivers/mxc/ipu3/ipu_disp.c
+++ b/drivers/mxc/ipu3/ipu_disp.c
@@ -54,54 +54,132 @@ struct dp_csc_param_t {
#define DC_DISP_ID_SERIAL 2
#define DC_DISP_ID_ASYNC 3
+int dmfc_type_setup;
+static int dmfc_size_28, dmfc_size_29, dmfc_size_24, dmfc_size_27, dmfc_size_23;
-/* all value below is determined by fix reg setting in _ipu_dmfc_init*/
-#define DMFC_FIFO_SIZE_28 (128*4)
-#define DMFC_FIFO_SIZE_29 (64*4)
-#define DMFC_FIFO_SIZE_24 (64*4)
-#define DMFC_FIFO_SIZE_27 (128*4)
-#define DMFC_FIFO_SIZE_23 (128*4)
-
-void _ipu_dmfc_init(void)
+void _ipu_dmfc_init(int dmfc_type, int first)
{
- /* disable DMFC-IC channel*/
- __raw_writel(0x2, DMFC_IC_CTRL);
- /* 1 - segment 0 and 1; 2, 1C and 2C unused */
- __raw_writel(0x00000088, DMFC_WR_CHAN);
+ u32 dmfc_wr_chan, dmfc_dp_chan;
+
+ if (first) {
+ if (dmfc_type_setup > dmfc_type)
+ dmfc_type = dmfc_type_setup;
+ else
+ dmfc_type_setup = dmfc_type;
+
+ /* disable DMFC-IC channel*/
+ __raw_writel(0x2, DMFC_IC_CTRL);
+ } else if (dmfc_type_setup >= DMFC_HIGH_RESOLUTION_DC) {
+ printk(KERN_DEBUG "DMFC high resolution has set, will not change\n");
+ return;
+ } else
+ dmfc_type_setup = dmfc_type;
+
+ if (dmfc_type == DMFC_HIGH_RESOLUTION_DC) {
+ /* 1 - segment 0~3;
+ * 5B - segement 4, 5;
+ * 5F - segement 6, 7;
+ * 1C, 2C and 6B, 6F unused;
+ */
+ printk(KERN_INFO "IPU DMFC DC HIGH RESOLUTION: 1(0~3), 5B(4,5), 5F(6,7)\n");
+ dmfc_wr_chan = 0x00000088;
+ dmfc_dp_chan = 0x00009694;
+ dmfc_size_28 = 256*4;
+ dmfc_size_29 = 0;
+ dmfc_size_24 = 0;
+ dmfc_size_27 = 128*4;
+ dmfc_size_23 = 128*4;
+ } else if (dmfc_type == DMFC_HIGH_RESOLUTION_DP) {
+ /* 1 - segment 0, 1;
+ * 5B - segement 2~5;
+ * 5F - segement 6,7;
+ * 1C, 2C and 6B, 6F unused;
+ */
+ printk(KERN_INFO "IPU DMFC DP HIGH RESOLUTION: 1(0,1), 5B(2~5), 5F(6,7)\n");
+ dmfc_wr_chan = 0x00000090;
+ dmfc_dp_chan = 0x0000968a;
+ dmfc_size_28 = 128*4;
+ dmfc_size_29 = 0;
+ dmfc_size_24 = 0;
+ dmfc_size_27 = 128*4;
+ dmfc_size_23 = 256*4;
+ } else if (dmfc_type == DMFC_HIGH_RESOLUTION_ONLY_DP) {
+ /* 5B - segement 0~3;
+ * 5F - segement 4~7;
+ * 1, 1C, 2C and 6B, 6F unused;
+ */
+ printk(KERN_INFO "IPU DMFC ONLY-DP HIGH RESOLUTION: 5B(0~3), 5F(4~7)\n");
+ dmfc_wr_chan = 0x00000000;
+ dmfc_dp_chan = 0x00008c88;
+ dmfc_size_28 = 0;
+ dmfc_size_29 = 0;
+ dmfc_size_24 = 0;
+ dmfc_size_27 = 256*4;
+ dmfc_size_23 = 256*4;
+ } else {
+ /* 1 - segment 0, 1;
+ * 5B - segement 4, 5;
+ * 5F - segement 6, 7;
+ * 1C, 2C and 6B, 6F unused;
+ */
+ printk(KERN_INFO "IPU DMFC NORMAL mode: 1(0~1), 5B(4,5), 5F(6,7)\n");
+ dmfc_wr_chan = 0x00000090;
+ dmfc_dp_chan = 0x00009694;
+ dmfc_size_28 = 128*4;
+ dmfc_size_29 = 0;
+ dmfc_size_24 = 0;
+ dmfc_size_27 = 128*4;
+ dmfc_size_23 = 128*4;
+ }
+ __raw_writel(dmfc_wr_chan, DMFC_WR_CHAN);
__raw_writel(0x202020F6, DMFC_WR_CHAN_DEF);
- /* 5B - segment 2 and 3; 5F - segment 4 and 5; */
- /* 6B - segment 6; 6F - segment 7 */
- __raw_writel(0x1F1E9694, DMFC_DP_CHAN);
+ __raw_writel(dmfc_dp_chan, DMFC_DP_CHAN);
/* Enable chan 5 watermark set at 5 bursts and clear at 7 bursts */
__raw_writel(0x2020F6F6, DMFC_DP_CHAN_DEF);
}
+static int __init dmfc_setup(char *options)
+{
+ get_option(&options, &dmfc_type_setup);
+ if (dmfc_type_setup > DMFC_HIGH_RESOLUTION_ONLY_DP)
+ dmfc_type_setup = DMFC_HIGH_RESOLUTION_ONLY_DP;
+ return 1;
+}
+__setup("dmfc=", dmfc_setup);
+
void _ipu_dmfc_set_wait4eot(int dma_chan, int width)
{
u32 dmfc_gen1 = __raw_readl(DMFC_GENERAL1);
+ if (width >= HIGH_RESOLUTION_WIDTH) {
+ if (dma_chan == 23)
+ _ipu_dmfc_init(DMFC_HIGH_RESOLUTION_DP, 0);
+ else if (dma_chan == 28)
+ _ipu_dmfc_init(DMFC_HIGH_RESOLUTION_DC, 0);
+ }
+
if (dma_chan == 23) { /*5B*/
- if (DMFC_FIFO_SIZE_23/width > 3)
+ if (dmfc_size_23/width > 3)
dmfc_gen1 |= 1UL << 20;
else
dmfc_gen1 &= ~(1UL << 20);
} else if (dma_chan == 24) { /*6B*/
- if (DMFC_FIFO_SIZE_24/width > 1)
+ if (dmfc_size_24/width > 1)
dmfc_gen1 |= 1UL << 22;
else
dmfc_gen1 &= ~(1UL << 22);
} else if (dma_chan == 27) { /*5F*/
- if (DMFC_FIFO_SIZE_27/width > 2)
+ if (dmfc_size_27/width > 2)
dmfc_gen1 |= 1UL << 21;
else
dmfc_gen1 &= ~(1UL << 21);
} else if (dma_chan == 28) { /*1*/
- if (DMFC_FIFO_SIZE_28/width > 2)
+ if (dmfc_size_28/width > 2)
dmfc_gen1 |= 1UL << 16;
else
dmfc_gen1 &= ~(1UL << 16);
} else if (dma_chan == 29) { /*6F*/
- if (DMFC_FIFO_SIZE_29/width > 1)
+ if (dmfc_size_29/width > 1)
dmfc_gen1 |= 1UL << 23;
else
dmfc_gen1 &= ~(1UL << 23);
@@ -1531,8 +1609,8 @@ int32_t ipu_disp_set_gamma_correction(ipu_channel_t channel, bool enable, int co
__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));
+ reg = __raw_readl(DP_COM_CONF(flow));
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
diff --git a/drivers/mxc/ipu3/ipu_prv.h b/drivers/mxc/ipu3/ipu_prv.h
index 6ed997f429f7..8947ee7fe921 100644
--- a/drivers/mxc/ipu3/ipu_prv.h
+++ b/drivers/mxc/ipu3/ipu_prv.h
@@ -31,6 +31,7 @@ extern unsigned char g_dc_di_assignment[];
extern int g_ipu_hw_rev;
#define IDMA_CHAN_INVALID 0xFF
+#define HIGH_RESOLUTION_WIDTH 1024
struct ipu_channel {
u8 video_in_dma;
@@ -39,6 +40,13 @@ struct ipu_channel {
u8 out_dma;
};
+enum ipu_dmfc_type {
+ DMFC_NORMAL = 0,
+ DMFC_HIGH_RESOLUTION_DC,
+ DMFC_HIGH_RESOLUTION_DP,
+ DMFC_HIGH_RESOLUTION_ONLY_DP,
+};
+
int register_ipu_device(void);
ipu_color_space_t format_to_colorspace(uint32_t fmt);
bool ipu_pixel_format_has_alpha(uint32_t fmt);
@@ -55,7 +63,7 @@ void _ipu_dc_init(int dc_chan, int di, bool interlaced);
void _ipu_dc_uninit(int dc_chan);
void _ipu_dp_dc_enable(ipu_channel_t channel);
void _ipu_dp_dc_disable(ipu_channel_t channel, bool swap);
-void _ipu_dmfc_init(void);
+void _ipu_dmfc_init(int dmfc_type, int first);
void _ipu_dmfc_set_wait4eot(int dma_chan, int width);
int _ipu_chan_is_interlaced(ipu_channel_t channel);