.. | .. |
---|
99 | 99 | |
---|
100 | 100 | #define GC4663_NUM_SUPPLIES ARRAY_SIZE(gc4663_supply_names) |
---|
101 | 101 | |
---|
102 | | -enum gc4663_max_pad { |
---|
103 | | - PAD0, /* link to isp */ |
---|
104 | | - PAD1, /* link to csi wr0 | hdr x2:L x3:M */ |
---|
105 | | - PAD2, /* link to csi wr1 | hdr x3:L */ |
---|
106 | | - PAD3, /* link to csi wr2 | hdr x2:M x3:S */ |
---|
107 | | - PAD_MAX, |
---|
108 | | -}; |
---|
109 | | - |
---|
110 | 102 | struct regval { |
---|
111 | 103 | u16 addr; |
---|
112 | 104 | u8 val; |
---|
.. | .. |
---|
278 | 270 | {0x0320, 0x77}, |
---|
279 | 271 | {0x0324, 0xc8}, |
---|
280 | 272 | {0x0325, 0x06}, |
---|
281 | | - {0x0326, 0x6c}, |
---|
| 273 | + {0x0326, 0x60}, |
---|
282 | 274 | {0x0327, 0x03}, |
---|
283 | 275 | {0x0334, 0x40}, |
---|
284 | | - {0x0336, 0x6c}, |
---|
| 276 | + {0x0336, 0x60}, |
---|
285 | 277 | {0x0337, 0x82}, |
---|
286 | 278 | {0x0315, 0x25}, |
---|
287 | 279 | {0x031c, 0xc6}, |
---|
.. | .. |
---|
781 | 773 | fmt->format.height = mode->height; |
---|
782 | 774 | fmt->format.code = mode->bus_fmt; |
---|
783 | 775 | fmt->format.field = V4L2_FIELD_NONE; |
---|
784 | | - /* format info: width/height/data type/virctual channel */ |
---|
785 | | - if (fmt->pad < PAD_MAX && mode->hdr_mode != NO_HDR) |
---|
786 | | - fmt->reserved[0] = mode->vc[fmt->pad]; |
---|
787 | | - else |
---|
788 | | - fmt->reserved[0] = mode->vc[PAD0]; |
---|
789 | 776 | } |
---|
790 | 777 | mutex_unlock(&gc4663->mutex); |
---|
791 | 778 | |
---|
.. | .. |
---|
1012 | 999 | struct gc4663 *gc4663 = to_gc4663(sd); |
---|
1013 | 1000 | const struct gc4663_mode *mode = gc4663->cur_mode; |
---|
1014 | 1001 | |
---|
1015 | | - mutex_lock(&gc4663->mutex); |
---|
1016 | 1002 | fi->interval = mode->max_fps; |
---|
1017 | | - mutex_unlock(&gc4663->mutex); |
---|
1018 | 1003 | |
---|
1019 | 1004 | return 0; |
---|
1020 | 1005 | } |
---|
1021 | 1006 | |
---|
1022 | | -static int gc4663_g_mbus_config(struct v4l2_subdev *sd, |
---|
| 1007 | +static int gc4663_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, |
---|
1023 | 1008 | struct v4l2_mbus_config *config) |
---|
1024 | 1009 | { |
---|
1025 | 1010 | struct gc4663 *gc4663 = to_gc4663(sd); |
---|
.. | .. |
---|
1036 | 1021 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | |
---|
1037 | 1022 | V4L2_MBUS_CSI2_CHANNEL_1; |
---|
1038 | 1023 | |
---|
1039 | | - config->type = V4L2_MBUS_CSI2; |
---|
| 1024 | + config->type = V4L2_MBUS_CSI2_DPHY; |
---|
1040 | 1025 | config->flags = val; |
---|
1041 | 1026 | |
---|
1042 | 1027 | return 0; |
---|
.. | .. |
---|
1052 | 1037 | strlcpy(inf->base.lens, gc4663->len_name, sizeof(inf->base.lens)); |
---|
1053 | 1038 | } |
---|
1054 | 1039 | |
---|
| 1040 | +static int gc4663_get_channel_info(struct gc4663 *gc4663, struct rkmodule_channel_info *ch_info) |
---|
| 1041 | +{ |
---|
| 1042 | + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) |
---|
| 1043 | + return -EINVAL; |
---|
| 1044 | + ch_info->vc = gc4663->cur_mode->vc[ch_info->index]; |
---|
| 1045 | + ch_info->width = gc4663->cur_mode->width; |
---|
| 1046 | + ch_info->height = gc4663->cur_mode->height; |
---|
| 1047 | + ch_info->bus_fmt = gc4663->cur_mode->bus_fmt; |
---|
| 1048 | + return 0; |
---|
| 1049 | +} |
---|
| 1050 | + |
---|
1055 | 1051 | static long gc4663_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) |
---|
1056 | 1052 | { |
---|
1057 | 1053 | struct gc4663 *gc4663 = to_gc4663(sd); |
---|
.. | .. |
---|
1059 | 1055 | u32 i, h, w; |
---|
1060 | 1056 | long ret = 0; |
---|
1061 | 1057 | u32 stream = 0; |
---|
| 1058 | + struct rkmodule_channel_info *ch_info; |
---|
1062 | 1059 | |
---|
1063 | 1060 | switch (cmd) { |
---|
1064 | 1061 | case RKMODULE_GET_MODULE_INFO: |
---|
.. | .. |
---|
1123 | 1120 | ret = gc4663_write_reg(gc4663->client, GC4663_REG_CTRL_MODE, |
---|
1124 | 1121 | GC4663_REG_VALUE_08BIT, GC4663_MODE_SW_STANDBY); |
---|
1125 | 1122 | break; |
---|
| 1123 | + case RKMODULE_GET_CHANNEL_INFO: |
---|
| 1124 | + ch_info = (struct rkmodule_channel_info *)arg; |
---|
| 1125 | + ret = gc4663_get_channel_info(gc4663, ch_info); |
---|
| 1126 | + break; |
---|
1126 | 1127 | default: |
---|
1127 | 1128 | ret = -ENOIOCTLCMD; |
---|
1128 | 1129 | break; |
---|
.. | .. |
---|
1142 | 1143 | struct preisp_hdrae_exp_s *hdrae; |
---|
1143 | 1144 | long ret; |
---|
1144 | 1145 | u32 stream = 0; |
---|
| 1146 | + struct rkmodule_channel_info *ch_info; |
---|
1145 | 1147 | |
---|
1146 | 1148 | switch (cmd) { |
---|
1147 | 1149 | case RKMODULE_GET_MODULE_INFO: |
---|
.. | .. |
---|
1152 | 1154 | } |
---|
1153 | 1155 | |
---|
1154 | 1156 | ret = gc4663_ioctl(sd, cmd, inf); |
---|
1155 | | - if (!ret) |
---|
| 1157 | + if (!ret) { |
---|
1156 | 1158 | ret = copy_to_user(up, inf, sizeof(*inf)); |
---|
| 1159 | + if (ret) |
---|
| 1160 | + ret = -EFAULT; |
---|
| 1161 | + } |
---|
1157 | 1162 | kfree(inf); |
---|
1158 | 1163 | break; |
---|
1159 | 1164 | case RKMODULE_AWB_CFG: |
---|
.. | .. |
---|
1166 | 1171 | ret = copy_from_user(cfg, up, sizeof(*cfg)); |
---|
1167 | 1172 | if (!ret) |
---|
1168 | 1173 | ret = gc4663_ioctl(sd, cmd, cfg); |
---|
| 1174 | + else |
---|
| 1175 | + ret = -EFAULT; |
---|
1169 | 1176 | kfree(cfg); |
---|
1170 | 1177 | break; |
---|
1171 | 1178 | case RKMODULE_GET_HDR_CFG: |
---|
.. | .. |
---|
1176 | 1183 | } |
---|
1177 | 1184 | |
---|
1178 | 1185 | ret = gc4663_ioctl(sd, cmd, hdr); |
---|
1179 | | - if (!ret) |
---|
| 1186 | + if (!ret) { |
---|
1180 | 1187 | ret = copy_to_user(up, hdr, sizeof(*hdr)); |
---|
| 1188 | + if (ret) |
---|
| 1189 | + ret = -EFAULT; |
---|
| 1190 | + } |
---|
1181 | 1191 | kfree(hdr); |
---|
1182 | 1192 | break; |
---|
1183 | 1193 | case RKMODULE_SET_HDR_CFG: |
---|
.. | .. |
---|
1190 | 1200 | ret = copy_from_user(hdr, up, sizeof(*hdr)); |
---|
1191 | 1201 | if (!ret) |
---|
1192 | 1202 | ret = gc4663_ioctl(sd, cmd, hdr); |
---|
| 1203 | + else |
---|
| 1204 | + ret = -EFAULT; |
---|
1193 | 1205 | kfree(hdr); |
---|
1194 | 1206 | break; |
---|
1195 | 1207 | case PREISP_CMD_SET_HDRAE_EXP: |
---|
.. | .. |
---|
1202 | 1214 | ret = copy_from_user(hdrae, up, sizeof(*hdrae)); |
---|
1203 | 1215 | if (!ret) |
---|
1204 | 1216 | ret = gc4663_ioctl(sd, cmd, hdrae); |
---|
| 1217 | + else |
---|
| 1218 | + ret = -EFAULT; |
---|
1205 | 1219 | kfree(hdrae); |
---|
1206 | 1220 | break; |
---|
1207 | 1221 | case RKMODULE_SET_QUICK_STREAM: |
---|
1208 | 1222 | ret = copy_from_user(&stream, up, sizeof(u32)); |
---|
1209 | 1223 | if (!ret) |
---|
1210 | 1224 | ret = gc4663_ioctl(sd, cmd, &stream); |
---|
| 1225 | + else |
---|
| 1226 | + ret = -EFAULT; |
---|
| 1227 | + break; |
---|
| 1228 | + case RKMODULE_GET_CHANNEL_INFO: |
---|
| 1229 | + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); |
---|
| 1230 | + if (!ch_info) { |
---|
| 1231 | + ret = -ENOMEM; |
---|
| 1232 | + return ret; |
---|
| 1233 | + } |
---|
| 1234 | + |
---|
| 1235 | + ret = gc4663_ioctl(sd, cmd, ch_info); |
---|
| 1236 | + if (!ret) { |
---|
| 1237 | + ret = copy_to_user(up, ch_info, sizeof(*ch_info)); |
---|
| 1238 | + if (ret) |
---|
| 1239 | + ret = -EFAULT; |
---|
| 1240 | + } |
---|
| 1241 | + kfree(ch_info); |
---|
1211 | 1242 | break; |
---|
1212 | 1243 | default: |
---|
1213 | 1244 | ret = -ENOIOCTLCMD; |
---|
.. | .. |
---|
1495 | 1526 | static const struct v4l2_subdev_video_ops gc4663_video_ops = { |
---|
1496 | 1527 | .s_stream = gc4663_s_stream, |
---|
1497 | 1528 | .g_frame_interval = gc4663_g_frame_interval, |
---|
1498 | | - .g_mbus_config = gc4663_g_mbus_config, |
---|
1499 | 1529 | }; |
---|
1500 | 1530 | |
---|
1501 | 1531 | static const struct v4l2_subdev_pad_ops gc4663_pad_ops = { |
---|
.. | .. |
---|
1504 | 1534 | .enum_frame_interval = gc4663_enum_frame_interval, |
---|
1505 | 1535 | .get_fmt = gc4663_get_fmt, |
---|
1506 | 1536 | .set_fmt = gc4663_set_fmt, |
---|
| 1537 | + .get_mbus_config = gc4663_g_mbus_config, |
---|
1507 | 1538 | }; |
---|
1508 | 1539 | |
---|
1509 | 1540 | static const struct v4l2_subdev_ops gc4663_subdev_ops = { |
---|