aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-03-26 09:24:50 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-08 13:08:53 -0400
commitb0b29e1e29ee5357f36f27411b5881e470484da5 (patch)
tree70a2b1cf6c6e61b0ab8af8d6a3d59a9a05d69582 /drivers
parentbac387efbb88cf0e8df6f46a38387897cea464ee (diff)
[media] omap3isp: preview: Shorten shadow update delay
When applications modify preview engine parameters, the new values are applied to the hardware by the preview engine interrupt handler during vertical blanking. If the parameters are being changed when the interrupt handler is called, it just delays applying the parameters until the next frame. If an application modifies the parameters for every frame, and the preview engine interrupt is triggerred synchronously, the parameters are never applied to the hardware. Fix this by storing new parameters in a shadow copy, and switch the active parameters with the shadow values atomically. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/omap3isp/isppreview.c299
-rw-r--r--drivers/media/video/omap3isp/isppreview.h21
2 files changed, 212 insertions, 108 deletions
diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c
index fd1807d36d40..5bdf9e742c8e 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)
649static void 649static void
650preview_update_contrast(struct isp_prev_device *prev, u8 contrast) 650preview_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)
681static void 687static void
682preview_update_brightness(struct isp_prev_device *prev, u8 brightness) 688preview_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
736static u32
737preview_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
757static void
758preview_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
781static 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 */
725struct preview_update { 806struct 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 */
846static 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,
876static int preview_config(struct isp_prev_device *prev, 926static 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 */
932static void preview_setup_hw(struct isp_prev_device *prev) 992static 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, &param_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,
997static void preview_config_averager(struct isp_prev_device *prev, u8 average) 1060static 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 */
1024static void preview_config_input_size(struct isp_prev_device *prev) 1091static 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 */
1183void omap3isp_preview_restore_context(struct isp_device *isp) 1252void 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 */
1247static void preview_init_params(struct isp_prev_device *prev) 1323static 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)
1448void omap3isp_preview_isr(struct isp_prev_device *prev) 1545void 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
1462done:
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);
diff --git a/drivers/media/video/omap3isp/isppreview.h b/drivers/media/video/omap3isp/isppreview.h
index 6ee830623d5d..6663ab64e4b1 100644
--- a/drivers/media/video/omap3isp/isppreview.h
+++ b/drivers/media/video/omap3isp/isppreview.h
@@ -69,6 +69,8 @@ enum preview_ycpos_mode {
69 69
70/* 70/*
71 * struct prev_params - Structure for all configuration 71 * struct prev_params - Structure for all configuration
72 * @busy: Bitmask of busy parameters (being updated or used)
73 * @update: Bitmask of the parameters to be updated
72 * @features: Set of features enabled. 74 * @features: Set of features enabled.
73 * @cfa: CFA coefficients. 75 * @cfa: CFA coefficients.
74 * @csup: Chroma suppression coefficients. 76 * @csup: Chroma suppression coefficients.
@@ -86,6 +88,8 @@ enum preview_ycpos_mode {
86 * @brightness: Brightness. 88 * @brightness: Brightness.
87 */ 89 */
88struct prev_params { 90struct prev_params {
91 u32 busy;
92 u32 update;
89 u32 features; 93 u32 features;
90 struct omap3isp_prev_cfa cfa; 94 struct omap3isp_prev_cfa cfa;
91 struct omap3isp_prev_csup csup; 95 struct omap3isp_prev_csup csup;
@@ -118,12 +122,11 @@ struct prev_params {
118 * @output: Bitmask of the active output 122 * @output: Bitmask of the active output
119 * @video_in: Input video entity 123 * @video_in: Input video entity
120 * @video_out: Output video entity 124 * @video_out: Output video entity
121 * @params: Module configuration data 125 * @params.params : Active and shadow parameters sets
122 * @shadow_update: If set, update the hardware configured in the next interrupt 126 * @params.active: Bitmask of parameters active in set 0
127 * @params.lock: Parameters lock, protects params.active and params.shadow
123 * @underrun: Whether the preview entity has queued buffers on the output 128 * @underrun: Whether the preview entity has queued buffers on the output
124 * @state: Current preview pipeline state 129 * @state: Current preview pipeline state
125 * @lock: Shadow update lock
126 * @update: Bitmask of the parameters to be updated
127 * 130 *
128 * This structure is used to store the OMAP ISP Preview module Information. 131 * This structure is used to store the OMAP ISP Preview module Information.
129 */ 132 */
@@ -140,13 +143,15 @@ struct isp_prev_device {
140 struct isp_video video_in; 143 struct isp_video video_in;
141 struct isp_video video_out; 144 struct isp_video video_out;
142 145
143 struct prev_params params; 146 struct {
144 unsigned int shadow_update:1; 147 struct prev_params params[2];
148 u32 active;
149 spinlock_t lock;
150 } params;
151
145 enum isp_pipeline_stream_state state; 152 enum isp_pipeline_stream_state state;
146 wait_queue_head_t wait; 153 wait_queue_head_t wait;
147 atomic_t stopping; 154 atomic_t stopping;
148 spinlock_t lock;
149 u32 update;
150}; 155};
151 156
152struct isp_device; 157struct isp_device;