aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/mxsfb.c
diff options
context:
space:
mode:
authorShawn Guo <shawn.guo@linaro.org>2013-03-13 22:57:34 -0400
committerShawn Guo <shawn.guo@linaro.org>2013-04-04 09:22:41 -0400
commit669406534b4abb827d1bdc39bb5e2d5255818ae2 (patch)
tree0999716da16a54cb37f66c1f7ebf75b025a1852b /drivers/video/mxsfb.c
parent36f3e99649baa77b2d22e385b2ea09e8f308c905 (diff)
video: mxsfb: get display timings from device tree
Use videomode helpers to get display timings and configurations from device tree when platform_data is absent. Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Diffstat (limited to 'drivers/video/mxsfb.c')
-rw-r--r--drivers/video/mxsfb.c122
1 files changed, 110 insertions, 12 deletions
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index a89901c7f5e9..e5ceba54d22f 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -43,12 +43,14 @@
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 <linux/of_gpio.h>
46#include <video/of_display_timing.h>
46#include <linux/platform_device.h> 47#include <linux/platform_device.h>
47#include <linux/clk.h> 48#include <linux/clk.h>
48#include <linux/dma-mapping.h> 49#include <linux/dma-mapping.h>
49#include <linux/io.h> 50#include <linux/io.h>
50#include <linux/pinctrl/consumer.h> 51#include <linux/pinctrl/consumer.h>
51#include <linux/mxsfb.h> 52#include <linux/mxsfb.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
@@ -678,6 +680,97 @@ static int mxsfb_restore_mode(struct mxsfb_info *host)
678 return 0; 680 return 0;
679} 681}
680 682
683static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host)
684{
685 struct fb_info *fb_info = &host->fb_info;
686 struct fb_var_screeninfo *var = &fb_info->var;
687 struct device *dev = &host->pdev->dev;
688 struct device_node *np = host->pdev->dev.of_node;
689 struct device_node *display_np;
690 struct device_node *timings_np;
691 struct display_timings *timings;
692 u32 width;
693 int i;
694 int ret = 0;
695
696 display_np = of_parse_phandle(np, "display", 0);
697 if (!display_np) {
698 dev_err(dev, "failed to find display phandle\n");
699 return -ENOENT;
700 }
701
702 ret = of_property_read_u32(display_np, "bus-width", &width);
703 if (ret < 0) {
704 dev_err(dev, "failed to get property bus-width\n");
705 goto put_display_node;
706 }
707
708 switch (width) {
709 case 8:
710 host->ld_intf_width = STMLCDIF_8BIT;
711 break;
712 case 16:
713 host->ld_intf_width = STMLCDIF_16BIT;
714 break;
715 case 18:
716 host->ld_intf_width = STMLCDIF_18BIT;
717 break;
718 case 24:
719 host->ld_intf_width = STMLCDIF_24BIT;
720 break;
721 default:
722 dev_err(dev, "invalid bus-width value\n");
723 ret = -EINVAL;
724 goto put_display_node;
725 }
726
727 ret = of_property_read_u32(display_np, "bits-per-pixel",
728 &var->bits_per_pixel);
729 if (ret < 0) {
730 dev_err(dev, "failed to get property bits-per-pixel\n");
731 goto put_display_node;
732 }
733
734 timings = of_get_display_timings(display_np);
735 if (!timings) {
736 dev_err(dev, "failed to get display timings\n");
737 ret = -ENOENT;
738 goto put_display_node;
739 }
740
741 timings_np = of_find_node_by_name(display_np,
742 "display-timings");
743 if (!timings_np) {
744 dev_err(dev, "failed to find display-timings node\n");
745 ret = -ENOENT;
746 goto put_display_node;
747 }
748
749 for (i = 0; i < of_get_child_count(timings_np); i++) {
750 struct videomode vm;
751 struct fb_videomode fb_vm;
752
753 ret = videomode_from_timing(timings, &vm, i);
754 if (ret < 0)
755 goto put_timings_node;
756 ret = fb_videomode_from_videomode(&vm, &fb_vm);
757 if (ret < 0)
758 goto put_timings_node;
759
760 if (vm.data_flags & DISPLAY_FLAGS_DE_HIGH)
761 host->sync |= MXSFB_SYNC_DATA_ENABLE_HIGH_ACT;
762 if (vm.data_flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
763 host->sync |= MXSFB_SYNC_DOTCLK_FAILING_ACT;
764 fb_add_videomode(&fb_vm, &fb_info->modelist);
765 }
766
767put_timings_node:
768 of_node_put(timings_np);
769put_display_node:
770 of_node_put(display_np);
771 return ret;
772}
773
681static int mxsfb_init_fbinfo(struct mxsfb_info *host) 774static int mxsfb_init_fbinfo(struct mxsfb_info *host)
682{ 775{
683 struct fb_info *fb_info = &host->fb_info; 776 struct fb_info *fb_info = &host->fb_info;
@@ -686,6 +779,7 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host)
686 dma_addr_t fb_phys; 779 dma_addr_t fb_phys;
687 void *fb_virt; 780 void *fb_virt;
688 unsigned fb_size; 781 unsigned fb_size;
782 int ret;
689 783
690 fb_info->fbops = &mxsfb_ops; 784 fb_info->fbops = &mxsfb_ops;
691 fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST; 785 fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST;
@@ -695,14 +789,21 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host)
695 fb_info->fix.visual = FB_VISUAL_TRUECOLOR, 789 fb_info->fix.visual = FB_VISUAL_TRUECOLOR,
696 fb_info->fix.accel = FB_ACCEL_NONE; 790 fb_info->fix.accel = FB_ACCEL_NONE;
697 791
698 var->bits_per_pixel = pdata->default_bpp ? pdata->default_bpp : 16; 792 if (pdata) {
793 host->ld_intf_width = pdata->ld_intf_width;
794 var->bits_per_pixel =
795 pdata->default_bpp ? pdata->default_bpp : 16;
796 } else {
797 ret = mxsfb_init_fbinfo_dt(host);
798 if (ret)
799 return ret;
800 }
801
699 var->nonstd = 0; 802 var->nonstd = 0;
700 var->activate = FB_ACTIVATE_NOW; 803 var->activate = FB_ACTIVATE_NOW;
701 var->accel_flags = 0; 804 var->accel_flags = 0;
702 var->vmode = FB_VMODE_NONINTERLACED; 805 var->vmode = FB_VMODE_NONINTERLACED;
703 806
704 host->ld_intf_width = pdata->ld_intf_width;
705
706 /* Memory allocation for framebuffer */ 807 /* Memory allocation for framebuffer */
707 fb_size = SZ_2M; 808 fb_size = SZ_2M;
708 fb_virt = alloc_pages_exact(fb_size, GFP_DMA); 809 fb_virt = alloc_pages_exact(fb_size, GFP_DMA);
@@ -765,11 +866,6 @@ static int mxsfb_probe(struct platform_device *pdev)
765 if (of_id) 866 if (of_id)
766 pdev->id_entry = of_id->data; 867 pdev->id_entry = of_id->data;
767 868
768 if (!pdata) {
769 dev_err(&pdev->dev, "No platformdata. Giving up\n");
770 return -ENODEV;
771 }
772
773 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 869 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
774 if (!res) { 870 if (!res) {
775 dev_err(&pdev->dev, "Cannot get memory IO resource\n"); 871 dev_err(&pdev->dev, "Cannot get memory IO resource\n");
@@ -833,14 +929,16 @@ static int mxsfb_probe(struct platform_device *pdev)
833 929
834 INIT_LIST_HEAD(&fb_info->modelist); 930 INIT_LIST_HEAD(&fb_info->modelist);
835 931
836 host->sync = pdata->sync;
837
838 ret = mxsfb_init_fbinfo(host); 932 ret = mxsfb_init_fbinfo(host);
839 if (ret != 0) 933 if (ret != 0)
840 goto fb_release; 934 goto fb_release;
841 935
842 for (i = 0; i < pdata->mode_count; i++) 936 if (pdata) {
843 fb_add_videomode(&pdata->mode_list[i], &fb_info->modelist); 937 host->sync = pdata->sync;
938 for (i = 0; i < pdata->mode_count; i++)
939 fb_add_videomode(&pdata->mode_list[i],
940 &fb_info->modelist);
941 }
844 942
845 modelist = list_first_entry(&fb_info->modelist, 943 modelist = list_first_entry(&fb_info->modelist,
846 struct fb_modelist, list); 944 struct fb_modelist, list);