| .. | .. |
|---|
| 121 | 121 | |
|---|
| 122 | 122 | #define SC2310_NUM_SUPPLIES ARRAY_SIZE(sc2310_supply_names) |
|---|
| 123 | 123 | |
|---|
| 124 | | -enum sc2310_max_pad { |
|---|
| 125 | | - PAD0, |
|---|
| 126 | | - PAD1, |
|---|
| 127 | | - PAD2, |
|---|
| 128 | | - PAD3, |
|---|
| 129 | | - PAD_MAX, |
|---|
| 130 | | -}; |
|---|
| 131 | | - |
|---|
| 132 | 124 | struct regval { |
|---|
| 133 | 125 | u16 addr; |
|---|
| 134 | 126 | u8 val; |
|---|
| .. | .. |
|---|
| 170 | 162 | struct v4l2_ctrl *pixel_rate; |
|---|
| 171 | 163 | struct v4l2_ctrl *link_freq; |
|---|
| 172 | 164 | struct mutex mutex; |
|---|
| 165 | + struct v4l2_fract cur_fps; |
|---|
| 173 | 166 | bool streaming; |
|---|
| 174 | 167 | bool power_on; |
|---|
| 175 | 168 | const struct sc2310_mode *cur_mode; |
|---|
| .. | .. |
|---|
| 776 | 769 | pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] / |
|---|
| 777 | 770 | mode->bpp * 2 * SC2310_LANES; |
|---|
| 778 | 771 | __v4l2_ctrl_s_ctrl_int64(sc2310->pixel_rate, pixel_rate); |
|---|
| 772 | + sc2310->cur_fps = mode->max_fps; |
|---|
| 773 | + sc2310->cur_vts = mode->vts_def; |
|---|
| 779 | 774 | } |
|---|
| 780 | 775 | |
|---|
| 781 | 776 | mutex_unlock(&sc2310->mutex); |
|---|
| .. | .. |
|---|
| 868 | 863 | struct sc2310 *sc2310 = to_sc2310(sd); |
|---|
| 869 | 864 | const struct sc2310_mode *mode = sc2310->cur_mode; |
|---|
| 870 | 865 | |
|---|
| 871 | | - mutex_lock(&sc2310->mutex); |
|---|
| 872 | | - fi->interval = mode->max_fps; |
|---|
| 873 | | - mutex_unlock(&sc2310->mutex); |
|---|
| 866 | + if (sc2310->streaming) |
|---|
| 867 | + fi->interval = sc2310->cur_fps; |
|---|
| 868 | + else |
|---|
| 869 | + fi->interval = mode->max_fps; |
|---|
| 874 | 870 | |
|---|
| 875 | 871 | return 0; |
|---|
| 876 | 872 | } |
|---|
| 877 | 873 | |
|---|
| 878 | | -static int sc2310_g_mbus_config(struct v4l2_subdev *sd, |
|---|
| 874 | +static int sc2310_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, |
|---|
| 879 | 875 | struct v4l2_mbus_config *config) |
|---|
| 880 | 876 | { |
|---|
| 881 | 877 | struct sc2310 *sc2310 = to_sc2310(sd); |
|---|
| .. | .. |
|---|
| 892 | 888 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | |
|---|
| 893 | 889 | V4L2_MBUS_CSI2_CHANNEL_1; |
|---|
| 894 | 890 | |
|---|
| 895 | | - config->type = V4L2_MBUS_CSI2; |
|---|
| 891 | + config->type = V4L2_MBUS_CSI2_DPHY; |
|---|
| 896 | 892 | config->flags = val; |
|---|
| 897 | 893 | |
|---|
| 898 | 894 | return 0; |
|---|
| .. | .. |
|---|
| 1078 | 1074 | return 0; |
|---|
| 1079 | 1075 | } |
|---|
| 1080 | 1076 | |
|---|
| 1077 | +static int sc2310_get_channel_info(struct sc2310 *sc2310, struct rkmodule_channel_info *ch_info) |
|---|
| 1078 | +{ |
|---|
| 1079 | + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) |
|---|
| 1080 | + return -EINVAL; |
|---|
| 1081 | + ch_info->vc = sc2310->cur_mode->vc[ch_info->index]; |
|---|
| 1082 | + ch_info->width = sc2310->cur_mode->width; |
|---|
| 1083 | + ch_info->height = sc2310->cur_mode->height; |
|---|
| 1084 | + ch_info->bus_fmt = sc2310->cur_mode->bus_fmt; |
|---|
| 1085 | + return 0; |
|---|
| 1086 | +} |
|---|
| 1087 | + |
|---|
| 1081 | 1088 | static long sc2310_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) |
|---|
| 1082 | 1089 | { |
|---|
| 1083 | 1090 | struct sc2310 *sc2310 = to_sc2310(sd); |
|---|
| 1084 | 1091 | struct rkmodule_hdr_cfg *hdr_cfg; |
|---|
| 1085 | 1092 | const struct sc2310_mode *mode; |
|---|
| 1093 | + struct rkmodule_channel_info *ch_info; |
|---|
| 1086 | 1094 | long ret = 0; |
|---|
| 1087 | 1095 | u64 pixel_rate = 0; |
|---|
| 1088 | 1096 | u32 i, h, w, stream; |
|---|
| .. | .. |
|---|
| 1127 | 1135 | mode->bpp * 2 * SC2310_LANES; |
|---|
| 1128 | 1136 | __v4l2_ctrl_s_ctrl_int64(sc2310->pixel_rate, |
|---|
| 1129 | 1137 | pixel_rate); |
|---|
| 1138 | + sc2310->cur_fps = mode->max_fps; |
|---|
| 1139 | + sc2310->cur_vts = mode->vts_def; |
|---|
| 1130 | 1140 | dev_info(&sc2310->client->dev, |
|---|
| 1131 | 1141 | "sensor mode: %d\n", mode->hdr_mode); |
|---|
| 1132 | 1142 | } |
|---|
| .. | .. |
|---|
| 1150 | 1160 | ret = sc2310_write_reg(sc2310->client, SC2310_REG_CTRL_MODE, |
|---|
| 1151 | 1161 | SC2310_REG_VALUE_08BIT, SC2310_MODE_SW_STANDBY); |
|---|
| 1152 | 1162 | break; |
|---|
| 1163 | + case RKMODULE_GET_CHANNEL_INFO: |
|---|
| 1164 | + ch_info = (struct rkmodule_channel_info *)arg; |
|---|
| 1165 | + ret = sc2310_get_channel_info(sc2310, ch_info); |
|---|
| 1166 | + break; |
|---|
| 1153 | 1167 | default: |
|---|
| 1154 | 1168 | ret = -ENOIOCTLCMD; |
|---|
| 1155 | 1169 | break; |
|---|
| .. | .. |
|---|
| 1167 | 1181 | struct rkmodule_awb_cfg *cfg; |
|---|
| 1168 | 1182 | struct rkmodule_hdr_cfg *hdr; |
|---|
| 1169 | 1183 | struct preisp_hdrae_exp_s *hdrae; |
|---|
| 1184 | + struct rkmodule_channel_info *ch_info; |
|---|
| 1170 | 1185 | long ret = 0; |
|---|
| 1171 | 1186 | u32 cg = 0; |
|---|
| 1172 | 1187 | u32 stream = 0; |
|---|
| .. | .. |
|---|
| 1255 | 1270 | if (copy_from_user(&stream, up, sizeof(u32))) |
|---|
| 1256 | 1271 | return -EFAULT; |
|---|
| 1257 | 1272 | ret = sc2310_ioctl(sd, cmd, &stream); |
|---|
| 1273 | + break; |
|---|
| 1274 | + case RKMODULE_GET_CHANNEL_INFO: |
|---|
| 1275 | + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); |
|---|
| 1276 | + if (!ch_info) { |
|---|
| 1277 | + ret = -ENOMEM; |
|---|
| 1278 | + return ret; |
|---|
| 1279 | + } |
|---|
| 1280 | + |
|---|
| 1281 | + ret = sc2310_ioctl(sd, cmd, ch_info); |
|---|
| 1282 | + if (!ret) { |
|---|
| 1283 | + ret = copy_to_user(up, ch_info, sizeof(*ch_info)); |
|---|
| 1284 | + if (ret) |
|---|
| 1285 | + ret = -EFAULT; |
|---|
| 1286 | + } |
|---|
| 1287 | + kfree(ch_info); |
|---|
| 1258 | 1288 | break; |
|---|
| 1259 | 1289 | default: |
|---|
| 1260 | 1290 | ret = -ENOIOCTLCMD; |
|---|
| .. | .. |
|---|
| 1523 | 1553 | static const struct v4l2_subdev_video_ops sc2310_video_ops = { |
|---|
| 1524 | 1554 | .s_stream = sc2310_s_stream, |
|---|
| 1525 | 1555 | .g_frame_interval = sc2310_g_frame_interval, |
|---|
| 1526 | | - .g_mbus_config = sc2310_g_mbus_config, |
|---|
| 1527 | 1556 | }; |
|---|
| 1528 | 1557 | |
|---|
| 1529 | 1558 | static const struct v4l2_subdev_pad_ops sc2310_pad_ops = { |
|---|
| .. | .. |
|---|
| 1532 | 1561 | .enum_frame_interval = sc2310_enum_frame_interval, |
|---|
| 1533 | 1562 | .get_fmt = sc2310_get_fmt, |
|---|
| 1534 | 1563 | .set_fmt = sc2310_set_fmt, |
|---|
| 1564 | + .get_mbus_config = sc2310_g_mbus_config, |
|---|
| 1535 | 1565 | }; |
|---|
| 1536 | 1566 | |
|---|
| 1537 | 1567 | static const struct v4l2_subdev_ops sc2310_subdev_ops = { |
|---|
| .. | .. |
|---|
| 1539 | 1569 | .video = &sc2310_video_ops, /* */ |
|---|
| 1540 | 1570 | .pad = &sc2310_pad_ops, /* */ |
|---|
| 1541 | 1571 | }; |
|---|
| 1572 | + |
|---|
| 1573 | +static void sc2310_modify_fps_info(struct sc2310 *sc2310) |
|---|
| 1574 | +{ |
|---|
| 1575 | + const struct sc2310_mode *mode = sc2310->cur_mode; |
|---|
| 1576 | + |
|---|
| 1577 | + sc2310->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / |
|---|
| 1578 | + sc2310->cur_vts; |
|---|
| 1579 | +} |
|---|
| 1542 | 1580 | |
|---|
| 1543 | 1581 | static int sc2310_set_ctrl(struct v4l2_ctrl *ctrl) |
|---|
| 1544 | 1582 | { |
|---|
| .. | .. |
|---|
| 1613 | 1651 | ret = sc2310_write_reg(sc2310->client, SC2310_REG_VTS, |
|---|
| 1614 | 1652 | SC2310_REG_VALUE_16BIT, |
|---|
| 1615 | 1653 | ctrl->val + sc2310->cur_mode->height); |
|---|
| 1654 | + if (!ret) |
|---|
| 1655 | + sc2310->cur_vts = ctrl->val + sc2310->cur_mode->height; |
|---|
| 1656 | + sc2310_modify_fps_info(sc2310); |
|---|
| 1616 | 1657 | dev_dbg(&client->dev, "set vblank 0x%x\n", |
|---|
| 1617 | 1658 | ctrl->val); |
|---|
| 1618 | 1659 | break; |
|---|
| .. | .. |
|---|
| 1727 | 1768 | |
|---|
| 1728 | 1769 | sc2310->subdev.ctrl_handler = handler; |
|---|
| 1729 | 1770 | sc2310->has_init_exp = false; |
|---|
| 1771 | + sc2310->cur_fps = mode->max_fps; |
|---|
| 1772 | + sc2310->cur_vts = mode->vts_def; |
|---|
| 1730 | 1773 | |
|---|
| 1731 | 1774 | return 0; |
|---|
| 1732 | 1775 | |
|---|