]> rtime.felk.cvut.cz Git - vajnamar/linux-xlnx.git/commitdiff
dma: xilinx: Add private API to permit retrieval of supported mem formats
authorJeffrey Mouroux <jeff.mouroux@xilinx.com>
Wed, 6 Sep 2017 23:32:59 +0000 (16:32 -0700)
committerMichal Simek <michal.simek@xilinx.com>
Fri, 8 Sep 2017 06:40:45 +0000 (08:40 +0200)
The video Framebuffer DMA IP requires clients to send a fourcc code
to indicate the memory format layout.  The IP can be configured to support
a variety of memory formats ranging from YUYV, RGB and in either 8 bit
or 10 bit formats.  There has been no method for clients to obtain
this list of supported formats.  This patch adds private APIs that
can be called from clients to retrieve this list so that user space
applications can choose from any of the available memory formats.

Depends on patch 13fd162 (dma: xilinx: Bug fix to ensure only video formats
enabled in IP are in driver)

Signed-off-by: Jeffrey Mouroux <jmouroux@xilinx.com>
Reviewed-by: Hyun Kwon <hyun.kwon@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/dma/xilinx/xilinx_frmbuf.c
include/linux/dma/xilinx_frmbuf.h

index eb32e96948a849fc7f4c110132f605b25bd5d2f0..54ab68e34eee19d3a492465610057a814a83f318 100644 (file)
@@ -148,24 +148,6 @@ struct xilinx_frmbuf_chan {
        const struct xilinx_frmbuf_format_desc *vid_fmt;
 };
 
