Merge branch 'linux-linaro-lsk-v4.4' into linux-linaro-lsk-v4.4-android
[firefly-linux-kernel-4.4.55.git] / drivers / video / adf / adf_fops32.c
1 /*
2  * Copyright (C) 2013 Google, Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  */
14
15 #include <linux/uaccess.h>
16 #include <video/adf.h>
17
18 #include "adf_fops.h"
19 #include "adf_fops32.h"
20
21 long adf_compat_post_config(struct file *file,
22                 struct adf_post_config32 __user *arg)
23 {
24         struct adf_post_config32 cfg32;
25         struct adf_post_config __user *cfg;
26         int ret;
27
28         if (copy_from_user(&cfg32, arg, sizeof(cfg32)))
29                 return -EFAULT;
30
31         cfg = compat_alloc_user_space(sizeof(*cfg));
32         if (!access_ok(VERIFY_WRITE, cfg, sizeof(*cfg)))
33                 return -EFAULT;
34
35         if (put_user(cfg32.n_interfaces, &cfg->n_interfaces) ||
36                         put_user(compat_ptr(cfg32.interfaces),
37                                         &cfg->interfaces) ||
38                         put_user(cfg32.n_bufs, &cfg->n_bufs) ||
39                         put_user(compat_ptr(cfg32.bufs), &cfg->bufs) ||
40                         put_user(cfg32.custom_data_size,
41                                         &cfg->custom_data_size) ||
42                         put_user(compat_ptr(cfg32.custom_data),
43                                         &cfg->custom_data))
44                 return -EFAULT;
45
46         ret = adf_file_ioctl(file, ADF_POST_CONFIG, (unsigned long)cfg);
47         if (ret < 0)
48                 return ret;
49
50         if (copy_in_user(&arg->complete_fence, &cfg->complete_fence,
51                         sizeof(cfg->complete_fence)))
52                 return -EFAULT;
53
54         return 0;
55 }
56
57 long adf_compat_get_device_data(struct file *file,
58                 struct adf_device_data32 __user *arg)
59 {
60         struct adf_device_data32 data32;
61         struct adf_device_data __user *data;
62         int ret;
63
64         if (copy_from_user(&data32, arg, sizeof(data32)))
65                 return -EFAULT;
66
67         data = compat_alloc_user_space(sizeof(*data));
68         if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
69                 return -EFAULT;
70
71         if (put_user(data32.n_attachments, &data->n_attachments) ||
72                         put_user(compat_ptr(data32.attachments),
73                                         &data->attachments) ||
74                         put_user(data32.n_allowed_attachments,
75                                         &data->n_allowed_attachments) ||
76                         put_user(compat_ptr(data32.allowed_attachments),
77                                         &data->allowed_attachments) ||
78                         put_user(data32.custom_data_size,
79                                         &data->custom_data_size) ||
80                         put_user(compat_ptr(data32.custom_data),
81                                         &data->custom_data))
82                 return -EFAULT;
83
84         ret = adf_file_ioctl(file, ADF_GET_DEVICE_DATA, (unsigned long)data);
85         if (ret < 0)
86                 return ret;
87
88         if (copy_in_user(arg->name, data->name, sizeof(arg->name)) ||
89                         copy_in_user(&arg->n_attachments, &data->n_attachments,
90                                         sizeof(arg->n_attachments)) ||
91                         copy_in_user(&arg->n_allowed_attachments,
92                                         &data->n_allowed_attachments,
93                                         sizeof(arg->n_allowed_attachments)) ||
94                         copy_in_user(&arg->custom_data_size,
95                                         &data->custom_data_size,
96                                         sizeof(arg->custom_data_size)))
97                 return -EFAULT;
98
99         return 0;
100 }
101
102 long adf_compat_get_interface_data(struct file *file,
103                 struct adf_interface_data32 __user *arg)
104 {
105         struct adf_interface_data32 data32;
106         struct adf_interface_data __user *data;
107         int ret;
108
109         if (copy_from_user(&data32, arg, sizeof(data32)))
110                 return -EFAULT;
111
112         data = compat_alloc_user_space(sizeof(*data));
113         if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
114                 return -EFAULT;
115
116         if (put_user(data32.n_available_modes, &data->n_available_modes) ||
117                         put_user(compat_ptr(data32.available_modes),
118                                         &data->available_modes) ||
119                         put_user(data32.custom_data_size,
120                                         &data->custom_data_size) ||
121                         put_user(compat_ptr(data32.custom_data),
122                                         &data->custom_data))
123                 return -EFAULT;
124
125         ret = adf_file_ioctl(file, ADF_GET_INTERFACE_DATA, (unsigned long)data);
126         if (ret < 0)
127                 return ret;
128
129         if (copy_in_user(arg->name, data->name, sizeof(arg->name)) ||
130                         copy_in_user(&arg->type, &data->type,
131                                         sizeof(arg->type)) ||
132                         copy_in_user(&arg->id, &data->id, sizeof(arg->id)) ||
133                         copy_in_user(&arg->flags, &data->flags,
134                                         sizeof(arg->flags)) ||
135                         copy_in_user(&arg->dpms_state, &data->dpms_state,
136                                         sizeof(arg->dpms_state)) ||
137                         copy_in_user(&arg->hotplug_detect,
138                                         &data->hotplug_detect,
139                                         sizeof(arg->hotplug_detect)) ||
140                         copy_in_user(&arg->width_mm, &data->width_mm,
141                                         sizeof(arg->width_mm)) ||
142                         copy_in_user(&arg->height_mm, &data->height_mm,
143                                         sizeof(arg->height_mm)) ||
144                         copy_in_user(&arg->current_mode, &data->current_mode,
145                                         sizeof(arg->current_mode)) ||
146                         copy_in_user(&arg->n_available_modes,
147                                         &data->n_available_modes,
148                                         sizeof(arg->n_available_modes)) ||
149                         copy_in_user(&arg->custom_data_size,
150                                         &data->custom_data_size,
151                                         sizeof(arg->custom_data_size)))
152                 return -EFAULT;
153
154         return 0;
155 }
156
157 long adf_compat_get_overlay_engine_data(struct file *file,
158                 struct adf_overlay_engine_data32 __user *arg)
159 {
160         struct adf_overlay_engine_data32 data32;
161         struct adf_overlay_engine_data __user *data;
162         int ret;
163
164         if (copy_from_user(&data32, arg, sizeof(data32)))
165                 return -EFAULT;
166
167         data = compat_alloc_user_space(sizeof(*data));
168         if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
169                 return -EFAULT;
170
171         if (put_user(data32.n_supported_formats, &data->n_supported_formats) ||
172                         put_user(compat_ptr(data32.supported_formats),
173                                         &data->supported_formats) ||
174                         put_user(data32.custom_data_size,
175                                         &data->custom_data_size) ||
176                         put_user(compat_ptr(data32.custom_data),
177                                         &data->custom_data))
178                 return -EFAULT;
179
180         ret = adf_file_ioctl(file, ADF_GET_OVERLAY_ENGINE_DATA,
181                         (unsigned long)data);
182         if (ret < 0)
183                 return ret;
184
185         if (copy_in_user(arg->name, data->name, sizeof(arg->name)) ||
186                         copy_in_user(&arg->n_supported_formats,
187                                         &data->n_supported_formats,
188                                         sizeof(arg->n_supported_formats)) ||
189                         copy_in_user(&arg->custom_data_size,
190                                         &data->custom_data_size,
191                                         sizeof(arg->custom_data_size)))
192                 return -EFAULT;
193
194         return 0;
195 }
196
197 long adf_file_compat_ioctl(struct file *file, unsigned int cmd,
198                 unsigned long arg)
199 {
200         switch (cmd) {
201         case ADF_POST_CONFIG32:
202                 return adf_compat_post_config(file, compat_ptr(arg));
203
204         case ADF_GET_DEVICE_DATA32:
205                 return adf_compat_get_device_data(file, compat_ptr(arg));
206
207         case ADF_GET_INTERFACE_DATA32:
208                 return adf_compat_get_interface_data(file, compat_ptr(arg));
209
210         case ADF_GET_OVERLAY_ENGINE_DATA32:
211                 return adf_compat_get_overlay_engine_data(file,
212                                 compat_ptr(arg));
213
214         default:
215                 return adf_file_ioctl(file, cmd, arg);
216         }
217 }