| .. | .. |
|---|
| 8 | 8 | * V0.0X01.0X02 fix mclk issue when probe multiple camera. |
|---|
| 9 | 9 | * V0.0X01.0X03 add otp function. |
|---|
| 10 | 10 | * V0.0X01.0X04 add enum_frame_interval function. |
|---|
| 11 | | - * V0.0X01.0X05 add quick stream on/off |
|---|
| 12 | | - * V0.0X01.0X06 add function g_mmbus_config |
|---|
| 13 | 11 | */ |
|---|
| 14 | 12 | |
|---|
| 15 | 13 | #include <linux/clk.h> |
|---|
| .. | .. |
|---|
| 39 | 37 | #include <linux/rk-camera-module.h> |
|---|
| 40 | 38 | |
|---|
| 41 | 39 | /* verify default register values */ |
|---|
| 42 | | -//#define CHECK_REG_VALUE |
|---|
| 40 | +#define CHECK_REG_VALUE |
|---|
| 43 | 41 | |
|---|
| 44 | | -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x06) |
|---|
| 42 | +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x04) |
|---|
| 45 | 43 | |
|---|
| 46 | 44 | #ifndef V4L2_CID_DIGITAL_GAIN |
|---|
| 47 | 45 | #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN |
|---|
| .. | .. |
|---|
| 543 | 541 | {0x5045, 0x05}, //[2] enable MWB manual bias |
|---|
| 544 | 542 | {0x5048, 0x10}, //MWB manual bias be the same with 0x4003 BLC target. |
|---|
| 545 | 543 | //{0x0100, 0x01}, |
|---|
| 546 | | - |
|---|
| 547 | 544 | {REG_NULL, 0x00}, |
|---|
| 548 | 545 | }; |
|---|
| 549 | 546 | |
|---|
| .. | .. |
|---|
| 932 | 929 | if (ov5670_module_info[i].id == otp->module_id) |
|---|
| 933 | 930 | break; |
|---|
| 934 | 931 | } |
|---|
| 935 | | - strlcpy(inf->fac.module, ov5670_module_info[i].name, |
|---|
| 932 | + strscpy(inf->fac.module, ov5670_module_info[i].name, |
|---|
| 936 | 933 | sizeof(inf->fac.module)); |
|---|
| 937 | 934 | |
|---|
| 938 | 935 | for (i = 0; i < ARRAY_SIZE(ov5670_lens_info) - 1; i++) { |
|---|
| 939 | 936 | if (ov5670_lens_info[i].id == otp->lens_id) |
|---|
| 940 | 937 | break; |
|---|
| 941 | 938 | } |
|---|
| 942 | | - strlcpy(inf->fac.lens, ov5670_lens_info[i].name, |
|---|
| 939 | + strscpy(inf->fac.lens, ov5670_lens_info[i].name, |
|---|
| 943 | 940 | sizeof(inf->fac.lens)); |
|---|
| 944 | 941 | } |
|---|
| 945 | 942 | |
|---|
| .. | .. |
|---|
| 978 | 975 | struct rkmodule_inf *inf) |
|---|
| 979 | 976 | { |
|---|
| 980 | 977 | struct ov5670_otp_info *otp = ov5670->otp; |
|---|
| 978 | + |
|---|
| 981 | 979 | memset(inf, 0, sizeof(*inf)); |
|---|
| 982 | | - strlcpy(inf->base.sensor, OV5670_NAME, sizeof(inf->base.sensor)); |
|---|
| 983 | | - strlcpy(inf->base.module, ov5670->module_name, |
|---|
| 980 | + strscpy(inf->base.sensor, OV5670_NAME, sizeof(inf->base.sensor)); |
|---|
| 981 | + strscpy(inf->base.module, ov5670->module_name, |
|---|
| 984 | 982 | sizeof(inf->base.module)); |
|---|
| 985 | | - strlcpy(inf->base.lens, ov5670->len_name, sizeof(inf->base.lens)); |
|---|
| 983 | + strscpy(inf->base.lens, ov5670->len_name, sizeof(inf->base.lens)); |
|---|
| 986 | 984 | if (otp) |
|---|
| 987 | 985 | ov5670_get_otp(otp, inf); |
|---|
| 988 | 986 | } |
|---|
| .. | .. |
|---|
| 999 | 997 | { |
|---|
| 1000 | 998 | struct ov5670 *ov5670 = to_ov5670(sd); |
|---|
| 1001 | 999 | long ret = 0; |
|---|
| 1002 | | - u32 stream = 0; |
|---|
| 1003 | 1000 | |
|---|
| 1004 | 1001 | switch (cmd) { |
|---|
| 1005 | 1002 | case RKMODULE_GET_MODULE_INFO: |
|---|
| .. | .. |
|---|
| 1007 | 1004 | break; |
|---|
| 1008 | 1005 | case RKMODULE_AWB_CFG: |
|---|
| 1009 | 1006 | ov5670_set_awb_cfg(ov5670, (struct rkmodule_awb_cfg *)arg); |
|---|
| 1010 | | - break; |
|---|
| 1011 | | - case RKMODULE_SET_QUICK_STREAM: |
|---|
| 1012 | | - |
|---|
| 1013 | | - stream = *((u32 *)arg); |
|---|
| 1014 | | - |
|---|
| 1015 | | - if (stream) |
|---|
| 1016 | | - ret = ov5670_write_reg(ov5670->client, OV5670_REG_CTRL_MODE, |
|---|
| 1017 | | - OV5670_REG_VALUE_08BIT, OV5670_MODE_STREAMING); |
|---|
| 1018 | | - else |
|---|
| 1019 | | - ret = ov5670_write_reg(ov5670->client, OV5670_REG_CTRL_MODE, |
|---|
| 1020 | | - OV5670_REG_VALUE_08BIT, OV5670_MODE_SW_STANDBY); |
|---|
| 1021 | 1007 | break; |
|---|
| 1022 | 1008 | default: |
|---|
| 1023 | 1009 | ret = -ENOIOCTLCMD; |
|---|
| .. | .. |
|---|
| 1035 | 1021 | struct rkmodule_inf *inf; |
|---|
| 1036 | 1022 | struct rkmodule_awb_cfg *awb_cfg; |
|---|
| 1037 | 1023 | long ret; |
|---|
| 1038 | | - u32 stream = 0; |
|---|
| 1039 | 1024 | |
|---|
| 1040 | 1025 | switch (cmd) { |
|---|
| 1041 | 1026 | case RKMODULE_GET_MODULE_INFO: |
|---|
| .. | .. |
|---|
| 1046 | 1031 | } |
|---|
| 1047 | 1032 | |
|---|
| 1048 | 1033 | ret = ov5670_ioctl(sd, cmd, inf); |
|---|
| 1049 | | - if (!ret) |
|---|
| 1050 | | - ret = copy_to_user(up, inf, sizeof(*inf)); |
|---|
| 1034 | + if (!ret) { |
|---|
| 1035 | + if (copy_to_user(up, inf, sizeof(*inf))) |
|---|
| 1036 | + return -EFAULT; |
|---|
| 1037 | + } |
|---|
| 1051 | 1038 | kfree(inf); |
|---|
| 1052 | 1039 | break; |
|---|
| 1053 | 1040 | case RKMODULE_AWB_CFG: |
|---|
| .. | .. |
|---|
| 1057 | 1044 | return ret; |
|---|
| 1058 | 1045 | } |
|---|
| 1059 | 1046 | |
|---|
| 1060 | | - ret = copy_from_user(awb_cfg, up, sizeof(*awb_cfg)); |
|---|
| 1061 | | - if (!ret) |
|---|
| 1062 | | - ret = ov5670_ioctl(sd, cmd, awb_cfg); |
|---|
| 1047 | + if (copy_from_user(awb_cfg, up, sizeof(*awb_cfg))) |
|---|
| 1048 | + return -EFAULT; |
|---|
| 1049 | + |
|---|
| 1050 | + ret = ov5670_ioctl(sd, cmd, awb_cfg); |
|---|
| 1063 | 1051 | kfree(awb_cfg); |
|---|
| 1064 | | - break; |
|---|
| 1065 | | - case RKMODULE_SET_QUICK_STREAM: |
|---|
| 1066 | | - ret = copy_from_user(&stream, up, sizeof(u32)); |
|---|
| 1067 | | - if (!ret) |
|---|
| 1068 | | - ret = ov5670_ioctl(sd, cmd, &stream); |
|---|
| 1069 | 1052 | break; |
|---|
| 1070 | 1053 | default: |
|---|
| 1071 | 1054 | ret = -ENOIOCTLCMD; |
|---|
| .. | .. |
|---|
| 1075 | 1058 | return ret; |
|---|
| 1076 | 1059 | } |
|---|
| 1077 | 1060 | #endif |
|---|
| 1061 | + |
|---|
| 1078 | 1062 | /*--------------------------------------------------------------------------*/ |
|---|
| 1079 | 1063 | static int ov5670_apply_otp(struct ov5670 *ov5670) |
|---|
| 1080 | 1064 | { |
|---|
| .. | .. |
|---|
| 1195 | 1179 | int ret = 0; |
|---|
| 1196 | 1180 | |
|---|
| 1197 | 1181 | dev_info(&client->dev, "%s: on: %d, %dx%d@%d\n", __func__, on, |
|---|
| 1198 | | - ov5670->cur_mode->width, |
|---|
| 1199 | | - ov5670->cur_mode->height, |
|---|
| 1182 | + ov5670->cur_mode->width, |
|---|
| 1183 | + ov5670->cur_mode->height, |
|---|
| 1200 | 1184 | DIV_ROUND_CLOSEST(ov5670->cur_mode->max_fps.denominator, |
|---|
| 1201 | 1185 | ov5670->cur_mode->max_fps.numerator)); |
|---|
| 1202 | 1186 | |
|---|
| .. | .. |
|---|
| 1414 | 1398 | if (fie->index >= ov5670->cfg_num) |
|---|
| 1415 | 1399 | return -EINVAL; |
|---|
| 1416 | 1400 | |
|---|
| 1417 | | - if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) |
|---|
| 1418 | | - return -EINVAL; |
|---|
| 1419 | | - |
|---|
| 1401 | + fie->code = MEDIA_BUS_FMT_SBGGR10_1X10; |
|---|
| 1420 | 1402 | fie->width = supported_modes[fie->index].width; |
|---|
| 1421 | 1403 | fie->height = supported_modes[fie->index].height; |
|---|
| 1422 | 1404 | fie->interval = supported_modes[fie->index].max_fps; |
|---|
| .. | .. |
|---|
| 1424 | 1406 | } |
|---|
| 1425 | 1407 | |
|---|
| 1426 | 1408 | static int ov5670_g_mbus_config(struct v4l2_subdev *sd, |
|---|
| 1409 | + unsigned int pad_id, |
|---|
| 1427 | 1410 | struct v4l2_mbus_config *config) |
|---|
| 1428 | 1411 | { |
|---|
| 1429 | | - u32 val = 0; |
|---|
| 1412 | + u32 val = 1 << (OV5670_LANES - 1) | |
|---|
| 1413 | + V4L2_MBUS_CSI2_CHANNEL_0 | |
|---|
| 1414 | + V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; |
|---|
| 1430 | 1415 | |
|---|
| 1431 | | - val = 1 << (OV5670_LANES - 1) | |
|---|
| 1432 | | - V4L2_MBUS_CSI2_CHANNEL_0 | |
|---|
| 1433 | | - V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; |
|---|
| 1434 | | - config->type = V4L2_MBUS_CSI2; |
|---|
| 1416 | + config->type = V4L2_MBUS_CSI2_DPHY; |
|---|
| 1435 | 1417 | config->flags = val; |
|---|
| 1436 | 1418 | |
|---|
| 1437 | 1419 | return 0; |
|---|
| .. | .. |
|---|
| 1459 | 1441 | static const struct v4l2_subdev_video_ops ov5670_video_ops = { |
|---|
| 1460 | 1442 | .s_stream = ov5670_s_stream, |
|---|
| 1461 | 1443 | .g_frame_interval = ov5670_g_frame_interval, |
|---|
| 1462 | | - .g_mbus_config = ov5670_g_mbus_config, |
|---|
| 1463 | 1444 | }; |
|---|
| 1464 | 1445 | |
|---|
| 1465 | 1446 | static const struct v4l2_subdev_pad_ops ov5670_pad_ops = { |
|---|
| .. | .. |
|---|
| 1468 | 1449 | .enum_frame_interval = ov5670_enum_frame_interval, |
|---|
| 1469 | 1450 | .get_fmt = ov5670_get_fmt, |
|---|
| 1470 | 1451 | .set_fmt = ov5670_set_fmt, |
|---|
| 1452 | + .get_mbus_config = ov5670_g_mbus_config, |
|---|
| 1471 | 1453 | }; |
|---|
| 1472 | 1454 | |
|---|
| 1473 | 1455 | static const struct v4l2_subdev_ops ov5670_subdev_ops = { |
|---|
| .. | .. |
|---|
| 1496 | 1478 | break; |
|---|
| 1497 | 1479 | } |
|---|
| 1498 | 1480 | |
|---|
| 1499 | | - if (!pm_runtime_get_if_in_use(&client->dev)) |
|---|
| 1481 | + if (pm_runtime_get(&client->dev) <= 0) |
|---|
| 1500 | 1482 | return 0; |
|---|
| 1501 | 1483 | |
|---|
| 1502 | 1484 | switch (ctrl->id) { |
|---|
| .. | .. |
|---|
| 1505 | 1487 | /*group 0*/ |
|---|
| 1506 | 1488 | ret = ov5670_write_reg(ov5670->client, OV5670_REG_GROUP, |
|---|
| 1507 | 1489 | OV5670_REG_VALUE_08BIT, 0x00); |
|---|
| 1508 | | - ret = ov5670_write_reg(ov5670->client, OV5670_REG_EXPOSURE, |
|---|
| 1490 | + ret |= ov5670_write_reg(ov5670->client, OV5670_REG_EXPOSURE, |
|---|
| 1509 | 1491 | OV5670_REG_VALUE_24BIT, ctrl->val << 4); |
|---|
| 1510 | | - ret = ov5670_write_reg(ov5670->client, OV5670_REG_GROUP, |
|---|
| 1492 | + ret |= ov5670_write_reg(ov5670->client, OV5670_REG_GROUP, |
|---|
| 1511 | 1493 | OV5670_REG_VALUE_08BIT, 0x10); |
|---|
| 1512 | | - ret = ov5670_write_reg(ov5670->client, OV5670_REG_GROUP, |
|---|
| 1494 | + ret |= ov5670_write_reg(ov5670->client, OV5670_REG_GROUP, |
|---|
| 1513 | 1495 | OV5670_REG_VALUE_08BIT, 0xa0); |
|---|
| 1514 | 1496 | |
|---|
| 1515 | 1497 | break; |
|---|
| .. | .. |
|---|
| 1518 | 1500 | ret = ov5670_write_reg(ov5670->client, OV5670_REG_GROUP, |
|---|
| 1519 | 1501 | OV5670_REG_VALUE_08BIT, 0x01); |
|---|
| 1520 | 1502 | |
|---|
| 1521 | | - ret = ov5670_write_reg(ov5670->client, OV5670_REG_GAIN_L, |
|---|
| 1503 | + ret |= ov5670_write_reg(ov5670->client, OV5670_REG_GAIN_L, |
|---|
| 1522 | 1504 | OV5670_REG_VALUE_08BIT, |
|---|
| 1523 | 1505 | ctrl->val & OV5670_GAIN_L_MASK); |
|---|
| 1524 | 1506 | ret |= ov5670_write_reg(ov5670->client, OV5670_REG_GAIN_H, |
|---|
| 1525 | 1507 | OV5670_REG_VALUE_08BIT, |
|---|
| 1526 | 1508 | (ctrl->val >> OV5670_GAIN_H_SHIFT) & |
|---|
| 1527 | 1509 | OV5670_GAIN_H_MASK); |
|---|
| 1528 | | - ret = ov5670_write_reg(ov5670->client, OV5670_REG_GROUP, |
|---|
| 1510 | + ret |= ov5670_write_reg(ov5670->client, OV5670_REG_GROUP, |
|---|
| 1529 | 1511 | OV5670_REG_VALUE_08BIT, 0x11); |
|---|
| 1530 | | - ret = ov5670_write_reg(ov5670->client, OV5670_REG_GROUP, |
|---|
| 1512 | + ret |= ov5670_write_reg(ov5670->client, OV5670_REG_GROUP, |
|---|
| 1531 | 1513 | OV5670_REG_VALUE_08BIT, 0xa1); |
|---|
| 1532 | 1514 | break; |
|---|
| 1533 | 1515 | case V4L2_CID_VBLANK: |
|---|
| .. | .. |
|---|
| 1625 | 1607 | |
|---|
| 1626 | 1608 | static int ov5670_otp_read(struct ov5670 *ov5670) |
|---|
| 1627 | 1609 | { |
|---|
| 1628 | | - int otp_flag, addr, temp, i; |
|---|
| 1610 | + int otp_flag, addr, temp = 0, i; |
|---|
| 1629 | 1611 | struct ov5670_otp_info *otp_ptr; |
|---|
| 1630 | 1612 | struct device *dev = &ov5670->client->dev; |
|---|
| 1631 | 1613 | struct i2c_client *client = ov5670->client; |
|---|
| .. | .. |
|---|
| 1804 | 1786 | } |
|---|
| 1805 | 1787 | |
|---|
| 1806 | 1788 | ov5670->lane_num = rval; |
|---|
| 1807 | | - if (2 == ov5670->lane_num) { |
|---|
| 1789 | + if (ov5670->lane_num == 2) { |
|---|
| 1808 | 1790 | ov5670->cur_mode = &supported_modes_2lane[0]; |
|---|
| 1809 | 1791 | supported_modes = supported_modes_2lane; |
|---|
| 1810 | 1792 | ov5670->cfg_num = ARRAY_SIZE(supported_modes_2lane); |
|---|
| .. | .. |
|---|
| 1925 | 1907 | |
|---|
| 1926 | 1908 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API |
|---|
| 1927 | 1909 | sd->internal_ops = &ov5670_internal_ops; |
|---|
| 1928 | | - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | |
|---|
| 1929 | | - V4L2_SUBDEV_FL_HAS_EVENTS; |
|---|
| 1910 | + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
|---|
| 1930 | 1911 | #endif |
|---|
| 1931 | 1912 | #if defined(CONFIG_MEDIA_CONTROLLER) |
|---|
| 1932 | 1913 | ov5670->pad.flags = MEDIA_PAD_FL_SOURCE; |
|---|