diff options
-rw-r--r-- | drivers/video/s3c2410fb.c | 88 | ||||
-rw-r--r-- | drivers/video/s3c2410fb.h | 3 |
2 files changed, 60 insertions, 31 deletions
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index ed3426062a8b..8a4c6470d799 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c | |||
@@ -474,6 +474,7 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi, | |||
474 | { | 474 | { |
475 | unsigned long flags; | 475 | unsigned long flags; |
476 | unsigned long irqen; | 476 | unsigned long irqen; |
477 | void __iomem *regs = fbi->io; | ||
477 | 478 | ||
478 | local_irq_save(flags); | 479 | local_irq_save(flags); |
479 | 480 | ||
@@ -483,9 +484,9 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi, | |||
483 | fbi->palette_ready = 1; | 484 | fbi->palette_ready = 1; |
484 | 485 | ||
485 | /* enable IRQ */ | 486 | /* enable IRQ */ |
486 | irqen = readl(S3C2410_LCDINTMSK); | 487 | irqen = readl(regs + S3C2410_LCDINTMSK); |
487 | irqen &= ~S3C2410_LCDINT_FRSYNC; | 488 | irqen &= ~S3C2410_LCDINT_FRSYNC; |
488 | writel(irqen, S3C2410_LCDINTMSK); | 489 | writel(irqen, regs + S3C2410_LCDINTMSK); |
489 | } | 490 | } |
490 | 491 | ||
491 | local_irq_restore(flags); | 492 | local_irq_restore(flags); |
@@ -680,6 +681,7 @@ static inline void modify_gpio(void __iomem *reg, | |||
680 | static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi) | 681 | static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi) |
681 | { | 682 | { |
682 | unsigned long flags; | 683 | unsigned long flags; |
684 | void __iomem *regs = fbi->io; | ||
683 | 685 | ||
684 | /* Initialise LCD with values from haret */ | 686 | /* Initialise LCD with values from haret */ |
685 | 687 | ||
@@ -694,25 +696,25 @@ static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi) | |||
694 | 696 | ||
695 | local_irq_restore(flags); | 697 | local_irq_restore(flags); |
696 | 698 | ||
697 | writel(fbi->regs.lcdcon1, S3C2410_LCDCON1); | 699 | writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1); |
698 | writel(fbi->regs.lcdcon2, S3C2410_LCDCON2); | 700 | writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2); |
699 | writel(fbi->regs.lcdcon3, S3C2410_LCDCON3); | 701 | writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3); |
700 | writel(fbi->regs.lcdcon4, S3C2410_LCDCON4); | 702 | writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4); |
701 | writel(fbi->regs.lcdcon5, S3C2410_LCDCON5); | 703 | writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5); |
702 | 704 | ||
703 | s3c2410fb_set_lcdaddr(fbi); | 705 | s3c2410fb_set_lcdaddr(fbi); |
704 | 706 | ||
705 | dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel); | 707 | dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel); |
706 | writel(mach_info->lpcsel, S3C2410_LPCSEL); | 708 | writel(mach_info->lpcsel, regs + S3C2410_LPCSEL); |
707 | 709 | ||
708 | dprintk("replacing TPAL %08x\n", readl(S3C2410_TPAL)); | 710 | dprintk("replacing TPAL %08x\n", readl(regs + S3C2410_TPAL)); |
709 | 711 | ||
710 | /* ensure temporary palette disabled */ | 712 | /* ensure temporary palette disabled */ |
711 | writel(0x00, S3C2410_TPAL); | 713 | writel(0x00, regs + S3C2410_TPAL); |
712 | 714 | ||
713 | /* Enable video by setting the ENVID bit to 1 */ | 715 | /* Enable video by setting the ENVID bit to 1 */ |
714 | fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID; | 716 | fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID; |
715 | writel(fbi->regs.lcdcon1, S3C2410_LCDCON1); | 717 | writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1); |
716 | return 0; | 718 | return 0; |
717 | } | 719 | } |
718 | 720 | ||
@@ -720,6 +722,7 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi) | |||
720 | { | 722 | { |
721 | unsigned int i; | 723 | unsigned int i; |
722 | unsigned long ent; | 724 | unsigned long ent; |
725 | void __iomem *regs = fbi->io; | ||
723 | 726 | ||
724 | fbi->palette_ready = 0; | 727 | fbi->palette_ready = 0; |
725 | 728 | ||
@@ -727,14 +730,14 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi) | |||
727 | if ((ent = fbi->palette_buffer[i]) == PALETTE_BUFF_CLEAR) | 730 | if ((ent = fbi->palette_buffer[i]) == PALETTE_BUFF_CLEAR) |
728 | continue; | 731 | continue; |
729 | 732 | ||
730 | writel(ent, S3C2410_TFTPAL(i)); | 733 | writel(ent, regs + S3C2410_TFTPAL(i)); |
731 | 734 | ||
732 | /* it seems the only way to know exactly | 735 | /* it seems the only way to know exactly |
733 | * if the palette wrote ok, is to check | 736 | * if the palette wrote ok, is to check |
734 | * to see if the value verifies ok | 737 | * to see if the value verifies ok |
735 | */ | 738 | */ |
736 | 739 | ||
737 | if (readw(S3C2410_TFTPAL(i)) == ent) | 740 | if (readw(regs + S3C2410_TFTPAL(i)) == ent) |
738 | fbi->palette_buffer[i] = PALETTE_BUFF_CLEAR; | 741 | fbi->palette_buffer[i] = PALETTE_BUFF_CLEAR; |
739 | else | 742 | else |
740 | fbi->palette_ready = 1; /* retry */ | 743 | fbi->palette_ready = 1; /* retry */ |
@@ -744,14 +747,15 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi) | |||
744 | static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) | 747 | static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) |
745 | { | 748 | { |
746 | struct s3c2410fb_info *fbi = dev_id; | 749 | struct s3c2410fb_info *fbi = dev_id; |
747 | unsigned long lcdirq = readl(S3C2410_LCDINTPND); | 750 | void __iomem *regs = fbi->io; |
751 | unsigned long lcdirq = readl(regs + S3C2410_LCDINTPND); | ||
748 | 752 | ||
749 | if (lcdirq & S3C2410_LCDINT_FRSYNC) { | 753 | if (lcdirq & S3C2410_LCDINT_FRSYNC) { |
750 | if (fbi->palette_ready) | 754 | if (fbi->palette_ready) |
751 | s3c2410fb_write_palette(fbi); | 755 | s3c2410fb_write_palette(fbi); |
752 | 756 | ||
753 | writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDINTPND); | 757 | writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDINTPND); |
754 | writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDSRCPND); | 758 | writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDSRCPND); |
755 | } | 759 | } |
756 | 760 | ||
757 | return IRQ_HANDLED; | 761 | return IRQ_HANDLED; |
@@ -764,9 +768,11 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
764 | struct s3c2410fb_info *info; | 768 | struct s3c2410fb_info *info; |
765 | struct fb_info *fbinfo; | 769 | struct fb_info *fbinfo; |
766 | struct s3c2410fb_hw *mregs; | 770 | struct s3c2410fb_hw *mregs; |
771 | struct resource *res; | ||
767 | int ret; | 772 | int ret; |
768 | int irq; | 773 | int irq; |
769 | int i; | 774 | int i; |
775 | int size; | ||
770 | u32 lcdcon1; | 776 | u32 lcdcon1; |
771 | 777 | ||
772 | mach_info = pdev->dev.platform_data; | 778 | mach_info = pdev->dev.platform_data; |
@@ -788,11 +794,32 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
788 | return -ENOMEM; | 794 | return -ENOMEM; |
789 | } | 795 | } |
790 | 796 | ||
791 | |||
792 | info = fbinfo->par; | 797 | info = fbinfo->par; |
793 | info->fb = fbinfo; | 798 | info->fb = fbinfo; |
794 | info->dev = &pdev->dev; | 799 | info->dev = &pdev->dev; |
795 | 800 | ||
801 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
802 | if (res == NULL) { | ||
803 | dev_err(&pdev->dev, "failed to get memory registersn"); | ||
804 | ret = -ENXIO; | ||
805 | goto dealloc_fb; | ||
806 | } | ||
807 | |||
808 | size = (res->end - res->start)+1; | ||
809 | info->mem = request_mem_region(res->start, size, pdev->name); | ||
810 | if (info->mem == NULL) { | ||
811 | dev_err(&pdev->dev, "failed to get memory region\n"); | ||
812 | ret = -ENOENT; | ||
813 | goto dealloc_fb; | ||
814 | } | ||
815 | |||
816 | info->io = ioremap(res->start, size); | ||
817 | if (info->io == NULL) { | ||
818 | dev_err(&pdev->dev, "ioremap() of registers failed\n"); | ||
819 | ret = -ENXIO; | ||
820 | goto release_mem; | ||
821 | } | ||
822 | |||
796 | platform_set_drvdata(pdev, fbinfo); | 823 | platform_set_drvdata(pdev, fbinfo); |
797 | 824 | ||
798 | dprintk("devinit\n"); | 825 | dprintk("devinit\n"); |
@@ -803,8 +830,8 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
803 | 830 | ||
804 | /* Stop the video and unset ENVID if set */ | 831 | /* Stop the video and unset ENVID if set */ |
805 | info->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID; | 832 | info->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID; |
806 | lcdcon1 = readl(S3C2410_LCDCON1); | 833 | lcdcon1 = readl(info->io + S3C2410_LCDCON1); |
807 | writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1); | 834 | writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1); |
808 | 835 | ||
809 | info->mach_info = pdev->dev.platform_data; | 836 | info->mach_info = pdev->dev.platform_data; |
810 | 837 | ||
@@ -855,19 +882,11 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
855 | for (i = 0; i < 256; i++) | 882 | for (i = 0; i < 256; i++) |
856 | info->palette_buffer[i] = PALETTE_BUFF_CLEAR; | 883 | info->palette_buffer[i] = PALETTE_BUFF_CLEAR; |
857 | 884 | ||
858 | if (!request_mem_region((unsigned long)S3C24XX_VA_LCD, SZ_1M, "s3c2410-lcd")) { | ||
859 | ret = -EBUSY; | ||
860 | goto dealloc_fb; | ||
861 | } | ||
862 | |||
863 | |||
864 | dprintk("got LCD region\n"); | ||
865 | |||
866 | ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info); | 885 | ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info); |
867 | if (ret) { | 886 | if (ret) { |
868 | dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret); | 887 | dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret); |
869 | ret = -EBUSY; | 888 | ret = -EBUSY; |
870 | goto release_mem; | 889 | goto release_regs; |
871 | } | 890 | } |
872 | 891 | ||
873 | info->clk = clk_get(NULL, "lcd"); | 892 | info->clk = clk_get(NULL, "lcd"); |
@@ -889,6 +908,7 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
889 | ret = -ENOMEM; | 908 | ret = -ENOMEM; |
890 | goto release_clock; | 909 | goto release_clock; |
891 | } | 910 | } |
911 | |||
892 | dprintk("got video memory\n"); | 912 | dprintk("got video memory\n"); |
893 | 913 | ||
894 | ret = s3c2410fb_init_registers(info); | 914 | ret = s3c2410fb_init_registers(info); |
@@ -916,8 +936,11 @@ release_clock: | |||
916 | clk_put(info->clk); | 936 | clk_put(info->clk); |
917 | release_irq: | 937 | release_irq: |
918 | free_irq(irq,info); | 938 | free_irq(irq,info); |
939 | release_regs: | ||
940 | iounmap(info->io); | ||
919 | release_mem: | 941 | release_mem: |
920 | release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD); | 942 | release_resource(info->mem); |
943 | kfree(info->mem); | ||
921 | dealloc_fb: | 944 | dealloc_fb: |
922 | framebuffer_release(fbinfo); | 945 | framebuffer_release(fbinfo); |
923 | return ret; | 946 | return ret; |
@@ -935,7 +958,7 @@ static void s3c2410fb_stop_lcd(struct s3c2410fb_info *fbi) | |||
935 | local_irq_save(flags); | 958 | local_irq_save(flags); |
936 | 959 | ||
937 | fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID; | 960 | fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID; |
938 | writel(fbi->regs.lcdcon1, S3C2410_LCDCON1); | 961 | writel(fbi->regs.lcdcon1, fbi->io + S3C2410_LCDCON1); |
939 | 962 | ||
940 | local_irq_restore(flags); | 963 | local_irq_restore(flags); |
941 | } | 964 | } |
@@ -962,7 +985,10 @@ static int s3c2410fb_remove(struct platform_device *pdev) | |||
962 | 985 | ||
963 | irq = platform_get_irq(pdev, 0); | 986 | irq = platform_get_irq(pdev, 0); |
964 | free_irq(irq,info); | 987 | free_irq(irq,info); |
965 | release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD); | 988 | |
989 | release_resource(info->mem); | ||
990 | kfree(info->mem); | ||
991 | iounmap(info->io); | ||
966 | unregister_framebuffer(fbinfo); | 992 | unregister_framebuffer(fbinfo); |
967 | 993 | ||
968 | return 0; | 994 | return 0; |
diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h index f3f8a8e15012..17c7915b7acd 100644 --- a/drivers/video/s3c2410fb.h +++ b/drivers/video/s3c2410fb.h | |||
@@ -30,6 +30,9 @@ struct s3c2410fb_info { | |||
30 | struct device *dev; | 30 | struct device *dev; |
31 | struct clk *clk; | 31 | struct clk *clk; |
32 | 32 | ||
33 | struct resource *mem; | ||
34 | void __iomem *io; | ||
35 | |||
33 | struct s3c2410fb_mach_info *mach_info; | 36 | struct s3c2410fb_mach_info *mach_info; |
34 | 37 | ||
35 | /* raw memory addresses */ | 38 | /* raw memory addresses */ |