aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap/dispc.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2009-09-24 16:22:33 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-09-24 16:22:33 -0400
commitbaea7b946f00a291b166ccae7fcfed6c01530cc6 (patch)
tree4aa275fbdbec9c7b9b4629e8bee2bbecd3c6a6af /drivers/video/omap/dispc.c
parentae19ffbadc1b2100285a5b5b3d0a4e0a11390904 (diff)
parent94e0fb086fc5663c38bbc0fe86d698be8314f82f (diff)
Merge branch 'origin' into for-linus
Conflicts: MAINTAINERS
Diffstat (limited to 'drivers/video/omap/dispc.c')
-rw-r--r--drivers/video/omap/dispc.c136
1 files changed, 77 insertions, 59 deletions
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
index 148cbcc39602..80a11d078df4 100644
--- a/drivers/video/omap/dispc.c
+++ b/drivers/video/omap/dispc.c
@@ -155,6 +155,8 @@ struct resmap {
155 unsigned long *map; 155 unsigned long *map;
156}; 156};
157 157
158#define MAX_IRQ_HANDLERS 4
159
158static struct { 160static struct {
159 void __iomem *base; 161 void __iomem *base;
160 162
@@ -167,9 +169,11 @@ static struct {
167 169
168 int ext_mode; 170 int ext_mode;
169 171
170 unsigned long enabled_irqs; 172 struct {
171 void (*irq_callback)(void *); 173 u32 irq_mask;
172 void *irq_callback_data; 174 void (*callback)(void *);
175 void *data;
176 } irq_handlers[MAX_IRQ_HANDLERS];
173 struct completion frame_done; 177 struct completion frame_done;
174 178
175 int fir_hinc[OMAPFB_PLANE_NUM]; 179 int fir_hinc[OMAPFB_PLANE_NUM];
@@ -212,9 +216,9 @@ static void enable_rfbi_mode(int enable)
212 dispc_write_reg(DISPC_CONTROL, l); 216 dispc_write_reg(DISPC_CONTROL, l);
213 217
214 /* Set bypass mode in RFBI module */ 218 /* Set bypass mode in RFBI module */
215 l = __raw_readl(IO_ADDRESS(RFBI_CONTROL)); 219 l = __raw_readl(OMAP2_IO_ADDRESS(RFBI_CONTROL));
216 l |= enable ? 0 : (1 << 1); 220 l |= enable ? 0 : (1 << 1);
217 __raw_writel(l, IO_ADDRESS(RFBI_CONTROL)); 221 __raw_writel(l, OMAP2_IO_ADDRESS(RFBI_CONTROL));
218} 222}
219 223
220static void set_lcd_data_lines(int data_lines) 224static void set_lcd_data_lines(int data_lines)
@@ -286,7 +290,7 @@ static void setup_plane_fifo(int plane, int ext_mode)
286 BUG_ON(plane > 2); 290 BUG_ON(plane > 2);
287 291
288 l = dispc_read_reg(fsz_reg[plane]); 292 l = dispc_read_reg(fsz_reg[plane]);
289 l &= FLD_MASK(0, 9); 293 l &= FLD_MASK(0, 11);
290 if (ext_mode) { 294 if (ext_mode) {
291 low = l * 3 / 4; 295 low = l * 3 / 4;
292 high = l; 296 high = l;
@@ -294,7 +298,7 @@ static void setup_plane_fifo(int plane, int ext_mode)
294 low = l / 4; 298 low = l / 4;
295 high = l * 3 / 4; 299 high = l * 3 / 4;
296 } 300 }
297 MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 9) | FLD_MASK(0, 9), 301 MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 12) | FLD_MASK(0, 12),
298 (high << 16) | low); 302 (high << 16) | low);
299} 303}
300 304
@@ -809,57 +813,74 @@ static void set_lcd_timings(void)
809 panel->pixel_clock = fck / lck_div / pck_div / 1000; 813 panel->pixel_clock = fck / lck_div / pck_div / 1000;
810} 814}
811 815
812int omap_dispc_request_irq(void (*callback)(void *data), void *data) 816static void recalc_irq_mask(void)
813{ 817{
814 int r = 0; 818 int i;
819 unsigned long irq_mask = DISPC_IRQ_MASK_ERROR;
815 820
816 BUG_ON(callback == NULL); 821 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
822 if (!dispc.irq_handlers[i].callback)
823 continue;
817 824
818 if (dispc.irq_callback) 825 irq_mask |= dispc.irq_handlers[i].irq_mask;
819 r = -EBUSY;
820 else {
821 dispc.irq_callback = callback;
822 dispc.irq_callback_data = data;
823 } 826 }
824 827
825 return r;
826}
827EXPORT_SYMBOL(omap_dispc_request_irq);
828
829void omap_dispc_enable_irqs(int irq_mask)
830{
831 enable_lcd_clocks(1); 828 enable_lcd_clocks(1);
832 dispc.enabled_irqs = irq_mask;
833 irq_mask |= DISPC_IRQ_MASK_ERROR;
834 MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask); 829 MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
835 enable_lcd_clocks(0); 830 enable_lcd_clocks(0);
836} 831}
837EXPORT_SYMBOL(omap_dispc_enable_irqs);
838 832
839void omap_dispc_disable_irqs(int irq_mask) 833int omap_dispc_request_irq(unsigned long irq_mask, void (*callback)(void *data),
834 void *data)
840{ 835{
841 enable_lcd_clocks(1); 836 int i;
842 dispc.enabled_irqs &= ~irq_mask; 837
843 irq_mask &= ~DISPC_IRQ_MASK_ERROR; 838 BUG_ON(callback == NULL);
844 MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask); 839
845 enable_lcd_clocks(0); 840 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
841 if (dispc.irq_handlers[i].callback)
842 continue;
843
844 dispc.irq_handlers[i].irq_mask = irq_mask;
845 dispc.irq_handlers[i].callback = callback;
846 dispc.irq_handlers[i].data = data;
847 recalc_irq_mask();
848
849 return 0;
850 }
851
852 return -EBUSY;
846} 853}
847EXPORT_SYMBOL(omap_dispc_disable_irqs); 854EXPORT_SYMBOL(omap_dispc_request_irq);
848 855
849void omap_dispc_free_irq(void) 856void omap_dispc_free_irq(unsigned long irq_mask, void (*callback)(void *data),
857 void *data)
850{ 858{
851 enable_lcd_clocks(1); 859 int i;
852 omap_dispc_disable_irqs(DISPC_IRQ_MASK_ALL); 860
853 dispc.irq_callback = NULL; 861 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
854 dispc.irq_callback_data = NULL; 862 if (dispc.irq_handlers[i].callback == callback &&
855 enable_lcd_clocks(0); 863 dispc.irq_handlers[i].data == data) {
864 dispc.irq_handlers[i].irq_mask = 0;
865 dispc.irq_handlers[i].callback = NULL;
866 dispc.irq_handlers[i].data = NULL;
867 recalc_irq_mask();
868 return;
869 }
870 }
871
872 BUG();
856} 873}
857EXPORT_SYMBOL(omap_dispc_free_irq); 874EXPORT_SYMBOL(omap_dispc_free_irq);
858 875
859static irqreturn_t omap_dispc_irq_handler(int irq, void *dev) 876static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
860{ 877{
861 u32 stat = dispc_read_reg(DISPC_IRQSTATUS); 878 u32 stat;
879 int i = 0;
880
881 enable_lcd_clocks(1);
862 882
883 stat = dispc_read_reg(DISPC_IRQSTATUS);
863 if (stat & DISPC_IRQ_FRAMEMASK) 884 if (stat & DISPC_IRQ_FRAMEMASK)
864 complete(&dispc.frame_done); 885 complete(&dispc.frame_done);
865 886
@@ -870,11 +891,17 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
870 } 891 }
871 } 892 }
872 893
873 if ((stat & dispc.enabled_irqs) && dispc.irq_callback) 894 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
874 dispc.irq_callback(dispc.irq_callback_data); 895 if (unlikely(dispc.irq_handlers[i].callback &&
896 (stat & dispc.irq_handlers[i].irq_mask)))
897 dispc.irq_handlers[i].callback(
898 dispc.irq_handlers[i].data);
899 }
875 900
876 dispc_write_reg(DISPC_IRQSTATUS, stat); 901 dispc_write_reg(DISPC_IRQSTATUS, stat);
877 902
903 enable_lcd_clocks(0);
904
878 return IRQ_HANDLED; 905 return IRQ_HANDLED;
879} 906}
880 907
@@ -913,18 +940,13 @@ static void put_dss_clocks(void)
913 940
914static void enable_lcd_clocks(int enable) 941static void enable_lcd_clocks(int enable)
915{ 942{
916 if (enable) 943 if (enable) {
944 clk_enable(dispc.dss_ick);
917 clk_enable(dispc.dss1_fck); 945 clk_enable(dispc.dss1_fck);
918 else 946 } else {
919 clk_disable(dispc.dss1_fck); 947 clk_disable(dispc.dss1_fck);
920}
921
922static void enable_interface_clocks(int enable)
923{
924 if (enable)
925 clk_enable(dispc.dss_ick);
926 else
927 clk_disable(dispc.dss_ick); 948 clk_disable(dispc.dss_ick);
949 }
928} 950}
929 951
930static void enable_digit_clocks(int enable) 952static void enable_digit_clocks(int enable)
@@ -1365,7 +1387,6 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1365 if ((r = get_dss_clocks()) < 0) 1387 if ((r = get_dss_clocks()) < 0)
1366 goto fail0; 1388 goto fail0;
1367 1389
1368 enable_interface_clocks(1);
1369 enable_lcd_clocks(1); 1390 enable_lcd_clocks(1);
1370 1391
1371#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT 1392#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
@@ -1396,10 +1417,10 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1396 enable_digit_clocks(0); 1417 enable_digit_clocks(0);
1397 } 1418 }
1398 1419
1399 /* Enable smart idle and autoidle */ 1420 /* Enable smart standby/idle, autoidle and wakeup */
1400 l = dispc_read_reg(DISPC_CONTROL); 1421 l = dispc_read_reg(DISPC_SYSCONFIG);
1401 l &= ~((3 << 12) | (3 << 3)); 1422 l &= ~((3 << 12) | (3 << 3));
1402 l |= (2 << 12) | (2 << 3) | (1 << 0); 1423 l |= (2 << 12) | (2 << 3) | (1 << 2) | (1 << 0);
1403 dispc_write_reg(DISPC_SYSCONFIG, l); 1424 dispc_write_reg(DISPC_SYSCONFIG, l);
1404 omap_writel(1 << 0, DSS_BASE + DSS_SYSCONFIG); 1425 omap_writel(1 << 0, DSS_BASE + DSS_SYSCONFIG);
1405 1426
@@ -1409,10 +1430,9 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1409 dispc_write_reg(DISPC_CONFIG, l); 1430 dispc_write_reg(DISPC_CONFIG, l);
1410 1431
1411 l = dispc_read_reg(DISPC_IRQSTATUS); 1432 l = dispc_read_reg(DISPC_IRQSTATUS);
1412 dispc_write_reg(l, DISPC_IRQSTATUS); 1433 dispc_write_reg(DISPC_IRQSTATUS, l);
1413 1434
1414 /* Enable those that we handle always */ 1435 recalc_irq_mask();
1415 omap_dispc_enable_irqs(DISPC_IRQ_FRAMEMASK);
1416 1436
1417 if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler, 1437 if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler,
1418 0, MODULE_NAME, fbdev)) < 0) { 1438 0, MODULE_NAME, fbdev)) < 0) {
@@ -1421,7 +1441,7 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1421 } 1441 }
1422 1442
1423 /* L3 firewall setting: enable access to OCM RAM */ 1443 /* L3 firewall setting: enable access to OCM RAM */
1424 __raw_writel(0x402000b0, IO_ADDRESS(0x680050a0)); 1444 __raw_writel(0x402000b0, OMAP2_IO_ADDRESS(0x680050a0));
1425 1445
1426 if ((r = alloc_palette_ram()) < 0) 1446 if ((r = alloc_palette_ram()) < 0)
1427 goto fail2; 1447 goto fail2;
@@ -1469,7 +1489,6 @@ fail2:
1469 free_irq(INT_24XX_DSS_IRQ, fbdev); 1489 free_irq(INT_24XX_DSS_IRQ, fbdev);
1470fail1: 1490fail1:
1471 enable_lcd_clocks(0); 1491 enable_lcd_clocks(0);
1472 enable_interface_clocks(0);
1473 put_dss_clocks(); 1492 put_dss_clocks();
1474fail0: 1493fail0:
1475 iounmap(dispc.base); 1494 iounmap(dispc.base);
@@ -1487,7 +1506,6 @@ static void omap_dispc_cleanup(void)
1487 cleanup_fbmem(); 1506 cleanup_fbmem();
1488 free_palette_ram(); 1507 free_palette_ram();
1489 free_irq(INT_24XX_DSS_IRQ, dispc.fbdev); 1508 free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
1490 enable_interface_clocks(0);
1491 put_dss_clocks(); 1509 put_dss_clocks();
1492 iounmap(dispc.base); 1510 iounmap(dispc.base);
1493} 1511}