diff options
Diffstat (limited to 'drivers/media/video/omap3isp/isppreview.c')
-rw-r--r-- | drivers/media/video/omap3isp/isppreview.c | 299 |
1 files changed, 199 insertions, 100 deletions
diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c index fd1807d36d4..5bdf9e742c8 100644 --- a/drivers/media/video/omap3isp/isppreview.c +++ b/drivers/media/video/omap3isp/isppreview.c | |||
@@ -649,12 +649,18 @@ preview_config_rgb_to_ycbcr(struct isp_prev_device *prev, const void *prev_csc) | |||
649 | static void | 649 | static void |
650 | preview_update_contrast(struct isp_prev_device *prev, u8 contrast) | 650 | preview_update_contrast(struct isp_prev_device *prev, u8 contrast) |
651 | { | 651 | { |
652 | struct prev_params *params = &prev->params; | 652 | struct prev_params *params; |
653 | unsigned long flags; | ||
654 | |||
655 | spin_lock_irqsave(&prev->params.lock, flags); | ||
656 | params = (prev->params.active & OMAP3ISP_PREV_CONTRAST) | ||
657 | ? &prev->params.params[0] : &prev->params.params[1]; | ||
653 | 658 | ||
654 | if (params->contrast != (contrast * ISPPRV_CONTRAST_UNITS)) { | 659 | if (params->contrast != (contrast * ISPPRV_CONTRAST_UNITS)) { |
655 | params->contrast = contrast * ISPPRV_CONTRAST_UNITS; | 660 | params->contrast = contrast * ISPPRV_CONTRAST_UNITS; |
656 | prev->update |= OMAP3ISP_PREV_CONTRAST; | 661 | params->update |= OMAP3ISP_PREV_CONTRAST; |
657 | } | 662 | } |
663 | spin_unlock_irqrestore(&prev->params.lock, flags); | ||
658 | } | 664 | } |
659 | 665 | ||
660 | /* | 666 | /* |
@@ -681,12 +687,18 @@ preview_config_contrast(struct isp_prev_device *prev, const void *params) | |||
681 | static void | 687 | static void |
682 | preview_update_brightness(struct isp_prev_device *prev, u8 brightness) | 688 | preview_update_brightness(struct isp_prev_device *prev, u8 brightness) |
683 | { | 689 | { |
684 | struct prev_params *params = &prev->params; | 690 | struct prev_params *params; |
691 | unsigned long flags; | ||
692 | |||
693 | spin_lock_irqsave(&prev->params.lock, flags); | ||
694 | params = (prev->params.active & OMAP3ISP_PREV_BRIGHTNESS) | ||
695 | ? &prev->params.params[0] : &prev->params.params[1]; | ||
685 | 696 | ||
686 | if (params->brightness != (brightness * ISPPRV_BRIGHT_UNITS)) { | 697 | if (params->brightness != (brightness * ISPPRV_BRIGHT_UNITS)) { |
687 | params->brightness = brightness * ISPPRV_BRIGHT_UNITS; | 698 | params->brightness = brightness * ISPPRV_BRIGHT_UNITS; |
688 | prev->update |= OMAP3ISP_PREV_BRIGHTNESS; | 699 | params->update |= OMAP3ISP_PREV_BRIGHTNESS; |
689 | } | 700 | } |
701 | spin_unlock_irqrestore(&prev->params.lock, flags); | ||
690 | } | 702 | } |
691 | 703 | ||
692 | /* | 704 | /* |
@@ -721,6 +733,75 @@ preview_config_yc_range(struct isp_prev_device *prev, const void *yclimit) | |||
721 | OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC); | 733 | OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC); |
722 | } | 734 | } |
723 | 735 | ||
736 | static u32 | ||
737 | preview_params_lock(struct isp_prev_device *prev, u32 update, bool shadow) | ||
738 | { | ||
739 | u32 active = prev->params.active; | ||
740 | |||
741 | if (shadow) { | ||
742 | /* Mark all shadow parameters we are going to touch as busy. */ | ||
743 | prev->params.params[0].busy |= ~active & update; | ||
744 | prev->params.params[1].busy |= active & update; | ||
745 | } else { | ||
746 | /* Mark all active parameters we are going to touch as busy. */ | ||
747 | update = (prev->params.params[0].update & active) | ||
748 | | (prev->params.params[1].update & ~active); | ||
749 | |||
750 | prev->params.params[0].busy |= active & update; | ||
751 | prev->params.params[1].busy |= ~active & update; | ||
752 | } | ||
753 | |||
754 | return update; | ||
755 | } | ||
756 | |||
757 | static void | ||
758 | preview_params_unlock(struct isp_prev_device *prev, u32 update, bool shadow) | ||
759 | { | ||
760 | u32 active = prev->params.active; | ||
761 | |||
762 | if (shadow) { | ||
763 | /* Set the update flag for shadow parameters that have been | ||
764 | * updated and clear the busy flag for all shadow parameters. | ||
765 | */ | ||
766 | prev->params.params[0].update |= (~active & update); | ||
767 | prev->params.params[1].update |= (active & update); | ||
768 | prev->params.params[0].busy &= active; | ||
769 | prev->params.params[1].busy &= ~active; | ||
770 | } else { | ||
771 | /* Clear the update flag for active parameters that have been | ||
772 | * applied and the busy flag for all active parameters. | ||
773 | */ | ||
774 | prev->params.params[0].update &= ~(active & update); | ||
775 | prev->params.params[1].update &= ~(~active & update); | ||
776 | prev->params.params[0].busy &= ~active; | ||
777 | prev->params.params[1].busy &= active; | ||
778 | } | ||
779 | } | ||
780 | |||
781 | static void preview_params_switch(struct isp_prev_device *prev) | ||
782 | { | ||
783 | u32 to_switch; | ||
784 | |||
785 | /* Switch active parameters with updated shadow parameters when the | ||
786 | * shadow parameter has been updated and neither the active not the | ||
787 | * shadow parameter is busy. | ||
788 | */ | ||
789 | to_switch = (prev->params.params[0].update & ~prev->params.active) | ||
790 | | (prev->params.params[1].update & prev->params.active); | ||
791 | to_switch &= ~(prev->params.params[0].busy | | ||
792 | prev->params.params[1].busy); | ||
793 | if (to_switch == 0) | ||
794 | return; | ||
795 | |||
796 | prev->params.active ^= to_switch; | ||
797 | |||
798 | /* Remove the update flag for the shadow copy of parameters we have | ||
799 | * switched. | ||
800 | */ | ||
801 | prev->params.params[0].update &= ~(~prev->params.active & to_switch); | ||
802 | prev->params.params[1].update &= ~(prev->params.active & to_switch); | ||
803 | } | ||
804 | |||
724 | /* preview parameters update structure */ | 805 | /* preview parameters update structure */ |
725 | struct preview_update { | 806 | struct preview_update { |
726 | void (*config)(struct isp_prev_device *, const void *); | 807 | void (*config)(struct isp_prev_device *, const void *); |
@@ -834,37 +915,6 @@ static const struct preview_update update_attrs[] = { | |||
834 | }; | 915 | }; |
835 | 916 | ||
836 | /* | 917 | /* |
837 | * __preview_get_ptrs - helper function which return pointers to members | ||
838 | * of params and config structures. | ||
839 | * @params - pointer to preview_params structure. | ||
840 | * @param - return pointer to appropriate structure field. | ||
841 | * @configs - pointer to update config structure. | ||
842 | * @config - return pointer to appropriate structure field. | ||
843 | * @bit - for which feature to return pointers. | ||
844 | * Return size of corresponding prev_params member | ||
845 | */ | ||
846 | static u32 | ||
847 | __preview_get_ptrs(struct prev_params *params, void **param, | ||
848 | struct omap3isp_prev_update_config *configs, | ||
849 | void __user **config, unsigned int index) | ||
850 | { | ||
851 | const struct preview_update *info = &update_attrs[index]; | ||
852 | |||
853 | if (index >= ARRAY_SIZE(update_attrs)) { | ||
854 | if (config) | ||
855 | *config = NULL; | ||
856 | *param = NULL; | ||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | if (configs && config) | ||
861 | *config = *(void **)((void *)configs + info->config_offset); | ||
862 | |||
863 | *param = (void *)params + info->param_offset; | ||
864 | return info->param_size; | ||
865 | } | ||
866 | |||
867 | /* | ||
868 | * preview_config - Copy and update local structure with userspace preview | 918 | * preview_config - Copy and update local structure with userspace preview |
869 | * configuration. | 919 | * configuration. |
870 | * @prev: ISP preview engine | 920 | * @prev: ISP preview engine |
@@ -876,37 +926,41 @@ __preview_get_ptrs(struct prev_params *params, void **param, | |||
876 | static int preview_config(struct isp_prev_device *prev, | 926 | static int preview_config(struct isp_prev_device *prev, |
877 | struct omap3isp_prev_update_config *cfg) | 927 | struct omap3isp_prev_update_config *cfg) |
878 | { | 928 | { |
879 | const struct preview_update *attr; | 929 | unsigned long flags; |
880 | struct prev_params *params; | 930 | unsigned int i; |
881 | int i, bit, rval = 0; | 931 | int rval = 0; |
932 | u32 update; | ||
933 | u32 active; | ||
882 | 934 | ||
883 | if (cfg->update == 0) | 935 | if (cfg->update == 0) |
884 | return 0; | 936 | return 0; |
885 | 937 | ||
886 | params = &prev->params; | 938 | /* Mark the shadow parameters we're going to update as busy. */ |
939 | spin_lock_irqsave(&prev->params.lock, flags); | ||
940 | preview_params_lock(prev, cfg->update, true); | ||
941 | active = prev->params.active; | ||
942 | spin_unlock_irqrestore(&prev->params.lock, flags); | ||
887 | 943 | ||
888 | if (prev->state != ISP_PIPELINE_STREAM_STOPPED) { | 944 | update = 0; |
889 | unsigned long flags; | ||
890 | |||
891 | spin_lock_irqsave(&prev->lock, flags); | ||
892 | prev->shadow_update = 1; | ||
893 | spin_unlock_irqrestore(&prev->lock, flags); | ||
894 | } | ||
895 | 945 | ||
896 | for (i = 0; i < ARRAY_SIZE(update_attrs); i++) { | 946 | for (i = 0; i < ARRAY_SIZE(update_attrs); i++) { |
897 | attr = &update_attrs[i]; | 947 | const struct preview_update *attr = &update_attrs[i]; |
898 | bit = 1 << i; | 948 | struct prev_params *params; |
949 | unsigned int bit = 1 << i; | ||
899 | 950 | ||
900 | if (attr->skip || !(cfg->update & bit)) | 951 | if (attr->skip || !(cfg->update & bit)) |
901 | continue; | 952 | continue; |
902 | 953 | ||
954 | params = &prev->params.params[!!(active & bit)]; | ||
955 | |||
903 | if (cfg->flag & bit) { | 956 | if (cfg->flag & bit) { |
904 | void *to = NULL, __user *from = NULL; | 957 | void __user *from = *(void * __user *) |
905 | unsigned long sz = 0; | 958 | ((void *)cfg + attr->config_offset); |
959 | void *to = (void *)params + attr->param_offset; | ||
960 | size_t size = attr->param_size; | ||
906 | 961 | ||
907 | sz = __preview_get_ptrs(params, &to, cfg, &from, i); | 962 | if (to && from && size) { |
908 | if (to && from && sz) { | 963 | if (copy_from_user(to, from, size)) { |
909 | if (copy_from_user(to, from, sz)) { | ||
910 | rval = -EFAULT; | 964 | rval = -EFAULT; |
911 | break; | 965 | break; |
912 | } | 966 | } |
@@ -916,50 +970,59 @@ static int preview_config(struct isp_prev_device *prev, | |||
916 | params->features &= ~bit; | 970 | params->features &= ~bit; |
917 | } | 971 | } |
918 | 972 | ||
919 | prev->update |= bit; | 973 | update |= bit; |
920 | } | 974 | } |
921 | 975 | ||
922 | prev->shadow_update = 0; | 976 | spin_lock_irqsave(&prev->params.lock, flags); |
977 | preview_params_unlock(prev, update, true); | ||
978 | preview_params_switch(prev); | ||
979 | spin_unlock_irqrestore(&prev->params.lock, flags); | ||
980 | |||
923 | return rval; | 981 | return rval; |
924 | } | 982 | } |
925 | 983 | ||
926 | /* | 984 | /* |
927 | * preview_setup_hw - Setup preview registers and/or internal memory | 985 | * preview_setup_hw - Setup preview registers and/or internal memory |
928 | * @prev: pointer to preview private structure | 986 | * @prev: pointer to preview private structure |
987 | * @update: Bitmask of parameters to setup | ||
988 | * @active: Bitmask of parameters active in set 0 | ||
929 | * Note: can be called from interrupt context | 989 | * Note: can be called from interrupt context |
930 | * Return none | 990 | * Return none |
931 | */ | 991 | */ |
932 | static void preview_setup_hw(struct isp_prev_device *prev) | 992 | static void preview_setup_hw(struct isp_prev_device *prev, u32 update, |
993 | u32 active) | ||
933 | { | 994 | { |
934 | struct prev_params *params = &prev->params; | ||
935 | const struct preview_update *attr; | ||
936 | unsigned int bit; | ||
937 | unsigned int i; | 995 | unsigned int i; |
938 | void *param_ptr; | 996 | u32 features; |
939 | 997 | ||
940 | if (prev->update == 0) | 998 | if (update == 0) |
941 | return; | 999 | return; |
942 | 1000 | ||
1001 | features = (prev->params.params[0].features & active) | ||
1002 | | (prev->params.params[1].features & ~active); | ||
1003 | |||
943 | for (i = 0; i < ARRAY_SIZE(update_attrs); i++) { | 1004 | for (i = 0; i < ARRAY_SIZE(update_attrs); i++) { |
944 | attr = &update_attrs[i]; | 1005 | const struct preview_update *attr = &update_attrs[i]; |
945 | bit = 1 << i; | 1006 | struct prev_params *params; |
1007 | unsigned int bit = 1 << i; | ||
1008 | void *param_ptr; | ||
946 | 1009 | ||
947 | if (!(prev->update & bit)) | 1010 | if (!(update & bit)) |
948 | continue; | 1011 | continue; |
949 | 1012 | ||
1013 | params = &prev->params.params[!(active & bit)]; | ||
1014 | |||
950 | if (params->features & bit) { | 1015 | if (params->features & bit) { |
951 | if (attr->config) { | 1016 | if (attr->config) { |
952 | __preview_get_ptrs(params, ¶m_ptr, NULL, | 1017 | param_ptr = (void *)params + attr->param_offset; |
953 | NULL, i); | ||
954 | attr->config(prev, param_ptr); | 1018 | attr->config(prev, param_ptr); |
955 | } | 1019 | } |
956 | if (attr->enable) | 1020 | if (attr->enable) |
957 | attr->enable(prev, 1); | 1021 | attr->enable(prev, 1); |
958 | } else | 1022 | } else { |
959 | if (attr->enable) | 1023 | if (attr->enable) |
960 | attr->enable(prev, 0); | 1024 | attr->enable(prev, 0); |
961 | 1025 | } | |
962 | prev->update &= ~bit; | ||
963 | } | 1026 | } |
964 | } | 1027 | } |
965 | 1028 | ||
@@ -997,13 +1060,17 @@ preview_config_ycpos(struct isp_prev_device *prev, | |||
997 | static void preview_config_averager(struct isp_prev_device *prev, u8 average) | 1060 | static void preview_config_averager(struct isp_prev_device *prev, u8 average) |
998 | { | 1061 | { |
999 | struct isp_device *isp = to_isp_device(prev); | 1062 | struct isp_device *isp = to_isp_device(prev); |
1063 | struct prev_params *params; | ||
1000 | int reg = 0; | 1064 | int reg = 0; |
1001 | 1065 | ||
1002 | if (prev->params.cfa.format == OMAP3ISP_CFAFMT_BAYER) | 1066 | params = (prev->params.active & OMAP3ISP_PREV_CFA) |
1067 | ? &prev->params.params[0] : &prev->params.params[1]; | ||
1068 | |||
1069 | if (params->cfa.format == OMAP3ISP_CFAFMT_BAYER) | ||
1003 | reg = ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT | | 1070 | reg = ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT | |
1004 | ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT | | 1071 | ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT | |
1005 | average; | 1072 | average; |
1006 | else if (prev->params.cfa.format == OMAP3ISP_CFAFMT_RGBFOVEON) | 1073 | else if (params->cfa.format == OMAP3ISP_CFAFMT_RGBFOVEON) |
1007 | reg = ISPPRV_AVE_EVENDIST_3 << ISPPRV_AVE_EVENDIST_SHIFT | | 1074 | reg = ISPPRV_AVE_EVENDIST_3 << ISPPRV_AVE_EVENDIST_SHIFT | |
1008 | ISPPRV_AVE_ODDDIST_3 << ISPPRV_AVE_ODDDIST_SHIFT | | 1075 | ISPPRV_AVE_ODDDIST_3 << ISPPRV_AVE_ODDDIST_SHIFT | |
1009 | average; | 1076 | average; |
@@ -1021,33 +1088,35 @@ static void preview_config_averager(struct isp_prev_device *prev, u8 average) | |||
1021 | * | 1088 | * |
1022 | * See the explanation at the PREV_MARGIN_* definitions for more details. | 1089 | * See the explanation at the PREV_MARGIN_* definitions for more details. |
1023 | */ | 1090 | */ |
1024 | static void preview_config_input_size(struct isp_prev_device *prev) | 1091 | static void preview_config_input_size(struct isp_prev_device *prev, u32 active) |
1025 | { | 1092 | { |
1026 | struct isp_device *isp = to_isp_device(prev); | 1093 | struct isp_device *isp = to_isp_device(prev); |
1027 | struct prev_params *params = &prev->params; | ||
1028 | unsigned int sph = prev->crop.left; | 1094 | unsigned int sph = prev->crop.left; |
1029 | unsigned int eph = prev->crop.left + prev->crop.width - 1; | 1095 | unsigned int eph = prev->crop.left + prev->crop.width - 1; |
1030 | unsigned int slv = prev->crop.top; | 1096 | unsigned int slv = prev->crop.top; |
1031 | unsigned int elv = prev->crop.top + prev->crop.height - 1; | 1097 | unsigned int elv = prev->crop.top + prev->crop.height - 1; |
1098 | u32 features; | ||
1032 | 1099 | ||
1033 | if (params->features & OMAP3ISP_PREV_CFA) { | 1100 | features = (prev->params.params[0].features & active) |
1101 | | (prev->params.params[1].features & ~active); | ||
1102 | |||
1103 | if (features & OMAP3ISP_PREV_CFA) { | ||
1034 | sph -= 2; | 1104 | sph -= 2; |
1035 | eph += 2; | 1105 | eph += 2; |
1036 | slv -= 2; | 1106 | slv -= 2; |
1037 | elv += 2; | 1107 | elv += 2; |
1038 | } | 1108 | } |
1039 | if (params->features & (OMAP3ISP_PREV_DEFECT_COR | OMAP3ISP_PREV_NF)) { | 1109 | if (features & (OMAP3ISP_PREV_DEFECT_COR | OMAP3ISP_PREV_NF)) { |
1040 | sph -= 2; | 1110 | sph -= 2; |
1041 | eph += 2; | 1111 | eph += 2; |
1042 | slv -= 2; | 1112 | slv -= 2; |
1043 | elv += 2; | 1113 | elv += 2; |
1044 | } | 1114 | } |
1045 | if (params->features & OMAP3ISP_PREV_HRZ_MED) { | 1115 | if (features & OMAP3ISP_PREV_HRZ_MED) { |
1046 | sph -= 2; | 1116 | sph -= 2; |
1047 | eph += 2; | 1117 | eph += 2; |
1048 | } | 1118 | } |
1049 | if (params->features & (OMAP3ISP_PREV_CHROMA_SUPP | | 1119 | if (features & (OMAP3ISP_PREV_CHROMA_SUPP | OMAP3ISP_PREV_LUMAENH)) |
1050 | OMAP3ISP_PREV_LUMAENH)) | ||
1051 | sph -= 2; | 1120 | sph -= 2; |
1052 | 1121 | ||
1053 | isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph, | 1122 | isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph, |
@@ -1182,8 +1251,16 @@ int omap3isp_preview_busy(struct isp_prev_device *prev) | |||
1182 | */ | 1251 | */ |
1183 | void omap3isp_preview_restore_context(struct isp_device *isp) | 1252 | void omap3isp_preview_restore_context(struct isp_device *isp) |
1184 | { | 1253 | { |
1185 | isp->isp_prev.update = OMAP3ISP_PREV_FEATURES_END - 1; | 1254 | struct isp_prev_device *prev = &isp->isp_prev; |
1186 | preview_setup_hw(&isp->isp_prev); | 1255 | const u32 update = OMAP3ISP_PREV_FEATURES_END - 1; |
1256 | |||
1257 | prev->params.params[0].update = prev->params.active & update; | ||
1258 | prev->params.params[1].update = ~prev->params.active & update; | ||
1259 | |||
1260 | preview_setup_hw(prev, update, prev->params.active); | ||
1261 | |||
1262 | prev->params.params[0].update = 0; | ||
1263 | prev->params.params[1].update = 0; | ||
1187 | } | 1264 | } |
1188 | 1265 | ||
1189 | /* | 1266 | /* |
@@ -1242,12 +1319,21 @@ static void preview_print_status(struct isp_prev_device *prev) | |||
1242 | /* | 1319 | /* |
1243 | * preview_init_params - init image processing parameters. | 1320 | * preview_init_params - init image processing parameters. |
1244 | * @prev: pointer to previewer private structure | 1321 | * @prev: pointer to previewer private structure |
1245 | * return none | ||
1246 | */ | 1322 | */ |
1247 | static void preview_init_params(struct isp_prev_device *prev) | 1323 | static void preview_init_params(struct isp_prev_device *prev) |
1248 | { | 1324 | { |
1249 | struct prev_params *params = &prev->params; | 1325 | struct prev_params *params; |
1250 | int i = 0; | 1326 | unsigned int i; |
1327 | |||
1328 | spin_lock_init(&prev->params.lock); | ||
1329 | |||
1330 | prev->params.active = ~0; | ||
1331 | prev->params.params[0].busy = 0; | ||
1332 | prev->params.params[0].update = OMAP3ISP_PREV_FEATURES_END - 1; | ||
1333 | prev->params.params[1].busy = 0; | ||
1334 | prev->params.params[1].update = 0; | ||
1335 | |||
1336 | params = &prev->params.params[0]; | ||
1251 | 1337 | ||
1252 | /* Init values */ | 1338 | /* Init values */ |
1253 | params->contrast = ISPPRV_CONTRAST_DEF * ISPPRV_CONTRAST_UNITS; | 1339 | params->contrast = ISPPRV_CONTRAST_DEF * ISPPRV_CONTRAST_UNITS; |
@@ -1291,8 +1377,6 @@ static void preview_init_params(struct isp_prev_device *prev) | |||
1291 | | OMAP3ISP_PREV_RGB2RGB | OMAP3ISP_PREV_COLOR_CONV | 1377 | | OMAP3ISP_PREV_RGB2RGB | OMAP3ISP_PREV_COLOR_CONV |
1292 | | OMAP3ISP_PREV_WB | OMAP3ISP_PREV_BRIGHTNESS | 1378 | | OMAP3ISP_PREV_WB | OMAP3ISP_PREV_BRIGHTNESS |
1293 | | OMAP3ISP_PREV_CONTRAST; | 1379 | | OMAP3ISP_PREV_CONTRAST; |
1294 | |||
1295 | prev->update = OMAP3ISP_PREV_FEATURES_END - 1; | ||
1296 | } | 1380 | } |
1297 | 1381 | ||
1298 | /* | 1382 | /* |
@@ -1321,8 +1405,17 @@ static void preview_configure(struct isp_prev_device *prev) | |||
1321 | { | 1405 | { |
1322 | struct isp_device *isp = to_isp_device(prev); | 1406 | struct isp_device *isp = to_isp_device(prev); |
1323 | struct v4l2_mbus_framefmt *format; | 1407 | struct v4l2_mbus_framefmt *format; |
1408 | unsigned long flags; | ||
1409 | u32 update; | ||
1410 | u32 active; | ||
1324 | 1411 | ||
1325 | preview_setup_hw(prev); | 1412 | spin_lock_irqsave(&prev->params.lock, flags); |
1413 | /* Mark all active parameters we are going to touch as busy. */ | ||
1414 | update = preview_params_lock(prev, 0, false); | ||
1415 | active = prev->params.active; | ||
1416 | spin_unlock_irqrestore(&prev->params.lock, flags); | ||
1417 | |||
1418 | preview_setup_hw(prev, update, active); | ||
1326 | 1419 | ||
1327 | if (prev->output & PREVIEW_OUTPUT_MEMORY) | 1420 | if (prev->output & PREVIEW_OUTPUT_MEMORY) |
1328 | isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, | 1421 | isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, |
@@ -1343,7 +1436,7 @@ static void preview_configure(struct isp_prev_device *prev) | |||
1343 | 1436 | ||
1344 | preview_adjust_bandwidth(prev); | 1437 | preview_adjust_bandwidth(prev); |
1345 | 1438 | ||
1346 | preview_config_input_size(prev); | 1439 | preview_config_input_size(prev, active); |
1347 | 1440 | ||
1348 | if (prev->input == PREVIEW_INPUT_CCDC) | 1441 | if (prev->input == PREVIEW_INPUT_CCDC) |
1349 | preview_config_inlineoffset(prev, 0); | 1442 | preview_config_inlineoffset(prev, 0); |
@@ -1360,6 +1453,10 @@ static void preview_configure(struct isp_prev_device *prev) | |||
1360 | 1453 | ||
1361 | preview_config_averager(prev, 0); | 1454 | preview_config_averager(prev, 0); |
1362 | preview_config_ycpos(prev, format->code); | 1455 | preview_config_ycpos(prev, format->code); |
1456 | |||
1457 | spin_lock_irqsave(&prev->params.lock, flags); | ||
1458 | preview_params_unlock(prev, update, false); | ||
1459 | spin_unlock_irqrestore(&prev->params.lock, flags); | ||
1363 | } | 1460 | } |
1364 | 1461 | ||
1365 | /* ----------------------------------------------------------------------------- | 1462 | /* ----------------------------------------------------------------------------- |
@@ -1448,25 +1545,30 @@ static void preview_isr_buffer(struct isp_prev_device *prev) | |||
1448 | void omap3isp_preview_isr(struct isp_prev_device *prev) | 1545 | void omap3isp_preview_isr(struct isp_prev_device *prev) |
1449 | { | 1546 | { |
1450 | unsigned long flags; | 1547 | unsigned long flags; |
1548 | u32 update; | ||
1549 | u32 active; | ||
1451 | 1550 | ||
1452 | if (omap3isp_module_sync_is_stopping(&prev->wait, &prev->stopping)) | 1551 | if (omap3isp_module_sync_is_stopping(&prev->wait, &prev->stopping)) |
1453 | return; | 1552 | return; |
1454 | 1553 | ||
1455 | spin_lock_irqsave(&prev->lock, flags); | 1554 | spin_lock_irqsave(&prev->params.lock, flags); |
1456 | if (prev->shadow_update) | 1555 | preview_params_switch(prev); |
1457 | goto done; | 1556 | update = preview_params_lock(prev, 0, false); |
1557 | active = prev->params.active; | ||
1558 | spin_unlock_irqrestore(&prev->params.lock, flags); | ||
1458 | 1559 | ||
1459 | preview_setup_hw(prev); | 1560 | preview_setup_hw(prev, update, active); |
1460 | preview_config_input_size(prev); | 1561 | preview_config_input_size(prev, active); |
1461 | |||
1462 | done: | ||
1463 | spin_unlock_irqrestore(&prev->lock, flags); | ||
1464 | 1562 | ||
1465 | if (prev->input == PREVIEW_INPUT_MEMORY || | 1563 | if (prev->input == PREVIEW_INPUT_MEMORY || |
1466 | prev->output & PREVIEW_OUTPUT_MEMORY) | 1564 | prev->output & PREVIEW_OUTPUT_MEMORY) |
1467 | preview_isr_buffer(prev); | 1565 | preview_isr_buffer(prev); |
1468 | else if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS) | 1566 | else if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS) |
1469 | preview_enable_oneshot(prev); | 1567 | preview_enable_oneshot(prev); |
1568 | |||
1569 | spin_lock_irqsave(&prev->params.lock, flags); | ||
1570 | preview_params_unlock(prev, update, false); | ||
1571 | spin_unlock_irqrestore(&prev->params.lock, flags); | ||
1470 | } | 1572 | } |
1471 | 1573 | ||
1472 | /* ----------------------------------------------------------------------------- | 1574 | /* ----------------------------------------------------------------------------- |
@@ -1552,7 +1654,6 @@ static int preview_set_stream(struct v4l2_subdev *sd, int enable) | |||
1552 | struct isp_video *video_out = &prev->video_out; | 1654 | struct isp_video *video_out = &prev->video_out; |
1553 | struct isp_device *isp = to_isp_device(prev); | 1655 | struct isp_device *isp = to_isp_device(prev); |
1554 | struct device *dev = to_device(prev); | 1656 | struct device *dev = to_device(prev); |
1555 | unsigned long flags; | ||
1556 | 1657 | ||
1557 | if (prev->state == ISP_PIPELINE_STREAM_STOPPED) { | 1658 | if (prev->state == ISP_PIPELINE_STREAM_STOPPED) { |
1558 | if (enable == ISP_PIPELINE_STREAM_STOPPED) | 1659 | if (enable == ISP_PIPELINE_STREAM_STOPPED) |
@@ -1589,11 +1690,9 @@ static int preview_set_stream(struct v4l2_subdev *sd, int enable) | |||
1589 | if (omap3isp_module_sync_idle(&sd->entity, &prev->wait, | 1690 | if (omap3isp_module_sync_idle(&sd->entity, &prev->wait, |
1590 | &prev->stopping)) | 1691 | &prev->stopping)) |
1591 | dev_dbg(dev, "%s: stop timeout.\n", sd->name); | 1692 | dev_dbg(dev, "%s: stop timeout.\n", sd->name); |
1592 | spin_lock_irqsave(&prev->lock, flags); | ||
1593 | omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_READ); | 1693 | omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_READ); |
1594 | omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE); | 1694 | omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE); |
1595 | omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_PREVIEW); | 1695 | omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_PREVIEW); |
1596 | spin_unlock_irqrestore(&prev->lock, flags); | ||
1597 | isp_video_dmaqueue_flags_clr(video_out); | 1696 | isp_video_dmaqueue_flags_clr(video_out); |
1598 | break; | 1697 | break; |
1599 | } | 1698 | } |
@@ -2201,7 +2300,7 @@ error_video_in: | |||
2201 | } | 2300 | } |
2202 | 2301 | ||
2203 | /* | 2302 | /* |
2204 | * isp_preview_init - Previewer initialization. | 2303 | * omap3isp_preview_init - Previewer initialization. |
2205 | * @dev : Pointer to ISP device | 2304 | * @dev : Pointer to ISP device |
2206 | * return -ENOMEM or zero on success | 2305 | * return -ENOMEM or zero on success |
2207 | */ | 2306 | */ |
@@ -2209,8 +2308,8 @@ int omap3isp_preview_init(struct isp_device *isp) | |||
2209 | { | 2308 | { |
2210 | struct isp_prev_device *prev = &isp->isp_prev; | 2309 | struct isp_prev_device *prev = &isp->isp_prev; |
2211 | 2310 | ||
2212 | spin_lock_init(&prev->lock); | ||
2213 | init_waitqueue_head(&prev->wait); | 2311 | init_waitqueue_head(&prev->wait); |
2312 | |||
2214 | preview_init_params(prev); | 2313 | preview_init_params(prev); |
2215 | 2314 | ||
2216 | return preview_init_entities(prev); | 2315 | return preview_init_entities(prev); |