.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * ov2640 Camera Driver |
---|
3 | 4 | * |
---|
.. | .. |
---|
7 | 8 | * |
---|
8 | 9 | * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved. |
---|
9 | 10 | * Copyright (C) 2006, OmniVision |
---|
10 | | - * |
---|
11 | | - * This program is free software; you can redistribute it and/or modify |
---|
12 | | - * it under the terms of the GNU General Public License version 2 as |
---|
13 | | - * published by the Free Software Foundation. |
---|
14 | 11 | */ |
---|
15 | 12 | |
---|
16 | 13 | #include <linux/init.h> |
---|
.. | .. |
---|
26 | 23 | #include <linux/videodev2.h> |
---|
27 | 24 | |
---|
28 | 25 | #include <media/v4l2-device.h> |
---|
| 26 | +#include <media/v4l2-event.h> |
---|
29 | 27 | #include <media/v4l2-subdev.h> |
---|
30 | 28 | #include <media/v4l2-ctrls.h> |
---|
31 | 29 | #include <media/v4l2-image-sizes.h> |
---|
.. | .. |
---|
705 | 703 | return ret; |
---|
706 | 704 | } |
---|
707 | 705 | |
---|
| 706 | +static const char * const ov2640_test_pattern_menu[] = { |
---|
| 707 | + "Disabled", |
---|
| 708 | + "Eight Vertical Colour Bars", |
---|
| 709 | +}; |
---|
| 710 | + |
---|
708 | 711 | /* |
---|
709 | 712 | * functions |
---|
710 | 713 | */ |
---|
.. | .. |
---|
740 | 743 | case V4L2_CID_HFLIP: |
---|
741 | 744 | val = ctrl->val ? REG04_HFLIP_IMG : 0x00; |
---|
742 | 745 | return ov2640_mask_set(client, REG04, REG04_HFLIP_IMG, val); |
---|
| 746 | + case V4L2_CID_TEST_PATTERN: |
---|
| 747 | + val = ctrl->val ? COM7_COLOR_BAR_TEST : 0x00; |
---|
| 748 | + return ov2640_mask_set(client, COM7, COM7_COLOR_BAR_TEST, val); |
---|
743 | 749 | } |
---|
744 | 750 | |
---|
745 | 751 | return -EINVAL; |
---|
.. | .. |
---|
833 | 839 | u8 val; |
---|
834 | 840 | int ret; |
---|
835 | 841 | |
---|
836 | | - if (!win) |
---|
837 | | - return -EINVAL; |
---|
838 | | - |
---|
839 | 842 | switch (code) { |
---|
840 | 843 | case MEDIA_BUS_FMT_RGB565_2X8_BE: |
---|
841 | 844 | dev_dbg(&client->dev, "%s: Selected cfmt RGB565 BE", __func__); |
---|
.. | .. |
---|
920 | 923 | if (format->pad) |
---|
921 | 924 | return -EINVAL; |
---|
922 | 925 | |
---|
923 | | - if (!priv->win) { |
---|
924 | | - priv->win = ov2640_select_win(SVGA_WIDTH, SVGA_HEIGHT); |
---|
925 | | - priv->cfmt_code = MEDIA_BUS_FMT_UYVY8_2X8; |
---|
| 926 | + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { |
---|
| 927 | +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API |
---|
| 928 | + mf = v4l2_subdev_get_try_format(sd, cfg, 0); |
---|
| 929 | + format->format = *mf; |
---|
| 930 | + return 0; |
---|
| 931 | +#else |
---|
| 932 | + return -EINVAL; |
---|
| 933 | +#endif |
---|
926 | 934 | } |
---|
927 | 935 | |
---|
928 | 936 | mf->width = priv->win->width; |
---|
.. | .. |
---|
930 | 938 | mf->code = priv->cfmt_code; |
---|
931 | 939 | mf->colorspace = V4L2_COLORSPACE_SRGB; |
---|
932 | 940 | mf->field = V4L2_FIELD_NONE; |
---|
| 941 | + mf->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; |
---|
| 942 | + mf->quantization = V4L2_QUANTIZATION_DEFAULT; |
---|
| 943 | + mf->xfer_func = V4L2_XFER_FUNC_DEFAULT; |
---|
933 | 944 | |
---|
934 | 945 | return 0; |
---|
935 | 946 | } |
---|
.. | .. |
---|
956 | 967 | |
---|
957 | 968 | mf->field = V4L2_FIELD_NONE; |
---|
958 | 969 | mf->colorspace = V4L2_COLORSPACE_SRGB; |
---|
| 970 | + mf->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; |
---|
| 971 | + mf->quantization = V4L2_QUANTIZATION_DEFAULT; |
---|
| 972 | + mf->xfer_func = V4L2_XFER_FUNC_DEFAULT; |
---|
959 | 973 | |
---|
960 | 974 | switch (mf->code) { |
---|
961 | 975 | case MEDIA_BUS_FMT_RGB565_2X8_BE: |
---|
.. | .. |
---|
990 | 1004 | return ret; |
---|
991 | 1005 | } |
---|
992 | 1006 | |
---|
| 1007 | +static int ov2640_init_cfg(struct v4l2_subdev *sd, |
---|
| 1008 | + struct v4l2_subdev_pad_config *cfg) |
---|
| 1009 | +{ |
---|
| 1010 | +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API |
---|
| 1011 | + struct v4l2_mbus_framefmt *try_fmt = |
---|
| 1012 | + v4l2_subdev_get_try_format(sd, cfg, 0); |
---|
| 1013 | + const struct ov2640_win_size *win = |
---|
| 1014 | + ov2640_select_win(SVGA_WIDTH, SVGA_HEIGHT); |
---|
| 1015 | + |
---|
| 1016 | + try_fmt->width = win->width; |
---|
| 1017 | + try_fmt->height = win->height; |
---|
| 1018 | + try_fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; |
---|
| 1019 | + try_fmt->colorspace = V4L2_COLORSPACE_SRGB; |
---|
| 1020 | + try_fmt->field = V4L2_FIELD_NONE; |
---|
| 1021 | + try_fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; |
---|
| 1022 | + try_fmt->quantization = V4L2_QUANTIZATION_DEFAULT; |
---|
| 1023 | + try_fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT; |
---|
| 1024 | +#endif |
---|
| 1025 | + return 0; |
---|
| 1026 | +} |
---|
| 1027 | + |
---|
993 | 1028 | static int ov2640_enum_mbus_code(struct v4l2_subdev *sd, |
---|
994 | 1029 | struct v4l2_subdev_pad_config *cfg, |
---|
995 | 1030 | struct v4l2_subdev_mbus_code_enum *code) |
---|
.. | .. |
---|
1010 | 1045 | |
---|
1011 | 1046 | switch (sel->target) { |
---|
1012 | 1047 | case V4L2_SEL_TGT_CROP_BOUNDS: |
---|
1013 | | - case V4L2_SEL_TGT_CROP_DEFAULT: |
---|
1014 | 1048 | case V4L2_SEL_TGT_CROP: |
---|
1015 | 1049 | sel->r.left = 0; |
---|
1016 | 1050 | sel->r.top = 0; |
---|
.. | .. |
---|
1089 | 1123 | }; |
---|
1090 | 1124 | |
---|
1091 | 1125 | static const struct v4l2_subdev_core_ops ov2640_subdev_core_ops = { |
---|
| 1126 | + .log_status = v4l2_ctrl_subdev_log_status, |
---|
| 1127 | + .subscribe_event = v4l2_ctrl_subdev_subscribe_event, |
---|
| 1128 | + .unsubscribe_event = v4l2_event_subdev_unsubscribe, |
---|
1092 | 1129 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
---|
1093 | 1130 | .g_register = ov2640_g_register, |
---|
1094 | 1131 | .s_register = ov2640_s_register, |
---|
.. | .. |
---|
1097 | 1134 | }; |
---|
1098 | 1135 | |
---|
1099 | 1136 | static const struct v4l2_subdev_pad_ops ov2640_subdev_pad_ops = { |
---|
| 1137 | + .init_cfg = ov2640_init_cfg, |
---|
1100 | 1138 | .enum_mbus_code = ov2640_enum_mbus_code, |
---|
1101 | 1139 | .get_selection = ov2640_get_selection, |
---|
1102 | 1140 | .get_fmt = ov2640_get_fmt, |
---|
.. | .. |
---|
1152 | 1190 | /* |
---|
1153 | 1191 | * i2c_driver functions |
---|
1154 | 1192 | */ |
---|
1155 | | -static int ov2640_probe(struct i2c_client *client, |
---|
1156 | | - const struct i2c_device_id *did) |
---|
| 1193 | +static int ov2640_probe(struct i2c_client *client) |
---|
1157 | 1194 | { |
---|
1158 | 1195 | struct ov2640_priv *priv; |
---|
1159 | | - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
---|
| 1196 | + struct i2c_adapter *adapter = client->adapter; |
---|
1160 | 1197 | int ret; |
---|
1161 | 1198 | |
---|
1162 | 1199 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
---|
.. | .. |
---|
1182 | 1219 | if (ret) |
---|
1183 | 1220 | goto err_clk; |
---|
1184 | 1221 | |
---|
| 1222 | + priv->win = ov2640_select_win(SVGA_WIDTH, SVGA_HEIGHT); |
---|
| 1223 | + priv->cfmt_code = MEDIA_BUS_FMT_UYVY8_2X8; |
---|
| 1224 | + |
---|
1185 | 1225 | v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops); |
---|
1186 | | - priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
---|
| 1226 | + priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | |
---|
| 1227 | + V4L2_SUBDEV_FL_HAS_EVENTS; |
---|
1187 | 1228 | mutex_init(&priv->lock); |
---|
1188 | | - v4l2_ctrl_handler_init(&priv->hdl, 2); |
---|
| 1229 | + v4l2_ctrl_handler_init(&priv->hdl, 3); |
---|
1189 | 1230 | priv->hdl.lock = &priv->lock; |
---|
1190 | 1231 | v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops, |
---|
1191 | 1232 | V4L2_CID_VFLIP, 0, 1, 1, 0); |
---|
1192 | 1233 | v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops, |
---|
1193 | 1234 | V4L2_CID_HFLIP, 0, 1, 1, 0); |
---|
| 1235 | + v4l2_ctrl_new_std_menu_items(&priv->hdl, &ov2640_ctrl_ops, |
---|
| 1236 | + V4L2_CID_TEST_PATTERN, |
---|
| 1237 | + ARRAY_SIZE(ov2640_test_pattern_menu) - 1, 0, 0, |
---|
| 1238 | + ov2640_test_pattern_menu); |
---|
1194 | 1239 | priv->subdev.ctrl_handler = &priv->hdl; |
---|
1195 | 1240 | if (priv->hdl.error) { |
---|
1196 | 1241 | ret = priv->hdl.error; |
---|
.. | .. |
---|
1256 | 1301 | .name = "ov2640", |
---|
1257 | 1302 | .of_match_table = of_match_ptr(ov2640_of_match), |
---|
1258 | 1303 | }, |
---|
1259 | | - .probe = ov2640_probe, |
---|
| 1304 | + .probe_new = ov2640_probe, |
---|
1260 | 1305 | .remove = ov2640_remove, |
---|
1261 | 1306 | .id_table = ov2640_id, |
---|
1262 | 1307 | }; |
---|