diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-09-24 16:22:33 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-09-24 16:22:33 -0400 |
commit | baea7b946f00a291b166ccae7fcfed6c01530cc6 (patch) | |
tree | 4aa275fbdbec9c7b9b4629e8bee2bbecd3c6a6af /drivers/video/omap/dispc.c | |
parent | ae19ffbadc1b2100285a5b5b3d0a4e0a11390904 (diff) | |
parent | 94e0fb086fc5663c38bbc0fe86d698be8314f82f (diff) |
Merge branch 'origin' into for-linus
Conflicts:
MAINTAINERS
Diffstat (limited to 'drivers/video/omap/dispc.c')
-rw-r--r-- | drivers/video/omap/dispc.c | 136 |
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 | |||
158 | static struct { | 160 | static 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 | ||
220 | static void set_lcd_data_lines(int data_lines) | 224 | static 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 | ||
812 | int omap_dispc_request_irq(void (*callback)(void *data), void *data) | 816 | static 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 | } | ||
827 | EXPORT_SYMBOL(omap_dispc_request_irq); | ||
828 | |||
829 | void 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 | } |
837 | EXPORT_SYMBOL(omap_dispc_enable_irqs); | ||
838 | 832 | ||
839 | void omap_dispc_disable_irqs(int irq_mask) | 833 | int 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 | } |
847 | EXPORT_SYMBOL(omap_dispc_disable_irqs); | 854 | EXPORT_SYMBOL(omap_dispc_request_irq); |
848 | 855 | ||
849 | void omap_dispc_free_irq(void) | 856 | void 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 | } |
857 | EXPORT_SYMBOL(omap_dispc_free_irq); | 874 | EXPORT_SYMBOL(omap_dispc_free_irq); |
858 | 875 | ||
859 | static irqreturn_t omap_dispc_irq_handler(int irq, void *dev) | 876 | static 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 | ||
914 | static void enable_lcd_clocks(int enable) | 941 | static 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 | |||
922 | static 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 | ||
930 | static void enable_digit_clocks(int enable) | 952 | static 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); |
1470 | fail1: | 1490 | fail1: |
1471 | enable_lcd_clocks(0); | 1491 | enable_lcd_clocks(0); |
1472 | enable_interface_clocks(0); | ||
1473 | put_dss_clocks(); | 1492 | put_dss_clocks(); |
1474 | fail0: | 1493 | fail0: |
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 | } |