.. | .. |
---|
114 | 114 | #define MIRROR_BIT_MASK (BIT(1) | BIT(2)) |
---|
115 | 115 | #define FLIP_BIT_MASK (BIT(6) | BIT(5)) |
---|
116 | 116 | |
---|
117 | | -enum sc4238_max_pad { |
---|
118 | | - PAD0, |
---|
119 | | - PAD1, |
---|
120 | | - PAD2, |
---|
121 | | - PAD3, |
---|
122 | | - PAD_MAX, |
---|
123 | | -}; |
---|
124 | | - |
---|
125 | 117 | struct regval { |
---|
126 | 118 | u16 addr; |
---|
127 | 119 | u8 val; |
---|
.. | .. |
---|
167 | 159 | struct v4l2_ctrl *h_flip; |
---|
168 | 160 | struct v4l2_ctrl *v_flip; |
---|
169 | 161 | struct mutex mutex; |
---|
| 162 | + struct v4l2_fract cur_fps; |
---|
170 | 163 | bool streaming; |
---|
171 | 164 | bool power_on; |
---|
172 | 165 | const struct sc4238_mode *cur_mode; |
---|
.. | .. |
---|
1581 | 1574 | mode->pixel_rate); |
---|
1582 | 1575 | __v4l2_ctrl_s_ctrl(sc4238->link_freq, |
---|
1583 | 1576 | mode->link_freq); |
---|
| 1577 | + sc4238->cur_fps = mode->max_fps; |
---|
| 1578 | + sc4238->cur_vts = mode->vts_def; |
---|
1584 | 1579 | } |
---|
1585 | 1580 | |
---|
1586 | 1581 | mutex_unlock(&sc4238->mutex); |
---|
.. | .. |
---|
1674 | 1669 | struct sc4238 *sc4238 = to_sc4238(sd); |
---|
1675 | 1670 | const struct sc4238_mode *mode = sc4238->cur_mode; |
---|
1676 | 1671 | |
---|
1677 | | - mutex_lock(&sc4238->mutex); |
---|
1678 | | - fi->interval = mode->max_fps; |
---|
1679 | | - mutex_unlock(&sc4238->mutex); |
---|
| 1672 | + if (sc4238->streaming) |
---|
| 1673 | + fi->interval = sc4238->cur_fps; |
---|
| 1674 | + else |
---|
| 1675 | + fi->interval = mode->max_fps; |
---|
1680 | 1676 | |
---|
1681 | 1677 | return 0; |
---|
1682 | 1678 | } |
---|
1683 | 1679 | |
---|
1684 | | -static int sc4238_g_mbus_config(struct v4l2_subdev *sd, |
---|
| 1680 | +static int sc4238_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, |
---|
1685 | 1681 | struct v4l2_mbus_config *config) |
---|
1686 | 1682 | { |
---|
1687 | 1683 | struct sc4238 *sc4238 = to_sc4238(sd); |
---|
.. | .. |
---|
1698 | 1694 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | |
---|
1699 | 1695 | V4L2_MBUS_CSI2_CHANNEL_1; |
---|
1700 | 1696 | |
---|
1701 | | - config->type = V4L2_MBUS_CSI2; |
---|
| 1697 | + config->type = V4L2_MBUS_CSI2_DPHY; |
---|
1702 | 1698 | config->flags = val; |
---|
1703 | 1699 | |
---|
1704 | 1700 | return 0; |
---|
.. | .. |
---|
1884 | 1880 | return ret; |
---|
1885 | 1881 | } |
---|
1886 | 1882 | |
---|
| 1883 | +static int sc4238_get_channel_info(struct sc4238 *sc4238, struct rkmodule_channel_info *ch_info) |
---|
| 1884 | +{ |
---|
| 1885 | + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) |
---|
| 1886 | + return -EINVAL; |
---|
| 1887 | + ch_info->vc = sc4238->cur_mode->vc[ch_info->index]; |
---|
| 1888 | + ch_info->width = sc4238->cur_mode->width; |
---|
| 1889 | + ch_info->height = sc4238->cur_mode->height; |
---|
| 1890 | + ch_info->bus_fmt = sc4238->cur_mode->bus_fmt; |
---|
| 1891 | + return 0; |
---|
| 1892 | +} |
---|
| 1893 | + |
---|
1887 | 1894 | static long sc4238_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) |
---|
1888 | 1895 | { |
---|
1889 | 1896 | struct sc4238 *sc4238 = to_sc4238(sd); |
---|
1890 | 1897 | struct rkmodule_hdr_cfg *hdr_cfg; |
---|
| 1898 | + struct rkmodule_channel_info *ch_info; |
---|
1891 | 1899 | long ret = 0; |
---|
1892 | 1900 | u32 i, h, w; |
---|
1893 | 1901 | u32 stream = 0; |
---|
.. | .. |
---|
1923 | 1931 | __v4l2_ctrl_modify_range(sc4238->vblank, h, |
---|
1924 | 1932 | SC4238_VTS_MAX - sc4238->cur_mode->height, |
---|
1925 | 1933 | 1, h); |
---|
| 1934 | + sc4238->cur_fps = sc4238->cur_mode->max_fps; |
---|
| 1935 | + sc4238->cur_vts = sc4238->cur_mode->vts_def; |
---|
1926 | 1936 | dev_info(&sc4238->client->dev, |
---|
1927 | 1937 | "sensor mode: %d\n", |
---|
1928 | 1938 | sc4238->cur_mode->hdr_mode); |
---|
.. | .. |
---|
1947 | 1957 | ret = sc4238_write_reg(sc4238->client, SC4238_REG_CTRL_MODE, |
---|
1948 | 1958 | SC4238_REG_VALUE_08BIT, SC4238_MODE_SW_STANDBY); |
---|
1949 | 1959 | break; |
---|
| 1960 | + case RKMODULE_GET_CHANNEL_INFO: |
---|
| 1961 | + ch_info = (struct rkmodule_channel_info *)arg; |
---|
| 1962 | + ret = sc4238_get_channel_info(sc4238, ch_info); |
---|
| 1963 | + break; |
---|
1950 | 1964 | default: |
---|
1951 | 1965 | ret = -ENOIOCTLCMD; |
---|
1952 | 1966 | break; |
---|
.. | .. |
---|
1964 | 1978 | struct rkmodule_awb_cfg *cfg; |
---|
1965 | 1979 | struct rkmodule_hdr_cfg *hdr; |
---|
1966 | 1980 | struct preisp_hdrae_exp_s *hdrae; |
---|
| 1981 | + struct rkmodule_channel_info *ch_info; |
---|
1967 | 1982 | long ret; |
---|
1968 | 1983 | u32 stream = 0; |
---|
1969 | 1984 | |
---|
.. | .. |
---|
1976 | 1991 | } |
---|
1977 | 1992 | |
---|
1978 | 1993 | ret = sc4238_ioctl(sd, cmd, inf); |
---|
1979 | | - if (!ret) |
---|
| 1994 | + if (!ret) { |
---|
1980 | 1995 | ret = copy_to_user(up, inf, sizeof(*inf)); |
---|
| 1996 | + if (ret) |
---|
| 1997 | + ret = -EFAULT; |
---|
| 1998 | + } |
---|
1981 | 1999 | kfree(inf); |
---|
1982 | 2000 | break; |
---|
1983 | 2001 | case RKMODULE_AWB_CFG: |
---|
.. | .. |
---|
1990 | 2008 | ret = copy_from_user(cfg, up, sizeof(*cfg)); |
---|
1991 | 2009 | if (!ret) |
---|
1992 | 2010 | ret = sc4238_ioctl(sd, cmd, cfg); |
---|
| 2011 | + else |
---|
| 2012 | + ret = -EFAULT; |
---|
1993 | 2013 | kfree(cfg); |
---|
1994 | 2014 | break; |
---|
1995 | 2015 | case RKMODULE_GET_HDR_CFG: |
---|
.. | .. |
---|
2000 | 2020 | } |
---|
2001 | 2021 | |
---|
2002 | 2022 | ret = sc4238_ioctl(sd, cmd, hdr); |
---|
2003 | | - if (!ret) |
---|
| 2023 | + if (!ret) { |
---|
2004 | 2024 | ret = copy_to_user(up, hdr, sizeof(*hdr)); |
---|
| 2025 | + if (ret) |
---|
| 2026 | + ret = -EFAULT; |
---|
| 2027 | + } |
---|
2005 | 2028 | kfree(hdr); |
---|
2006 | 2029 | break; |
---|
2007 | 2030 | case RKMODULE_SET_HDR_CFG: |
---|
.. | .. |
---|
2014 | 2037 | ret = copy_from_user(hdr, up, sizeof(*hdr)); |
---|
2015 | 2038 | if (!ret) |
---|
2016 | 2039 | ret = sc4238_ioctl(sd, cmd, hdr); |
---|
| 2040 | + else |
---|
| 2041 | + ret = -EFAULT; |
---|
2017 | 2042 | kfree(hdr); |
---|
2018 | 2043 | break; |
---|
2019 | 2044 | case PREISP_CMD_SET_HDRAE_EXP: |
---|
.. | .. |
---|
2026 | 2051 | ret = copy_from_user(hdrae, up, sizeof(*hdrae)); |
---|
2027 | 2052 | if (!ret) |
---|
2028 | 2053 | ret = sc4238_ioctl(sd, cmd, hdrae); |
---|
| 2054 | + else |
---|
| 2055 | + ret = -EFAULT; |
---|
2029 | 2056 | kfree(hdrae); |
---|
2030 | 2057 | break; |
---|
2031 | 2058 | case RKMODULE_SET_QUICK_STREAM: |
---|
2032 | 2059 | ret = copy_from_user(&stream, up, sizeof(u32)); |
---|
2033 | 2060 | if (!ret) |
---|
2034 | 2061 | ret = sc4238_ioctl(sd, cmd, &stream); |
---|
| 2062 | + else |
---|
| 2063 | + ret = -EFAULT; |
---|
| 2064 | + break; |
---|
| 2065 | + case RKMODULE_GET_CHANNEL_INFO: |
---|
| 2066 | + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); |
---|
| 2067 | + if (!ch_info) { |
---|
| 2068 | + ret = -ENOMEM; |
---|
| 2069 | + return ret; |
---|
| 2070 | + } |
---|
| 2071 | + |
---|
| 2072 | + ret = sc4238_ioctl(sd, cmd, ch_info); |
---|
| 2073 | + if (!ret) { |
---|
| 2074 | + ret = copy_to_user(up, ch_info, sizeof(*ch_info)); |
---|
| 2075 | + if (ret) |
---|
| 2076 | + ret = -EFAULT; |
---|
| 2077 | + } |
---|
| 2078 | + kfree(ch_info); |
---|
2035 | 2079 | break; |
---|
2036 | 2080 | default: |
---|
2037 | 2081 | ret = -ENOIOCTLCMD; |
---|
.. | .. |
---|
2345 | 2389 | static const struct v4l2_subdev_video_ops sc4238_video_ops = { |
---|
2346 | 2390 | .s_stream = sc4238_s_stream, |
---|
2347 | 2391 | .g_frame_interval = sc4238_g_frame_interval, |
---|
2348 | | - .g_mbus_config = sc4238_g_mbus_config, |
---|
2349 | 2392 | }; |
---|
2350 | 2393 | |
---|
2351 | 2394 | static const struct v4l2_subdev_pad_ops sc4238_pad_ops = { |
---|
.. | .. |
---|
2354 | 2397 | .enum_frame_interval = sc4238_enum_frame_interval, |
---|
2355 | 2398 | .get_fmt = sc4238_get_fmt, |
---|
2356 | 2399 | .set_fmt = sc4238_set_fmt, |
---|
| 2400 | + .get_mbus_config = sc4238_g_mbus_config, |
---|
2357 | 2401 | }; |
---|
2358 | 2402 | |
---|
2359 | 2403 | static const struct v4l2_subdev_ops sc4238_subdev_ops = { |
---|
.. | .. |
---|
2361 | 2405 | .video = &sc4238_video_ops, |
---|
2362 | 2406 | .pad = &sc4238_pad_ops, |
---|
2363 | 2407 | }; |
---|
| 2408 | + |
---|
| 2409 | +static void sc4238_modify_fps_info(struct sc4238 *sc4238) |
---|
| 2410 | +{ |
---|
| 2411 | + const struct sc4238_mode *mode = sc4238->cur_mode; |
---|
| 2412 | + |
---|
| 2413 | + sc4238->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / |
---|
| 2414 | + sc4238->cur_vts; |
---|
| 2415 | +} |
---|
2364 | 2416 | |
---|
2365 | 2417 | static int sc4238_set_ctrl(struct v4l2_ctrl *ctrl) |
---|
2366 | 2418 | { |
---|
.. | .. |
---|
2432 | 2484 | ctrl->val + sc4238->cur_mode->height); |
---|
2433 | 2485 | if (ret == 0) |
---|
2434 | 2486 | sc4238->cur_vts = ctrl->val + sc4238->cur_mode->height; |
---|
| 2487 | + sc4238_modify_fps_info(sc4238); |
---|
2435 | 2488 | dev_dbg(&client->dev, "set vblank 0x%x\n", |
---|
2436 | 2489 | ctrl->val); |
---|
2437 | 2490 | break; |
---|
.. | .. |
---|
2565 | 2618 | |
---|
2566 | 2619 | sc4238->subdev.ctrl_handler = handler; |
---|
2567 | 2620 | sc4238->has_init_exp = false; |
---|
| 2621 | + sc4238->cur_fps = mode->max_fps; |
---|
| 2622 | + sc4238->cur_vts = mode->vts_def; |
---|
2568 | 2623 | |
---|
2569 | 2624 | return 0; |
---|
2570 | 2625 | |
---|