aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-07 14:06:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-07 14:06:17 -0400
commit38f56f33ca381751f9b8910f67e7a805ec0b68cb (patch)
tree202f2ce60f3f43a948607ec76c8cc48c1cf73a4b /drivers/video
parentfcba914542082b272f31c8e4c40000b88ed3208d (diff)
parent4183bef2e093a2f0aab45f2d5fed82b0e02aeacf (diff)
Merge tag 'dt-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC device tree updates (part 2) from Arnd Bergmann: "These are mostly new device tree bindings for existing drivers, as well as changes to the device tree source files to add support for those devices, and a couple of new boards, most notably Samsung's Exynos5 based Chromebook. The changes depend on earlier platform specific updates and touch the usual platforms: omap, exynos, tegra, mxs, mvebu and davinci." * tag 'dt-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (169 commits) ARM: exynos: dts: cros5250: add EC device ARM: dts: Add sbs-battery for exynos5250-snow ARM: dts: Add i2c-arbitrator bus for exynos5250-snow ARM: dts: add mshc controller node for Exynos4x12 SoCs ARM: dts: Add chip-id controller node on Exynos4/5 SoC ARM: EXYNOS: Create virtual I/O mapping for Chip-ID controller using device tree ARM: davinci: da850-evm: add SPI flash support ARM: davinci: da850: override SPI DT node device name ARM: davinci: da850: add SPI1 DT node spi/davinci: add DT binding documentation spi/davinci: no wildcards in DT compatible property ARM: dts: mvebu: Convert mvebu device tree files to 64 bits ARM: dts: mvebu: introduce internal-regs node ARM: dts: mvebu: Convert all the mvebu files to use the range property ARM: dts: mvebu: move all peripherals inside soc ARM: dts: mvebu: fix cpus section indentation ARM: davinci: da850: add EHRPWM & ECAP DT node ARM/dts: OMAP3: fix pinctrl-single configuration ARM: dts: Add OMAP3430 SDP NOR flash memory binding ARM: dts: Add NOR flash bindings for OMAP2420 H4 ...
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig2
-rw-r--r--drivers/video/mxsfb.c260
2 files changed, 158 insertions, 104 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index ab5ba3d49e14..c04ccdf60eaa 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2428,6 +2428,8 @@ config FB_MXS
2428 select FB_CFB_FILLRECT 2428 select FB_CFB_FILLRECT
2429 select FB_CFB_COPYAREA 2429 select FB_CFB_COPYAREA
2430 select FB_CFB_IMAGEBLIT 2430 select FB_CFB_IMAGEBLIT
2431 select FB_MODE_HELPERS
2432 select OF_VIDEOMODE
2431 help 2433 help
2432 Framebuffer support for the MXS SoC. 2434 Framebuffer support for the MXS SoC.
2433 2435
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 45169cbaba6e..1b2c26d1658c 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -42,13 +42,15 @@
42#include <linux/module.h> 42#include <linux/module.h>
43#include <linux/kernel.h> 43#include <linux/kernel.h>
44#include <linux/of_device.h> 44#include <linux/of_device.h>
45#include <linux/of_gpio.h> 45#include <video/of_display_timing.h>
46#include <linux/platform_device.h> 46#include <linux/platform_device.h>
47#include <linux/clk.h> 47#include <linux/clk.h>
48#include <linux/dma-mapping.h> 48#include <linux/dma-mapping.h>
49#include <linux/io.h> 49#include <linux/io.h>
50#include <linux/pinctrl/consumer.h> 50#include <linux/pinctrl/consumer.h>
51#include <linux/mxsfb.h> 51#include <linux/fb.h>
52#include <linux/regulator/consumer.h>
53#include <video/videomode.h>
52 54
53#define REG_SET 4 55#define REG_SET 4
54#define REG_CLR 8 56#define REG_CLR 8
@@ -107,7 +109,7 @@
107#define VDCTRL0_ENABLE_PRESENT (1 << 28) 109#define VDCTRL0_ENABLE_PRESENT (1 << 28)
108#define VDCTRL0_VSYNC_ACT_HIGH (1 << 27) 110#define VDCTRL0_VSYNC_ACT_HIGH (1 << 27)
109#define VDCTRL0_HSYNC_ACT_HIGH (1 << 26) 111#define VDCTRL0_HSYNC_ACT_HIGH (1 << 26)
110#define VDCTRL0_DOTCLK_ACT_FAILING (1 << 25) 112#define VDCTRL0_DOTCLK_ACT_FALLING (1 << 25)
111#define VDCTRL0_ENABLE_ACT_HIGH (1 << 24) 113#define VDCTRL0_ENABLE_ACT_HIGH (1 << 24)
112#define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21) 114#define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21)
113#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20) 115#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20)
@@ -142,6 +144,14 @@
142#define BLUE 2 144#define BLUE 2
143#define TRANSP 3 145#define TRANSP 3
144 146
147#define STMLCDIF_8BIT 1 /** pixel data bus to the display is of 8 bit width */
148#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
149#define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
150#define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
151
152#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT (1 << 6)
153#define MXSFB_SYNC_DOTCLK_FALLING_ACT (1 << 7) /* negtive edge sampling */
154
145enum mxsfb_devtype { 155enum mxsfb_devtype {
146 MXSFB_V3, 156 MXSFB_V3,
147 MXSFB_V4, 157 MXSFB_V4,
@@ -168,8 +178,8 @@ struct mxsfb_info {
168 unsigned ld_intf_width; 178 unsigned ld_intf_width;
169 unsigned dotclk_delay; 179 unsigned dotclk_delay;
170 const struct mxsfb_devdata *devdata; 180 const struct mxsfb_devdata *devdata;
171 int mapped;
172 u32 sync; 181 u32 sync;
182 struct regulator *reg_lcd;
173}; 183};
174 184
175#define mxsfb_is_v3(host) (host->devdata->ipversion == 3) 185#define mxsfb_is_v3(host) (host->devdata->ipversion == 3)
@@ -329,9 +339,19 @@ static void mxsfb_enable_controller(struct fb_info *fb_info)
329{ 339{
330 struct mxsfb_info *host = to_imxfb_host(fb_info); 340 struct mxsfb_info *host = to_imxfb_host(fb_info);
331 u32 reg; 341 u32 reg;
342 int ret;
332 343
333 dev_dbg(&host->pdev->dev, "%s\n", __func__); 344 dev_dbg(&host->pdev->dev, "%s\n", __func__);
334 345
346 if (host->reg_lcd) {
347 ret = regulator_enable(host->reg_lcd);
348 if (ret) {
349 dev_err(&host->pdev->dev,
350 "lcd regulator enable failed: %d\n", ret);
351 return;
352 }
353 }
354
335 clk_prepare_enable(host->clk); 355 clk_prepare_enable(host->clk);
336 clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U); 356 clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
337 357
@@ -353,6 +373,7 @@ static void mxsfb_disable_controller(struct fb_info *fb_info)
353 struct mxsfb_info *host = to_imxfb_host(fb_info); 373 struct mxsfb_info *host = to_imxfb_host(fb_info);
354 unsigned loop; 374 unsigned loop;
355 u32 reg; 375 u32 reg;
376 int ret;
356 377
357 dev_dbg(&host->pdev->dev, "%s\n", __func__); 378 dev_dbg(&host->pdev->dev, "%s\n", __func__);
358 379
@@ -376,6 +397,13 @@ static void mxsfb_disable_controller(struct fb_info *fb_info)
376 clk_disable_unprepare(host->clk); 397 clk_disable_unprepare(host->clk);
377 398
378 host->enabled = 0; 399 host->enabled = 0;
400
401 if (host->reg_lcd) {
402 ret = regulator_disable(host->reg_lcd);
403 if (ret)
404 dev_err(&host->pdev->dev,
405 "lcd regulator disable failed: %d\n", ret);
406 }
379} 407}
380 408
381static int mxsfb_set_par(struct fb_info *fb_info) 409static int mxsfb_set_par(struct fb_info *fb_info)
@@ -459,8 +487,8 @@ static int mxsfb_set_par(struct fb_info *fb_info)
459 vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH; 487 vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
460 if (host->sync & MXSFB_SYNC_DATA_ENABLE_HIGH_ACT) 488 if (host->sync & MXSFB_SYNC_DATA_ENABLE_HIGH_ACT)
461 vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH; 489 vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
462 if (host->sync & MXSFB_SYNC_DOTCLK_FAILING_ACT) 490 if (host->sync & MXSFB_SYNC_DOTCLK_FALLING_ACT)
463 vdctrl0 |= VDCTRL0_DOTCLK_ACT_FAILING; 491 vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
464 492
465 writel(vdctrl0, host->base + LCDC_VDCTRL0); 493 writel(vdctrl0, host->base + LCDC_VDCTRL0);
466 494
@@ -679,14 +707,105 @@ static int mxsfb_restore_mode(struct mxsfb_info *host)
679 return 0; 707 return 0;
680} 708}
681 709
710static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host)
711{
712 struct fb_info *fb_info = &host->fb_info;
713 struct fb_var_screeninfo *var = &fb_info->var;
714 struct device *dev = &host->pdev->dev;
715 struct device_node *np = host->pdev->dev.of_node;
716 struct device_node *display_np;
717 struct device_node *timings_np;
718 struct display_timings *timings;
719 u32 width;
720 int i;
721 int ret = 0;
722
723 display_np = of_parse_phandle(np, "display", 0);
724 if (!display_np) {
725 dev_err(dev, "failed to find display phandle\n");
726 return -ENOENT;
727 }
728
729 ret = of_property_read_u32(display_np, "bus-width", &width);
730 if (ret < 0) {
731 dev_err(dev, "failed to get property bus-width\n");
732 goto put_display_node;
733 }
734
735 switch (width) {
736 case 8:
737 host->ld_intf_width = STMLCDIF_8BIT;
738 break;
739 case 16:
740 host->ld_intf_width = STMLCDIF_16BIT;
741 break;
742 case 18:
743 host->ld_intf_width = STMLCDIF_18BIT;
744 break;
745 case 24:
746 host->ld_intf_width = STMLCDIF_24BIT;
747 break;
748 default:
749 dev_err(dev, "invalid bus-width value\n");
750 ret = -EINVAL;
751 goto put_display_node;
752 }
753
754 ret = of_property_read_u32(display_np, "bits-per-pixel",
755 &var->bits_per_pixel);
756 if (ret < 0) {
757 dev_err(dev, "failed to get property bits-per-pixel\n");
758 goto put_display_node;
759 }
760
761 timings = of_get_display_timings(display_np);
762 if (!timings) {
763 dev_err(dev, "failed to get display timings\n");
764 ret = -ENOENT;
765 goto put_display_node;
766 }
767
768 timings_np = of_find_node_by_name(display_np,
769 "display-timings");
770 if (!timings_np) {
771 dev_err(dev, "failed to find display-timings node\n");
772 ret = -ENOENT;
773 goto put_display_node;
774 }
775
776 for (i = 0; i < of_get_child_count(timings_np); i++) {
777 struct videomode vm;
778 struct fb_videomode fb_vm;
779
780 ret = videomode_from_timing(timings, &vm, i);
781 if (ret < 0)
782 goto put_timings_node;
783 ret = fb_videomode_from_videomode(&vm, &fb_vm);
784 if (ret < 0)
785 goto put_timings_node;
786
787 if (vm.data_flags & DISPLAY_FLAGS_DE_HIGH)
788 host->sync |= MXSFB_SYNC_DATA_ENABLE_HIGH_ACT;
789 if (vm.data_flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
790 host->sync |= MXSFB_SYNC_DOTCLK_FALLING_ACT;
791 fb_add_videomode(&fb_vm, &fb_info->modelist);
792 }
793
794put_timings_node:
795 of_node_put(timings_np);
796put_display_node:
797 of_node_put(display_np);
798 return ret;
799}
800
682static int mxsfb_init_fbinfo(struct mxsfb_info *host) 801static int mxsfb_init_fbinfo(struct mxsfb_info *host)
683{ 802{
684 struct fb_info *fb_info = &host->fb_info; 803 struct fb_info *fb_info = &host->fb_info;
685 struct fb_var_screeninfo *var = &fb_info->var; 804 struct fb_var_screeninfo *var = &fb_info->var;
686 struct mxsfb_platform_data *pdata = host->pdev->dev.platform_data;
687 dma_addr_t fb_phys; 805 dma_addr_t fb_phys;
688 void *fb_virt; 806 void *fb_virt;
689 unsigned fb_size = pdata->fb_size; 807 unsigned fb_size;
808 int ret;
690 809
691 fb_info->fbops = &mxsfb_ops; 810 fb_info->fbops = &mxsfb_ops;
692 fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST; 811 fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST;
@@ -696,40 +815,22 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host)
696 fb_info->fix.visual = FB_VISUAL_TRUECOLOR, 815 fb_info->fix.visual = FB_VISUAL_TRUECOLOR,
697 fb_info->fix.accel = FB_ACCEL_NONE; 816 fb_info->fix.accel = FB_ACCEL_NONE;
698 817
699 var->bits_per_pixel = pdata->default_bpp ? pdata->default_bpp : 16; 818 ret = mxsfb_init_fbinfo_dt(host);
819 if (ret)
820 return ret;
821
700 var->nonstd = 0; 822 var->nonstd = 0;
701 var->activate = FB_ACTIVATE_NOW; 823 var->activate = FB_ACTIVATE_NOW;
702 var->accel_flags = 0; 824 var->accel_flags = 0;
703 var->vmode = FB_VMODE_NONINTERLACED; 825 var->vmode = FB_VMODE_NONINTERLACED;
704 826
705 host->dotclk_delay = pdata->dotclk_delay;
706 host->ld_intf_width = pdata->ld_intf_width;
707
708 /* Memory allocation for framebuffer */ 827 /* Memory allocation for framebuffer */
709 if (pdata->fb_phys) { 828 fb_size = SZ_2M;
710 if (!fb_size) 829 fb_virt = alloc_pages_exact(fb_size, GFP_DMA);
711 return -EINVAL; 830 if (!fb_virt)
712 831 return -ENOMEM;
713 fb_phys = pdata->fb_phys;
714
715 if (!request_mem_region(fb_phys, fb_size, host->pdev->name))
716 return -ENOMEM;
717 832
718 fb_virt = ioremap(fb_phys, fb_size); 833 fb_phys = virt_to_phys(fb_virt);
719 if (!fb_virt) {
720 release_mem_region(fb_phys, fb_size);
721 return -ENOMEM;
722 }
723 host->mapped = 1;
724 } else {
725 if (!fb_size)
726 fb_size = SZ_2M; /* default */
727 fb_virt = alloc_pages_exact(fb_size, GFP_DMA);
728 if (!fb_virt)
729 return -ENOMEM;
730
731 fb_phys = virt_to_phys(fb_virt);
732 }
733 834
734 fb_info->fix.smem_start = fb_phys; 835 fb_info->fix.smem_start = fb_phys;
735 fb_info->screen_base = fb_virt; 836 fb_info->screen_base = fb_virt;
@@ -745,13 +846,7 @@ static void mxsfb_free_videomem(struct mxsfb_info *host)
745{ 846{
746 struct fb_info *fb_info = &host->fb_info; 847 struct fb_info *fb_info = &host->fb_info;
747 848
748 if (host->mapped) { 849 free_pages_exact(fb_info->screen_base, fb_info->fix.smem_len);
749 iounmap(fb_info->screen_base);
750 release_mem_region(fb_info->fix.smem_start,
751 fb_info->screen_size);
752 } else {
753 free_pages_exact(fb_info->screen_base, fb_info->fix.smem_len);
754 }
755} 850}
756 851
757static struct platform_device_id mxsfb_devtype[] = { 852static struct platform_device_id mxsfb_devtype[] = {
@@ -778,47 +873,35 @@ static int mxsfb_probe(struct platform_device *pdev)
778{ 873{
779 const struct of_device_id *of_id = 874 const struct of_device_id *of_id =
780 of_match_device(mxsfb_dt_ids, &pdev->dev); 875 of_match_device(mxsfb_dt_ids, &pdev->dev);
781 struct mxsfb_platform_data *pdata = pdev->dev.platform_data;
782 struct resource *res; 876 struct resource *res;
783 struct mxsfb_info *host; 877 struct mxsfb_info *host;
784 struct fb_info *fb_info; 878 struct fb_info *fb_info;
785 struct fb_modelist *modelist; 879 struct fb_modelist *modelist;
786 struct pinctrl *pinctrl; 880 struct pinctrl *pinctrl;
787 int panel_enable; 881 int ret;
788 enum of_gpio_flags flags;
789 int i, ret;
790 882
791 if (of_id) 883 if (of_id)
792 pdev->id_entry = of_id->data; 884 pdev->id_entry = of_id->data;
793 885
794 if (!pdata) {
795 dev_err(&pdev->dev, "No platformdata. Giving up\n");
796 return -ENODEV;
797 }
798
799 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 886 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
800 if (!res) { 887 if (!res) {
801 dev_err(&pdev->dev, "Cannot get memory IO resource\n"); 888 dev_err(&pdev->dev, "Cannot get memory IO resource\n");
802 return -ENODEV; 889 return -ENODEV;
803 } 890 }
804 891
805 if (!request_mem_region(res->start, resource_size(res), pdev->name))
806 return -EBUSY;
807
808 fb_info = framebuffer_alloc(sizeof(struct mxsfb_info), &pdev->dev); 892 fb_info = framebuffer_alloc(sizeof(struct mxsfb_info), &pdev->dev);
809 if (!fb_info) { 893 if (!fb_info) {
810 dev_err(&pdev->dev, "Failed to allocate fbdev\n"); 894 dev_err(&pdev->dev, "Failed to allocate fbdev\n");
811 ret = -ENOMEM; 895 return -ENOMEM;
812 goto error_alloc_info;
813 } 896 }
814 897
815 host = to_imxfb_host(fb_info); 898 host = to_imxfb_host(fb_info);
816 899
817 host->base = ioremap(res->start, resource_size(res)); 900 host->base = devm_ioremap_resource(&pdev->dev, res);
818 if (!host->base) { 901 if (IS_ERR(host->base)) {
819 dev_err(&pdev->dev, "ioremap failed\n"); 902 dev_err(&pdev->dev, "ioremap failed\n");
820 ret = -ENOMEM; 903 ret = PTR_ERR(host->base);
821 goto error_ioremap; 904 goto fb_release;
822 } 905 }
823 906
824 host->pdev = pdev; 907 host->pdev = pdev;
@@ -829,47 +912,31 @@ static int mxsfb_probe(struct platform_device *pdev)
829 pinctrl = devm_pinctrl_get_select_default(&pdev->dev); 912 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
830 if (IS_ERR(pinctrl)) { 913 if (IS_ERR(pinctrl)) {
831 ret = PTR_ERR(pinctrl); 914 ret = PTR_ERR(pinctrl);
832 goto error_getpin; 915 goto fb_release;
833 } 916 }
834 917
835 host->clk = clk_get(&host->pdev->dev, NULL); 918 host->clk = devm_clk_get(&host->pdev->dev, NULL);
836 if (IS_ERR(host->clk)) { 919 if (IS_ERR(host->clk)) {
837 ret = PTR_ERR(host->clk); 920 ret = PTR_ERR(host->clk);
838 goto error_getclock; 921 goto fb_release;
839 } 922 }
840 923
841 panel_enable = of_get_named_gpio_flags(pdev->dev.of_node, 924 host->reg_lcd = devm_regulator_get(&pdev->dev, "lcd");
842 "panel-enable-gpios", 0, &flags); 925 if (IS_ERR(host->reg_lcd))
843 if (gpio_is_valid(panel_enable)) { 926 host->reg_lcd = NULL;
844 unsigned long f = GPIOF_OUT_INIT_HIGH;
845 if (flags == OF_GPIO_ACTIVE_LOW)
846 f = GPIOF_OUT_INIT_LOW;
847 ret = devm_gpio_request_one(&pdev->dev, panel_enable,
848 f, "panel-enable");
849 if (ret) {
850 dev_err(&pdev->dev,
851 "failed to request gpio %d: %d\n",
852 panel_enable, ret);
853 goto error_panel_enable;
854 }
855 }
856 927
857 fb_info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); 928 fb_info->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16,
929 GFP_KERNEL);
858 if (!fb_info->pseudo_palette) { 930 if (!fb_info->pseudo_palette) {
859 ret = -ENOMEM; 931 ret = -ENOMEM;
860 goto error_pseudo_pallette; 932 goto fb_release;
861 } 933 }
862 934
863 INIT_LIST_HEAD(&fb_info->modelist); 935 INIT_LIST_HEAD(&fb_info->modelist);
864 936
865 host->sync = pdata->sync;
866
867 ret = mxsfb_init_fbinfo(host); 937 ret = mxsfb_init_fbinfo(host);
868 if (ret != 0) 938 if (ret != 0)
869 goto error_init_fb; 939 goto fb_release;
870
871 for (i = 0; i < pdata->mode_count; i++)
872 fb_add_videomode(&pdata->mode_list[i], &fb_info->modelist);
873 940
874 modelist = list_first_entry(&fb_info->modelist, 941 modelist = list_first_entry(&fb_info->modelist,
875 struct fb_modelist, list); 942 struct fb_modelist, list);
@@ -883,7 +950,7 @@ static int mxsfb_probe(struct platform_device *pdev)
883 ret = register_framebuffer(fb_info); 950 ret = register_framebuffer(fb_info);
884 if (ret != 0) { 951 if (ret != 0) {
885 dev_err(&pdev->dev,"Failed to register framebuffer\n"); 952 dev_err(&pdev->dev,"Failed to register framebuffer\n");
886 goto error_register; 953 goto fb_destroy;
887 } 954 }
888 955
889 if (!host->enabled) { 956 if (!host->enabled) {
@@ -896,22 +963,12 @@ static int mxsfb_probe(struct platform_device *pdev)
896 963
897 return 0; 964 return 0;
898 965
899error_register: 966fb_destroy:
900 if (host->enabled) 967 if (host->enabled)
901 clk_disable_unprepare(host->clk); 968 clk_disable_unprepare(host->clk);
902 fb_destroy_modelist(&fb_info->modelist); 969 fb_destroy_modelist(&fb_info->modelist);
903error_init_fb: 970fb_release:
904 kfree(fb_info->pseudo_palette);
905error_pseudo_pallette:
906error_panel_enable:
907 clk_put(host->clk);
908error_getclock:
909error_getpin:
910 iounmap(host->base);
911error_ioremap:
912 framebuffer_release(fb_info); 971 framebuffer_release(fb_info);
913error_alloc_info:
914 release_mem_region(res->start, resource_size(res));
915 972
916 return ret; 973 return ret;
917} 974}
@@ -920,19 +977,14 @@ static int mxsfb_remove(struct platform_device *pdev)
920{ 977{
921 struct fb_info *fb_info = platform_get_drvdata(pdev); 978 struct fb_info *fb_info = platform_get_drvdata(pdev);
922 struct mxsfb_info *host = to_imxfb_host(fb_info); 979 struct mxsfb_info *host = to_imxfb_host(fb_info);
923 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
924 980
925 if (host->enabled) 981 if (host->enabled)
926 mxsfb_disable_controller(fb_info); 982 mxsfb_disable_controller(fb_info);
927 983
928 unregister_framebuffer(fb_info); 984 unregister_framebuffer(fb_info);
929 kfree(fb_info->pseudo_palette);
930 mxsfb_free_videomem(host); 985 mxsfb_free_videomem(host);
931 iounmap(host->base);
932 clk_put(host->clk);
933 986
934 framebuffer_release(fb_info); 987 framebuffer_release(fb_info);
935 release_mem_region(res->start, resource_size(res));
936 988
937 platform_set_drvdata(pdev, NULL); 989 platform_set_drvdata(pdev, NULL);
938 990