-/**
- * struct xilinx_frmbuf_device - dma device structure
- * @regs: I/O mapped base address
- * @dev: Device Structure
- * @common: DMA device structure
- * @chan: Driver specific dma channel
- * @rst_gpio: GPIO reset
- * @enabled_vid_fmts: Bitmask of video formats enabled in hardware
- */
-struct xilinx_frmbuf_device {
-       void __iomem *regs;
-       struct device *dev;
-       struct dma_device common;
-       struct xilinx_frmbuf_chan chan;
-       struct gpio_desc *rst_gpio;
-       u32 enabled_vid_fmts;
-};
-
 /**
  * struct xilinx_frmbuf_format_desc - lookup table to match fourcc to format
  * @dts_name: Device tree name for this entry.
@@ -265,6 +247,32 @@ static const struct xilinx_frmbuf_format_desc xilinx_frmbuf_formats[] = {
        },
 };
 
+/**
+ * struct xilinx_frmbuf_device - dma device structure
+ * @regs: I/O mapped base address
+ * @dev: Device Structure
+ * @common: DMA device structure
+ * @chan: Driver specific dma channel
+ * @rst_gpio: GPIO reset
+ * @enabled_vid_fmts: Bitmask of video formats enabled in hardware
+ * @drm_memory_fmts: Array of supported DRM fourcc codes
+ * @drm_fmt_cnt: Count of supported DRM fourcc codes
+ * @v4l2_memory_fmts: Array of supported V4L2 fourcc codes
+ * @v4l2_fmt_cnt: Count of supported V4L2 fourcc codes
+ */
+struct xilinx_frmbuf_device {
+       void __iomem *regs;
+       struct device *dev;
+       struct dma_device common;
+       struct xilinx_frmbuf_chan chan;
+       struct gpio_desc *rst_gpio;
+       u32 enabled_vid_fmts;
+       u32 drm_memory_fmts[ARRAY_SIZE(xilinx_frmbuf_formats)];
+       u32 drm_fmt_cnt;
+       u32 v4l2_memory_fmts[ARRAY_SIZE(xilinx_frmbuf_formats)];
+       u32 v4l2_fmt_cnt;
+};
+
 static const struct of_device_id xilinx_frmbuf_of_ids[] = {
        { .compatible = "xlnx,axi-frmbuf-wr-v2",
                .data = (void *)DMA_DEV_TO_MEM},
@@ -321,6 +329,49 @@ static inline void frmbuf_set(struct xilinx_frmbuf_chan *chan, u32 reg,
        frmbuf_write(chan, reg, frmbuf_read(chan, reg) | set);
 }
 
+static void frmbuf_init_format_array(struct xilinx_frmbuf_device *xdev)
+{
+       u32 i, cnt;
+
+       for (i = 0; i < ARRAY_SIZE(xilinx_frmbuf_formats); i++) {
+               if (!(xdev->enabled_vid_fmts &
+                     xilinx_frmbuf_formats[i].fmt_bitmask))
+                       continue;
+
+               if (xilinx_frmbuf_formats[i].drm_fmt) {
+                       cnt = xdev->drm_fmt_cnt++;
+                       xdev->drm_memory_fmts[cnt] =
+                               xilinx_frmbuf_formats[i].drm_fmt;
+               }
+
+               if (xilinx_frmbuf_formats[i].v4l2_fmt) {
+                       cnt = xdev->v4l2_fmt_cnt++;
+                       xdev->v4l2_memory_fmts[cnt] =
+                               xilinx_frmbuf_formats[i].v4l2_fmt;
+               }
+       }
+}
+
+static struct xilinx_frmbuf_device *frmbuf_find_dev(struct dma_chan *chan)
+{
+       struct xilinx_frmbuf_chan *xchan, *temp;
+       struct xilinx_frmbuf_device *xdev;
+       bool is_frmbuf_chan = false;
+
+       list_for_each_entry_safe(xchan, temp, &frmbuf_chan_list, chan_node) {
+               if (chan == &xchan->common)
+                       is_frmbuf_chan = true;
+       }
+
+       if (!is_frmbuf_chan)
+               return ERR_PTR(-ENODEV);
+
+       xchan = to_xilinx_chan(chan);
+       xdev = container_of(xchan, struct xilinx_frmbuf_device, chan);
+
+       return xdev;
+}
+
 static int frmbuf_verify_format(struct dma_chan *chan, u32 fourcc, u32 type)
 {
        struct xilinx_frmbuf_chan *xil_chan = to_xilinx_chan(chan);
@@ -385,6 +436,40 @@ void xilinx_xdma_v4l2_config(struct dma_chan *chan, u32 v4l2_fourcc)
 
 } EXPORT_SYMBOL_GPL(xilinx_xdma_v4l2_config);
 
+int xilinx_xdma_get_drm_vid_fmts(struct dma_chan *chan, u32 *fmt_cnt,
+                                u32 **fmts)
+{
+       struct xilinx_frmbuf_device *xdev;
+
+       xdev = frmbuf_find_dev(chan);
+
+       if (IS_ERR(xdev))
+               return PTR_ERR(xdev);
+
+       *fmt_cnt = xdev->drm_fmt_cnt;
+       *fmts = xdev->drm_memory_fmts;
+
+       return 0;
+}
+EXPORT_SYMBOL(xilinx_xdma_get_drm_vid_fmts);
+
+int xilinx_xdma_get_v4l2_vid_fmts(struct dma_chan *chan, u32 *fmt_cnt,
+                                 u32 **fmts)
+{
+       struct xilinx_frmbuf_device *xdev;
+
+       xdev = frmbuf_find_dev(chan);
+
+       if (IS_ERR(xdev))
+               return PTR_ERR(xdev);
+
+       *fmt_cnt = xdev->v4l2_fmt_cnt;
+       *fmts = xdev->v4l2_memory_fmts;
+
+       return 0;
+}
+EXPORT_SYMBOL(xilinx_xdma_get_v4l2_vid_fmts);
+
 /**
  * of_dma_xilinx_xlate - Translation function
  * @dma_spec: Pointer to DMA specifier as found in the device tree
@@ -1003,6 +1088,9 @@ static int xilinx_frmbuf_probe(struct platform_device *pdev)
                }
        }
 
+       /* Determine supported vid framework formats */
+       frmbuf_init_format_array(xdev);
+
        xdev->common.device_alloc_chan_resources =
                                xilinx_frmbuf_alloc_chan_resources;
        xdev->common.device_free_chan_resources =
index 6356d05eabeb832b27bb284578118fddfc96d34c..0c7160534e889b1a3bcc2ef0000c0c93f8257764 100644 (file)
@@ -48,6 +48,30 @@ void xilinx_xdma_drm_config(struct dma_chan *chan, u32 drm_fourcc);
  * data memory format within the hardware DMA.
  */
 void xilinx_xdma_v4l2_config(struct dma_chan *chan, u32 v4l2_fourcc);
+
+/**
+ * xilinx_xdma_get_drm_vid_fmts - obtain list of supported DRM mem formats
+ * @chan: dma channel instance
+ * @fmt_cnt: Output param - total count of supported DRM fourcc codes
+ * @fmts: Output param - pointer to array of DRM fourcc codes (not a copy)
+ *
+ * Return: a reference to an array of DRM fourcc codes supported by this
+ * instance of the Video Framebuffer Driver
+ */
+int xilinx_xdma_get_drm_vid_fmts(struct dma_chan *chan, u32 *fmt_cnt,
+                                u32 **fmts);
+
+/**
+ * xilinx_xdma_get_v4l2_vid_fmts - obtain list of supported V4L2 mem formats
+ * @chan: dma channel instance
+ * @fmt_cnt: Output param - total count of supported V4L2 fourcc codes
+ * @fmts: Output param - pointer to array of V4L2 fourcc codes (not a copy)
+ *
+ * Return: a reference to an array of V4L2 fourcc codes supported by this
+ * instance of the Video Framebuffer Driver
+ */
+int xilinx_xdma_get_v4l2_vid_fmts(struct dma_chan *chan, u32 *fmt_cnt,
+                                 u32 **fmts);
 #else
 static inline void xilinx_xdma_drm_config(struct dma_chan *chan, u32 drm_fourcc)
 { }
@@ -55,6 +79,18 @@ static inline void xilinx_xdma_drm_config(struct dma_chan *chan, u32 drm_fourcc)
 static inline void xilinx_xdma_v4l2_config(struct dma_chan *chan,
                                           u32 v4l2_fourcc)
 { }
+
+int xilinx_xdma_get_drm_vid_fmts(struct dma_chan *chan, u32 *fmt_cnt,
+                                u32 **fmts);
+{
+       return -ENODEV;
+}
+
+int xilinx_xdma_get_v4l2_vid_fmts(struct dma_chan *chan, u32 *fmt_cnt,
+                                 u32 **fmts);
+{
+       return -ENODEV;
+}
 #endif
 
 #endif /*__XILINX_FRMBUF_DMA_H*/