diff options
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0798-media-pxa_camera-Use-the-new-set_mbus_config-op.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.4/950-0798-media-pxa_camera-Use-the-new-set_mbus_config-op.patch | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0798-media-pxa_camera-Use-the-new-set_mbus_config-op.patch b/target/linux/bcm27xx/patches-5.4/950-0798-media-pxa_camera-Use-the-new-set_mbus_config-op.patch new file mode 100644 index 0000000000..d682cf842f --- /dev/null +++ b/target/linux/bcm27xx/patches-5.4/950-0798-media-pxa_camera-Use-the-new-set_mbus_config-op.patch @@ -0,0 +1,285 @@ +From 63f4970ce038e60455a6225b317d0b259e046c94 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi <jacopo+renesas@jmondi.org> +Date: Tue, 16 Jun 2020 16:12:39 +0200 +Subject: [PATCH] media: pxa_camera: Use the new set_mbus_config op + +Upstream https://patchwork.linuxtv.org/patch/64671/ + +Move the PXA camera driver to use the new set_mbus_config pad operation. +For this platform the change is not only cosmetic, as the pxa driver is +currently the only driver in mainline to make use of the g_mbus_config +and s_mbus_config video operations. + +The existing driver semantic is the following: +- Collect all supported mbus config flags from the remote end +- Match them with the supported PXA mbus configuration flags +- If the remote subdevice allows multiple options for for VSYNC, HSYNC + and PCLK polarity, use platform data requested settings + +The semantic of the new get_mbus_config and set_mbus_config differs from +the corresponding video ops, particularly in the fact get_mbus_config +reports the current mbus configuration and not the set of supported +configuration options, with set_mbus_config always reporting the actual +mbus configuration applied to the remote subdevice. + +Adapt the driver to perform the following +- Set the remote subdevice mbus configuration according to the PXA + platform data preferences. +- If the applied configuration differs from the requested one (i.e. the + remote subdevice does not allow changing one setting) make sure that + - The remote end does not claim for DATA_ACTIVE_LOW, which seems not + supported by the platform + - The bus mastering roles match + +While at there remove a few checks performed on the media bus +configuration at get_format() time as they do not belong there. + +Compile-tested only. + +Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org> +--- + drivers/media/platform/pxa_camera.c | 189 ++++++++-------------------- + 1 file changed, 51 insertions(+), 138 deletions(-) + +--- a/drivers/media/platform/pxa_camera.c ++++ b/drivers/media/platform/pxa_camera.c +@@ -605,42 +605,6 @@ static const struct pxa_mbus_pixelfmt *p + return pxa_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt)); + } + +-static unsigned int pxa_mbus_config_compatible(const struct v4l2_mbus_config *cfg, +- unsigned int flags) +-{ +- unsigned long common_flags; +- bool hsync = true, vsync = true, pclk, data, mode; +- bool mipi_lanes, mipi_clock; +- +- common_flags = cfg->flags & flags; +- +- switch (cfg->type) { +- case V4L2_MBUS_PARALLEL: +- hsync = common_flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH | +- V4L2_MBUS_HSYNC_ACTIVE_LOW); +- vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH | +- V4L2_MBUS_VSYNC_ACTIVE_LOW); +- /* fall through */ +- case V4L2_MBUS_BT656: +- pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING | +- V4L2_MBUS_PCLK_SAMPLE_FALLING); +- data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH | +- V4L2_MBUS_DATA_ACTIVE_LOW); +- mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE); +- return (!hsync || !vsync || !pclk || !data || !mode) ? +- 0 : common_flags; +- case V4L2_MBUS_CSI2_DPHY: +- mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES; +- mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK | +- V4L2_MBUS_CSI2_CONTINUOUS_CLOCK); +- return (!mipi_lanes || !mipi_clock) ? 0 : common_flags; +- default: +- WARN_ON(1); +- return -EINVAL; +- } +- return 0; +-} +- + /** + * struct pxa_camera_format_xlate - match between host and sensor formats + * @code: code of a sensor provided format +@@ -1231,31 +1195,6 @@ static irqreturn_t pxa_camera_irq(int ir + return IRQ_HANDLED; + } + +-static int test_platform_param(struct pxa_camera_dev *pcdev, +- unsigned char buswidth, unsigned long *flags) +-{ +- /* +- * Platform specified synchronization and pixel clock polarities are +- * only a recommendation and are only used during probing. The PXA270 +- * quick capture interface supports both. +- */ +- *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ? +- V4L2_MBUS_MASTER : V4L2_MBUS_SLAVE) | +- V4L2_MBUS_HSYNC_ACTIVE_HIGH | +- V4L2_MBUS_HSYNC_ACTIVE_LOW | +- V4L2_MBUS_VSYNC_ACTIVE_HIGH | +- V4L2_MBUS_VSYNC_ACTIVE_LOW | +- V4L2_MBUS_DATA_ACTIVE_HIGH | +- V4L2_MBUS_PCLK_SAMPLE_RISING | +- V4L2_MBUS_PCLK_SAMPLE_FALLING; +- +- /* If requested data width is supported by the platform, use it */ +- if ((1 << (buswidth - 1)) & pcdev->width_flags) +- return 0; +- +- return -EINVAL; +-} +- + static void pxa_camera_setup_cicr(struct pxa_camera_dev *pcdev, + unsigned long flags, __u32 pixfmt) + { +@@ -1598,99 +1537,78 @@ static int pxa_camera_init_videobuf2(str + */ + static int pxa_camera_set_bus_param(struct pxa_camera_dev *pcdev) + { ++ unsigned int bus_width = pcdev->current_fmt->host_fmt->bits_per_sample; + struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; + u32 pixfmt = pcdev->current_fmt->host_fmt->fourcc; +- unsigned long bus_flags, common_flags; ++ int mbus_config; + int ret; + +- ret = test_platform_param(pcdev, +- pcdev->current_fmt->host_fmt->bits_per_sample, +- &bus_flags); +- if (ret < 0) +- return ret; +- +- ret = sensor_call(pcdev, video, g_mbus_config, &cfg); +- if (!ret) { +- common_flags = pxa_mbus_config_compatible(&cfg, +- bus_flags); +- if (!common_flags) { +- dev_warn(pcdev_to_dev(pcdev), +- "Flags incompatible: camera 0x%x, host 0x%lx\n", +- cfg.flags, bus_flags); +- return -EINVAL; +- } +- } else if (ret != -ENOIOCTLCMD) { +- return ret; +- } else { +- common_flags = bus_flags; ++ if (!((1 << (bus_width - 1)) & pcdev->width_flags)) { ++ dev_err(pcdev_to_dev(pcdev), "Unsupported bus width %u", ++ bus_width); ++ return -EINVAL; + } + + pcdev->channels = 1; + + /* Make choices, based on platform preferences */ +- if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && +- (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { +- if (pcdev->platform_flags & PXA_CAMERA_HSP) +- common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; +- else +- common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; +- } +- +- if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && +- (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { +- if (pcdev->platform_flags & PXA_CAMERA_VSP) +- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; +- else +- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; +- } +- +- if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && +- (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { +- if (pcdev->platform_flags & PXA_CAMERA_PCP) +- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; +- else +- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; +- } +- +- cfg.flags = common_flags; +- ret = sensor_call(pcdev, video, s_mbus_config, &cfg); +- if (ret < 0 && ret != -ENOIOCTLCMD) { +- dev_dbg(pcdev_to_dev(pcdev), +- "camera s_mbus_config(0x%lx) returned %d\n", +- common_flags, ret); +- return ret; +- } ++ mbus_config = 0; ++ if (pcdev->platform_flags & PXA_CAMERA_MASTER) ++ mbus_config |= V4L2_MBUS_MASTER; ++ else ++ mbus_config |= V4L2_MBUS_SLAVE; + +- pxa_camera_setup_cicr(pcdev, common_flags, pixfmt); ++ if (pcdev->platform_flags & PXA_CAMERA_HSP) ++ mbus_config |= V4L2_MBUS_HSYNC_ACTIVE_HIGH; ++ else ++ mbus_config |= V4L2_MBUS_HSYNC_ACTIVE_LOW; + +- return 0; +-} ++ if (pcdev->platform_flags & PXA_CAMERA_VSP) ++ mbus_config |= V4L2_MBUS_VSYNC_ACTIVE_HIGH; ++ else ++ mbus_config |= V4L2_MBUS_VSYNC_ACTIVE_LOW; + +-static int pxa_camera_try_bus_param(struct pxa_camera_dev *pcdev, +- unsigned char buswidth) +-{ +- struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; +- unsigned long bus_flags, common_flags; +- int ret = test_platform_param(pcdev, buswidth, &bus_flags); ++ if (pcdev->platform_flags & PXA_CAMERA_PCP) ++ mbus_config |= V4L2_MBUS_PCLK_SAMPLE_RISING; ++ else ++ mbus_config |= V4L2_MBUS_PCLK_SAMPLE_FALLING; ++ mbus_config |= V4L2_MBUS_DATA_ACTIVE_HIGH; + +- if (ret < 0) ++ cfg.flags = mbus_config; ++ ret = sensor_call(pcdev, pad, set_mbus_config, 0, &cfg); ++ if (ret < 0 && ret != -ENOIOCTLCMD) { ++ dev_err(pcdev_to_dev(pcdev), ++ "Failed to call set_mbus_config: %d\n", ret); + return ret; ++ } ++ ++ /* ++ * If the requested media bus configuration has not been fully applied ++ * make sure it is supported by the platform. ++ * ++ * PXA does not support V4L2_MBUS_DATA_ACTIVE_LOW and the bus mastering ++ * roles should match. ++ */ ++ if (cfg.flags != mbus_config) { ++ unsigned int pxa_mbus_role = mbus_config & (V4L2_MBUS_MASTER | ++ V4L2_MBUS_SLAVE); ++ if (pxa_mbus_role != (cfg.flags & (V4L2_MBUS_MASTER | ++ V4L2_MBUS_SLAVE))) { ++ dev_err(pcdev_to_dev(pcdev), ++ "Unsupported mbus configuration: bus mastering\n"); ++ return -EINVAL; ++ } + +- ret = sensor_call(pcdev, video, g_mbus_config, &cfg); +- if (!ret) { +- common_flags = pxa_mbus_config_compatible(&cfg, +- bus_flags); +- if (!common_flags) { +- dev_warn(pcdev_to_dev(pcdev), +- "Flags incompatible: camera 0x%x, host 0x%lx\n", +- cfg.flags, bus_flags); ++ if (cfg.flags & V4L2_MBUS_DATA_ACTIVE_LOW) { ++ dev_err(pcdev_to_dev(pcdev), ++ "Unsupported mbus configuration: DATA_ACTIVE_LOW\n"); + return -EINVAL; + } +- } else if (ret == -ENOIOCTLCMD) { +- ret = 0; + } + +- return ret; ++ pxa_camera_setup_cicr(pcdev, cfg.flags, pixfmt); ++ ++ return 0; + } + + static const struct pxa_mbus_pixelfmt pxa_camera_formats[] = { +@@ -1738,11 +1656,6 @@ static int pxa_camera_get_formats(struct + return 0; + } + +- /* This also checks support for the requested bits-per-sample */ +- ret = pxa_camera_try_bus_param(pcdev, fmt->bits_per_sample); +- if (ret < 0) +- return 0; +- + switch (code.code) { + case MEDIA_BUS_FMT_UYVY8_2X8: + formats++; |