diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-07 14:06:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-07 14:06:17 -0400 |
commit | 38f56f33ca381751f9b8910f67e7a805ec0b68cb (patch) | |
tree | 202f2ce60f3f43a948607ec76c8cc48c1cf73a4b /drivers/video | |
parent | fcba914542082b272f31c8e4c40000b88ed3208d (diff) | |
parent | 4183bef2e093a2f0aab45f2d5fed82b0e02aeacf (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/Kconfig | 2 | ||||
-rw-r--r-- | drivers/video/mxsfb.c | 260 |
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 | |||
145 | enum mxsfb_devtype { | 155 | enum 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 | ||
381 | static int mxsfb_set_par(struct fb_info *fb_info) | 409 | static 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 | ||
710 | static 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 | |||
794 | put_timings_node: | ||
795 | of_node_put(timings_np); | ||
796 | put_display_node: | ||
797 | of_node_put(display_np); | ||
798 | return ret; | ||
799 | } | ||
800 | |||
682 | static int mxsfb_init_fbinfo(struct mxsfb_info *host) | 801 | static 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 | ||
757 | static struct platform_device_id mxsfb_devtype[] = { | 852 | static 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 | ||
899 | error_register: | 966 | fb_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); |
903 | error_init_fb: | 970 | fb_release: |
904 | kfree(fb_info->pseudo_palette); | ||
905 | error_pseudo_pallette: | ||
906 | error_panel_enable: | ||
907 | clk_put(host->clk); | ||
908 | error_getclock: | ||
909 | error_getpin: | ||
910 | iounmap(host->base); | ||
911 | error_ioremap: | ||
912 | framebuffer_release(fb_info); | 971 | framebuffer_release(fb_info); |
913 | error_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 | ||