22
22
#include <media/v4l2-event.h>
23
23
#include <linux/workqueue.h>
24
24
#include <linux/of.h>
25
+ #include <linux/of_reserved_mem.h>
25
26
#include <media/videobuf2-v4l2.h>
26
27
#include "s5p_mfc_common.h"
27
28
#include "s5p_mfc_ctrl.h"
@@ -1043,66 +1044,71 @@ static const struct v4l2_file_operations s5p_mfc_fops = {
1043
1044
.mmap = s5p_mfc_mmap ,
1044
1045
};
1045
1046
1046
- static int match_child (struct device * dev , void * data )
1047
- {
1048
- if (!dev_name (dev ))
1049
- return 0 ;
1050
- return !strcmp (dev_name (dev ), (char * )data );
1051
- }
1052
-
1047
+ /* DMA memory related helper functions */
1053
1048
static void s5p_mfc_memdev_release (struct device * dev )
1054
1049
{
1055
- dma_release_declared_memory (dev );
1050
+ of_reserved_mem_device_release (dev );
1056
1051
}
1057
1052
1058
- static void * mfc_get_drv_data (struct platform_device * pdev );
1059
-
1060
- static int s5p_mfc_alloc_memdevs (struct s5p_mfc_dev * dev )
1053
+ static struct device * s5p_mfc_alloc_memdev (struct device * dev ,
1054
+ const char * name , unsigned int idx )
1061
1055
{
1062
- unsigned int mem_info [2 ] = { };
1056
+ struct device * child ;
1057
+ int ret ;
1063
1058
1064
- dev -> mem_dev_l = devm_kzalloc (& dev -> plat_dev -> dev ,
1065
- sizeof (struct device ), GFP_KERNEL );
1066
- if (!dev -> mem_dev_l ) {
1067
- mfc_err ("Not enough memory\n" );
1068
- return - ENOMEM ;
1059
+ child = devm_kzalloc (dev , sizeof (struct device ), GFP_KERNEL );
1060
+ if (!child )
1061
+ return NULL ;
1062
+
1063
+ device_initialize (child );
1064
+ dev_set_name (child , "%s:%s" , dev_name (dev ), name );
1065
+ child -> parent = dev ;
1066
+ child -> bus = dev -> bus ;
1067
+ child -> coherent_dma_mask = dev -> coherent_dma_mask ;
1068
+ child -> dma_mask = dev -> dma_mask ;
1069
+ child -> release = s5p_mfc_memdev_release ;
1070
+
1071
+ if (device_add (child ) == 0 ) {
1072
+ ret = of_reserved_mem_device_init_by_idx (child , dev -> of_node ,
1073
+ idx );
1074
+ if (ret == 0 )
1075
+ return child ;
1069
1076
}
1070
1077
1071
- dev_set_name (dev -> mem_dev_l , "%s" , "s5p-mfc-l" );
1072
- dev -> mem_dev_l -> release = s5p_mfc_memdev_release ;
1073
- device_initialize (dev -> mem_dev_l );
1074
- of_property_read_u32_array (dev -> plat_dev -> dev .of_node ,
1075
- "samsung,mfc-l" , mem_info , 2 );
1076
- if (dma_declare_coherent_memory (dev -> mem_dev_l , mem_info [0 ],
1077
- mem_info [0 ], mem_info [1 ],
1078
- DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE ) == 0 ) {
1079
- mfc_err ("Failed to declare coherent memory for\n"
1080
- "MFC device\n" );
1081
- return - ENOMEM ;
1082
- }
1078
+ put_device (child );
1079
+ return NULL ;
1080
+ }
1083
1081
1084
- dev -> mem_dev_r = devm_kzalloc (& dev -> plat_dev -> dev ,
1085
- sizeof (struct device ), GFP_KERNEL );
1086
- if (!dev -> mem_dev_r ) {
1087
- mfc_err ("Not enough memory\n" );
1088
- return - ENOMEM ;
1089
- }
1082
+ static int s5p_mfc_configure_dma_memory (struct s5p_mfc_dev * mfc_dev )
1083
+ {
1084
+ struct device * dev = & mfc_dev -> plat_dev -> dev ;
1090
1085
1091
- dev_set_name (dev -> mem_dev_r , "%s" , "s5p-mfc-r" );
1092
- dev -> mem_dev_r -> release = s5p_mfc_memdev_release ;
1093
- device_initialize (dev -> mem_dev_r );
1094
- of_property_read_u32_array (dev -> plat_dev -> dev .of_node ,
1095
- "samsung,mfc-r" , mem_info , 2 );
1096
- if (dma_declare_coherent_memory (dev -> mem_dev_r , mem_info [0 ],
1097
- mem_info [0 ], mem_info [1 ],
1098
- DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE ) == 0 ) {
1099
- pr_err ("Failed to declare coherent memory for\n"
1100
- "MFC device\n" );
1101
- return - ENOMEM ;
1086
+ /*
1087
+ * Create and initialize virtual devices for accessing
1088
+ * reserved memory regions.
1089
+ */
1090
+ mfc_dev -> mem_dev_l = s5p_mfc_alloc_memdev (dev , "left" ,
1091
+ MFC_BANK1_ALLOC_CTX );
1092
+ if (!mfc_dev -> mem_dev_l )
1093
+ return - ENODEV ;
1094
+ mfc_dev -> mem_dev_r = s5p_mfc_alloc_memdev (dev , "right" ,
1095
+ MFC_BANK2_ALLOC_CTX );
1096
+ if (!mfc_dev -> mem_dev_r ) {
1097
+ device_unregister (mfc_dev -> mem_dev_l );
1098
+ return - ENODEV ;
1102
1099
}
1100
+
1103
1101
return 0 ;
1104
1102
}
1105
1103
1104
+ static void s5p_mfc_unconfigure_dma_memory (struct s5p_mfc_dev * mfc_dev )
1105
+ {
1106
+ device_unregister (mfc_dev -> mem_dev_l );
1107
+ device_unregister (mfc_dev -> mem_dev_r );
1108
+ }
1109
+
1110
+ static void * mfc_get_drv_data (struct platform_device * pdev );
1111
+
1106
1112
/* MFC probe function */
1107
1113
static int s5p_mfc_probe (struct platform_device * pdev )
1108
1114
{
@@ -1128,12 +1134,6 @@ static int s5p_mfc_probe(struct platform_device *pdev)
1128
1134
1129
1135
dev -> variant = mfc_get_drv_data (pdev );
1130
1136
1131
- ret = s5p_mfc_init_pm (dev );
1132
- if (ret < 0 ) {
1133
- dev_err (& pdev -> dev , "failed to get mfc clock source\n" );
1134
- return ret ;
1135
- }
1136
-
1137
1137
res = platform_get_resource (pdev , IORESOURCE_MEM , 0 );
1138
1138
1139
1139
dev -> regs_base = devm_ioremap_resource (& pdev -> dev , res );
@@ -1154,25 +1154,16 @@ static int s5p_mfc_probe(struct platform_device *pdev)
1154
1154
goto err_res ;
1155
1155
}
1156
1156
1157
- if (pdev -> dev .of_node ) {
1158
- ret = s5p_mfc_alloc_memdevs (dev );
1159
- if (ret < 0 )
1160
- goto err_res ;
1161
- } else {
1162
- dev -> mem_dev_l = device_find_child (& dev -> plat_dev -> dev ,
1163
- "s5p-mfc-l" , match_child );
1164
- if (!dev -> mem_dev_l ) {
1165
- mfc_err ("Mem child (L) device get failed\n" );
1166
- ret = - ENODEV ;
1167
- goto err_res ;
1168
- }
1169
- dev -> mem_dev_r = device_find_child (& dev -> plat_dev -> dev ,
1170
- "s5p-mfc-r" , match_child );
1171
- if (!dev -> mem_dev_r ) {
1172
- mfc_err ("Mem child (R) device get failed\n" );
1173
- ret = - ENODEV ;
1174
- goto err_res ;
1175
- }
1157
+ ret = s5p_mfc_configure_dma_memory (dev );
1158
+ if (ret < 0 ) {
1159
+ dev_err (& pdev -> dev , "failed to configure DMA memory\n" );
1160
+ return ret ;
1161
+ }
1162
+
1163
+ ret = s5p_mfc_init_pm (dev );
1164
+ if (ret < 0 ) {
1165
+ dev_err (& pdev -> dev , "failed to get mfc clock source\n" );
1166
+ return ret ;
1176
1167
}
1177
1168
1178
1169
vb2_dma_contig_set_max_seg_size (dev -> mem_dev_l , DMA_BIT_MASK (32 ));
@@ -1309,12 +1300,9 @@ static int s5p_mfc_remove(struct platform_device *pdev)
1309
1300
s5p_mfc_release_firmware (dev );
1310
1301
vb2_dma_contig_cleanup_ctx (dev -> alloc_ctx [0 ]);
1311
1302
vb2_dma_contig_cleanup_ctx (dev -> alloc_ctx [1 ]);
1303
+ s5p_mfc_unconfigure_dma_memory (dev );
1312
1304
vb2_dma_contig_clear_max_seg_size (dev -> mem_dev_l );
1313
1305
vb2_dma_contig_clear_max_seg_size (dev -> mem_dev_r );
1314
- if (pdev -> dev .of_node ) {
1315
- put_device (dev -> mem_dev_l );
1316
- put_device (dev -> mem_dev_r );
1317
- }
1318
1306
1319
1307
s5p_mfc_final_pm (dev );
1320
1308
return 0 ;
0 commit comments