aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/mx3fb.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <lg@denx.de>2009-04-06 22:01:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 11:31:09 -0400
commitd88ca815b5b3534ed2dae123ba0bf366861f850c (patch)
tree5bc6d85e0a50c342092cb53890f0b96f85148dac /drivers/video/mx3fb.c
parent215059d2421f95c30d1fca6ff31357fcae9f67dc (diff)
fbdev: i.MX31: fix panning, error handling, clean up
1. check for errors returned from clk_get() 2. fix "Unbalanced enable for IRQ 160" 3. fix transmit descriptor handling in panning 4. clean frame buffer on blank - useful for OLED displays 5. formatting clean up Signed-off-by: Guennadi Liakhovetski <lg@denx.de> Cc: Dan Williams <dan.j.williams@intel.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Krzysztof Helt <krzysztof.h1@poczta.fm> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/mx3fb.c')
-rw-r--r--drivers/video/mx3fb.c56
1 files changed, 31 insertions, 25 deletions
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index fa1a512ce030..21b3692092f2 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -400,12 +400,12 @@ static void sdc_disable_channel(struct mx3fb_info *mx3_fbi)
400static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel, 400static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel,
401 int16_t x_pos, int16_t y_pos) 401 int16_t x_pos, int16_t y_pos)
402{ 402{
403 x_pos += mx3fb->h_start_width;
404 y_pos += mx3fb->v_start_width;
405
406 if (channel != IDMAC_SDC_0) 403 if (channel != IDMAC_SDC_0)
407 return -EINVAL; 404 return -EINVAL;
408 405
406 x_pos += mx3fb->h_start_width;
407 y_pos += mx3fb->v_start_width;
408
409 mx3fb_write_reg(mx3fb, (x_pos << 16) | y_pos, SDC_BG_POS); 409 mx3fb_write_reg(mx3fb, (x_pos << 16) | y_pos, SDC_BG_POS);
410 return 0; 410 return 0;
411} 411}
@@ -491,11 +491,13 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
491 * 2^4 to get fractional part, as long as we stay under ~250MHz and on 491 * 2^4 to get fractional part, as long as we stay under ~250MHz and on
492 * i.MX31 it (HSP_CLK) is <= 178MHz. Currently 128.267MHz 492 * i.MX31 it (HSP_CLK) is <= 178MHz. Currently 128.267MHz
493 */ 493 */
494 dev_dbg(mx3fb->dev, "pixel clk = %d\n", pixel_clk);
495
496 ipu_clk = clk_get(mx3fb->dev, NULL); 494 ipu_clk = clk_get(mx3fb->dev, NULL);
497 div = clk_get_rate(ipu_clk) * 16 / pixel_clk; 495 if (!IS_ERR(ipu_clk)) {
498 clk_put(ipu_clk); 496 div = clk_get_rate(ipu_clk) * 16 / pixel_clk;
497 clk_put(ipu_clk);
498 } else {
499 div = 0;
500 }
499 501
500 if (div < 0x40) { /* Divider less than 4 */ 502 if (div < 0x40) { /* Divider less than 4 */
501 dev_dbg(mx3fb->dev, 503 dev_dbg(mx3fb->dev,
@@ -503,6 +505,9 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
503 div = 0x40; 505 div = 0x40;
504 } 506 }
505 507
508 dev_dbg(mx3fb->dev, "pixel clk = %u, divider %u.%u\n",
509 pixel_clk, div >> 4, (div & 7) * 125);
510
506 spin_lock_irqsave(&mx3fb->lock, lock_flags); 511 spin_lock_irqsave(&mx3fb->lock, lock_flags);
507 512
508 /* 513 /*
@@ -515,16 +520,16 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
515 /* DI settings */ 520 /* DI settings */
516 old_conf = mx3fb_read_reg(mx3fb, DI_DISP_IF_CONF) & 0x78FFFFFF; 521 old_conf = mx3fb_read_reg(mx3fb, DI_DISP_IF_CONF) & 0x78FFFFFF;
517 old_conf |= sig.datamask_en << DI_D3_DATAMSK_SHIFT | 522 old_conf |= sig.datamask_en << DI_D3_DATAMSK_SHIFT |
518 sig.clksel_en << DI_D3_CLK_SEL_SHIFT | 523 sig.clksel_en << DI_D3_CLK_SEL_SHIFT |
519 sig.clkidle_en << DI_D3_CLK_IDLE_SHIFT; 524 sig.clkidle_en << DI_D3_CLK_IDLE_SHIFT;
520 mx3fb_write_reg(mx3fb, old_conf, DI_DISP_IF_CONF); 525 mx3fb_write_reg(mx3fb, old_conf, DI_DISP_IF_CONF);
521 526
522 old_conf = mx3fb_read_reg(mx3fb, DI_DISP_SIG_POL) & 0xE0FFFFFF; 527 old_conf = mx3fb_read_reg(mx3fb, DI_DISP_SIG_POL) & 0xE0FFFFFF;
523 old_conf |= sig.data_pol << DI_D3_DATA_POL_SHIFT | 528 old_conf |= sig.data_pol << DI_D3_DATA_POL_SHIFT |
524 sig.clk_pol << DI_D3_CLK_POL_SHIFT | 529 sig.clk_pol << DI_D3_CLK_POL_SHIFT |
525 sig.enable_pol << DI_D3_DRDY_SHARP_POL_SHIFT | 530 sig.enable_pol << DI_D3_DRDY_SHARP_POL_SHIFT |
526 sig.Hsync_pol << DI_D3_HSYNC_POL_SHIFT | 531 sig.Hsync_pol << DI_D3_HSYNC_POL_SHIFT |
527 sig.Vsync_pol << DI_D3_VSYNC_POL_SHIFT; 532 sig.Vsync_pol << DI_D3_VSYNC_POL_SHIFT;
528 mx3fb_write_reg(mx3fb, old_conf, DI_DISP_SIG_POL); 533 mx3fb_write_reg(mx3fb, old_conf, DI_DISP_SIG_POL);
529 534
530 switch (pixel_fmt) { 535 switch (pixel_fmt) {
@@ -721,7 +726,6 @@ static int mx3fb_set_par(struct fb_info *fbi)
721 struct idmac_channel *ichan = mx3_fbi->idmac_channel; 726 struct idmac_channel *ichan = mx3_fbi->idmac_channel;
722 struct idmac_video_param *video = &ichan->params.video; 727 struct idmac_video_param *video = &ichan->params.video;
723 struct scatterlist *sg = mx3_fbi->sg; 728 struct scatterlist *sg = mx3_fbi->sg;
724 size_t screen_size;
725 729
726 dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+'); 730 dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+');
727 731
@@ -745,12 +749,10 @@ static int mx3fb_set_par(struct fb_info *fbi)
745 } 749 }
746 } 750 }
747 751
748 screen_size = fbi->fix.line_length * fbi->var.yres;
749
750 sg_init_table(&sg[0], 1); 752 sg_init_table(&sg[0], 1);
751 sg_init_table(&sg[1], 1); 753 sg_init_table(&sg[1], 1);
752 754
753 sg_dma_address(&sg[0]) = fbi->fix.smem_start; 755 sg_dma_address(&sg[0]) = fbi->fix.smem_start;
754 sg_set_page(&sg[0], virt_to_page(fbi->screen_base), 756 sg_set_page(&sg[0], virt_to_page(fbi->screen_base),
755 fbi->fix.smem_len, 757 fbi->fix.smem_len,
756 offset_in_page(fbi->screen_base)); 758 offset_in_page(fbi->screen_base));
@@ -927,7 +929,7 @@ static int mx3fb_setcolreg(unsigned int regno, unsigned int red,
927 u32 val; 929 u32 val;
928 int ret = 1; 930 int ret = 1;
929 931
930 dev_dbg(fbi->device, "%s\n", __func__); 932 dev_dbg(fbi->device, "%s, regno = %u\n", __func__, regno);
931 933
932 mutex_lock(&mx3_fbi->mutex); 934 mutex_lock(&mx3_fbi->mutex);
933 /* 935 /*
@@ -973,9 +975,8 @@ static int mx3fb_blank(int blank, struct fb_info *fbi)
973 struct mx3fb_info *mx3_fbi = fbi->par; 975 struct mx3fb_info *mx3_fbi = fbi->par;
974 struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; 976 struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
975 977
976 dev_dbg(fbi->device, "%s\n", __func__); 978 dev_dbg(fbi->device, "%s, blank = %d, base %p, len %u\n", __func__,
977 979 blank, fbi->screen_base, fbi->fix.smem_len);
978 dev_dbg(fbi->device, "blank = %d\n", blank);
979 980
980 if (mx3_fbi->blank == blank) 981 if (mx3_fbi->blank == blank)
981 return 0; 982 return 0;
@@ -988,8 +989,11 @@ static int mx3fb_blank(int blank, struct fb_info *fbi)
988 case FB_BLANK_VSYNC_SUSPEND: 989 case FB_BLANK_VSYNC_SUSPEND:
989 case FB_BLANK_HSYNC_SUSPEND: 990 case FB_BLANK_HSYNC_SUSPEND:
990 case FB_BLANK_NORMAL: 991 case FB_BLANK_NORMAL:
991 sdc_disable_channel(mx3_fbi);
992 sdc_set_brightness(mx3fb, 0); 992 sdc_set_brightness(mx3fb, 0);
993 memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
994 /* Give LCD time to update - enough for 50 and 60 Hz */
995 msleep(25);
996 sdc_disable_channel(mx3_fbi);
993 break; 997 break;
994 case FB_BLANK_UNBLANK: 998 case FB_BLANK_UNBLANK:
995 sdc_enable_channel(mx3_fbi); 999 sdc_enable_channel(mx3_fbi);
@@ -1063,6 +1067,7 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var,
1063 mutex_unlock(&mx3_fbi->mutex); 1067 mutex_unlock(&mx3_fbi->mutex);
1064 dev_info(fbi->device, "Panning failed due to %s\n", ret < 0 ? 1068 dev_info(fbi->device, "Panning failed due to %s\n", ret < 0 ?
1065 "user interrupt" : "timeout"); 1069 "user interrupt" : "timeout");
1070 disable_irq(mx3_fbi->idmac_channel->eof_irq);
1066 return ret ? : -ETIMEDOUT; 1071 return ret ? : -ETIMEDOUT;
1067 } 1072 }
1068 1073
@@ -1073,6 +1078,9 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var,
1073 virt_to_page(fbi->screen_base + offset), fbi->fix.smem_len, 1078 virt_to_page(fbi->screen_base + offset), fbi->fix.smem_len,
1074 offset_in_page(fbi->screen_base + offset)); 1079 offset_in_page(fbi->screen_base + offset));
1075 1080
1081 if (mx3_fbi->txd)
1082 async_tx_ack(mx3_fbi->txd);
1083
1076 txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg + 1084 txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg +
1077 mx3_fbi->cur_ipu_buf, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT); 1085 mx3_fbi->cur_ipu_buf, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT);
1078 if (!txd) { 1086 if (!txd) {
@@ -1099,8 +1107,6 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var,
1099 return -EIO; 1107 return -EIO;
1100 } 1108 }
1101 1109
1102 if (mx3_fbi->txd)
1103 async_tx_ack(mx3_fbi->txd);
1104 mx3_fbi->txd = txd; 1110 mx3_fbi->txd = txd;
1105 1111
1106 fbi->var.xoffset = var->xoffset; 1112 fbi->var.xoffset = var->xoffset;
@@ -1506,7 +1512,7 @@ static struct platform_driver mx3fb_driver = {
1506 * example: 1512 * example:
1507 * video=mx3fb:bpp=16 1513 * video=mx3fb:bpp=16
1508 */ 1514 */
1509static int mx3fb_setup(void) 1515static int __init mx3fb_setup(void)
1510{ 1516{
1511#ifndef MODULE 1517#ifndef MODULE
1512 char *opt, *options = NULL; 1518 char *opt, *options = NULL;