brcm2708: update to latest patches from RPi Foundation
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-4.19 / 950-0730-media-bcm2835-unicam-Support-unpacking-CSI-format-to.patch
diff --git a/target/linux/brcm2708/patches-4.19/950-0730-media-bcm2835-unicam-Support-unpacking-CSI-format-to.patch b/target/linux/brcm2708/patches-4.19/950-0730-media-bcm2835-unicam-Support-unpacking-CSI-format-to.patch
new file mode 100644 (file)
index 0000000..199c496
--- /dev/null
@@ -0,0 +1,254 @@
+From 5ae0488f5fc682877ae2a5d454f70884e62120ef Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 3 Oct 2019 13:35:01 +0100
+Subject: [PATCH] media: bcm2835-unicam: Support unpacking CSI format
+ to 16bpp
+
+The CSI packed formats are not the easiest to work with, and
+the peripheral supports unpacking them to 16bpp (but NOT
+shifting the data up into the MSBs).
+Where V4L2 exposes a pixfmt for both packed and unpacked
+formats advertise both as being supported, and unpack the
+data in the peripheral.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 102 +++++++++---------
+ 1 file changed, 51 insertions(+), 51 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -15,12 +15,15 @@
+  *
+  * This driver directly controls the Unicam peripheral - there is no
+  * involvement with the VideoCore firmware. Unicam receives CSI-2 or
+- * CCP2 data and writes it into SDRAM. The only potential processing options are
+- * to repack Bayer data into an alternate format, and applying windowing.
+- * The repacking does not shift the data, so could repack V4L2_PIX_FMT_Sxxxx10P
++ * CCP2 data and writes it into SDRAM.
++ * The only potential processing options are to repack Bayer data into an
++ * alternate format, and applying windowing.
++ * The repacking does not shift the data, so can repack V4L2_PIX_FMT_Sxxxx10P
+  * to V4L2_PIX_FMT_Sxxxx10, or V4L2_PIX_FMT_Sxxxx12P to V4L2_PIX_FMT_Sxxxx12,
+- * but not generically up to V4L2_PIX_FMT_Sxxxx16.
+- * Adding support for repacking and windowing may be added later.
++ * but not generically up to V4L2_PIX_FMT_Sxxxx16. The driver will add both
++ * formats where the relevant formats are defined, and will automatically
++ * configure the repacking as required.
++ * Support for windowing may be added later.
+  *
+  * It should be possible to connect this driver to any sensor with a
+  * suitable output interface and V4L2 subdevice driver.
+@@ -122,13 +125,16 @@ MODULE_PARM_DESC(debug, "Debug level 0-3
+ /*
+  * struct unicam_fmt - Unicam media bus format information
+- * @pixelformat: V4L2 pixel format FCC identifier.
++ * @pixelformat: V4L2 pixel format FCC identifier. 0 if n/a.
++ * @repacked_fourcc: V4L2 pixel format FCC identifier if the data is expanded
++ * out to 16bpp. 0 if n/a.
+  * @code: V4L2 media bus format code.
+- * @depth: Bits per pixel (when stored in memory).
++ * @depth: Bits per pixel as delivered from the source.
+  * @csi_dt: CSI data type.
+  */
+ struct unicam_fmt {
+       u32     fourcc;
++      u32     repacked_fourcc;
+       u32     code;
+       u8      depth;
+       u8      csi_dt;
+@@ -235,41 +241,49 @@ static const struct unicam_fmt formats[]
+               .csi_dt         = 0x2a,
+       }, {
+               .fourcc         = V4L2_PIX_FMT_SBGGR10P,
++              .repacked_fourcc = V4L2_PIX_FMT_SBGGR10,
+               .code           = MEDIA_BUS_FMT_SBGGR10_1X10,
+               .depth          = 10,
+               .csi_dt         = 0x2b,
+       }, {
+               .fourcc         = V4L2_PIX_FMT_SGBRG10P,
++              .repacked_fourcc = V4L2_PIX_FMT_SGBRG10,
+               .code           = MEDIA_BUS_FMT_SGBRG10_1X10,
+               .depth          = 10,
+               .csi_dt         = 0x2b,
+       }, {
+               .fourcc         = V4L2_PIX_FMT_SGRBG10P,
++              .repacked_fourcc = V4L2_PIX_FMT_SGRBG10,
+               .code           = MEDIA_BUS_FMT_SGRBG10_1X10,
+               .depth          = 10,
+               .csi_dt         = 0x2b,
+       }, {
+               .fourcc         = V4L2_PIX_FMT_SRGGB10P,
++              .repacked_fourcc = V4L2_PIX_FMT_SRGGB10,
+               .code           = MEDIA_BUS_FMT_SRGGB10_1X10,
+               .depth          = 10,
+               .csi_dt         = 0x2b,
+       }, {
+               .fourcc         = V4L2_PIX_FMT_SBGGR12P,
++              .repacked_fourcc = V4L2_PIX_FMT_SBGGR12,
+               .code           = MEDIA_BUS_FMT_SBGGR12_1X12,
+               .depth          = 12,
+               .csi_dt         = 0x2c,
+       }, {
+               .fourcc         = V4L2_PIX_FMT_SGBRG12P,
++              .repacked_fourcc = V4L2_PIX_FMT_SGBRG12,
+               .code           = MEDIA_BUS_FMT_SGBRG12_1X12,
+               .depth          = 12,
+               .csi_dt         = 0x2c,
+       }, {
+               .fourcc         = V4L2_PIX_FMT_SGRBG12P,
++              .repacked_fourcc = V4L2_PIX_FMT_SGRBG12,
+               .code           = MEDIA_BUS_FMT_SGRBG12_1X12,
+               .depth          = 12,
+               .csi_dt         = 0x2c,
+       }, {
+               .fourcc         = V4L2_PIX_FMT_SRGGB12P,
++              .repacked_fourcc = V4L2_PIX_FMT_SRGGB12,
+               .code           = MEDIA_BUS_FMT_SRGGB12_1X12,
+               .depth          = 12,
+               .csi_dt         = 0x2c,
+@@ -439,20 +453,6 @@ static inline void unicam_runtime_put(st
+ }
+ /* Format setup functions */
+-static int find_mbus_depth_by_code(u32 code)
+-{
+-      const struct unicam_fmt *fmt;
+-      unsigned int k;
+-
+-      for (k = 0; k < ARRAY_SIZE(formats); k++) {
+-              fmt = &formats[k];
+-              if (fmt->code == code)
+-                      return fmt->depth;
+-      }
+-
+-      return 0;
+-}
+-
+ static const struct unicam_fmt *find_format_by_code(u32 code)
+ {
+       unsigned int k;
+@@ -470,7 +470,8 @@ static const struct unicam_fmt *find_for
+       unsigned int k;
+       for (k = 0; k < ARRAY_SIZE(formats); k++) {
+-              if (formats[k].fourcc == pixelformat)
++              if (formats[k].fourcc == pixelformat ||
++                  formats[k].repacked_fourcc == pixelformat)
+                       return &formats[k];
+       }
+@@ -478,9 +479,14 @@ static const struct unicam_fmt *find_for
+ }
+ static inline unsigned int bytes_per_line(u32 width,
+-                                        const struct unicam_fmt *fmt)
++                                        const struct unicam_fmt *fmt,
++                                        u32 v4l2_fourcc)
+ {
+-      return ALIGN((width * fmt->depth) >> 3, BPL_ALIGNMENT);
++      if (v4l2_fourcc == fmt->repacked_fourcc)
++              /* Repacking always goes to 16bpp */
++              return ALIGN(width << 1, BPL_ALIGNMENT);
++      else
++              return ALIGN((width * fmt->depth) >> 3, BPL_ALIGNMENT);
+ }
+ static int __subdev_get_format(struct unicam_device *dev,
+@@ -538,7 +544,8 @@ static int unicam_calc_format_size_bpl(s
+                             &f->fmt.pix.height, MIN_HEIGHT, MAX_HEIGHT, 0,
+                             0);
+-      min_bytesperline = bytes_per_line(f->fmt.pix.width, fmt);
++      min_bytesperline = bytes_per_line(f->fmt.pix.width, fmt,
++                                        f->fmt.pix.pixelformat);
+       if (f->fmt.pix.bytesperline > min_bytesperline &&
+           f->fmt.pix.bytesperline <= MAX_BYTESPERLINE)
+@@ -738,6 +745,13 @@ static int unicam_enum_fmt_vid_cap(struc
+                               }
+                               index++;
+                       }
++                      if (fmt->repacked_fourcc) {
++                              if (index == f->index) {
++                                      f->pixelformat = fmt->repacked_fourcc;
++                                      break;
++                              }
++                              index++;
++                      }
+               }
+       }
+@@ -858,7 +872,10 @@ static int unicam_try_fmt_vid_cap(struct
+                       }
+               }
+-              f->fmt.pix.pixelformat = fmt->fourcc;
++              if (fmt->fourcc)
++                      f->fmt.pix.pixelformat = fmt->fourcc;
++              else
++                      f->fmt.pix.pixelformat = fmt->repacked_fourcc;
+       }
+       return unicam_calc_format_size_bpl(dev, fmt, f);
+@@ -998,16 +1015,14 @@ static void unicam_wr_dma_config(struct
+ static void unicam_set_packing_config(struct unicam_device *dev)
+ {
+-      int mbus_depth = find_mbus_depth_by_code(dev->fmt->code);
+-      int v4l2_depth = dev->fmt->depth;
+       int pack, unpack;
+       u32 val;
+-      if (mbus_depth == v4l2_depth) {
++      if (dev->v_fmt.fmt.pix.pixelformat == dev->fmt->fourcc) {
+               unpack = UNICAM_PUM_NONE;
+               pack = UNICAM_PPM_NONE;
+       } else {
+-              switch (mbus_depth) {
++              switch (dev->fmt->depth) {
+               case 8:
+                       unpack = UNICAM_PUM_UNPACK8;
+                       break;
+@@ -1028,26 +1043,8 @@ static void unicam_set_packing_config(st
+                       break;
+               }
+-              switch (v4l2_depth) {
+-              case 8:
+-                      pack = UNICAM_PPM_PACK8;
+-                      break;
+-              case 10:
+-                      pack = UNICAM_PPM_PACK10;
+-                      break;
+-              case 12:
+-                      pack = UNICAM_PPM_PACK12;
+-                      break;
+-              case 14:
+-                      pack = UNICAM_PPM_PACK14;
+-                      break;
+-              case 16:
+-                      pack = UNICAM_PPM_PACK16;
+-                      break;
+-              default:
+-                      pack = UNICAM_PPM_NONE;
+-                      break;
+-              }
++              /* Repacking is always to 16bpp */
++              pack = UNICAM_PPM_PACK16;
+       }
+       val = 0;
+@@ -1893,7 +1890,10 @@ static int unicam_probe_complete(struct
+       }
+       unicam->fmt = fmt;
+-      unicam->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
++      if (fmt->fourcc)
++              unicam->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
++      else
++              unicam->v_fmt.fmt.pix.pixelformat = fmt->repacked_fourcc;
+       /* Read current subdev format */
+       unicam_reset_format(unicam);