| .. | .. |
|---|
| 30 | 30 | #include <video/of_display_timing.h> |
|---|
| 31 | 31 | #include <video/videomode.h> |
|---|
| 32 | 32 | |
|---|
| 33 | | -#include "amba-clcd-nomadik.h" |
|---|
| 34 | | -#include "amba-clcd-versatile.h" |
|---|
| 35 | | - |
|---|
| 36 | 33 | #define to_clcd(info) container_of(info, struct clcd_fb, fb) |
|---|
| 37 | 34 | |
|---|
| 38 | 35 | /* This is limited to 16 characters when displayed by X startup */ |
|---|
| .. | .. |
|---|
| 223 | 220 | var->blue.length = 4; |
|---|
| 224 | 221 | } |
|---|
| 225 | 222 | break; |
|---|
| 226 | | - case 24: |
|---|
| 227 | | - if (fb->vendor->packed_24_bit_pixels) { |
|---|
| 228 | | - var->red.length = 8; |
|---|
| 229 | | - var->green.length = 8; |
|---|
| 230 | | - var->blue.length = 8; |
|---|
| 231 | | - } else { |
|---|
| 232 | | - ret = -EINVAL; |
|---|
| 233 | | - } |
|---|
| 234 | | - break; |
|---|
| 235 | 223 | case 32: |
|---|
| 236 | 224 | /* If we can't do 888, reject */ |
|---|
| 237 | 225 | caps &= CLCD_CAP_888; |
|---|
| .. | .. |
|---|
| 317 | 305 | fb->board->decode(fb, ®s); |
|---|
| 318 | 306 | |
|---|
| 319 | 307 | clcdfb_disable(fb); |
|---|
| 320 | | - |
|---|
| 321 | | - /* Some variants must be clocked here */ |
|---|
| 322 | | - if (fb->vendor->clock_timregs && !fb->clk_enabled) { |
|---|
| 323 | | - fb->clk_enabled = true; |
|---|
| 324 | | - clk_enable(fb->clk); |
|---|
| 325 | | - } |
|---|
| 326 | 308 | |
|---|
| 327 | 309 | writel(regs.tim0, fb->regs + CLCD_TIM0); |
|---|
| 328 | 310 | writel(regs.tim1, fb->regs + CLCD_TIM1); |
|---|
| .. | .. |
|---|
| 441 | 423 | return ret; |
|---|
| 442 | 424 | } |
|---|
| 443 | 425 | |
|---|
| 444 | | -static struct fb_ops clcdfb_ops = { |
|---|
| 426 | +static const struct fb_ops clcdfb_ops = { |
|---|
| 445 | 427 | .owner = THIS_MODULE, |
|---|
| 446 | 428 | .fb_check_var = clcdfb_check_var, |
|---|
| 447 | 429 | .fb_set_par = clcdfb_set_par, |
|---|
| .. | .. |
|---|
| 465 | 447 | fb->off_ienb = CLCD_PL111_IENB; |
|---|
| 466 | 448 | fb->off_cntl = CLCD_PL111_CNTL; |
|---|
| 467 | 449 | } else { |
|---|
| 468 | | - if (of_machine_is_compatible("arm,versatile-ab") || |
|---|
| 469 | | - of_machine_is_compatible("arm,versatile-pb")) { |
|---|
| 470 | | - fb->off_ienb = CLCD_PL111_IENB; |
|---|
| 471 | | - fb->off_cntl = CLCD_PL111_CNTL; |
|---|
| 472 | | - } else { |
|---|
| 473 | | - fb->off_ienb = CLCD_PL110_IENB; |
|---|
| 474 | | - fb->off_cntl = CLCD_PL110_CNTL; |
|---|
| 475 | | - } |
|---|
| 450 | + fb->off_ienb = CLCD_PL110_IENB; |
|---|
| 451 | + fb->off_cntl = CLCD_PL110_CNTL; |
|---|
| 476 | 452 | } |
|---|
| 477 | 453 | |
|---|
| 478 | 454 | fb->clk = clk_get(&fb->dev->dev, NULL); |
|---|
| .. | .. |
|---|
| 585 | 561 | struct videomode video; |
|---|
| 586 | 562 | |
|---|
| 587 | 563 | err = of_get_display_timing(node, "panel-timing", &timing); |
|---|
| 588 | | - if (err) |
|---|
| 564 | + if (err) { |
|---|
| 565 | + pr_err("%pOF: problems parsing panel-timing (%d)\n", node, err); |
|---|
| 589 | 566 | return err; |
|---|
| 567 | + } |
|---|
| 590 | 568 | |
|---|
| 591 | 569 | videomode_from_timing(&timing, &video); |
|---|
| 592 | 570 | |
|---|
| .. | .. |
|---|
| 624 | 602 | mode->refresh); |
|---|
| 625 | 603 | } |
|---|
| 626 | 604 | |
|---|
| 627 | | -static int clcdfb_of_get_backlight(struct device_node *panel, |
|---|
| 605 | +static int clcdfb_of_get_backlight(struct device *dev, |
|---|
| 628 | 606 | struct clcd_panel *clcd_panel) |
|---|
| 629 | 607 | { |
|---|
| 630 | | - struct device_node *backlight; |
|---|
| 608 | + struct backlight_device *backlight; |
|---|
| 631 | 609 | |
|---|
| 632 | | - /* Look up the optional backlight phandle */ |
|---|
| 633 | | - backlight = of_parse_phandle(panel, "backlight", 0); |
|---|
| 634 | | - if (backlight) { |
|---|
| 635 | | - clcd_panel->backlight = of_find_backlight_by_node(backlight); |
|---|
| 636 | | - of_node_put(backlight); |
|---|
| 610 | + /* Look up the optional backlight device */ |
|---|
| 611 | + backlight = devm_of_find_backlight(dev); |
|---|
| 612 | + if (IS_ERR(backlight)) |
|---|
| 613 | + return PTR_ERR(backlight); |
|---|
| 637 | 614 | |
|---|
| 638 | | - if (!clcd_panel->backlight) |
|---|
| 639 | | - return -EPROBE_DEFER; |
|---|
| 640 | | - } |
|---|
| 615 | + clcd_panel->backlight = backlight; |
|---|
| 641 | 616 | return 0; |
|---|
| 642 | 617 | } |
|---|
| 643 | 618 | |
|---|
| .. | .. |
|---|
| 713 | 688 | if (r0 != 0 && b0 == 0) |
|---|
| 714 | 689 | fb->panel->bgr_connection = true; |
|---|
| 715 | 690 | |
|---|
| 716 | | - if (fb->panel->caps && fb->vendor->st_bitmux_control) { |
|---|
| 717 | | - /* |
|---|
| 718 | | - * Set up the special bits for the Nomadik control register |
|---|
| 719 | | - * (other platforms tend to do this through an external |
|---|
| 720 | | - * register). |
|---|
| 721 | | - */ |
|---|
| 722 | | - |
|---|
| 723 | | - /* Offset of the highest used color */ |
|---|
| 724 | | - int maxoff = max3(r0, g0, b0); |
|---|
| 725 | | - /* Most significant bit out, highest used bit */ |
|---|
| 726 | | - int msb = 0; |
|---|
| 727 | | - |
|---|
| 728 | | - if (fb->panel->caps & CLCD_CAP_888) { |
|---|
| 729 | | - msb = maxoff + 8 - 1; |
|---|
| 730 | | - } else if (fb->panel->caps & CLCD_CAP_565) { |
|---|
| 731 | | - msb = maxoff + 5 - 1; |
|---|
| 732 | | - fb->panel->cntl |= CNTL_ST_1XBPP_565; |
|---|
| 733 | | - } else if (fb->panel->caps & CLCD_CAP_5551) { |
|---|
| 734 | | - msb = maxoff + 5 - 1; |
|---|
| 735 | | - fb->panel->cntl |= CNTL_ST_1XBPP_5551; |
|---|
| 736 | | - } else if (fb->panel->caps & CLCD_CAP_444) { |
|---|
| 737 | | - msb = maxoff + 4 - 1; |
|---|
| 738 | | - fb->panel->cntl |= CNTL_ST_1XBPP_444; |
|---|
| 739 | | - } |
|---|
| 740 | | - |
|---|
| 741 | | - /* Send out as many bits as we need */ |
|---|
| 742 | | - if (msb > 17) |
|---|
| 743 | | - fb->panel->cntl |= CNTL_ST_CDWID_24; |
|---|
| 744 | | - else if (msb > 15) |
|---|
| 745 | | - fb->panel->cntl |= CNTL_ST_CDWID_18; |
|---|
| 746 | | - else if (msb > 11) |
|---|
| 747 | | - fb->panel->cntl |= CNTL_ST_CDWID_16; |
|---|
| 748 | | - else |
|---|
| 749 | | - fb->panel->cntl |= CNTL_ST_CDWID_12; |
|---|
| 750 | | - } |
|---|
| 751 | | - |
|---|
| 752 | 691 | return fb->panel->caps ? 0 : -EINVAL; |
|---|
| 753 | 692 | } |
|---|
| 754 | 693 | |
|---|
| .. | .. |
|---|
| 772 | 711 | return -ENODEV; |
|---|
| 773 | 712 | |
|---|
| 774 | 713 | panel = of_graph_get_remote_port_parent(endpoint); |
|---|
| 775 | | - if (!panel) |
|---|
| 776 | | - return -ENODEV; |
|---|
| 777 | | - |
|---|
| 778 | | - if (fb->vendor->init_panel) { |
|---|
| 779 | | - err = fb->vendor->init_panel(fb, panel); |
|---|
| 780 | | - if (err) |
|---|
| 781 | | - return err; |
|---|
| 714 | + if (!panel) { |
|---|
| 715 | + err = -ENODEV; |
|---|
| 716 | + goto out_endpoint_put; |
|---|
| 782 | 717 | } |
|---|
| 783 | 718 | |
|---|
| 784 | | - err = clcdfb_of_get_backlight(panel, fb->panel); |
|---|
| 719 | + err = clcdfb_of_get_backlight(&fb->dev->dev, fb->panel); |
|---|
| 785 | 720 | if (err) |
|---|
| 786 | | - return err; |
|---|
| 721 | + goto out_panel_put; |
|---|
| 787 | 722 | |
|---|
| 788 | 723 | err = clcdfb_of_get_mode(&fb->dev->dev, panel, fb->panel); |
|---|
| 789 | 724 | if (err) |
|---|
| 790 | | - return err; |
|---|
| 725 | + goto out_panel_put; |
|---|
| 791 | 726 | |
|---|
| 792 | 727 | err = of_property_read_u32(fb->dev->dev.of_node, "max-memory-bandwidth", |
|---|
| 793 | 728 | &max_bandwidth); |
|---|
| .. | .. |
|---|
| 816 | 751 | |
|---|
| 817 | 752 | if (of_property_read_u32_array(endpoint, |
|---|
| 818 | 753 | "arm,pl11x,tft-r0g0b0-pads", |
|---|
| 819 | | - tft_r0b0g0, ARRAY_SIZE(tft_r0b0g0)) != 0) |
|---|
| 820 | | - return -ENOENT; |
|---|
| 754 | + tft_r0b0g0, ARRAY_SIZE(tft_r0b0g0)) != 0) { |
|---|
| 755 | + err = -ENOENT; |
|---|
| 756 | + goto out_panel_put; |
|---|
| 757 | + } |
|---|
| 758 | + |
|---|
| 759 | + of_node_put(panel); |
|---|
| 760 | + of_node_put(endpoint); |
|---|
| 821 | 761 | |
|---|
| 822 | 762 | return clcdfb_of_init_tft_panel(fb, tft_r0b0g0[0], |
|---|
| 823 | 763 | tft_r0b0g0[1], tft_r0b0g0[2]); |
|---|
| 764 | +out_panel_put: |
|---|
| 765 | + of_node_put(panel); |
|---|
| 766 | +out_endpoint_put: |
|---|
| 767 | + of_node_put(endpoint); |
|---|
| 768 | + return err; |
|---|
| 824 | 769 | } |
|---|
| 825 | 770 | |
|---|
| 826 | 771 | static int clcdfb_of_vram_setup(struct clcd_fb *fb) |
|---|
| .. | .. |
|---|
| 838 | 783 | return -ENODEV; |
|---|
| 839 | 784 | |
|---|
| 840 | 785 | fb->fb.screen_base = of_iomap(memory, 0); |
|---|
| 841 | | - if (!fb->fb.screen_base) |
|---|
| 786 | + if (!fb->fb.screen_base) { |
|---|
| 787 | + of_node_put(memory); |
|---|
| 842 | 788 | return -ENOMEM; |
|---|
| 789 | + } |
|---|
| 843 | 790 | |
|---|
| 844 | 791 | fb->fb.fix.smem_start = of_translate_address(memory, |
|---|
| 845 | 792 | of_get_address(memory, 0, &size, NULL)); |
|---|
| 846 | 793 | fb->fb.fix.smem_len = size; |
|---|
| 794 | + of_node_put(memory); |
|---|
| 847 | 795 | |
|---|
| 848 | 796 | return 0; |
|---|
| 849 | 797 | } |
|---|
| .. | .. |
|---|
| 941 | 889 | static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id) |
|---|
| 942 | 890 | { |
|---|
| 943 | 891 | struct clcd_board *board = dev_get_platdata(&dev->dev); |
|---|
| 944 | | - struct clcd_vendor_data *vendor = id->data; |
|---|
| 945 | 892 | struct clcd_fb *fb; |
|---|
| 946 | 893 | int ret; |
|---|
| 947 | 894 | |
|---|
| .. | .. |
|---|
| 950 | 897 | |
|---|
| 951 | 898 | if (!board) |
|---|
| 952 | 899 | return -EINVAL; |
|---|
| 953 | | - |
|---|
| 954 | | - if (vendor->init_board) { |
|---|
| 955 | | - ret = vendor->init_board(dev, board); |
|---|
| 956 | | - if (ret) |
|---|
| 957 | | - return ret; |
|---|
| 958 | | - } |
|---|
| 959 | 900 | |
|---|
| 960 | 901 | ret = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32)); |
|---|
| 961 | 902 | if (ret) |
|---|
| .. | .. |
|---|
| 974 | 915 | } |
|---|
| 975 | 916 | |
|---|
| 976 | 917 | fb->dev = dev; |
|---|
| 977 | | - fb->vendor = vendor; |
|---|
| 978 | 918 | fb->board = board; |
|---|
| 979 | 919 | |
|---|
| 980 | 920 | dev_info(&fb->dev->dev, "PL%03x designer %02x rev%u at 0x%08llx\n", |
|---|
| .. | .. |
|---|
| 1000 | 940 | return ret; |
|---|
| 1001 | 941 | } |
|---|
| 1002 | 942 | |
|---|
| 1003 | | -static int clcdfb_remove(struct amba_device *dev) |
|---|
| 943 | +static void clcdfb_remove(struct amba_device *dev) |
|---|
| 1004 | 944 | { |
|---|
| 1005 | 945 | struct clcd_fb *fb = amba_get_drvdata(dev); |
|---|
| 1006 | 946 | |
|---|
| .. | .. |
|---|
| 1017 | 957 | kfree(fb); |
|---|
| 1018 | 958 | |
|---|
| 1019 | 959 | amba_release_regions(dev); |
|---|
| 1020 | | - |
|---|
| 1021 | | - return 0; |
|---|
| 1022 | 960 | } |
|---|
| 1023 | | - |
|---|
| 1024 | | -static struct clcd_vendor_data vendor_arm = { |
|---|
| 1025 | | - /* Sets up the versatile board displays */ |
|---|
| 1026 | | - .init_panel = versatile_clcd_init_panel, |
|---|
| 1027 | | -}; |
|---|
| 1028 | | - |
|---|
| 1029 | | -static struct clcd_vendor_data vendor_nomadik = { |
|---|
| 1030 | | - .clock_timregs = true, |
|---|
| 1031 | | - .packed_24_bit_pixels = true, |
|---|
| 1032 | | - .st_bitmux_control = true, |
|---|
| 1033 | | - .init_board = nomadik_clcd_init_board, |
|---|
| 1034 | | - .init_panel = nomadik_clcd_init_panel, |
|---|
| 1035 | | -}; |
|---|
| 1036 | 961 | |
|---|
| 1037 | 962 | static const struct amba_id clcdfb_id_table[] = { |
|---|
| 1038 | 963 | { |
|---|
| 1039 | 964 | .id = 0x00041110, |
|---|
| 1040 | 965 | .mask = 0x000ffffe, |
|---|
| 1041 | | - .data = &vendor_arm, |
|---|
| 1042 | | - }, |
|---|
| 1043 | | - /* ST Electronics Nomadik variant */ |
|---|
| 1044 | | - { |
|---|
| 1045 | | - .id = 0x00180110, |
|---|
| 1046 | | - .mask = 0x00fffffe, |
|---|
| 1047 | | - .data = &vendor_nomadik, |
|---|
| 1048 | 966 | }, |
|---|
| 1049 | 967 | { 0, 0 }, |
|---|
| 1050 | 968 | }; |
|---|