.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * adv7180.c Analog Devices ADV7180 video decoder driver |
---|
3 | 4 | * Copyright (c) 2009 Intel Corporation |
---|
4 | 5 | * Copyright (C) 2013 Cogent Embedded, Inc. |
---|
5 | 6 | * Copyright (C) 2013 Renesas Solutions Corp. |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License version 2 as |
---|
9 | | - * published by the Free Software Foundation. |
---|
10 | | - * |
---|
11 | | - * This program is distributed in the hope that it will be useful, |
---|
12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
14 | | - * GNU General Public License for more details. |
---|
15 | 7 | */ |
---|
16 | | - |
---|
17 | 8 | #include <linux/module.h> |
---|
18 | 9 | #include <linux/init.h> |
---|
19 | 10 | #include <linux/errno.h> |
---|
.. | .. |
---|
188 | 179 | #define ADV7180_DEFAULT_VPP_I2C_ADDR 0x42 |
---|
189 | 180 | |
---|
190 | 181 | #define V4L2_CID_ADV_FAST_SWITCH (V4L2_CID_USER_ADV7180_BASE + 0x00) |
---|
| 182 | + |
---|
| 183 | +/* Initial number of frames to skip to avoid possible garbage */ |
---|
| 184 | +#define ADV7180_NUM_OF_SKIP_FRAMES 2 |
---|
191 | 185 | |
---|
192 | 186 | struct adv7180_state; |
---|
193 | 187 | |
---|
.. | .. |
---|
732 | 726 | case V4L2_FIELD_NONE: |
---|
733 | 727 | if (state->chip_info->flags & ADV7180_FLAG_I2P) |
---|
734 | 728 | break; |
---|
735 | | - /* fall through */ |
---|
| 729 | + fallthrough; |
---|
736 | 730 | default: |
---|
737 | 731 | format->format.field = V4L2_FIELD_ALTERNATE; |
---|
738 | 732 | break; |
---|
.. | .. |
---|
755 | 749 | return ret; |
---|
756 | 750 | } |
---|
757 | 751 | |
---|
758 | | -static int adv7180_g_mbus_config(struct v4l2_subdev *sd, |
---|
759 | | - struct v4l2_mbus_config *cfg) |
---|
| 752 | +static int adv7180_init_cfg(struct v4l2_subdev *sd, |
---|
| 753 | + struct v4l2_subdev_pad_config *cfg) |
---|
| 754 | +{ |
---|
| 755 | + struct v4l2_subdev_format fmt = { |
---|
| 756 | + .which = cfg ? V4L2_SUBDEV_FORMAT_TRY |
---|
| 757 | + : V4L2_SUBDEV_FORMAT_ACTIVE, |
---|
| 758 | + }; |
---|
| 759 | + |
---|
| 760 | + return adv7180_set_pad_format(sd, cfg, &fmt); |
---|
| 761 | +} |
---|
| 762 | + |
---|
| 763 | +static int adv7180_get_mbus_config(struct v4l2_subdev *sd, |
---|
| 764 | + unsigned int pad, |
---|
| 765 | + struct v4l2_mbus_config *cfg) |
---|
760 | 766 | { |
---|
761 | 767 | struct adv7180_state *state = to_state(sd); |
---|
762 | 768 | |
---|
763 | 769 | if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { |
---|
764 | | - cfg->type = V4L2_MBUS_CSI2; |
---|
| 770 | + cfg->type = V4L2_MBUS_CSI2_DPHY; |
---|
765 | 771 | cfg->flags = V4L2_MBUS_CSI2_1_LANE | |
---|
766 | 772 | V4L2_MBUS_CSI2_CHANNEL_0 | |
---|
767 | 773 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; |
---|
.. | .. |
---|
774 | 780 | V4L2_MBUS_DATA_ACTIVE_HIGH; |
---|
775 | 781 | cfg->type = V4L2_MBUS_BT656; |
---|
776 | 782 | } |
---|
| 783 | + |
---|
| 784 | + return 0; |
---|
| 785 | +} |
---|
| 786 | + |
---|
| 787 | +static int adv7180_get_skip_frames(struct v4l2_subdev *sd, u32 *frames) |
---|
| 788 | +{ |
---|
| 789 | + *frames = ADV7180_NUM_OF_SKIP_FRAMES; |
---|
777 | 790 | |
---|
778 | 791 | return 0; |
---|
779 | 792 | } |
---|
.. | .. |
---|
840 | 853 | .querystd = adv7180_querystd, |
---|
841 | 854 | .g_input_status = adv7180_g_input_status, |
---|
842 | 855 | .s_routing = adv7180_s_routing, |
---|
843 | | - .g_mbus_config = adv7180_g_mbus_config, |
---|
844 | 856 | .g_pixelaspect = adv7180_g_pixelaspect, |
---|
845 | 857 | .g_tvnorms = adv7180_g_tvnorms, |
---|
846 | 858 | .s_stream = adv7180_s_stream, |
---|
.. | .. |
---|
853 | 865 | }; |
---|
854 | 866 | |
---|
855 | 867 | static const struct v4l2_subdev_pad_ops adv7180_pad_ops = { |
---|
| 868 | + .init_cfg = adv7180_init_cfg, |
---|
856 | 869 | .enum_mbus_code = adv7180_enum_mbus_code, |
---|
857 | 870 | .set_fmt = adv7180_set_pad_format, |
---|
858 | 871 | .get_fmt = adv7180_get_pad_format, |
---|
| 872 | + .get_mbus_config = adv7180_get_mbus_config, |
---|
| 873 | +}; |
---|
| 874 | + |
---|
| 875 | +static const struct v4l2_subdev_sensor_ops adv7180_sensor_ops = { |
---|
| 876 | + .g_skip_frames = adv7180_get_skip_frames, |
---|
859 | 877 | }; |
---|
860 | 878 | |
---|
861 | 879 | static const struct v4l2_subdev_ops adv7180_ops = { |
---|
862 | 880 | .core = &adv7180_core_ops, |
---|
863 | 881 | .video = &adv7180_video_ops, |
---|
864 | 882 | .pad = &adv7180_pad_ops, |
---|
| 883 | + .sensor = &adv7180_sensor_ops, |
---|
865 | 884 | }; |
---|
866 | 885 | |
---|
867 | 886 | static irqreturn_t adv7180_irq(int irq, void *devid) |
---|
.. | .. |
---|
1303 | 1322 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
---|
1304 | 1323 | return -EIO; |
---|
1305 | 1324 | |
---|
1306 | | - v4l_info(client, "chip found @ 0x%02x (%s)\n", |
---|
1307 | | - client->addr, client->adapter->name); |
---|
1308 | | - |
---|
1309 | 1325 | state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); |
---|
1310 | 1326 | if (state == NULL) |
---|
1311 | 1327 | return -ENOMEM; |
---|
.. | .. |
---|
1323 | 1339 | } |
---|
1324 | 1340 | |
---|
1325 | 1341 | if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { |
---|
1326 | | - state->csi_client = i2c_new_dummy(client->adapter, |
---|
| 1342 | + state->csi_client = i2c_new_dummy_device(client->adapter, |
---|
1327 | 1343 | ADV7180_DEFAULT_CSI_I2C_ADDR); |
---|
1328 | | - if (!state->csi_client) |
---|
1329 | | - return -ENOMEM; |
---|
| 1344 | + if (IS_ERR(state->csi_client)) |
---|
| 1345 | + return PTR_ERR(state->csi_client); |
---|
1330 | 1346 | } |
---|
1331 | 1347 | |
---|
1332 | 1348 | if (state->chip_info->flags & ADV7180_FLAG_I2P) { |
---|
1333 | | - state->vpp_client = i2c_new_dummy(client->adapter, |
---|
| 1349 | + state->vpp_client = i2c_new_dummy_device(client->adapter, |
---|
1334 | 1350 | ADV7180_DEFAULT_VPP_I2C_ADDR); |
---|
1335 | | - if (!state->vpp_client) { |
---|
1336 | | - ret = -ENOMEM; |
---|
| 1351 | + if (IS_ERR(state->vpp_client)) { |
---|
| 1352 | + ret = PTR_ERR(state->vpp_client); |
---|
1337 | 1353 | goto err_unregister_csi_client; |
---|
1338 | 1354 | } |
---|
1339 | 1355 | } |
---|
.. | .. |
---|
1376 | 1392 | if (ret) |
---|
1377 | 1393 | goto err_free_irq; |
---|
1378 | 1394 | |
---|
| 1395 | + v4l_info(client, "chip found @ 0x%02x (%s)\n", |
---|
| 1396 | + client->addr, client->adapter->name); |
---|
| 1397 | + |
---|
1379 | 1398 | return 0; |
---|
1380 | 1399 | |
---|
1381 | 1400 | err_free_irq: |
---|