| .. | .. |
|---|
| 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 = { |
|---|