diff options
author | Tomi Valkeinen <tomi.valkeinen@nokia.com> | 2010-03-03 07:31:45 -0500 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@nokia.com> | 2010-05-18 07:14:30 -0400 |
commit | a3201a0eaed38dd7ece72393a778b4408ec79627 (patch) | |
tree | b7539e0059653e124c56c4829a9a4a8f11789240 /drivers/video/omap2/displays | |
parent | f49a951f8a2dacbbb145b6199297fcc3e493b90f (diff) |
OMAP: DSS2: Taal: add mutex to protect panel data
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Diffstat (limited to 'drivers/video/omap2/displays')
-rw-r--r-- | drivers/video/omap2/displays/panel-taal.c | 140 |
1 files changed, 119 insertions, 21 deletions
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 4f3988a41082..1799096a1388 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/completion.h> | 31 | #include <linux/completion.h> |
32 | #include <linux/workqueue.h> | 32 | #include <linux/workqueue.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/mutex.h> | ||
34 | 35 | ||
35 | #include <plat/display.h> | 36 | #include <plat/display.h> |
36 | 37 | ||
@@ -67,6 +68,8 @@ | |||
67 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); | 68 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); |
68 | 69 | ||
69 | struct taal_data { | 70 | struct taal_data { |
71 | struct mutex lock; | ||
72 | |||
70 | struct backlight_device *bldev; | 73 | struct backlight_device *bldev; |
71 | 74 | ||
72 | unsigned long hw_guard_end; /* next value of jiffies when we can | 75 | unsigned long hw_guard_end; /* next value of jiffies when we can |
@@ -510,6 +513,8 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
510 | } | 513 | } |
511 | td->dssdev = dssdev; | 514 | td->dssdev = dssdev; |
512 | 515 | ||
516 | mutex_init(&td->lock); | ||
517 | |||
513 | td->esd_wq = create_singlethread_workqueue("taal_esd"); | 518 | td->esd_wq = create_singlethread_workqueue("taal_esd"); |
514 | if (td->esd_wq == NULL) { | 519 | if (td->esd_wq == NULL) { |
515 | dev_err(&dssdev->dev, "can't create ESD workqueue\n"); | 520 | dev_err(&dssdev->dev, "can't create ESD workqueue\n"); |
@@ -733,54 +738,96 @@ static void taal_power_off(struct omap_dss_device *dssdev) | |||
733 | 738 | ||
734 | static int taal_enable(struct omap_dss_device *dssdev) | 739 | static int taal_enable(struct omap_dss_device *dssdev) |
735 | { | 740 | { |
741 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
736 | int r; | 742 | int r; |
743 | |||
737 | dev_dbg(&dssdev->dev, "enable\n"); | 744 | dev_dbg(&dssdev->dev, "enable\n"); |
738 | 745 | ||
739 | if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) | 746 | mutex_lock(&td->lock); |
740 | return -EINVAL; | 747 | |
748 | if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { | ||
749 | r = -EINVAL; | ||
750 | goto err; | ||
751 | } | ||
741 | 752 | ||
742 | r = taal_power_on(dssdev); | 753 | r = taal_power_on(dssdev); |
743 | if (r) | 754 | if (r) |
744 | return r; | 755 | goto err; |
745 | 756 | ||
746 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 757 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; |
747 | 758 | ||
759 | mutex_unlock(&td->lock); | ||
760 | |||
761 | return 0; | ||
762 | err: | ||
763 | dev_dbg(&dssdev->dev, "enable failed\n"); | ||
764 | mutex_unlock(&td->lock); | ||
748 | return r; | 765 | return r; |
749 | } | 766 | } |
750 | 767 | ||
751 | static void taal_disable(struct omap_dss_device *dssdev) | 768 | static void taal_disable(struct omap_dss_device *dssdev) |
752 | { | 769 | { |
770 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
771 | |||
753 | dev_dbg(&dssdev->dev, "disable\n"); | 772 | dev_dbg(&dssdev->dev, "disable\n"); |
754 | 773 | ||
774 | mutex_lock(&td->lock); | ||
775 | |||
755 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | 776 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) |
756 | taal_power_off(dssdev); | 777 | taal_power_off(dssdev); |
757 | 778 | ||
758 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | 779 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; |
780 | |||
781 | mutex_unlock(&td->lock); | ||
759 | } | 782 | } |
760 | 783 | ||
761 | static int taal_suspend(struct omap_dss_device *dssdev) | 784 | static int taal_suspend(struct omap_dss_device *dssdev) |
762 | { | 785 | { |
786 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
787 | int r; | ||
788 | |||
763 | dev_dbg(&dssdev->dev, "suspend\n"); | 789 | dev_dbg(&dssdev->dev, "suspend\n"); |
764 | 790 | ||
765 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | 791 | mutex_lock(&td->lock); |
766 | return -EINVAL; | 792 | |
793 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | ||
794 | r = -EINVAL; | ||
795 | goto err; | ||
796 | } | ||
767 | 797 | ||
768 | taal_power_off(dssdev); | 798 | taal_power_off(dssdev); |
769 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | 799 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; |
770 | 800 | ||
801 | mutex_unlock(&td->lock); | ||
802 | |||
771 | return 0; | 803 | return 0; |
804 | err: | ||
805 | mutex_unlock(&td->lock); | ||
806 | return r; | ||
772 | } | 807 | } |
773 | 808 | ||
774 | static int taal_resume(struct omap_dss_device *dssdev) | 809 | static int taal_resume(struct omap_dss_device *dssdev) |
775 | { | 810 | { |
811 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
776 | int r; | 812 | int r; |
813 | |||
777 | dev_dbg(&dssdev->dev, "resume\n"); | 814 | dev_dbg(&dssdev->dev, "resume\n"); |
778 | 815 | ||
779 | if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) | 816 | mutex_lock(&td->lock); |
780 | return -EINVAL; | 817 | |
818 | if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { | ||
819 | r = -EINVAL; | ||
820 | goto err; | ||
821 | } | ||
781 | 822 | ||
782 | r = taal_power_on(dssdev); | 823 | r = taal_power_on(dssdev); |
783 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 824 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; |
825 | |||
826 | mutex_unlock(&td->lock); | ||
827 | |||
828 | return r; | ||
829 | err: | ||
830 | mutex_unlock(&td->lock); | ||
784 | return r; | 831 | return r; |
785 | } | 832 | } |
786 | 833 | ||
@@ -799,6 +846,7 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
799 | 846 | ||
800 | dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); | 847 | dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); |
801 | 848 | ||
849 | mutex_lock(&td->lock); | ||
802 | dsi_bus_lock(); | 850 | dsi_bus_lock(); |
803 | 851 | ||
804 | if (!td->enabled) { | 852 | if (!td->enabled) { |
@@ -820,18 +868,24 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
820 | goto err; | 868 | goto err; |
821 | 869 | ||
822 | /* note: no bus_unlock here. unlock is in framedone_cb */ | 870 | /* note: no bus_unlock here. unlock is in framedone_cb */ |
871 | mutex_unlock(&td->lock); | ||
823 | return 0; | 872 | return 0; |
824 | err: | 873 | err: |
825 | dsi_bus_unlock(); | 874 | dsi_bus_unlock(); |
875 | mutex_unlock(&td->lock); | ||
826 | return r; | 876 | return r; |
827 | } | 877 | } |
828 | 878 | ||
829 | static int taal_sync(struct omap_dss_device *dssdev) | 879 | static int taal_sync(struct omap_dss_device *dssdev) |
830 | { | 880 | { |
881 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
882 | |||
831 | dev_dbg(&dssdev->dev, "sync\n"); | 883 | dev_dbg(&dssdev->dev, "sync\n"); |
832 | 884 | ||
885 | mutex_lock(&td->lock); | ||
833 | dsi_bus_lock(); | 886 | dsi_bus_lock(); |
834 | dsi_bus_unlock(); | 887 | dsi_bus_unlock(); |
888 | mutex_unlock(&td->lock); | ||
835 | 889 | ||
836 | dev_dbg(&dssdev->dev, "sync done\n"); | 890 | dev_dbg(&dssdev->dev, "sync done\n"); |
837 | 891 | ||
@@ -861,13 +915,16 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
861 | 915 | ||
862 | static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) | 916 | static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) |
863 | { | 917 | { |
918 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
864 | int r; | 919 | int r; |
865 | 920 | ||
921 | mutex_lock(&td->lock); | ||
866 | dsi_bus_lock(); | 922 | dsi_bus_lock(); |
867 | 923 | ||
868 | r = _taal_enable_te(dssdev, enable); | 924 | r = _taal_enable_te(dssdev, enable); |
869 | 925 | ||
870 | dsi_bus_unlock(); | 926 | dsi_bus_unlock(); |
927 | mutex_unlock(&td->lock); | ||
871 | 928 | ||
872 | return r; | 929 | return r; |
873 | } | 930 | } |
@@ -875,7 +932,13 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
875 | static int taal_get_te(struct omap_dss_device *dssdev) | 932 | static int taal_get_te(struct omap_dss_device *dssdev) |
876 | { | 933 | { |
877 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 934 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
878 | return td->te_enabled; | 935 | int r; |
936 | |||
937 | mutex_lock(&td->lock); | ||
938 | r = td->te_enabled; | ||
939 | mutex_unlock(&td->lock); | ||
940 | |||
941 | return r; | ||
879 | } | 942 | } |
880 | 943 | ||
881 | static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) | 944 | static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) |
@@ -885,6 +948,7 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) | |||
885 | 948 | ||
886 | dev_dbg(&dssdev->dev, "rotate %d\n", rotate); | 949 | dev_dbg(&dssdev->dev, "rotate %d\n", rotate); |
887 | 950 | ||
951 | mutex_lock(&td->lock); | ||
888 | dsi_bus_lock(); | 952 | dsi_bus_lock(); |
889 | 953 | ||
890 | if (td->enabled) { | 954 | if (td->enabled) { |
@@ -896,16 +960,24 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) | |||
896 | td->rotate = rotate; | 960 | td->rotate = rotate; |
897 | 961 | ||
898 | dsi_bus_unlock(); | 962 | dsi_bus_unlock(); |
963 | mutex_unlock(&td->lock); | ||
899 | return 0; | 964 | return 0; |
900 | err: | 965 | err: |
901 | dsi_bus_unlock(); | 966 | dsi_bus_unlock(); |
967 | mutex_unlock(&td->lock); | ||
902 | return r; | 968 | return r; |
903 | } | 969 | } |
904 | 970 | ||
905 | static u8 taal_get_rotate(struct omap_dss_device *dssdev) | 971 | static u8 taal_get_rotate(struct omap_dss_device *dssdev) |
906 | { | 972 | { |
907 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 973 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
908 | return td->rotate; | 974 | int r; |
975 | |||
976 | mutex_lock(&td->lock); | ||
977 | r = td->rotate; | ||
978 | mutex_unlock(&td->lock); | ||
979 | |||
980 | return r; | ||
909 | } | 981 | } |
910 | 982 | ||
911 | static int taal_mirror(struct omap_dss_device *dssdev, bool enable) | 983 | static int taal_mirror(struct omap_dss_device *dssdev, bool enable) |
@@ -915,6 +987,7 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable) | |||
915 | 987 | ||
916 | dev_dbg(&dssdev->dev, "mirror %d\n", enable); | 988 | dev_dbg(&dssdev->dev, "mirror %d\n", enable); |
917 | 989 | ||
990 | mutex_lock(&td->lock); | ||
918 | dsi_bus_lock(); | 991 | dsi_bus_lock(); |
919 | if (td->enabled) { | 992 | if (td->enabled) { |
920 | r = taal_set_addr_mode(td->rotate, enable); | 993 | r = taal_set_addr_mode(td->rotate, enable); |
@@ -925,23 +998,33 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable) | |||
925 | td->mirror = enable; | 998 | td->mirror = enable; |
926 | 999 | ||
927 | dsi_bus_unlock(); | 1000 | dsi_bus_unlock(); |
1001 | mutex_unlock(&td->lock); | ||
928 | return 0; | 1002 | return 0; |
929 | err: | 1003 | err: |
930 | dsi_bus_unlock(); | 1004 | dsi_bus_unlock(); |
1005 | mutex_unlock(&td->lock); | ||
931 | return r; | 1006 | return r; |
932 | } | 1007 | } |
933 | 1008 | ||
934 | static bool taal_get_mirror(struct omap_dss_device *dssdev) | 1009 | static bool taal_get_mirror(struct omap_dss_device *dssdev) |
935 | { | 1010 | { |
936 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1011 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
937 | return td->mirror; | 1012 | int r; |
1013 | |||
1014 | mutex_lock(&td->lock); | ||
1015 | r = td->mirror; | ||
1016 | mutex_unlock(&td->lock); | ||
1017 | |||
1018 | return r; | ||
938 | } | 1019 | } |
939 | 1020 | ||
940 | static int taal_run_test(struct omap_dss_device *dssdev, int test_num) | 1021 | static int taal_run_test(struct omap_dss_device *dssdev, int test_num) |
941 | { | 1022 | { |
1023 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
942 | u8 id1, id2, id3; | 1024 | u8 id1, id2, id3; |
943 | int r; | 1025 | int r; |
944 | 1026 | ||
1027 | mutex_lock(&td->lock); | ||
945 | dsi_bus_lock(); | 1028 | dsi_bus_lock(); |
946 | 1029 | ||
947 | r = taal_dcs_read_1(DCS_GET_ID1, &id1); | 1030 | r = taal_dcs_read_1(DCS_GET_ID1, &id1); |
@@ -955,9 +1038,11 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num) | |||
955 | goto err; | 1038 | goto err; |
956 | 1039 | ||
957 | dsi_bus_unlock(); | 1040 | dsi_bus_unlock(); |
1041 | mutex_unlock(&td->lock); | ||
958 | return 0; | 1042 | return 0; |
959 | err: | 1043 | err: |
960 | dsi_bus_unlock(); | 1044 | dsi_bus_unlock(); |
1045 | mutex_unlock(&td->lock); | ||
961 | return r; | 1046 | return r; |
962 | } | 1047 | } |
963 | 1048 | ||
@@ -971,12 +1056,16 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
971 | unsigned buf_used = 0; | 1056 | unsigned buf_used = 0; |
972 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1057 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
973 | 1058 | ||
974 | if (!td->enabled) | ||
975 | return -ENODEV; | ||
976 | |||
977 | if (size < w * h * 3) | 1059 | if (size < w * h * 3) |
978 | return -ENOMEM; | 1060 | return -ENOMEM; |
979 | 1061 | ||
1062 | mutex_lock(&td->lock); | ||
1063 | |||
1064 | if (!td->enabled) { | ||
1065 | r = -ENODEV; | ||
1066 | goto err1; | ||
1067 | } | ||
1068 | |||
980 | size = min(w * h * 3, | 1069 | size = min(w * h * 3, |
981 | dssdev->panel.timings.x_res * | 1070 | dssdev->panel.timings.x_res * |
982 | dssdev->panel.timings.y_res * 3); | 1071 | dssdev->panel.timings.y_res * 3); |
@@ -995,7 +1084,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
995 | 1084 | ||
996 | r = dsi_vc_set_max_rx_packet_size(TCH, plen); | 1085 | r = dsi_vc_set_max_rx_packet_size(TCH, plen); |
997 | if (r) | 1086 | if (r) |
998 | goto err0; | 1087 | goto err2; |
999 | 1088 | ||
1000 | while (buf_used < size) { | 1089 | while (buf_used < size) { |
1001 | u8 dcs_cmd = first ? 0x2e : 0x3e; | 1090 | u8 dcs_cmd = first ? 0x2e : 0x3e; |
@@ -1006,7 +1095,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1006 | 1095 | ||
1007 | if (r < 0) { | 1096 | if (r < 0) { |
1008 | dev_err(&dssdev->dev, "read error\n"); | 1097 | dev_err(&dssdev->dev, "read error\n"); |
1009 | goto err; | 1098 | goto err3; |
1010 | } | 1099 | } |
1011 | 1100 | ||
1012 | buf_used += r; | 1101 | buf_used += r; |
@@ -1020,16 +1109,18 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1020 | dev_err(&dssdev->dev, "signal pending, " | 1109 | dev_err(&dssdev->dev, "signal pending, " |
1021 | "aborting memory read\n"); | 1110 | "aborting memory read\n"); |
1022 | r = -ERESTARTSYS; | 1111 | r = -ERESTARTSYS; |
1023 | goto err; | 1112 | goto err3; |
1024 | } | 1113 | } |
1025 | } | 1114 | } |
1026 | 1115 | ||
1027 | r = buf_used; | 1116 | r = buf_used; |
1028 | 1117 | ||
1029 | err: | 1118 | err3: |
1030 | dsi_vc_set_max_rx_packet_size(TCH, 1); | 1119 | dsi_vc_set_max_rx_packet_size(TCH, 1); |
1031 | err0: | 1120 | err2: |
1032 | dsi_bus_unlock(); | 1121 | dsi_bus_unlock(); |
1122 | err1: | ||
1123 | mutex_unlock(&td->lock); | ||
1033 | return r; | 1124 | return r; |
1034 | } | 1125 | } |
1035 | 1126 | ||
@@ -1041,8 +1132,12 @@ static void taal_esd_work(struct work_struct *work) | |||
1041 | u8 state1, state2; | 1132 | u8 state1, state2; |
1042 | int r; | 1133 | int r; |
1043 | 1134 | ||
1044 | if (!td->enabled) | 1135 | mutex_lock(&td->lock); |
1136 | |||
1137 | if (!td->enabled) { | ||
1138 | mutex_unlock(&td->lock); | ||
1045 | return; | 1139 | return; |
1140 | } | ||
1046 | 1141 | ||
1047 | dsi_bus_lock(); | 1142 | dsi_bus_lock(); |
1048 | 1143 | ||
@@ -1084,16 +1179,19 @@ static void taal_esd_work(struct work_struct *work) | |||
1084 | 1179 | ||
1085 | queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); | 1180 | queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); |
1086 | 1181 | ||
1182 | mutex_unlock(&td->lock); | ||
1087 | return; | 1183 | return; |
1088 | err: | 1184 | err: |
1089 | dev_err(&dssdev->dev, "performing LCD reset\n"); | 1185 | dev_err(&dssdev->dev, "performing LCD reset\n"); |
1090 | 1186 | ||
1091 | taal_disable(dssdev); | 1187 | taal_power_off(dssdev); |
1092 | taal_enable(dssdev); | 1188 | taal_power_on(dssdev); |
1093 | 1189 | ||
1094 | dsi_bus_unlock(); | 1190 | dsi_bus_unlock(); |
1095 | 1191 | ||
1096 | queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); | 1192 | queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); |
1193 | |||
1194 | mutex_unlock(&td->lock); | ||
1097 | } | 1195 | } |
1098 | 1196 | ||
1099 | static int taal_set_update_mode(struct omap_dss_device *dssdev, | 1197 | static int taal_set_update_mode(struct omap_dss_device *dssdev, |