diff options
author | Mauro Carvalho Chehab <mchehab@kernel.org> | 2022-12-06 07:28:26 +0000 |
---|---|---|
committer | Hans Verkuil <hverkuil-cisco@xs4all.nl> | 2022-12-07 17:58:47 +0100 |
commit | 3178804c64ef7c8c87a53cd5bba0b2942dd64fec (patch) | |
tree | 82b2fd9364178df5ce3629d185c2811898a99305 /drivers | |
parent | b2ea130c2541a8439fd9a288f319cb257ee8e9a0 (diff) | |
parent | a14e84dbce2eeebde5e9aacd8bb49e85c1e1a067 (diff) | |
download | linux-stable-3178804c64ef7c8c87a53cd5bba0b2942dd64fec.tar.gz linux-stable-3178804c64ef7c8c87a53cd5bba0b2942dd64fec.tar.bz2 linux-stable-3178804c64ef7c8c87a53cd5bba0b2942dd64fec.zip |
Merge tag 'br-v6.2i' of git://linuxtv.org/hverkuil/media_tree into media_stage
Tag branch
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
* tag 'br-v6.2i' of git://linuxtv.org/hverkuil/media_tree: (31 commits)
media: s5c73m3: Switch to GPIO descriptors
media: i2c: s5k5baf: switch to using gpiod API
media: i2c: s5k6a3: switch to using gpiod API
media: imx: remove code for non-existing config IMX_GPT_ICAP
media: si470x: Fix use-after-free in si470x_int_in_callback()
media: staging: stkwebcam: Restore MEDIA_{USB,CAMERA}_SUPPORT dependencies
media: coda: Add check for kmalloc
media: coda: Add check for dcoda_iram_alloc
dt-bindings: media: s5c73m3: Fix reset-gpio descriptor
media: dt-bindings: allwinner: h6-vpu-g2: Add IOMMU reference property
media: s5k4ecgx: Delete driver
media: s5k4ecgx: Switch to GPIO descriptors
media: Switch to use dev_err_probe() helper
headers: Remove some left-over license text in include/uapi/linux/v4l2-*
headers: Remove some left-over license text in include/uapi/linux/dvb/
media: usb: pwc-uncompress: Use flex array destination for memcpy()
media: s5p-mfc: Fix to handle reference queue during finishing
media: s5p-mfc: Clear workbit to handle error condition
media: s5p-mfc: Fix in register read and write for H264
media: imx: Use get_mbus_config instead of parsing upstream DT endpoints
...
Diffstat (limited to 'drivers')
39 files changed, 227 insertions, 1504 deletions
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 283b78b5766e..6abc9302cd84 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -182,7 +182,7 @@ config MEDIA_CONTROLLER # config DVB_CORE - tristate + tristate "DVB Core" depends on MEDIA_DIGITAL_TV_SUPPORT depends on (I2C || I2C=n) default MEDIA_DIGITAL_TV_SUPPORT diff --git a/drivers/media/cec/platform/stm32/stm32-cec.c b/drivers/media/cec/platform/stm32/stm32-cec.c index 40db7911b437..7b2db46a5722 100644 --- a/drivers/media/cec/platform/stm32/stm32-cec.c +++ b/drivers/media/cec/platform/stm32/stm32-cec.c @@ -288,12 +288,9 @@ static int stm32_cec_probe(struct platform_device *pdev) return ret; cec->clk_cec = devm_clk_get(&pdev->dev, "cec"); - if (IS_ERR(cec->clk_cec)) { - if (PTR_ERR(cec->clk_cec) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Cannot get cec clock\n"); - - return PTR_ERR(cec->clk_cec); - } + if (IS_ERR(cec->clk_cec)) + return dev_err_probe(&pdev->dev, PTR_ERR(cec->clk_cec), + "Cannot get cec clock\n"); ret = clk_prepare(cec->clk_cec); if (ret) { diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index a3f756d8922c..833241897d63 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -751,16 +751,6 @@ config VIDEO_S5C73M3 This is a V4L2 sensor driver for Samsung S5C73M3 8 Mpixel camera. -config VIDEO_S5K4ECGX - tristate "Samsung S5K4ECGX sensor support" - depends on I2C && VIDEO_DEV - select MEDIA_CONTROLLER - select VIDEO_V4L2_SUBDEV_API - select CRC32 - help - This is a V4L2 sensor driver for Samsung S5K4ECGX 5M - camera sensor with an embedded SoC image signal processor. - config VIDEO_S5K5BAF tristate "Samsung S5K5BAF sensor support" depends on I2C && VIDEO_DEV diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index ba28a8f8a07f..4d6c052bb5a7 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -105,7 +105,6 @@ obj-$(CONFIG_VIDEO_RDACM20) += rdacm20.o obj-$(CONFIG_VIDEO_RDACM21) += rdacm21.o obj-$(CONFIG_VIDEO_RJ54N1) += rj54n1cb0c.o obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/ -obj-$(CONFIG_VIDEO_S5K4ECGX) += s5k4ecgx.o obj-$(CONFIG_VIDEO_S5K5BAF) += s5k5baf.o obj-$(CONFIG_VIDEO_S5K6A3) += s5k6a3.o obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c index 9945d17fadd6..44c26af49071 100644 --- a/drivers/media/i2c/ad5820.c +++ b/drivers/media/i2c/ad5820.c @@ -300,21 +300,15 @@ static int ad5820_probe(struct i2c_client *client) return -ENOMEM; coil->vana = devm_regulator_get(&client->dev, "VANA"); - if (IS_ERR(coil->vana)) { - ret = PTR_ERR(coil->vana); - if (ret != -EPROBE_DEFER) - dev_err(&client->dev, "could not get regulator for vana\n"); - return ret; - } + if (IS_ERR(coil->vana)) + return dev_err_probe(&client->dev, PTR_ERR(coil->vana), + "could not get regulator for vana\n"); coil->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_LOW); - if (IS_ERR(coil->enable_gpio)) { - ret = PTR_ERR(coil->enable_gpio); - if (ret != -EPROBE_DEFER) - dev_err(&client->dev, "could not get enable gpio\n"); - return ret; - } + if (IS_ERR(coil->enable_gpio)) + return dev_err_probe(&client->dev, PTR_ERR(coil->enable_gpio), + "could not get enable gpio\n"); mutex_init(&coil->power_lock); diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index a00761b1e18c..9219f3c9594b 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -2060,9 +2060,8 @@ static int imx274_probe(struct i2c_client *client) imx274->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(imx274->reset_gpio)) { - if (PTR_ERR(imx274->reset_gpio) != -EPROBE_DEFER) - dev_err(dev, "Reset GPIO not setup in DT"); - ret = PTR_ERR(imx274->reset_gpio); + ret = dev_err_probe(dev, PTR_ERR(imx274->reset_gpio), + "Reset GPIO not setup in DT\n"); goto err_me; } diff --git a/drivers/media/i2c/isl7998x.c b/drivers/media/i2c/isl7998x.c index 20f548a8a054..ae7af2cc94f5 100644 --- a/drivers/media/i2c/isl7998x.c +++ b/drivers/media/i2c/isl7998x.c @@ -665,7 +665,7 @@ static int isl7998x_set_standard(struct isl7998x *isl7998x, v4l2_std_id norm) static int isl7998x_init(struct isl7998x *isl7998x) { const unsigned int lanes = isl7998x->nr_mipi_lanes; - const u32 isl7998x_video_in_chan_map[] = { 0x00, 0x11, 0x02, 0x02 }; + static const u32 isl7998x_video_in_chan_map[] = { 0x00, 0x11, 0x02, 0x02 }; const struct reg_sequence isl7998x_init_seq_custom[] = { { ISL7998X_REG_P0_VIDEO_IN_CHAN_CTL, isl7998x_video_in_chan_map[isl7998x->nr_inputs - 1] }, diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index d96ba58ce1e5..59b03b0860d5 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -10,12 +10,11 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/firmware.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/media.h> #include <linux/module.h> -#include <linux/of_gpio.h> #include <linux/of_graph.h> #include <linux/regulator/consumer.h> #include <linux/sizes.h> @@ -1347,24 +1346,6 @@ static int s5c73m3_oif_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) return 0; } -static int s5c73m3_gpio_set_value(struct s5c73m3 *priv, int id, u32 val) -{ - if (!gpio_is_valid(priv->gpio[id].gpio)) - return 0; - gpio_set_value(priv->gpio[id].gpio, !!val); - return 1; -} - -static int s5c73m3_gpio_assert(struct s5c73m3 *priv, int id) -{ - return s5c73m3_gpio_set_value(priv, id, priv->gpio[id].level); -} - -static int s5c73m3_gpio_deassert(struct s5c73m3 *priv, int id) -{ - return s5c73m3_gpio_set_value(priv, id, !priv->gpio[id].level); -} - static int __s5c73m3_power_on(struct s5c73m3 *state) { int i, ret; @@ -1386,10 +1367,9 @@ static int __s5c73m3_power_on(struct s5c73m3 *state) v4l2_dbg(1, s5c73m3_dbg, &state->oif_sd, "clock frequency: %ld\n", clk_get_rate(state->clock)); - s5c73m3_gpio_deassert(state, STBY); + gpiod_set_value(state->stby, 0); usleep_range(100, 200); - - s5c73m3_gpio_deassert(state, RSET); + gpiod_set_value(state->reset, 0); usleep_range(50, 100); return 0; @@ -1404,11 +1384,10 @@ static int __s5c73m3_power_off(struct s5c73m3 *state) { int i, ret; - if (s5c73m3_gpio_assert(state, RSET)) - usleep_range(10, 50); - - if (s5c73m3_gpio_assert(state, STBY)) - usleep_range(100, 200); + gpiod_set_value(state->reset, 1); + usleep_range(10, 50); + gpiod_set_value(state->stby, 1); + usleep_range(100, 200); clk_disable_unprepare(state->clock); @@ -1543,58 +1522,10 @@ static const struct v4l2_subdev_ops oif_subdev_ops = { .video = &s5c73m3_oif_video_ops, }; -static int s5c73m3_configure_gpios(struct s5c73m3 *state) -{ - static const char * const gpio_names[] = { - "S5C73M3_STBY", "S5C73M3_RST" - }; - struct i2c_client *c = state->i2c_client; - struct s5c73m3_gpio *g = state->gpio; - int ret, i; - - for (i = 0; i < GPIO_NUM; ++i) { - unsigned int flags = GPIOF_DIR_OUT; - if (g[i].level) - flags |= GPIOF_INIT_HIGH; - ret = devm_gpio_request_one(&c->dev, g[i].gpio, flags, - gpio_names[i]); - if (ret) { - v4l2_err(c, "failed to request gpio %s\n", - gpio_names[i]); - return ret; - } - } - return 0; -} - -static int s5c73m3_parse_gpios(struct s5c73m3 *state) -{ - static const char * const prop_names[] = { - "standby-gpios", "xshutdown-gpios", - }; - struct device *dev = &state->i2c_client->dev; - struct device_node *node = dev->of_node; - int ret, i; - - for (i = 0; i < GPIO_NUM; ++i) { - enum of_gpio_flags of_flags; - - ret = of_get_named_gpio_flags(node, prop_names[i], - 0, &of_flags); - if (ret < 0) { - dev_err(dev, "failed to parse %s DT property\n", - prop_names[i]); - return -EINVAL; - } - state->gpio[i].gpio = ret; - state->gpio[i].level = !(of_flags & OF_GPIO_ACTIVE_LOW); - } - return 0; -} - static int s5c73m3_get_platform_data(struct s5c73m3 *state) { - struct device *dev = &state->i2c_client->dev; + struct i2c_client *c = state->i2c_client; + struct device *dev = &c->dev; const struct s5c73m3_platform_data *pdata = dev->platform_data; struct device_node *node = dev->of_node; struct device_node *node_ep; @@ -1608,8 +1539,6 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state) } state->mclk_frequency = pdata->mclk_frequency; - state->gpio[STBY] = pdata->gpio_stby; - state->gpio[RSET] = pdata->gpio_reset; return 0; } @@ -1624,9 +1553,17 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state) state->mclk_frequency); } - ret = s5c73m3_parse_gpios(state); - if (ret < 0) - return -EINVAL; + /* Request GPIO lines asserted */ + state->stby = devm_gpiod_get(dev, "standby", GPIOD_OUT_HIGH); + if (IS_ERR(state->stby)) + return dev_err_probe(dev, PTR_ERR(state->stby), + "failed to request gpio S5C73M3_STBY\n"); + gpiod_set_consumer_name(state->stby, "S5C73M3_STBY"); + state->reset = devm_gpiod_get(dev, "xshutdown", GPIOD_OUT_HIGH); + if (IS_ERR(state->reset)) + return dev_err_probe(dev, PTR_ERR(state->reset), + "failed to request gpio S5C73M3_RST\n"); + gpiod_set_consumer_name(state->reset, "S5C73M3_RST"); node_ep = of_graph_get_next_endpoint(node, NULL); if (!node_ep) { @@ -1708,10 +1645,6 @@ static int s5c73m3_probe(struct i2c_client *client) if (ret < 0) return ret; - ret = s5c73m3_configure_gpios(state); - if (ret) - goto out_err; - for (i = 0; i < S5C73M3_MAX_SUPPLIES; i++) state->supplies[i].supply = s5c73m3_supply_names[i]; diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c b/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c index 141ad0ba7f5a..e3543ae384ed 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c @@ -10,7 +10,6 @@ #include <linux/sizes.h> #include <linux/delay.h> #include <linux/firmware.h> -#include <linux/gpio.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/media.h> diff --git a/drivers/media/i2c/s5c73m3/s5c73m3.h b/drivers/media/i2c/s5c73m3/s5c73m3.h index c3fcfdd3ea66..1fc7df41c5ee 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3.h +++ b/drivers/media/i2c/s5c73m3/s5c73m3.h @@ -12,6 +12,7 @@ #include <linux/clk.h> #include <linux/kernel.h> #include <linux/regulator/consumer.h> +#include <linux/gpio/consumer.h> #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-subdev.h> @@ -351,12 +352,6 @@ struct s5c73m3_ctrls { struct v4l2_ctrl *scene_mode; }; -enum s5c73m3_gpio_id { - STBY, - RSET, - GPIO_NUM, -}; - enum s5c73m3_resolution_types { RES_ISP, RES_JPEG, @@ -383,7 +378,8 @@ struct s5c73m3 { u32 i2c_read_address; struct regulator_bulk_data supplies[S5C73M3_MAX_SUPPLIES]; - struct s5c73m3_gpio gpio[GPIO_NUM]; + struct gpio_desc *stby; + struct gpio_desc *reset; struct clk *clock; diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c deleted file mode 100644 index f266e848f52b..000000000000 --- a/drivers/media/i2c/s5k4ecgx.c +++ /dev/null @@ -1,1031 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Driver for Samsung S5K4ECGX 1/4" 5Mp CMOS Image Sensor SoC - * with an Embedded Image Signal Processor. - * - * Copyright (C) 2012, Linaro, Sangwook Lee <sangwook.lee@linaro.org> - * Copyright (C) 2012, Insignal Co,. Ltd, Homin Lee <suapapa@insignal.co.kr> - * - * Based on s5k6aa and noon010pc30 driver - * Copyright (C) 2011, Samsung Electronics Co., Ltd. - */ - -#include <linux/clk.h> -#include <linux/crc32.h> -#include <linux/ctype.h> -#include <linux/delay.h> -#include <linux/firmware.h> -#include <linux/gpio.h> -#include <linux/i2c.h> -#include <linux/module.h> -#include <linux/regulator/consumer.h> -#include <linux/slab.h> -#include <asm/unaligned.h> - -#include <media/media-entity.h> -#include <media/i2c/s5k4ecgx.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-device.h> -#include <media/v4l2-mediabus.h> -#include <media/v4l2-subdev.h> - -static int debug; -module_param(debug, int, 0644); - -#define S5K4ECGX_DRIVER_NAME "s5k4ecgx" -#define S5K4ECGX_FIRMWARE "s5k4ecgx.bin" - -/* Firmware revision information */ -#define REG_FW_REVISION 0x700001a6 -#define REG_FW_VERSION 0x700001a4 -#define S5K4ECGX_REVISION_1_1 0x11 -#define S5K4ECGX_FW_VERSION 0x4ec0 - -/* General purpose parameters */ -#define REG_USER_BRIGHTNESS 0x7000022c -#define REG_USER_CONTRAST 0x7000022e -#define REG_USER_SATURATION 0x70000230 - -#define REG_G_ENABLE_PREV 0x7000023e -#define REG_G_ENABLE_PREV_CHG 0x70000240 -#define REG_G_NEW_CFG_SYNC 0x7000024a -#define REG_G_PREV_IN_WIDTH 0x70000250 -#define REG_G_PREV_IN_HEIGHT 0x70000252 -#define REG_G_PREV_IN_XOFFS 0x70000254 -#define REG_G_PREV_IN_YOFFS 0x70000256 -#define REG_G_CAP_IN_WIDTH 0x70000258 -#define REG_G_CAP_IN_HEIGHT 0x7000025a -#define REG_G_CAP_IN_XOFFS 0x7000025c -#define REG_G_CAP_IN_YOFFS 0x7000025e -#define REG_G_INPUTS_CHANGE_REQ 0x70000262 -#define REG_G_ACTIVE_PREV_CFG 0x70000266 -#define REG_G_PREV_CFG_CHG 0x70000268 -#define REG_G_PREV_OPEN_AFTER_CH 0x7000026a - -/* Preview context register sets. n = 0...4. */ -#define PREG(n, x) ((n) * 0x30 + (x)) -#define REG_P_OUT_WIDTH(n) PREG(n, 0x700002a6) -#define REG_P_OUT_HEIGHT(n) PREG(n, 0x700002a8) -#define REG_P_FMT(n) PREG(n, 0x700002aa) -#define REG_P_PVI_MASK(n) PREG(n, 0x700002b4) -#define REG_P_FR_TIME_TYPE(n) PREG(n, 0x700002be) -#define FR_TIME_DYNAMIC 0 -#define FR_TIME_FIXED 1 -#define FR_TIME_FIXED_ACCURATE 2 -#define REG_P_FR_TIME_Q_TYPE(n) PREG(n, 0x700002c0) -#define FR_TIME_Q_DYNAMIC 0 -#define FR_TIME_Q_BEST_FRRATE 1 -#define FR_TIME_Q_BEST_QUALITY 2 - -/* Frame period in 0.1 ms units */ -#define REG_P_MAX_FR_TIME(n) PREG(n, 0x700002c2) -#define REG_P_MIN_FR_TIME(n) PREG(n, 0x700002c4) -#define US_TO_FR_TIME(__t) ((__t) / 100) -#define REG_P_PREV_MIRROR(n) PREG(n, 0x700002d0) -#define REG_P_CAP_MIRROR(n) PREG(n, 0x700002d2) - -#define REG_G_PREVZOOM_IN_WIDTH 0x70000494 -#define REG_G_PREVZOOM_IN_HEIGHT 0x70000496 -#define REG_G_PREVZOOM_IN_XOFFS 0x70000498 -#define REG_G_PREVZOOM_IN_YOFFS 0x7000049a -#define REG_G_CAPZOOM_IN_WIDTH 0x7000049c -#define REG_G_CAPZOOM_IN_HEIGHT 0x7000049e -#define REG_G_CAPZOOM_IN_XOFFS 0x700004a0 -#define REG_G_CAPZOOM_IN_YOFFS 0x700004a2 - -/* n = 0...4 */ -#define REG_USER_SHARPNESS(n) (0x70000a28 + (n) * 0xb6) - -/* Reduce sharpness range for user space API */ -#define SHARPNESS_DIV 8208 -#define TOK_TERM 0xffffffff - -/* - * FIXME: This is copied from s5k6aa, because of no information - * in the S5K4ECGX datasheet. - * H/W register Interface (0xd0000000 - 0xd0000fff) - */ -#define AHB_MSB_ADDR_PTR 0xfcfc -#define GEN_REG_OFFSH 0xd000 -#define REG_CMDWR_ADDRH 0x0028 -#define REG_CMDWR_ADDRL 0x002a -#define REG_CMDRD_ADDRH 0x002c -#define REG_CMDRD_ADDRL 0x002e -#define REG_CMDBUF0_ADDR 0x0f12 - -struct s5k4ecgx_frmsize { - struct v4l2_frmsize_discrete size; - /* Fixed sensor matrix crop rectangle */ - struct v4l2_rect input_window; -}; - -struct regval_list { - u32 addr; - u16 val; -}; - -/* - * TODO: currently only preview is supported and snapshot (capture) - * is not implemented yet - */ -static const struct s5k4ecgx_frmsize s5k4ecgx_prev_sizes[] = { - { - .size = { 176, 144 }, - .input_window = { 0x00, 0x00, 0x928, 0x780 }, - }, { - .size = { 352, 288 }, - .input_window = { 0x00, 0x00, 0x928, 0x780 }, - }, { - .size = { 640, 480 }, - .input_window = { 0x00, 0x00, 0xa00, 0x780 }, - }, { - .size = { 720, 480 }, - .input_window = { 0x00, 0x00, 0xa00, 0x6a8 }, - } -}; - -#define S5K4ECGX_NUM_PREV ARRAY_SIZE(s5k4ecgx_prev_sizes) - -struct s5k4ecgx_pixfmt { - u32 code; - u32 colorspace; - /* REG_TC_PCFG_Format register value */ - u16 reg_p_format; -}; - -/* By default value, output from sensor will be YUV422 0-255 */ -static const struct s5k4ecgx_pixfmt s5k4ecgx_formats[] = { - { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 5 }, -}; - -static const char * const s5k4ecgx_supply_names[] = { - /* - * Usually 2.8V is used for analog power (vdda) - * and digital IO (vddio, vdddcore) - */ - "vdda", - "vddio", - "vddcore", - "vddreg", /* The internal s5k4ecgx regulator's supply (1.8V) */ -}; - -#define S5K4ECGX_NUM_SUPPLIES ARRAY_SIZE(s5k4ecgx_supply_names) - -enum s5k4ecgx_gpio_id { - STBY, - RSET, - GPIO_NUM, -}; - -struct s5k4ecgx { - struct v4l2_subdev sd; - struct media_pad pad; - struct v4l2_ctrl_handler handler; - - struct s5k4ecgx_platform_data *pdata; - const struct s5k4ecgx_pixfmt *curr_pixfmt; - const struct s5k4ecgx_frmsize *curr_frmsize; - struct mutex lock; - u8 streaming; - u8 set_params; - - struct regulator_bulk_data supplies[S5K4ECGX_NUM_SUPPLIES]; - struct s5k4ecgx_gpio gpio[GPIO_NUM]; -}; - -static inline struct s5k4ecgx *to_s5k4ecgx(struct v4l2_subdev *sd) -{ - return container_of(sd, struct s5k4ecgx, sd); -} - -static int s5k4ecgx_i2c_read(struct i2c_client *client, u16 addr, u16 *val) -{ - u8 wbuf[2] = { addr >> 8, addr & 0xff }; - struct i2c_msg msg[2]; - u8 rbuf[2]; - int ret; - - msg[0].addr = client->addr; - msg[0].flags = 0; - msg[0].len = 2; - msg[0].buf = wbuf; - - msg[1].addr = client->addr; - msg[1].flags = I2C_M_RD; - msg[1].len = 2; - msg[1].buf = rbuf; - - ret = i2c_transfer(client->adapter, msg, 2); - *val = be16_to_cpu(*((__be16 *)rbuf)); - - v4l2_dbg(4, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val); - - return ret == 2 ? 0 : ret; -} - -static int s5k4ecgx_i2c_write(struct i2c_client *client, u16 addr, u16 val) -{ - u8 buf[4] = { addr >> 8, addr & 0xff, val >> 8, val & 0xff }; - - int ret = i2c_master_send(client, buf, 4); - v4l2_dbg(4, debug, client, "i2c_write: 0x%04x : 0x%04x\n", addr, val); - - return ret == 4 ? 0 : ret; -} - -static int s5k4ecgx_write(struct i2c_client *client, u32 addr, u16 val) -{ - u16 high = addr >> 16, low = addr & 0xffff; - int ret; - - v4l2_dbg(3, debug, client, "write: 0x%08x : 0x%04x\n", addr, val); - - ret = s5k4ecgx_i2c_write(client, REG_CMDWR_ADDRH, high); - if (!ret) - ret = s5k4ecgx_i2c_write(client, REG_CMDWR_ADDRL, low); - if (!ret) - ret = s5k4ecgx_i2c_write(client, REG_CMDBUF0_ADDR, val); - - return ret; -} - -static int s5k4ecgx_read(struct i2c_client *client, u32 addr, u16 *val) -{ - u16 high = addr >> 16, low = addr & 0xffff; - int ret; - - ret = s5k4ecgx_i2c_write(client, REG_CMDRD_ADDRH, high); - if (!ret) - ret = s5k4ecgx_i2c_write(client, REG_CMDRD_ADDRL, low); - if (!ret) - ret = s5k4ecgx_i2c_read(client, REG_CMDBUF0_ADDR, val); - - return ret; -} - -static int s5k4ecgx_read_fw_ver(struct v4l2_subdev *sd) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - u16 hw_rev, fw_ver = 0; - int ret; - - ret = s5k4ecgx_read(client, REG_FW_VERSION, &fw_ver); - if (ret < 0 || fw_ver != S5K4ECGX_FW_VERSION) { - v4l2_err(sd, "FW version check failed!\n"); - return -ENODEV; - } - - ret = s5k4ecgx_read(client, REG_FW_REVISION, &hw_rev); - if (ret < 0) - return ret; - - v4l2_info(sd, "chip found FW ver: 0x%x, HW rev: 0x%x\n", - fw_ver, hw_rev); - return 0; -} - -static int s5k4ecgx_set_ahb_address(struct v4l2_subdev *sd) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - int ret; - - /* Set APB peripherals start address */ - ret = s5k4ecgx_i2c_write(client, AHB_MSB_ADDR_PTR, GEN_REG_OFFSH); - if (ret < 0) - return ret; - /* - * FIXME: This is copied from s5k6aa, because of no information - * in s5k4ecgx's datasheet. - * sw_reset is activated to put device into idle status - */ - ret = s5k4ecgx_i2c_write(client, 0x0010, 0x0001); - if (ret < 0) - return ret; - - ret = s5k4ecgx_i2c_write(client, 0x1030, 0x0000); - if (ret < 0) - return ret; - /* Halt ARM CPU */ - return s5k4ecgx_i2c_write(client, 0x0014, 0x0001); -} - -#define FW_CRC_SIZE 4 -/* Register address, value are 4, 2 bytes */ -#define FW_RECORD_SIZE 6 -/* - * The firmware has following format: - * < total number of records (4 bytes + 2 bytes padding) N >, - * < record 0 >, ..., < record N - 1 >, < CRC32-CCITT (4-bytes) >, - * where "record" is a 4-byte register address followed by 2-byte - * register value (little endian). - * The firmware generator can be found in following git repository: - * git://git.linaro.org/people/sangwook/fimc-v4l2-app.git - */ -static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - const struct firmware *fw; - const u8 *ptr; - int err, i, regs_num; - u32 addr, crc, crc_file, addr_inc = 0; - u16 val; - - err = request_firmware(&fw, S5K4ECGX_FIRMWARE, sd->v4l2_dev->dev); - if (err) { - v4l2_err(sd, "Failed to read firmware %s\n", S5K4ECGX_FIRMWARE); - return err; - } - regs_num = get_unaligned_le32(fw->data); - - v4l2_dbg(3, debug, sd, "FW: %s size %zu register sets %d\n", - S5K4ECGX_FIRMWARE, fw->size, regs_num); - - regs_num++; /* Add header */ - if (fw->size != regs_num * FW_RECORD_SIZE + FW_CRC_SIZE) { - err = -EINVAL; - goto fw_out; - } - crc_file = get_unaligned_le32(fw->data + regs_num * FW_RECORD_SIZE); - crc = crc32_le(~0, fw->data, regs_num * FW_RECORD_SIZE); - if (crc != crc_file) { - v4l2_err(sd, "FW: invalid crc (%#x:%#x)\n", crc, crc_file); - err = -EINVAL; - goto fw_out; - } - ptr = fw->data + FW_RECORD_SIZE; - for (i = 1; i < regs_num; i++) { - addr = get_unaligned_le32(ptr); - ptr += sizeof(u32); - val = get_unaligned_le16(ptr); - ptr += sizeof(u16); - if (addr - addr_inc != 2) - err = s5k4ecgx_write(client, addr, val); - else - err = s5k4ecgx_i2c_write(client, REG_CMDBUF0_ADDR, val); - if (err) - break; - addr_inc = addr; - } -fw_out: - release_firmware(fw); - return err; -} - -/* Set preview and capture input window */ -static int s5k4ecgx_set_input_window(struct i2c_client *c, - const struct v4l2_rect *r) -{ - int ret; - - ret = s5k4ecgx_write(c, REG_G_PREV_IN_WIDTH, r->width); - if (!ret) - ret = s5k4ecgx_write(c, REG_G_PREV_IN_HEIGHT, r->height); - if (!ret) - ret = s5k4ecgx_write(c, REG_G_PREV_IN_XOFFS, r->left); - if (!ret) - ret = s5k4ecgx_write(c, REG_G_PREV_IN_YOFFS, r->top); - if (!ret) - ret = s5k4ecgx_write(c, REG_G_CAP_IN_WIDTH, r->width); - if (!ret) - ret = s5k4ecgx_write(c, REG_G_CAP_IN_HEIGHT, r->height); - if (!ret) - ret = s5k4ecgx_write(c, REG_G_CAP_IN_XOFFS, r->left); - if (!ret) - ret = s5k4ecgx_write(c, REG_G_CAP_IN_YOFFS, r->top); - - return ret; -} - -/* Set preview and capture zoom input window */ -static int s5k4ecgx_set_zoom_window(struct i2c_client *c, - const struct v4l2_rect *r) -{ - int ret; - - ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_WIDTH, r->width); - if (!ret) - ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_HEIGHT, r->height); - if (!ret) - ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_XOFFS, r->left); - if (!ret) - ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_YOFFS, r->top); - if (!ret) - ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_WIDTH, r->width); - if (!ret) - ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_HEIGHT, r->height); - if (!ret) - ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_XOFFS, r->left); - if (!ret) - ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_YOFFS, r->top); - - return ret; -} - -static int s5k4ecgx_set_output_framefmt(struct s5k4ecgx *priv) -{ - struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); - int ret; - - ret = s5k4ecgx_write(client, REG_P_OUT_WIDTH(0), - priv->curr_frmsize->size.width); - if (!ret) - ret = s5k4ecgx_write(client, REG_P_OUT_HEIGHT(0), - priv->curr_frmsize->size.height); - if (!ret) - ret = s5k4ecgx_write(client, REG_P_FMT(0), - priv->curr_pixfmt->reg_p_format); - return ret; -} - -static int s5k4ecgx_init_sensor(struct v4l2_subdev *sd) -{ - int ret; - - ret = s5k4ecgx_set_ahb_address(sd); - - /* The delay is from manufacturer's settings */ - msleep(100); - - if (!ret) - ret = s5k4ecgx_load_firmware(sd); - if (ret) - v4l2_err(sd, "Failed to write initial settings\n"); - - return ret; -} - -static int s5k4ecgx_gpio_set_value(struct s5k4ecgx *priv, int id, u32 val) -{ - if (!gpio_is_valid(priv->gpio[id].gpio)) - return 0; - gpio_set_value(priv->gpio[id].gpio, val); - - return 1; -} - -static int __s5k4ecgx_power_on(struct s5k4ecgx *priv) -{ - int ret; - - ret = regulator_bulk_enable(S5K4ECGX_NUM_SUPPLIES, priv->supplies); - if (ret) - return ret; - usleep_range(30, 50); - - /* The polarity of STBY is controlled by TSP */ - if (s5k4ecgx_gpio_set_value(priv, STBY, priv->gpio[STBY].level)) - usleep_range(30, 50); - - if (s5k4ecgx_gpio_set_value(priv, RSET, priv->gpio[RSET].level)) - usleep_range(30, 50); - - return 0; -} - -static int __s5k4ecgx_power_off(struct s5k4ecgx *priv) -{ - if (s5k4ecgx_gpio_set_value(priv, RSET, !priv->gpio[RSET].level)) - usleep_range(30, 50); - - if (s5k4ecgx_gpio_set_value(priv, STBY, !priv->gpio[STBY].level)) - usleep_range(30, 50); - - priv->streaming = 0; - - return regulator_bulk_disable(S5K4ECGX_NUM_SUPPLIES, priv->supplies); -} - -/* Find nearest matching image pixel size. */ -static int s5k4ecgx_try_frame_size(struct v4l2_mbus_framefmt *mf, - const struct s5k4ecgx_frmsize **size) -{ - unsigned int min_err = ~0; - int i = ARRAY_SIZE(s5k4ecgx_prev_sizes); - const struct s5k4ecgx_frmsize *fsize = &s5k4ecgx_prev_sizes[0], - *match = NULL; - - while (i--) { - int err = abs(fsize->size.width - mf->width) - + abs(fsize->size.height - mf->height); - if (err < min_err) { - min_err = err; - match = fsize; - } - fsize++; - } - if (match) { - mf->width = match->size.width; - mf->height = match->size.height; - if (size) - *size = match; - return 0; - } - - return -EINVAL; -} - -static int s5k4ecgx_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_mbus_code_enum *code) -{ - if (code->index >= ARRAY_SIZE(s5k4ecgx_formats)) - return -EINVAL; - code->code = s5k4ecgx_formats[code->index].code; - - return 0; -} - -static int s5k4ecgx_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct s5k4ecgx *priv = to_s5k4ecgx(sd); - struct v4l2_mbus_framefmt *mf; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - if (sd_state) { - mf = v4l2_subdev_get_try_format(sd, sd_state, 0); - fmt->format = *mf; - } - return 0; - } - - mf = &fmt->format; - - mutex_lock(&priv->lock); - mf->width = priv->curr_frmsize->size.width; - mf->height = priv->curr_frmsize->size.height; - mf->code = priv->curr_pixfmt->code; - mf->colorspace = priv->curr_pixfmt->colorspace; - mf->field = V4L2_FIELD_NONE; - mutex_unlock(&priv->lock); - - return 0; -} - -static const struct s5k4ecgx_pixfmt *s5k4ecgx_try_fmt(struct v4l2_subdev *sd, - struct v4l2_mbus_framefmt *mf) -{ - int i = ARRAY_SIZE(s5k4ecgx_formats); - - while (--i) - if (mf->code == s5k4ecgx_formats[i].code) - break; - mf->code = s5k4ecgx_formats[i].code; - - return &s5k4ecgx_formats[i]; -} - -static int s5k4ecgx_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct s5k4ecgx *priv = to_s5k4ecgx(sd); - const struct s5k4ecgx_frmsize *fsize = NULL; - const struct s5k4ecgx_pixfmt *pf; - struct v4l2_mbus_framefmt *mf; - int ret = 0; - - pf = s5k4ecgx_try_fmt(sd, &fmt->format); - s5k4ecgx_try_frame_size(&fmt->format, &fsize); - fmt->format.colorspace = V4L2_COLORSPACE_JPEG; - fmt->format.field = V4L2_FIELD_NONE; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - if (sd_state) { - mf = v4l2_subdev_get_try_format(sd, sd_state, 0); - *mf = fmt->format; - } - return 0; - } - - mutex_lock(&priv->lock); - if (!priv->streaming) { - priv->curr_frmsize = fsize; - priv->curr_pixfmt = pf; - priv->set_params = 1; - } else { - ret = -EBUSY; - } - mutex_unlock(&priv->lock); - - return ret; -} - -static const struct v4l2_subdev_pad_ops s5k4ecgx_pad_ops = { - .enum_mbus_code = s5k4ecgx_enum_mbus_code, - .get_fmt = s5k4ecgx_get_fmt, - .set_fmt = s5k4ecgx_set_fmt, -}; - -/* - * V4L2 subdev controls - */ -static int s5k4ecgx_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct v4l2_subdev *sd = &container_of(ctrl->handler, struct s5k4ecgx, - handler)->sd; - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct s5k4ecgx *priv = to_s5k4ecgx(sd); - unsigned int i; - int err = 0; - - v4l2_dbg(1, debug, sd, "ctrl: 0x%x, value: %d\n", ctrl->id, ctrl->val); - - mutex_lock(&priv->lock); - switch (ctrl->id) { - case V4L2_CID_CONTRAST: - err = s5k4ecgx_write(client, REG_USER_CONTRAST, ctrl->val); - break; - - case V4L2_CID_SATURATION: - err = s5k4ecgx_write(client, REG_USER_SATURATION, ctrl->val); - break; - - case V4L2_CID_SHARPNESS: - /* TODO: Revisit, is this setting for all presets ? */ - for (i = 0; i < 4 && !err; i++) - err = s5k4ecgx_write(client, REG_USER_SHARPNESS(i), - ctrl->val * SHARPNESS_DIV); - break; - - case V4L2_CID_BRIGHTNESS: - err = s5k4ecgx_write(client, REG_USER_BRIGHTNESS, ctrl->val); - break; - } - mutex_unlock(&priv->lock); - if (err < 0) - v4l2_err(sd, "Failed to write s_ctrl err %d\n", err); - - return err; -} - -static const struct v4l2_ctrl_ops s5k4ecgx_ctrl_ops = { - .s_ctrl = s5k4ecgx_s_ctrl, -}; - -/* - * Reading s5k4ecgx version information - */ -static int s5k4ecgx_registered(struct v4l2_subdev *sd) -{ - int ret; - struct s5k4ecgx *priv = to_s5k4ecgx(sd); - - mutex_lock(&priv->lock); - ret = __s5k4ecgx_power_on(priv); - if (!ret) { - ret = s5k4ecgx_read_fw_ver(sd); - __s5k4ecgx_power_off(priv); - } - mutex_unlock(&priv->lock); - - return ret; -} - -/* - * V4L2 subdev internal operations - */ -static int s5k4ecgx_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(sd, - fh->state, - 0); - - mf->width = s5k4ecgx_prev_sizes[0].size.width; - mf->height = s5k4ecgx_prev_sizes[0].size.height; - mf->code = s5k4ecgx_formats[0].code; - mf->colorspace = V4L2_COLORSPACE_JPEG; - mf->field = V4L2_FIELD_NONE; - - return 0; -} - -static const struct v4l2_subdev_internal_ops s5k4ecgx_subdev_internal_ops = { - .registered = s5k4ecgx_registered, - .open = s5k4ecgx_open, -}; - -static int s5k4ecgx_s_power(struct v4l2_subdev *sd, int on) -{ - struct s5k4ecgx *priv = to_s5k4ecgx(sd); - int ret; - - v4l2_dbg(1, debug, sd, "Switching %s\n", on ? "on" : "off"); - - if (on) { - ret = __s5k4ecgx_power_on(priv); - if (ret < 0) - return ret; - /* Time to stabilize sensor */ - msleep(100); - ret = s5k4ecgx_init_sensor(sd); - if (ret < 0) - __s5k4ecgx_power_off(priv); - else - priv->set_params = 1; - } else { - ret = __s5k4ecgx_power_off(priv); - } - - return ret; -} - -static int s5k4ecgx_log_status(struct v4l2_subdev *sd) -{ - v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name); - - return 0; -} - -static const struct v4l2_subdev_core_ops s5k4ecgx_core_ops = { - .s_power = s5k4ecgx_s_power, - .log_status = s5k4ecgx_log_status, -}; - -static int __s5k4ecgx_s_params(struct s5k4ecgx *priv) -{ - struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); - const struct v4l2_rect *crop_rect = &priv->curr_frmsize->input_window; - int ret; - - ret = s5k4ecgx_set_input_window(client, crop_rect); - if (!ret) - ret = s5k4ecgx_set_zoom_window(client, crop_rect); - if (!ret) - ret = s5k4ecgx_write(client, REG_G_INPUTS_CHANGE_REQ, 1); - if (!ret) - ret = s5k4ecgx_write(client, 0x70000a1e, 0x28); - if (!ret) - ret = s5k4ecgx_write(client, 0x70000ad4, 0x3c); - if (!ret) - ret = s5k4ecgx_set_output_framefmt(priv); - if (!ret) - ret = s5k4ecgx_write(client, REG_P_PVI_MASK(0), 0x52); - if (!ret) - ret = s5k4ecgx_write(client, REG_P_FR_TIME_TYPE(0), - FR_TIME_DYNAMIC); - if (!ret) - ret = s5k4ecgx_write(client, REG_P_FR_TIME_Q_TYPE(0), - FR_TIME_Q_BEST_FRRATE); - if (!ret) - ret = s5k4ecgx_write(client, REG_P_MIN_FR_TIME(0), - US_TO_FR_TIME(33300)); - if (!ret) - ret = s5k4ecgx_write(client, REG_P_MAX_FR_TIME(0), - US_TO_FR_TIME(66600)); - if (!ret) - ret = s5k4ecgx_write(client, REG_P_PREV_MIRROR(0), 0); - if (!ret) - ret = s5k4ecgx_write(client, REG_P_CAP_MIRROR(0), 0); - if (!ret) - ret = s5k4ecgx_write(client, REG_G_ACTIVE_PREV_CFG, 0); - if (!ret) - ret = s5k4ecgx_write(client, REG_G_PREV_OPEN_AFTER_CH, 1); - if (!ret) - ret = s5k4ecgx_write(client, REG_G_NEW_CFG_SYNC, 1); - if (!ret) - ret = s5k4ecgx_write(client, REG_G_PREV_CFG_CHG, 1); - - return ret; -} - -static int __s5k4ecgx_s_stream(struct s5k4ecgx *priv, int on) -{ - struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); - int ret; - - if (on && priv->set_params) { - ret = __s5k4ecgx_s_params(priv); - if (ret < 0) - return ret; - priv->set_params = 0; - } - /* - * This enables/disables preview stream only. Capture requests - * are not supported yet. - */ - ret = s5k4ecgx_write(client, REG_G_ENABLE_PREV, on); - if (ret < 0) - return ret; - return s5k4ecgx_write(client, REG_G_ENABLE_PREV_CHG, 1); -} - -static int s5k4ecgx_s_stream(struct v4l2_subdev *sd, int on) -{ - struct s5k4ecgx *priv = to_s5k4ecgx(sd); - int ret = 0; - - v4l2_dbg(1, debug, sd, "Turn streaming %s\n", on ? "on" : "off"); - - mutex_lock(&priv->lock); - - if (priv->streaming == !on) { - ret = __s5k4ecgx_s_stream(priv, on); - if (!ret) - priv->streaming = on & 1; - } - - mutex_unlock(&priv->lock); - return ret; -} - -static const struct v4l2_subdev_video_ops s5k4ecgx_video_ops = { - .s_stream = s5k4ecgx_s_stream, -}; - -static const struct v4l2_subdev_ops s5k4ecgx_ops = { - .core = &s5k4ecgx_core_ops, - .pad = &s5k4ecgx_pad_ops, - .video = &s5k4ecgx_video_ops, -}; - -/* - * GPIO setup - */ -static int s5k4ecgx_config_gpio(int nr, int val, const char *name) -{ - unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; - int ret; - - if (!gpio_is_valid(nr)) - return 0; - ret = gpio_request_one(nr, flags, name); - if (!ret) - gpio_export(nr, 0); - - return ret; -} - -static void s5k4ecgx_free_gpios(struct s5k4ecgx *priv) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(priv->gpio); i++) { - if (!gpio_is_valid(priv->gpio[i].gpio)) - continue; - gpio_free(priv->gpio[i].gpio); - priv->gpio[i].gpio = -EINVAL; - } -} - -static int s5k4ecgx_config_gpios(struct s5k4ecgx *priv, - const struct s5k4ecgx_platform_data *pdata) -{ - const struct s5k4ecgx_gpio *gpio = &pdata->gpio_stby; - int ret; - - priv->gpio[STBY].gpio = -EINVAL; - priv->gpio[RSET].gpio = -EINVAL; - - ret = s5k4ecgx_config_gpio(gpio->gpio, gpio->level, "S5K4ECGX_STBY"); - - if (ret) { - s5k4ecgx_free_gpios(priv); - return ret; - } - priv->gpio[STBY] = *gpio; - if (gpio_is_valid(gpio->gpio)) - gpio_set_value(gpio->gpio, 0); - - gpio = &pdata->gpio_reset; - - ret = s5k4ecgx_config_gpio(gpio->gpio, gpio->level, "S5K4ECGX_RST"); - if (ret) { - s5k4ecgx_free_gpios(priv); - return ret; - } - priv->gpio[RSET] = *gpio; - if (gpio_is_valid(gpio->gpio)) - gpio_set_value(gpio->gpio, 0); - - return 0; -} - -static int s5k4ecgx_init_v4l2_ctrls(struct s5k4ecgx *priv) -{ - const struct v4l2_ctrl_ops *ops = &s5k4ecgx_ctrl_ops; - struct v4l2_ctrl_handler *hdl = &priv->handler; - int ret; - - ret = v4l2_ctrl_handler_init(hdl, 4); - if (ret) - return ret; - - v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -208, 127, 1, 0); - v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -127, 127, 1, 0); - v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -127, 127, 1, 0); - - /* Sharpness default is 24612, and then (24612/SHARPNESS_DIV) = 2 */ - v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS, -32704/SHARPNESS_DIV, - 24612/SHARPNESS_DIV, 1, 2); - if (hdl->error) { - ret = hdl->error; - v4l2_ctrl_handler_free(hdl); - return ret; - } - priv->sd.ctrl_handler = hdl; - - return 0; -}; - -static int s5k4ecgx_probe(struct i2c_client *client) -{ - struct s5k4ecgx_platform_data *pdata = client->dev.platform_data; - struct v4l2_subdev *sd; - struct s5k4ecgx *priv; - int ret, i; - - if (pdata == NULL) { - dev_err(&client->dev, "platform data is missing!\n"); - return -EINVAL; - } - - priv = devm_kzalloc(&client->dev, sizeof(struct s5k4ecgx), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - mutex_init(&priv->lock); - priv->streaming = 0; - - sd = &priv->sd; - /* Registering subdev */ - v4l2_i2c_subdev_init(sd, client, &s5k4ecgx_ops); - /* Static name; NEVER use in new drivers! */ - strscpy(sd->name, S5K4ECGX_DRIVER_NAME, sizeof(sd->name)); - - sd->internal_ops = &s5k4ecgx_subdev_internal_ops; - /* Support v4l2 sub-device user space API */ - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - priv->pad.flags = MEDIA_PAD_FL_SOURCE; - sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; - ret = media_entity_pads_init(&sd->entity, 1, &priv->pad); - if (ret) - return ret; - - ret = s5k4ecgx_config_gpios(priv, pdata); - if (ret) { - dev_err(&client->dev, "Failed to set gpios\n"); - goto out_err1; - } - for (i = 0; i < S5K4ECGX_NUM_SUPPLIES; i++) - priv->supplies[i].supply = s5k4ecgx_supply_names[i]; - - ret = devm_regulator_bulk_get(&client->dev, S5K4ECGX_NUM_SUPPLIES, - priv->supplies); - if (ret) { - dev_err(&client->dev, "Failed to get regulators\n"); - goto out_err2; - } - ret = s5k4ecgx_init_v4l2_ctrls(priv); - if (ret) - goto out_err2; - - priv->curr_pixfmt = &s5k4ecgx_formats[0]; - priv->curr_frmsize = &s5k4ecgx_prev_sizes[0]; - - return 0; - -out_err2: - s5k4ecgx_free_gpios(priv); -out_err1: - media_entity_cleanup(&priv->sd.entity); - - return ret; -} - -static void s5k4ecgx_remove(struct i2c_client *client) -{ - struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct s5k4ecgx *priv = to_s5k4ecgx(sd); - - mutex_destroy(&priv->lock); - s5k4ecgx_free_gpios(priv); - v4l2_device_unregister_subdev(sd); - v4l2_ctrl_handler_free(&priv->handler); - media_entity_cleanup(&sd->entity); -} - -static const struct i2c_device_id s5k4ecgx_id[] = { - { S5K4ECGX_DRIVER_NAME, 0 }, - {} -}; -MODULE_DEVICE_TABLE(i2c, s5k4ecgx_id); - -static struct i2c_driver v4l2_i2c_driver = { - .driver = { - .name = S5K4ECGX_DRIVER_NAME, - }, - .probe_new = s5k4ecgx_probe, - .remove = s5k4ecgx_remove, - .id_table = s5k4ecgx_id, -}; - -module_i2c_driver(v4l2_i2c_driver); - -MODULE_DESCRIPTION("Samsung S5K4ECGX 5MP SOC camera"); -MODULE_AUTHOR("Sangwook Lee <sangwook.lee@linaro.org>"); -MODULE_AUTHOR("Seok-Young Jang <quartz.jang@samsung.com>"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(S5K4ECGX_FIRMWARE); diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index 5c2253ab3b6f..960fbf6428ea 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -13,11 +13,10 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/firmware.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/media.h> #include <linux/module.h> -#include <linux/of_gpio.h> #include <linux/of_graph.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> @@ -228,11 +227,6 @@ static const char * const s5k5baf_supply_names[] = { }; #define S5K5BAF_NUM_SUPPLIES ARRAY_SIZE(s5k5baf_supply_names) -struct s5k5baf_gpio { - int gpio; - int level; -}; - enum s5k5baf_gpio_id { STBY, RSET, @@ -284,7 +278,7 @@ struct s5k5baf_fw { }; struct s5k5baf { - struct s5k5baf_gpio gpios[NUM_GPIOS]; + struct gpio_desc *gpios[NUM_GPIOS]; enum v4l2_mbus_type bus_type; u8 nlanes; struct regulator_bulk_data supplies[S5K5BAF_NUM_SUPPLIES]; @@ -936,16 +930,12 @@ static void s5k5baf_hw_set_test_pattern(struct s5k5baf *state, int id) static void s5k5baf_gpio_assert(struct s5k5baf *state, int id) { - struct s5k5baf_gpio *gpio = &state->gpios[id]; - - gpio_set_value(gpio->gpio, gpio->level); + gpiod_set_value_cansleep(state->gpios[id], 1); } static void s5k5baf_gpio_deassert(struct s5k5baf *state, int id) { - struct s5k5baf_gpio *gpio = &state->gpios[id]; - - gpio_set_value(gpio->gpio, !gpio->level); + gpiod_set_value_cansleep(state->gpios[id], 0); } static int s5k5baf_power_on(struct s5k5baf *state) @@ -1799,44 +1789,30 @@ static const struct v4l2_subdev_ops s5k5baf_subdev_ops = { static int s5k5baf_configure_gpios(struct s5k5baf *state) { - static const char * const name[] = { "S5K5BAF_STBY", "S5K5BAF_RST" }; + static const char * const name[] = { "stbyn", "rstn" }; + static const char * const label[] = { "S5K5BAF_STBY", "S5K5BAF_RST" }; struct i2c_client *c = v4l2_get_subdevdata(&state->sd); - struct s5k5baf_gpio *g = state->gpios; + struct gpio_desc *gpio; int ret, i; for (i = 0; i < NUM_GPIOS; ++i) { - int flags = GPIOF_DIR_OUT; - if (g[i].level) - flags |= GPIOF_INIT_HIGH; - ret = devm_gpio_request_one(&c->dev, g[i].gpio, flags, name[i]); - if (ret < 0) { - v4l2_err(c, "failed to request gpio %s\n", name[i]); + gpio = devm_gpiod_get(&c->dev, name[i], GPIOD_OUT_HIGH); + ret = PTR_ERR_OR_ZERO(gpio); + if (ret) { + v4l2_err(c, "failed to request gpio %s: %d\n", + name[i], ret); return ret; } - } - return 0; -} - -static int s5k5baf_parse_gpios(struct s5k5baf_gpio *gpios, struct device *dev) -{ - static const char * const names[] = { - "stbyn-gpios", - "rstn-gpios", - }; - struct device_node *node = dev->of_node; - enum of_gpio_flags flags; - int ret, i; - for (i = 0; i < NUM_GPIOS; ++i) { - ret = of_get_named_gpio_flags(node, names[i], 0, &flags); - if (ret < 0) { - dev_err(dev, "no %s GPIO pin provided\n", names[i]); + ret = gpiod_set_consumer_name(gpio, label[i]); + if (ret) { + v4l2_err(c, "failed to set up name for gpio %s: %d\n", + name[i], ret); return ret; } - gpios[i].gpio = ret; - gpios[i].level = !(flags & OF_GPIO_ACTIVE_LOW); - } + state->gpios[i] = gpio; + } return 0; } @@ -1860,10 +1836,6 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev) state->mclk_frequency); } - ret = s5k5baf_parse_gpios(state->gpios, dev); - if (ret < 0) - return ret; - node_ep = of_graph_get_next_endpoint(node, NULL); if (!node_ep) { dev_err(dev, "no endpoint defined at node %pOF\n", node); diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c index a4efd6d10b43..ef6673b10580 100644 --- a/drivers/media/i2c/s5k6a3.c +++ b/drivers/media/i2c/s5k6a3.c @@ -9,12 +9,12 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/device.h> +#include <linux/err.h> #include <linux/errno.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_gpio.h> #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> @@ -59,7 +59,7 @@ struct s5k6a3 { struct v4l2_subdev subdev; struct media_pad pad; struct regulator_bulk_data supplies[S5K6A3_NUM_SUPPLIES]; - int gpio_reset; + struct gpio_desc *gpio_reset; struct mutex lock; struct v4l2_mbus_framefmt format; struct clk *clock; @@ -216,11 +216,11 @@ static int __s5k6a3_power_on(struct s5k6a3 *sensor) goto error_clk; } - gpio_set_value(sensor->gpio_reset, 1); + gpiod_set_value_cansleep(sensor->gpio_reset, 0); usleep_range(600, 800); - gpio_set_value(sensor->gpio_reset, 0); + gpiod_set_value_cansleep(sensor->gpio_reset, 1); usleep_range(600, 800); - gpio_set_value(sensor->gpio_reset, 1); + gpiod_set_value_cansleep(sensor->gpio_reset, 0); /* Delay needed for the sensor initialization */ msleep(20); @@ -240,7 +240,7 @@ static int __s5k6a3_power_off(struct s5k6a3 *sensor) { int i; - gpio_set_value(sensor->gpio_reset, 0); + gpiod_set_value_cansleep(sensor->gpio_reset, 1); for (i = S5K6A3_NUM_SUPPLIES - 1; i >= 0; i--) regulator_disable(sensor->supplies[i].consumer); @@ -285,32 +285,24 @@ static int s5k6a3_probe(struct i2c_client *client) struct device *dev = &client->dev; struct s5k6a3 *sensor; struct v4l2_subdev *sd; - int gpio, i, ret; + int i, ret; sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); if (!sensor) return -ENOMEM; mutex_init(&sensor->lock); - sensor->gpio_reset = -EINVAL; - sensor->clock = ERR_PTR(-EINVAL); sensor->dev = dev; sensor->clock = devm_clk_get(sensor->dev, S5K6A3_CLK_NAME); if (IS_ERR(sensor->clock)) return PTR_ERR(sensor->clock); - gpio = of_get_gpio_flags(dev->of_node, 0, NULL); - if (!gpio_is_valid(gpio)) - return gpio; - - ret = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_LOW, - S5K6A3_DRV_NAME); - if (ret < 0) + sensor->gpio_reset = devm_gpiod_get(dev, NULL, GPIOD_OUT_HIGH); + ret = PTR_ERR_OR_ZERO(sensor->gpio_reset); + if (ret) return ret; - sensor->gpio_reset = gpio; - if (of_property_read_u32(dev->of_node, "clock-frequency", &sensor->clock_frequency)) { sensor->clock_frequency = S5K6A3_DEFAULT_CLK_FREQ; diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 200841c1f5cf..9197fa0b1bc2 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -1891,12 +1891,9 @@ static int tc358743_probe_of(struct tc358743_state *state) int ret; refclk = devm_clk_get(dev, "refclk"); - if (IS_ERR(refclk)) { - if (PTR_ERR(refclk) != -EPROBE_DEFER) - dev_err(dev, "failed to get refclk: %ld\n", - PTR_ERR(refclk)); - return PTR_ERR(refclk); - } + if (IS_ERR(refclk)) + return dev_err_probe(dev, PTR_ERR(refclk), + "failed to get refclk\n"); ep = of_graph_get_next_endpoint(dev->of_node, NULL); if (!ep) { diff --git a/drivers/media/pci/pt3/pt3.c b/drivers/media/pci/pt3/pt3.c index f6deac85962e..246f73b8a9e7 100644 --- a/drivers/media/pci/pt3/pt3.c +++ b/drivers/media/pci/pt3/pt3.c @@ -707,18 +707,10 @@ static int pt3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret < 0) return ret; - ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); - if (ret == 0) - dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); - else { - ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (ret == 0) - dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - else { - dev_err(&pdev->dev, "Failed to set DMA mask\n"); - return ret; - } - dev_info(&pdev->dev, "Use 32bit DMA\n"); + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (ret) { + dev_err(&pdev->dev, "Failed to set DMA mask\n"); + return ret; } pt3 = devm_kzalloc(&pdev->dev, sizeof(*pt3), GFP_KERNEL); diff --git a/drivers/media/platform/chips-media/coda-bit.c b/drivers/media/platform/chips-media/coda-bit.c index 2736a902e3df..ed47d5bd8d61 100644 --- a/drivers/media/platform/chips-media/coda-bit.c +++ b/drivers/media/platform/chips-media/coda-bit.c @@ -854,7 +854,7 @@ static void coda_setup_iram(struct coda_ctx *ctx) /* Only H.264BP and H.263P3 are considered */ iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w64); iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w64); - if (!iram_info->buf_dbk_c_use) + if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use) goto out; iram_info->axi_sram_use |= dbk_bits; @@ -878,7 +878,7 @@ static void coda_setup_iram(struct coda_ctx *ctx) iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w128); iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w128); - if (!iram_info->buf_dbk_c_use) + if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use) goto out; iram_info->axi_sram_use |= dbk_bits; @@ -1084,10 +1084,16 @@ static int coda_start_encoding(struct coda_ctx *ctx) } if (dst_fourcc == V4L2_PIX_FMT_JPEG) { - if (!ctx->params.jpeg_qmat_tab[0]) + if (!ctx->params.jpeg_qmat_tab[0]) { ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL); - if (!ctx->params.jpeg_qmat_tab[1]) + if (!ctx->params.jpeg_qmat_tab[0]) + return -ENOMEM; + } + if (!ctx->params.jpeg_qmat_tab[1]) { ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL); + if (!ctx->params.jpeg_qmat_tab[1]) + return -ENOMEM; + } coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality); } diff --git a/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.c b/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.c index 1e3833f1c9ae..ad5fab2d8bfa 100644 --- a/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.c +++ b/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.c @@ -52,9 +52,8 @@ int mtk_mdp_comp_init(struct device *dev, struct device_node *node, for (i = 0; i < ARRAY_SIZE(comp->clk); i++) { comp->clk[i] = of_clk_get(node, i); if (IS_ERR(comp->clk[i])) { - if (PTR_ERR(comp->clk[i]) != -EPROBE_DEFER) - dev_err(dev, "Failed to get clock\n"); - ret = PTR_ERR(comp->clk[i]); + ret = dev_err_probe(dev, PTR_ERR(comp->clk[i]), + "Failed to get clock\n"); goto put_dev; } diff --git a/drivers/media/platform/samsung/exynos4-is/media-dev.c b/drivers/media/platform/samsung/exynos4-is/media-dev.c index 2f3071acb9c9..98a60f01129d 100644 --- a/drivers/media/platform/samsung/exynos4-is/media-dev.c +++ b/drivers/media/platform/samsung/exynos4-is/media-dev.c @@ -1471,9 +1471,7 @@ static int fimc_md_probe(struct platform_device *pdev) pinctrl = devm_pinctrl_get(dev); if (IS_ERR(pinctrl)) { - ret = PTR_ERR(pinctrl); - if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to get pinctrl: %d\n", ret); + ret = dev_err_probe(dev, PTR_ERR(pinctrl), "Failed to get pinctrl\n"); goto err_clk; } diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c index 72d70984e99a..6d3c92045c05 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c @@ -468,8 +468,10 @@ void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx) s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); /* Wait until instance is returned or timeout occurred */ if (s5p_mfc_wait_for_done_ctx(ctx, - S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) + S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)){ + clear_work_bit_irqsave(ctx); mfc_err("Err returning instance\n"); + } /* Free resources */ s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx); diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c index b65e506665af..f62703cebb77 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c @@ -1218,6 +1218,7 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) unsigned long mb_y_addr, mb_c_addr; int slice_type; unsigned int strm_size; + bool src_ready; slice_type = s5p_mfc_hw_call(dev->mfc_ops, get_enc_slice_type, dev); strm_size = s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev); @@ -1257,7 +1258,8 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) } } } - if ((ctx->src_queue_cnt > 0) && (ctx->state == MFCINST_RUNNING)) { + if (ctx->src_queue_cnt > 0 && (ctx->state == MFCINST_RUNNING || + ctx->state == MFCINST_FINISHING)) { mb_entry = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); if (mb_entry->flags & MFC_BUF_FLAG_USED) { @@ -1288,7 +1290,13 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) vb2_set_plane_payload(&mb_entry->b->vb2_buf, 0, strm_size); vb2_buffer_done(&mb_entry->b->vb2_buf, VB2_BUF_STATE_DONE); } - if ((ctx->src_queue_cnt == 0) || (ctx->dst_queue_cnt == 0)) + + src_ready = true; + if (ctx->state == MFCINST_RUNNING && ctx->src_queue_cnt == 0) + src_ready = false; + if (ctx->state == MFCINST_FINISHING && ctx->ref_queue_cnt == 0) + src_ready = false; + if (!src_ready || ctx->dst_queue_cnt == 0) clear_work_bit(ctx); return 0; diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c index 8227004f6746..c0df5ac9fcff 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c @@ -1060,7 +1060,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) } /* aspect ratio VUI */ - readl(mfc_regs->e_h264_options); + reg = readl(mfc_regs->e_h264_options); reg &= ~(0x1 << 5); reg |= ((p_h264->vui_sar & 0x1) << 5); writel(reg, mfc_regs->e_h264_options); @@ -1083,7 +1083,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) /* intra picture period for H.264 open GOP */ /* control */ - readl(mfc_regs->e_h264_options); + reg = readl(mfc_regs->e_h264_options); reg &= ~(0x1 << 4); reg |= ((p_h264->open_gop & 0x1) << 4); writel(reg, mfc_regs->e_h264_options); @@ -1097,23 +1097,23 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) } /* 'WEIGHTED_BI_PREDICTION' for B is disable */ - readl(mfc_regs->e_h264_options); + reg = readl(mfc_regs->e_h264_options); reg &= ~(0x3 << 9); writel(reg, mfc_regs->e_h264_options); /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */ - readl(mfc_regs->e_h264_options); + reg = readl(mfc_regs->e_h264_options); reg &= ~(0x1 << 14); writel(reg, mfc_regs->e_h264_options); /* ASO */ - readl(mfc_regs->e_h264_options); + reg = readl(mfc_regs->e_h264_options); reg &= ~(0x1 << 6); reg |= ((p_h264->aso & 0x1) << 6); writel(reg, mfc_regs->e_h264_options); /* hier qp enable */ - readl(mfc_regs->e_h264_options); + reg = readl(mfc_regs->e_h264_options); reg &= ~(0x1 << 8); reg |= ((p_h264->open_gop & 0x1) << 8); writel(reg, mfc_regs->e_h264_options); @@ -1134,7 +1134,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) writel(reg, mfc_regs->e_h264_num_t_layer); /* frame packing SEI generation */ - readl(mfc_regs->e_h264_options); + reg = readl(mfc_regs->e_h264_options); reg &= ~(0x1 << 25); reg |= ((p_h264->sei_frame_packing & 0x1) << 25); writel(reg, mfc_regs->e_h264_options); diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c index 4c5027a0480d..c38b62d4f1ae 100644 --- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c @@ -927,6 +927,7 @@ static int configure_channels(struct c8sectpfei *fei) if (ret) { dev_err(fei->dev, "configure_memdma_and_inputblock failed\n"); + of_node_put(child); goto err_unmap; } index++; diff --git a/drivers/media/platform/st/stm32/stm32-dcmi.c b/drivers/media/platform/st/stm32/stm32-dcmi.c index 7d393f696bff..ad8e9742e1ae 100644 --- a/drivers/media/platform/st/stm32/stm32-dcmi.c +++ b/drivers/media/platform/st/stm32/stm32-dcmi.c @@ -1946,12 +1946,9 @@ static int dcmi_probe(struct platform_device *pdev) return -ENOMEM; dcmi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); - if (IS_ERR(dcmi->rstc)) { - if (PTR_ERR(dcmi->rstc) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Could not get reset control\n"); - - return PTR_ERR(dcmi->rstc); - } + if (IS_ERR(dcmi->rstc)) + return dev_err_probe(&pdev->dev, PTR_ERR(dcmi->rstc), + "Could not get reset control\n"); /* Get bus characteristics from devicetree */ np = of_graph_get_next_endpoint(np, NULL); @@ -2001,20 +1998,14 @@ static int dcmi_probe(struct platform_device *pdev) return PTR_ERR(dcmi->regs); mclk = devm_clk_get(&pdev->dev, "mclk"); - if (IS_ERR(mclk)) { - if (PTR_ERR(mclk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Unable to get mclk\n"); - return PTR_ERR(mclk); - } + if (IS_ERR(mclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(mclk), + "Unable to get mclk\n"); chan = dma_request_chan(&pdev->dev, "tx"); - if (IS_ERR(chan)) { - ret = PTR_ERR(chan); - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "Failed to request DMA channel: %d\n", ret); - return ret; - } + if (IS_ERR(chan)) + return dev_err_probe(&pdev->dev, PTR_ERR(chan), + "Failed to request DMA channel\n"); dcmi->dma_max_burst = UINT_MAX; ret = dma_get_slave_caps(chan, &caps); diff --git a/drivers/media/platform/ti/omap3isp/isp.c b/drivers/media/platform/ti/omap3isp/isp.c index 24d2383400b0..1d40bb59ff81 100644 --- a/drivers/media/platform/ti/omap3isp/isp.c +++ b/drivers/media/platform/ti/omap3isp/isp.c @@ -1884,8 +1884,7 @@ static int isp_initialize_modules(struct isp_device *isp) ret = omap3isp_ccp2_init(isp); if (ret < 0) { - if (ret != -EPROBE_DEFER) - dev_err(isp->dev, "CCP2 initialization failed\n"); + dev_err_probe(isp->dev, ret, "CCP2 initialization failed\n"); goto error_ccp2; } diff --git a/drivers/media/platform/xilinx/xilinx-csi2rxss.c b/drivers/media/platform/xilinx/xilinx-csi2rxss.c index 29b53febc2e7..d8a23f18cfbc 100644 --- a/drivers/media/platform/xilinx/xilinx-csi2rxss.c +++ b/drivers/media/platform/xilinx/xilinx-csi2rxss.c @@ -976,11 +976,9 @@ static int xcsi2rxss_probe(struct platform_device *pdev) /* Reset GPIO */ xcsi2rxss->rst_gpio = devm_gpiod_get_optional(dev, "video-reset", GPIOD_OUT_HIGH); - if (IS_ERR(xcsi2rxss->rst_gpio)) { - if (PTR_ERR(xcsi2rxss->rst_gpio) != -EPROBE_DEFER) - dev_err(dev, "Video Reset GPIO not setup in DT"); - return PTR_ERR(xcsi2rxss->rst_gpio); - } + if (IS_ERR(xcsi2rxss->rst_gpio)) + return dev_err_probe(dev, PTR_ERR(xcsi2rxss->rst_gpio), + "Video Reset GPIO not setup in DT\n"); ret = xcsi2rxss_parse_of(xcsi2rxss); if (ret < 0) diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index 6b2768623c88..aa7a580dbecc 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c @@ -727,8 +727,10 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, /* start radio */ retval = si470x_start_usb(radio); - if (retval < 0) + if (retval < 0 && !radio->int_in_running) goto err_buf; + else if (retval < 0) /* in case of radio->int_in_running == 1 */ + goto err_all; /* set initial frequency */ si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 22e524b69806..8f1fff7af6c9 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -74,13 +74,9 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) return -ENOMEM; gpio_dev->gpiod = devm_gpiod_get(dev, NULL, GPIOD_IN); - if (IS_ERR(gpio_dev->gpiod)) { - rc = PTR_ERR(gpio_dev->gpiod); - /* Just try again if this happens */ - if (rc != -EPROBE_DEFER) - dev_err(dev, "error getting gpio (%d)\n", rc); - return rc; - } + if (IS_ERR(gpio_dev->gpiod)) + return dev_err_probe(dev, PTR_ERR(gpio_dev->gpiod), + "error getting gpio\n"); gpio_dev->irq = gpiod_to_irq(gpio_dev->gpiod); if (gpio_dev->irq < 0) return gpio_dev->irq; diff --git a/drivers/media/rc/gpio-ir-tx.c b/drivers/media/rc/gpio-ir-tx.c index d3063ddb472e..2b829c146db1 100644 --- a/drivers/media/rc/gpio-ir-tx.c +++ b/drivers/media/rc/gpio-ir-tx.c @@ -174,12 +174,9 @@ static int gpio_ir_tx_probe(struct platform_device *pdev) return -ENOMEM; gpio_ir->gpio = devm_gpiod_get(&pdev->dev, NULL, GPIOD_OUT_LOW); - if (IS_ERR(gpio_ir->gpio)) { - if (PTR_ERR(gpio_ir->gpio) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to get gpio (%ld)\n", - PTR_ERR(gpio_ir->gpio)); - return PTR_ERR(gpio_ir->gpio); - } + if (IS_ERR(gpio_ir->gpio)) + return dev_err_probe(&pdev->dev, PTR_ERR(gpio_ir->gpio), + "Failed to get gpio\n"); rcdev->priv = gpio_ir; rcdev->driver_name = DRIVER_NAME; diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c index a3b145183260..85080c3d2053 100644 --- a/drivers/media/rc/ir-rx51.c +++ b/drivers/media/rc/ir-rx51.c @@ -231,13 +231,8 @@ static int ir_rx51_probe(struct platform_device *dev) struct rc_dev *rcdev; pwm = pwm_get(&dev->dev, NULL); - if (IS_ERR(pwm)) { - int err = PTR_ERR(pwm); - - if (err != -EPROBE_DEFER) - dev_err(&dev->dev, "pwm_get failed: %d\n", err); - return err; - } + if (IS_ERR(pwm)) + return dev_err_probe(&dev->dev, PTR_ERR(pwm), "pwm_get failed\n"); /* Use default, in case userspace does not set the carrier */ ir_rx51.freq = DIV_ROUND_CLOSEST_ULL(pwm_get_period(pwm), NSEC_PER_SEC); diff --git a/drivers/media/usb/pwc/pwc-uncompress.c b/drivers/media/usb/pwc/pwc-uncompress.c index faf44cdeb268..cf2591a9675c 100644 --- a/drivers/media/usb/pwc/pwc-uncompress.c +++ b/drivers/media/usb/pwc/pwc-uncompress.c @@ -39,7 +39,7 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) * first 3 bytes is filled (Nala case). We can * determine this using the type of the webcam */ memcpy(raw_frame->cmd, pdev->cmd_buf, 4); - memcpy(raw_frame+1, yuv, pdev->frame_size); + memcpy(raw_frame->rawframe, yuv, pdev->frame_size); vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, struct_size(raw_frame, rawframe, pdev->frame_size)); return 0; diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 215fb483efb0..e4bcb5011360 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1266,12 +1266,9 @@ static int uvc_gpio_parse(struct uvc_device *dev) return PTR_ERR_OR_ZERO(gpio_privacy); irq = gpiod_to_irq(gpio_privacy); - if (irq < 0) { - if (irq != EPROBE_DEFER) - dev_err(&dev->udev->dev, - "No IRQ for privacy GPIO (%d)\n", irq); - return irq; - } + if (irq < 0) + return dev_err_probe(&dev->udev->dev, irq, + "No IRQ for privacy GPIO\n"); unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1); if (!unit) diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index 3d85a8600f57..3d9533c1b202 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -298,10 +298,25 @@ v4l2_fwnode_endpoint_parse_parallel_bus(struct fwnode_handle *fwnode, if (!fwnode_property_read_u32(fwnode, "pclk-sample", &v)) { flags &= ~(V4L2_MBUS_PCLK_SAMPLE_RISING | - V4L2_MBUS_PCLK_SAMPLE_FALLING); - flags |= v ? V4L2_MBUS_PCLK_SAMPLE_RISING : - V4L2_MBUS_PCLK_SAMPLE_FALLING; - pr_debug("pclk-sample %s\n", v ? "high" : "low"); + V4L2_MBUS_PCLK_SAMPLE_FALLING | + V4L2_MBUS_PCLK_SAMPLE_DUALEDGE); + switch (v) { + case 0: + flags |= V4L2_MBUS_PCLK_SAMPLE_FALLING; + pr_debug("pclk-sample low\n"); + break; + case 1: + flags |= V4L2_MBUS_PCLK_SAMPLE_RISING; + pr_debug("pclk-sample high\n"); + break; + case 2: + flags |= V4L2_MBUS_PCLK_SAMPLE_DUALEDGE; + pr_debug("pclk-sample dual edge\n"); + break; + default: + pr_warn("invalid argument for pclk-sample"); + break; + } } if (!fwnode_property_read_u32(fwnode, "data-active", &v)) { diff --git a/drivers/staging/media/deprecated/stkwebcam/Kconfig b/drivers/staging/media/deprecated/stkwebcam/Kconfig index 4450403dff41..7234498e634a 100644 --- a/drivers/staging/media/deprecated/stkwebcam/Kconfig +++ b/drivers/staging/media/deprecated/stkwebcam/Kconfig @@ -2,7 +2,7 @@ config VIDEO_STKWEBCAM tristate "USB Syntek DC1125 Camera support (DEPRECATED)" depends on VIDEO_DEV - depends on USB + depends on MEDIA_USB_SUPPORT && MEDIA_CAMERA_SUPPORT help Say Y here if you want to use this type of camera. Supported devices are typically found in some Asus laptops, diff --git a/drivers/staging/media/imx/TODO b/drivers/staging/media/imx/TODO index afee26870af7..11c9e10d34ae 100644 --- a/drivers/staging/media/imx/TODO +++ b/drivers/staging/media/imx/TODO @@ -2,18 +2,6 @@ - The Frame Interval Monitor could be exported to v4l2-core for general use. -- The CSI subdevice parses its nearest upstream neighbor's device-tree - bus config in order to setup the CSI. Laurent Pinchart argues that - instead the CSI subdev should call its neighbor's g_mbus_config op - (which should be propagated if necessary) to get this info. However - Hans Verkuil is planning to remove the g_mbus_config op. For now this - driver uses the parsed DT bus config method until this issue is - resolved. - - 2020-06: g_mbus has been removed in favour of the get_mbus_config pad - operation which should be used to avoid parsing the remote endpoint - configuration. - - This media driver supports inheriting V4L2 controls to the video capture devices, from the subdevices in the capture device's pipeline. The controls for each capture device are updated in the diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index b2b1f4dd41d7..5c3cc7de209d 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -97,8 +97,8 @@ struct csi_priv { /* the mipi virtual channel number at link validate */ int vc_num; - /* the upstream endpoint CSI is receiving from */ - struct v4l2_fwnode_endpoint upstream_ep; + /* media bus config of the upstream subdevice CSI is receiving from */ + struct v4l2_mbus_config mbus_cfg; spinlock_t irqlock; /* protect eof_irq handler */ struct timer_list eof_timeout_timer; @@ -125,14 +125,14 @@ static inline struct csi_priv *notifier_to_dev(struct v4l2_async_notifier *n) return container_of(n, struct csi_priv, notifier); } -static inline bool is_parallel_bus(struct v4l2_fwnode_endpoint *ep) +static inline bool is_parallel_bus(struct v4l2_mbus_config *mbus_cfg) { - return ep->bus_type != V4L2_MBUS_CSI2_DPHY; + return mbus_cfg->type != V4L2_MBUS_CSI2_DPHY; } -static inline bool is_parallel_16bit_bus(struct v4l2_fwnode_endpoint *ep) +static inline bool is_parallel_16bit_bus(struct v4l2_mbus_config *mbus_cfg) { - return is_parallel_bus(ep) && ep->bus.parallel.bus_width >= 16; + return is_parallel_bus(mbus_cfg) && mbus_cfg->bus.parallel.bus_width >= 16; } /* @@ -145,36 +145,31 @@ static inline bool is_parallel_16bit_bus(struct v4l2_fwnode_endpoint *ep) * - the CSI is receiving from an 8-bit parallel bus and the incoming * media bus format is other than UYVY8_2X8/YUYV8_2X8. */ -static inline bool requires_passthrough(struct v4l2_fwnode_endpoint *ep, +static inline bool requires_passthrough(struct v4l2_mbus_config *mbus_cfg, struct v4l2_mbus_framefmt *infmt, const struct imx_media_pixfmt *incc) { - if (ep->bus_type == V4L2_MBUS_BT656) // including BT.1120 + if (mbus_cfg->type == V4L2_MBUS_BT656) // including BT.1120 return false; - return incc->bayer || is_parallel_16bit_bus(ep) || - (is_parallel_bus(ep) && + return incc->bayer || is_parallel_16bit_bus(mbus_cfg) || + (is_parallel_bus(mbus_cfg) && infmt->code != MEDIA_BUS_FMT_UYVY8_2X8 && infmt->code != MEDIA_BUS_FMT_YUYV8_2X8); } /* - * Parses the fwnode endpoint from the source pad of the entity - * connected to this CSI. This will either be the entity directly - * upstream from the CSI-2 receiver, directly upstream from the - * video mux, or directly upstream from the CSI itself. The endpoint - * is needed to determine the bus type and bus config coming into - * the CSI. + * Queries the media bus config of the upstream entity that provides data to + * the CSI. This will either be the entity directly upstream from the CSI-2 + * receiver, directly upstream from a video mux, or directly upstream from + * the CSI itself. */ -static int csi_get_upstream_endpoint(struct csi_priv *priv, - struct v4l2_fwnode_endpoint *ep) +static int csi_get_upstream_mbus_config(struct csi_priv *priv, + struct v4l2_mbus_config *mbus_cfg) { - struct fwnode_handle *endpoint; - struct v4l2_subdev *sd; - struct media_pad *pad; - - if (!IS_ENABLED(CONFIG_OF)) - return -ENXIO; + struct v4l2_subdev *sd, *remote_sd; + struct media_pad *remote_pad; + int ret; if (!priv->src_sd) return -EPIPE; @@ -206,19 +201,21 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv, } /* get source pad of entity directly upstream from sd */ - pad = imx_media_pipeline_pad(&sd->entity, 0, 0, true); - if (!pad) - return -ENODEV; - - endpoint = imx_media_get_pad_fwnode(pad); - if (IS_ERR(endpoint)) - return PTR_ERR(endpoint); + remote_pad = media_entity_remote_pad_unique(&sd->entity, + MEDIA_PAD_FL_SOURCE); + if (IS_ERR(remote_pad)) + return PTR_ERR(remote_pad); - v4l2_fwnode_endpoint_parse(endpoint, ep); + remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity); - fwnode_handle_put(endpoint); + ret = v4l2_subdev_call(remote_sd, pad, get_mbus_config, + remote_pad->index, mbus_cfg); + if (ret == -ENOIOCTLCMD) + v4l2_err(&priv->sd, + "entity %s does not implement get_mbus_config()\n", + remote_pad->entity->name); - return 0; + return ret; } static void csi_idmac_put_ipu_resources(struct csi_priv *priv) @@ -435,7 +432,7 @@ static int csi_idmac_setup_channel(struct csi_priv *priv) image.phys0 = phys[0]; image.phys1 = phys[1]; - passthrough = requires_passthrough(&priv->upstream_ep, infmt, incc); + passthrough = requires_passthrough(&priv->mbus_cfg, infmt, incc); passthrough_cycles = 1; /* @@ -708,7 +705,6 @@ static int csi_setup(struct csi_priv *priv) { struct v4l2_mbus_framefmt *infmt, *outfmt; const struct imx_media_pixfmt *incc; - struct v4l2_mbus_config mbus_cfg; struct v4l2_mbus_framefmt if_fmt; struct v4l2_rect crop; @@ -716,13 +712,6 @@ static int csi_setup(struct csi_priv *priv) incc = priv->cc[CSI_SINK_PAD]; outfmt = &priv->format_mbus[priv->active_output_pad]; - /* compose mbus_config from the upstream endpoint */ - mbus_cfg.type = priv->upstream_ep.bus_type; - if (is_parallel_bus(&priv->upstream_ep)) - mbus_cfg.bus.parallel = priv->upstream_ep.bus.parallel; - else - mbus_cfg.bus.mipi_csi2 = priv->upstream_ep.bus.mipi_csi2; - if_fmt = *infmt; crop = priv->crop; @@ -730,7 +719,7 @@ static int csi_setup(struct csi_priv *priv) * if cycles is set, we need to handle this over multiple cycles as * generic/bayer data */ - if (is_parallel_bus(&priv->upstream_ep) && incc->cycles) { + if (is_parallel_bus(&priv->mbus_cfg) && incc->cycles) { if_fmt.width *= incc->cycles; crop.width *= incc->cycles; } @@ -741,7 +730,7 @@ static int csi_setup(struct csi_priv *priv) priv->crop.width == 2 * priv->compose.width, priv->crop.height == 2 * priv->compose.height); - ipu_csi_init_interface(priv->csi, &mbus_cfg, &if_fmt, outfmt); + ipu_csi_init_interface(priv->csi, &priv->mbus_cfg, &if_fmt, outfmt); ipu_csi_set_dest(priv->csi, priv->dest); @@ -769,7 +758,7 @@ static int csi_start(struct csi_priv *priv) return ret; /* Skip first few frames from a BT.656 source */ - if (priv->upstream_ep.bus_type == V4L2_MBUS_BT656) { + if (priv->mbus_cfg.type == V4L2_MBUS_BT656) { u32 delay_usec, bad_frames = 20; delay_usec = DIV_ROUND_UP_ULL((u64)USEC_PER_SEC * @@ -1118,7 +1107,7 @@ static int csi_link_validate(struct v4l2_subdev *sd, struct v4l2_subdev_format *sink_fmt) { struct csi_priv *priv = v4l2_get_subdevdata(sd); - struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 }; + struct v4l2_mbus_config mbus_cfg = { .type = 0 }; bool is_csi2; int ret; @@ -1127,16 +1116,17 @@ static int csi_link_validate(struct v4l2_subdev *sd, if (ret) return ret; - ret = csi_get_upstream_endpoint(priv, &upstream_ep); + ret = csi_get_upstream_mbus_config(priv, &mbus_cfg); if (ret) { - v4l2_err(&priv->sd, "failed to find upstream endpoint\n"); + v4l2_err(&priv->sd, + "failed to get upstream media bus configuration\n"); return ret; } mutex_lock(&priv->lock); - priv->upstream_ep = upstream_ep; - is_csi2 = !is_parallel_bus(&upstream_ep); + priv->mbus_cfg = mbus_cfg; + is_csi2 = !is_parallel_bus(&mbus_cfg); if (is_csi2) { /* * NOTE! It seems the virtual channels from the mipi csi-2 @@ -1192,7 +1182,7 @@ static void csi_try_crop(struct csi_priv *priv, struct v4l2_rect *crop, struct v4l2_subdev_state *sd_state, struct v4l2_mbus_framefmt *infmt, - struct v4l2_fwnode_endpoint *upstream_ep) + struct v4l2_mbus_config *mbus_cfg) { u32 in_height; @@ -1216,7 +1206,7 @@ static void csi_try_crop(struct csi_priv *priv, * sync, so fix it to NTSC/PAL active lines. NTSC contains * 2 extra lines of active video that need to be cropped. */ - if (upstream_ep->bus_type == V4L2_MBUS_BT656 && + if (mbus_cfg->type == V4L2_MBUS_BT656 && (V4L2_FIELD_HAS_BOTH(infmt->field) || infmt->field == V4L2_FIELD_ALTERNATE)) { crop->height = in_height; @@ -1233,7 +1223,7 @@ static int csi_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_mbus_code_enum *code) { struct csi_priv *priv = v4l2_get_subdevdata(sd); - struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 }; + struct v4l2_mbus_config mbus_cfg = { .type = 0 }; const struct imx_media_pixfmt *incc; struct v4l2_mbus_framefmt *infmt; int ret = 0; @@ -1250,13 +1240,14 @@ static int csi_enum_mbus_code(struct v4l2_subdev *sd, break; case CSI_SRC_PAD_DIRECT: case CSI_SRC_PAD_IDMAC: - ret = csi_get_upstream_endpoint(priv, &upstream_ep); + ret = csi_get_upstream_mbus_config(priv, &mbus_cfg); if (ret) { - v4l2_err(&priv->sd, "failed to find upstream endpoint\n"); + v4l2_err(&priv->sd, + "failed to get upstream media bus configuration\n"); goto out; } - if (requires_passthrough(&upstream_ep, infmt, incc)) { + if (requires_passthrough(&mbus_cfg, infmt, incc)) { if (code->index != 0) { ret = -EINVAL; goto out; @@ -1426,7 +1417,7 @@ static void csi_try_field(struct csi_priv *priv, } static void csi_try_fmt(struct csi_priv *priv, - struct v4l2_fwnode_endpoint *upstream_ep, + struct v4l2_mbus_config *mbus_cfg, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *sdformat, struct v4l2_rect *crop, @@ -1447,7 +1438,7 @@ static void csi_try_fmt(struct csi_priv *priv, sdformat->format.width = compose->width; sdformat->format.height = compose->height; - if (requires_passthrough(upstream_ep, infmt, incc)) { + if (requires_passthrough(mbus_cfg, infmt, incc)) { sdformat->format.code = infmt->code; *cc = incc; } else { @@ -1497,8 +1488,7 @@ static void csi_try_fmt(struct csi_priv *priv, crop->height = sdformat->format.height; if (sdformat->format.field == V4L2_FIELD_ALTERNATE) crop->height *= 2; - csi_try_crop(priv, crop, sd_state, &sdformat->format, - upstream_ep); + csi_try_crop(priv, crop, sd_state, &sdformat->format, mbus_cfg); compose->left = 0; compose->top = 0; compose->width = crop->width; @@ -1516,7 +1506,7 @@ static int csi_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_format *sdformat) { struct csi_priv *priv = v4l2_get_subdevdata(sd); - struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 }; + struct v4l2_mbus_config mbus_cfg = { .type = 0 }; const struct imx_media_pixfmt *cc; struct v4l2_mbus_framefmt *fmt; struct v4l2_rect *crop, *compose; @@ -1525,9 +1515,10 @@ static int csi_set_fmt(struct v4l2_subdev *sd, if (sdformat->pad >= CSI_NUM_PADS) return -EINVAL; - ret = csi_get_upstream_endpoint(priv, &upstream_ep); + ret = csi_get_upstream_mbus_config(priv, &mbus_cfg); if (ret) { - v4l2_err(&priv->sd, "failed to find upstream endpoint\n"); + v4l2_err(&priv->sd, + "failed to get upstream media bus configuration\n"); return ret; } @@ -1541,8 +1532,7 @@ static int csi_set_fmt(struct v4l2_subdev *sd, crop = __csi_get_crop(priv, sd_state, sdformat->which); compose = __csi_get_compose(priv, sd_state, sdformat->which); - csi_try_fmt(priv, &upstream_ep, sd_state, sdformat, crop, compose, - &cc); + csi_try_fmt(priv, &mbus_cfg, sd_state, sdformat, crop, compose, &cc); fmt = __csi_get_fmt(priv, sd_state, sdformat->pad, sdformat->which); *fmt = sdformat->format; @@ -1559,8 +1549,8 @@ static int csi_set_fmt(struct v4l2_subdev *sd, format.pad = pad; format.which = sdformat->which; format.format = sdformat->format; - csi_try_fmt(priv, &upstream_ep, sd_state, &format, - NULL, compose, &outcc); + csi_try_fmt(priv, &mbus_cfg, sd_state, &format, NULL, + compose, &outcc); outfmt = __csi_get_fmt(priv, sd_state, pad, sdformat->which); @@ -1648,7 +1638,7 @@ static int csi_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_selection *sel) { struct csi_priv *priv = v4l2_get_subdevdata(sd); - struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 }; + struct v4l2_mbus_config mbus_cfg = { .type = 0 }; struct v4l2_mbus_framefmt *infmt; struct v4l2_rect *crop, *compose; int pad, ret; @@ -1656,9 +1646,10 @@ static int csi_set_selection(struct v4l2_subdev *sd, if (sel->pad != CSI_SINK_PAD) return -EINVAL; - ret = csi_get_upstream_endpoint(priv, &upstream_ep); + ret = csi_get_upstream_mbus_config(priv, &mbus_cfg); if (ret) { - v4l2_err(&priv->sd, "failed to find upstream endpoint\n"); + v4l2_err(&priv->sd, + "failed to get upstream media bus configuration\n"); return ret; } @@ -1687,7 +1678,7 @@ static int csi_set_selection(struct v4l2_subdev *sd, goto out; } - csi_try_crop(priv, &sel->r, sd_state, infmt, &upstream_ep); + csi_try_crop(priv, &sel->r, sd_state, infmt, &mbus_cfg); *crop = sel->r; diff --git a/drivers/staging/media/imx/imx-media-fim.c b/drivers/staging/media/imx/imx-media-fim.c index 3a9182933508..fb6590dcfc36 100644 --- a/drivers/staging/media/imx/imx-media-fim.c +++ b/drivers/staging/media/imx/imx-media-fim.c @@ -187,54 +187,6 @@ out_update_ts: send_fim_event(fim, error_avg); } -#ifdef CONFIG_IMX_GPT_ICAP -/* - * Input Capture method of measuring frame intervals. Not subject - * to interrupt latency. - */ -static void fim_input_capture_handler(int channel, void *dev_id, - ktime_t timestamp) -{ - struct imx_media_fim *fim = dev_id; - unsigned long flags; - - spin_lock_irqsave(&fim->lock, flags); - - frame_interval_monitor(fim, timestamp); - - if (!completion_done(&fim->icap_first_event)) - complete(&fim->icap_first_event); - - spin_unlock_irqrestore(&fim->lock, flags); -} - -static int fim_request_input_capture(struct imx_media_fim *fim) -{ - init_completion(&fim->icap_first_event); - - return mxc_request_input_capture(fim->icap_channel, - fim_input_capture_handler, - fim->icap_flags, fim); -} - -static void fim_free_input_capture(struct imx_media_fim *fim) -{ - mxc_free_input_capture(fim->icap_channel, fim); -} - -#else /* CONFIG_IMX_GPT_ICAP */ - -static int fim_request_input_capture(struct imx_media_fim *fim) -{ - return 0; -} - -static void fim_free_input_capture(struct imx_media_fim *fim) -{ -} - -#endif /* CONFIG_IMX_GPT_ICAP */ - /* * In case we are monitoring the first frame interval after streamon * (when fim->num_skip = 0), we need a valid fim->last_ts before we @@ -434,15 +386,8 @@ int imx_media_fim_set_stream(struct imx_media_fim *fim, update_fim_nominal(fim, fi); spin_unlock_irqrestore(&fim->lock, flags); - if (icap_enabled(fim)) { - ret = fim_request_input_capture(fim); - if (ret) - goto out; - fim_acquire_first_ts(fim); - } - } else { if (icap_enabled(fim)) - fim_free_input_capture(fim); + fim_acquire_first_ts(fim); } fim->stream_on = on; diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index 3e7462112649..411e907b68eb 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -814,39 +814,6 @@ imx_media_pipeline_video_device(struct media_entity *start_entity, EXPORT_SYMBOL_GPL(imx_media_pipeline_video_device); /* - * Find a fwnode endpoint that maps to the given subdevice's pad. - * If there are multiple endpoints that map to the pad, only the - * first endpoint encountered is returned. - * - * On success the refcount of the returned fwnode endpoint is - * incremented. - */ -struct fwnode_handle *imx_media_get_pad_fwnode(struct media_pad *pad) -{ - struct fwnode_handle *endpoint; - struct v4l2_subdev *sd; - - if (!is_media_entity_v4l2_subdev(pad->entity)) - return ERR_PTR(-ENODEV); - - sd = media_entity_to_v4l2_subdev(pad->entity); - - fwnode_graph_for_each_endpoint(dev_fwnode(sd->dev), endpoint) { - int pad_idx = media_entity_get_fwnode_pad(&sd->entity, - endpoint, - pad->flags); - if (pad_idx < 0) - continue; - - if (pad_idx == pad->index) - return endpoint; - } - - return ERR_PTR(-ENODEV); -} -EXPORT_SYMBOL_GPL(imx_media_get_pad_fwnode); - -/* * Turn current pipeline streaming on/off starting from entity. */ int imx_media_pipeline_set_stream(struct imx_media_dev *imxmd, diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h index f263fc3adbb9..f679249d82e4 100644 --- a/drivers/staging/media/imx/imx-media.h +++ b/drivers/staging/media/imx/imx-media.h @@ -219,7 +219,6 @@ imx_media_pipeline_subdev(struct media_entity *start_entity, u32 grp_id, struct video_device * imx_media_pipeline_video_device(struct media_entity *start_entity, enum v4l2_buf_type buftype, bool upstream); -struct fwnode_handle *imx_media_get_pad_fwnode(struct media_pad *pad); struct imx_media_dma_buf { void *virt; diff --git a/drivers/staging/media/omap4iss/iss_video.h b/drivers/staging/media/omap4iss/iss_video.h index ca2d5edb6261..19668d28b682 100644 --- a/drivers/staging/media/omap4iss/iss_video.h +++ b/drivers/staging/media/omap4iss/iss_video.h @@ -53,19 +53,19 @@ enum iss_pipeline_stream_state { enum iss_pipeline_state { /* The stream has been started on the input video node. */ - ISS_PIPELINE_STREAM_INPUT = 1, + ISS_PIPELINE_STREAM_INPUT = BIT(0), /* The stream has been started on the output video node. */ - ISS_PIPELINE_STREAM_OUTPUT = (1 << 1), + ISS_PIPELINE_STREAM_OUTPUT = BIT(1), /* At least one buffer is queued on the input video node. */ - ISS_PIPELINE_QUEUE_INPUT = (1 << 2), + ISS_PIPELINE_QUEUE_INPUT = BIT(2), /* At least one buffer is queued on the output video node. */ - ISS_PIPELINE_QUEUE_OUTPUT = (1 << 3), + ISS_PIPELINE_QUEUE_OUTPUT = BIT(3), /* The input entity is idle, ready to be started. */ - ISS_PIPELINE_IDLE_INPUT = (1 << 4), + ISS_PIPELINE_IDLE_INPUT = BIT(4), /* The output entity is idle, ready to be started. */ - ISS_PIPELINE_IDLE_OUTPUT = (1 << 5), + ISS_PIPELINE_IDLE_OUTPUT = BIT(5), /* The pipeline is currently streaming. */ - ISS_PIPELINE_STREAM = (1 << 6), + ISS_PIPELINE_STREAM = BIT(6), }; /* @@ -126,9 +126,9 @@ struct iss_buffer { enum iss_video_dmaqueue_flags { /* Set if DMA queue becomes empty when ISS_PIPELINE_STREAM_CONTINUOUS */ - ISS_VIDEO_DMAQUEUE_UNDERRUN = (1 << 0), + ISS_VIDEO_DMAQUEUE_UNDERRUN = BIT(0), /* Set when queuing buffer to an empty DMA queue */ - ISS_VIDEO_DMAQUEUE_QUEUED = (1 << 1), + ISS_VIDEO_DMAQUEUE_QUEUED = BIT(1), }; #define iss_video_dmaqueue_flags_clr(video) \ |