MLK-15110-15 gpu: imx: dpu: fetchdecode: Add DPR support
authorLiu Ying <victor.liu@nxp.com>
Mon, 19 Jun 2017 03:39:56 +0000 (11:39 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Tue, 20 Mar 2018 19:50:50 +0000 (14:50 -0500)
This patch adds DPR support for fetchdecode in the DPU base driver.

Signed-off-by: Liu Ying <victor.liu@nxp.com>
Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
drivers/gpu/imx/dpu/dpu-common.c
drivers/gpu/imx/dpu/dpu-fetchdecode.c
drivers/gpu/imx/dpu/dpu-prv.h
include/video/dpu.h

index 9365b54..de36167 100644 (file)
@@ -74,6 +74,8 @@ Required properties:
   Documentation/devicetree/bindings/clock/imx8qm-clock.txt, and in
   Documentation/devicetree/bindings/clock/imx8qxp-clock.txt.
 - power-domains: phandle pointing to power domain.
+- fsl,dpr-channels: phandles to the DPR channels attached to this DPU,
+  sorted by memory map addresses.  Only valid for i.MX8qm and i.MX8qxp.
 Optional properties:
 - port@[0-1]: Port nodes with endpoint definitions as defined in
   Documentation/devicetree/bindings/media/video-interfaces.txt.
@@ -110,6 +112,9 @@ dpu: dpu@56180000 {
                 <&clk IMX8QM_DC0_DISP1_CLK>;
        clock-names = "pll0", "pll1", "disp0", "disp1";
        power-domains = <&pd_dc0>;
+       fsl,dpr-channels = <&dpr1_channel1>, <&dpr1_channel2>,
+                          <&dpr1_channel3>, <&dpr2_channel1>,
+                          <&dpr2_channel2>, <&dpr2_channel3>;
 
        dpu1_disp1: port@1 {
                reg = <1>;
index 4328301..b2fc883 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/clk.h>
 #include <linux/fb.h>
 #include <linux/io.h>
+#include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqdomain.h>
@@ -26,6 +27,7 @@
 #include <linux/regmap.h>
 #include <soc/imx8/sc/sci.h>
 #include <video/dpu.h>
+#include <video/imx8-prefetch.h>
 #include "dpu-prv.h"
 
 static bool display_plane_video_proc = true;
@@ -264,6 +266,7 @@ static const struct dpu_unit fds_v2 = {
        .ids = fd_ids,
        .pec_ofss = fd_pec_ofss_v2,
        .ofss = fd_ofss_v2,
+       .dprc_ids = fd_dprc_ids,
 };
 
 static const struct dpu_unit fes_v1 = {
@@ -512,6 +515,7 @@ static const struct dpu_devtype dpu_type_v1 = {
        .intsteer_map_size = ARRAY_SIZE(intsteer_map_v1),
        .unused_irq = unused_irq_v1,
        .has_capture = true,
+       .has_prefetch = false,
        .pixel_link_quirks = false,
        .pixel_link_nhvsync = false,
        .version = DPU_V1,
@@ -537,6 +541,7 @@ static const struct dpu_devtype dpu_type_v2 = {
        .sw2hw_irq_map = sw2hw_irq_map_v2,
        .sw2hw_block_id_map = sw2hw_block_id_map_v2,
        .has_capture = false,
+       .has_prefetch = true,
        .pixel_link_quirks = true,
        .pixel_link_nhvsync = true,
        .version = DPU_V2,
@@ -714,6 +719,7 @@ static int dpu_submodules_init(struct dpu_soc *dpu,
                struct platform_device *pdev, unsigned long dpu_base)
 {
        const struct dpu_devtype *devtype = dpu->devtype;
+       const struct dpu_unit *fds = devtype->fds;
 
        DPU_UNITS_INIT(cf);
        DPU_UNITS_INIT(dec);
@@ -727,6 +733,25 @@ static int dpu_submodules_init(struct dpu_soc *dpu,
        DPU_UNITS_INIT(tcon);
        DPU_UNITS_INIT(vs);
 
+       /* get DPR channel for submodules */
+       if (devtype->has_prefetch) {
+               struct dpu_fetchdecode *fd;
+               struct dprc *dprc;
+               int i;
+
+               for (i = 0; i < fds->num; i++) {
+                       dprc = dprc_lookup_by_phandle(dpu->dev,
+                                                     "fsl,dpr-channels",
+                                                     fds->dprc_ids[i]);
+                       if (!dprc)
+                               return -EPROBE_DEFER;
+
+                       fd = dpu_fd_get(dpu, i);
+                       fetchdecode_get_dprc(fd, dprc);
+                       dpu_fd_put(fd);
+               }
+       }
+
        return 0;
 }
 
@@ -1238,6 +1263,18 @@ irq_set_chained_handler_and_data(dpu->irq_##name, NULL, NULL)
        irq_domain_remove(dpu->domain);
 }
 
+static irqreturn_t dpu_dpr1_irq_handler(int irq, void *desc)
+{
+       struct dpu_soc *dpu = desc;
+       const struct dpu_unit *fds = dpu->devtype->fds;
+       int i;
+
+       for (i = 0; i < fds->num; i++)
+               fetchdecode_prefetch_irq_handle(dpu->fd_priv[i]);
+
+       return IRQ_HANDLED;
+}
+
 static void dpu_debug_ip_identity(struct dpu_soc *dpu)
 {
        struct device *dev = dpu->dev;
@@ -1484,6 +1521,25 @@ static int dpu_probe(struct platform_device *pdev)
                return PTR_ERR(dpu->intsteer_regmap);
        }
 
+       /* DPR irqs */
+       if (dpu->devtype->has_prefetch) {
+               dpu->irq_dpr0 = platform_get_irq(pdev, 8);
+               dpu->irq_dpr1 = platform_get_irq(pdev, 9);
+
+               dev_dbg(dpu->dev, "irq_dpr0: %d\n", dpu->irq_dpr0);
+               dev_dbg(dpu->dev, "irq_dpr1: %d\n", dpu->irq_dpr1);
+
+               if (dpu->irq_dpr0 < 0 || dpu->irq_dpr1 < 0)
+                       return -ENODEV;
+
+               ret = devm_request_irq(dpu->dev, dpu->irq_dpr1,
+                               dpu_dpr1_irq_handler, 0, pdev->name, dpu);
+               if (ret) {
+                       dev_err(dpu->dev, "request dpr1 interrupt failed\n");
+                       return ret;
+               }
+       }
+
        spin_lock_init(&dpu->lock);
        spin_lock_init(&dpu->intsteer_lock);
 
index fe5dd37..b4ec261 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/types.h>
 #include <video/dpu.h>
+#include <video/imx8-prefetch.h>
 #include "dpu-prv.h"
 
 #define FD_NUM_V1                      4
@@ -102,11 +103,13 @@ struct dpu_fetchdecode {
        struct mutex mutex;
        int id;
        bool inuse;
+       bool pin_off;
        struct dpu_soc *dpu;
        fetchtype_t fetchtype;
        shadow_load_req_t shdlreq;
        /* see DPU_PLANE_SRC_xxx */
        unsigned int stream_id;
+       struct dprc *dprc;
 };
 
 static inline u32 dpu_pec_fd_read(struct dpu_fetchdecode *fd,
@@ -675,6 +678,144 @@ void fetchdecode_set_stream_id(struct dpu_fetchdecode *fd, unsigned int id)
 }
 EXPORT_SYMBOL_GPL(fetchdecode_set_stream_id);
 
+void
+fetchdecode_configure_prefetch(struct dpu_fetchdecode *fd,
+                              unsigned int stream_id,
+                              unsigned int width, unsigned int height,
+                              unsigned int x_offset, unsigned int y_offset,
+                              unsigned int stride, u32 format, u64 modifier,
+                              unsigned long baddr, unsigned long uv_baddr,
+                              bool start, bool aux_start)
+{
+       if (WARN_ON(!fd || !fd->dprc))
+               return;
+
+       dprc_configure(fd->dprc,
+                       stream_id, width, height, x_offset, y_offset, stride,
+                       format, modifier, baddr, uv_baddr, start, aux_start);
+}
+EXPORT_SYMBOL_GPL(fetchdecode_configure_prefetch);
+
+void fetchdecode_enable_prefetch(struct dpu_fetchdecode *fd)
+{
+       if (WARN_ON(!fd || !fd->dprc))
+               return;
+
+       dprc_enable(fd->dprc);
+}
+EXPORT_SYMBOL_GPL(fetchdecode_enable_prefetch);
+
+void fetchdecode_disable_prefetch(struct dpu_fetchdecode *fd)
+{
+       if (WARN_ON(!fd || !fd->dprc))
+               return;
+
+       dprc_disable(fd->dprc);
+}
+EXPORT_SYMBOL_GPL(fetchdecode_disable_prefetch);
+
+void fetchdecode_reg_update_prefetch(struct dpu_fetchdecode *fd)
+{
+       if (WARN_ON(!fd || !fd->dprc))
+               return;
+
+       dprc_reg_update(fd->dprc);
+}
+EXPORT_SYMBOL_GPL(fetchdecode_reg_update_prefetch);
+
+void fetchdecode_prefetch_irq_handle(struct dpu_fetchdecode *fd)
+{
+       if (WARN_ON(!fd || !fd->dprc))
+               return;
+
+       dprc_irq_handle(fd->dprc);
+}
+EXPORT_SYMBOL_GPL(fetchdecode_prefetch_irq_handle);
+
+void fetchdecode_prefetch_enable_first_frame_irq(struct dpu_fetchdecode *fd)
+{
+       if (WARN_ON(!fd || !fd->dprc))
+               return;
+
+       dprc_enable_ctrl_done_irq(fd->dprc);
+}
+EXPORT_SYMBOL_GPL(fetchdecode_prefetch_enable_first_frame_irq);
+
+bool fetchdecode_has_prefetch(struct dpu_fetchdecode *fd)
+{
+       return !!fd->dprc;
+}
+EXPORT_SYMBOL_GPL(fetchdecode_has_prefetch);
+
+bool fetchdecode_prefetch_format_supported(struct dpu_fetchdecode *fd,
+                                          u32 format, u64 modifier)
+{
+       if (WARN_ON(!fd || !fd->dprc))
+               return false;
+
+       return dprc_format_supported(fd->dprc, format, modifier);
+}
+EXPORT_SYMBOL_GPL(fetchdecode_prefetch_format_supported);
+
+bool fetchdecode_prefetch_stride_supported(struct dpu_fetchdecode *fd,
+                                          unsigned int stride,
+                                          unsigned int uv_stride,
+                                          unsigned int width,
+                                          u32 format)
+{
+       if (WARN_ON(!fd || !fd->dprc))
+               return false;
+
+       return dprc_stride_supported(fd->dprc,
+                                       stride, uv_stride, width, format);
+}
+EXPORT_SYMBOL_GPL(fetchdecode_prefetch_stride_supported);
+
+bool fetchdecode_prefetch_crop_supported(struct dpu_fetchdecode *fd,
+                                        u64 modifier, u32 y_offset)
+{
+       if (WARN_ON(!fd || !fd->dprc))
+               return false;
+
+       return dprc_crop_supported(fd->dprc, modifier, y_offset);
+}
+EXPORT_SYMBOL_GPL(fetchdecode_prefetch_crop_supported);
+
+bool fetchdecode_prefetch_stride_double_check(struct dpu_fetchdecode *fd,
+                                             unsigned int stride,
+                                             unsigned int uv_stride,
+                                             unsigned int width,
+                                             u32 format,
+                                             dma_addr_t baseaddr,
+                                             dma_addr_t uv_baseaddr)
+{
+       if (WARN_ON(!fd || !fd->dprc))
+               return false;
+
+       return dprc_stride_double_check(fd->dprc,
+                                       stride, uv_stride, width, format,
+                                       baseaddr, uv_baseaddr);
+}
+EXPORT_SYMBOL_GPL(fetchdecode_prefetch_stride_double_check);
+
+void fetchdecode_pin_off(struct dpu_fetchdecode *fd)
+{
+       fd->pin_off = true;
+}
+EXPORT_SYMBOL_GPL(fetchdecode_pin_off);
+
+void fetchdecode_unpin_off(struct dpu_fetchdecode *fd)
+{
+       fd->pin_off = false;
+}
+EXPORT_SYMBOL_GPL(fetchdecode_unpin_off);
+
+bool fetchdecode_is_pinned_off(struct dpu_fetchdecode *fd)
+{
+       return fd->pin_off;
+}
+EXPORT_SYMBOL_GPL(fetchdecode_is_pinned_off);
+
 struct dpu_fetchdecode *dpu_fd_get(struct dpu_soc *dpu, int id)
 {
        struct dpu_fetchdecode *fd;
@@ -780,3 +921,11 @@ int dpu_fd_init(struct dpu_soc *dpu, unsigned int id,
 
        return 0;
 }
+
+void fetchdecode_get_dprc(struct dpu_fetchdecode *fd, void *data)
+{
+       if (WARN_ON(!fd))
+               return;
+
+       fd->dprc = data;
+}
index b18e5b6..d6111b9 100644 (file)
@@ -155,6 +155,7 @@ struct dpu_unit {
        const unsigned int *ids;
        const unsigned long *pec_ofss;  /* PixEngCFG */
        const unsigned long *ofss;
+       const unsigned int *dprc_ids;
 };
 
 struct cm_reg_ofs {
@@ -193,6 +194,7 @@ struct dpu_devtype {
        const unsigned int *sw2hw_irq_map;      /* NULL means linear */
        const unsigned int *sw2hw_block_id_map; /* NULL means linear */
        bool has_capture;
+       bool has_prefetch;
        bool pixel_link_quirks;
        bool pixel_link_nhvsync;        /* HSYNC and VSYNC high active */
        unsigned int version;
@@ -217,6 +219,8 @@ struct dpu_soc {
        int                     irq_reserved0;
        int                     irq_reserved1;
        int                     irq_blit;
+       int                     irq_dpr0;
+       int                     irq_dpr1;
        struct irq_domain       *domain;
 
        struct dpu_constframe   *cf_priv[4];
@@ -269,6 +273,8 @@ DECLARE_DPU_UNIT_INIT_FUNC(lb);
 DECLARE_DPU_UNIT_INIT_FUNC(tcon);
 DECLARE_DPU_UNIT_INIT_FUNC(vs);
 
+void fetchdecode_get_dprc(struct dpu_fetchdecode *fd, void *data);
+
 static const unsigned int cf_ids[] = {0, 1, 4, 5};
 static const unsigned int dec_ids[] = {0, 1};
 static const unsigned int ed_ids[] = {0, 1, 4, 5};
@@ -281,6 +287,8 @@ static const unsigned int lb_ids[] = {0, 1, 2, 3, 4, 5, 6};
 static const unsigned int tcon_ids[] = {0, 1};
 static const unsigned int vs_ids[] = {4, 5, 9};
 
+static const unsigned int fd_dprc_ids[] = {3, 4};
+
 struct dpu_pixel_format {
        u32 pixel_format;
        u32 bits;
index 71bb346..45d253e 100644 (file)
@@ -500,6 +500,39 @@ u32 fetchdecode_get_vproc_mask(struct dpu_fetchdecode *fd);
 bool fetchdecode_need_fetcheco(struct dpu_fetchdecode *fd, u32 fmt);
 unsigned int fetchdecode_get_stream_id(struct dpu_fetchdecode *fd);
 void fetchdecode_set_stream_id(struct dpu_fetchdecode *fd, unsigned int id);
+void
+fetchdecode_configure_prefetch(struct dpu_fetchdecode *fd,
+                              unsigned int stream_id,
+                              unsigned int width, unsigned int height,
+                              unsigned int x_offset, unsigned int y_offset,
+                              unsigned int stride, u32 format, u64 modifier,
+                              unsigned long baddr, unsigned long uv_baddr,
+                              bool start, bool aux_start);
+void fetchdecode_enable_prefetch(struct dpu_fetchdecode *fd);
+void fetchdecode_disable_prefetch(struct dpu_fetchdecode *fd);
+void fetchdecode_reg_update_prefetch(struct dpu_fetchdecode *fd);
+void fetchdecode_prefetch_irq_handle(struct dpu_fetchdecode *fd);
+void fetchdecode_prefetch_enable_first_frame_irq(struct dpu_fetchdecode *fd);
+bool fetchdecode_has_prefetch(struct dpu_fetchdecode *fd);
+bool fetchdecode_prefetch_format_supported(struct dpu_fetchdecode *fd,
+                                          u32 format, u64 modifier);
+bool fetchdecode_prefetch_stride_supported(struct dpu_fetchdecode *fd,
+                                          unsigned int stride,
+                                          unsigned int uv_stride,
+                                          unsigned int width,
+                                          u32 format);
+bool fetchdecode_prefetch_crop_supported(struct dpu_fetchdecode *fd,
+                                        u64 modifier, u32 y_offset);
+bool fetchdecode_prefetch_stride_double_check(struct dpu_fetchdecode *fd,
+                                             unsigned int stride,
+                                             unsigned int uv_stride,
+                                             unsigned int width,
+                                             u32 format,
+                                             dma_addr_t baseaddr,
+                                             dma_addr_t uv_baseaddr);
+void fetchdecode_pin_off(struct dpu_fetchdecode *fd);
+void fetchdecode_unpin_off(struct dpu_fetchdecode *fd);
+bool fetchdecode_is_pinned_off(struct dpu_fetchdecode *fd);
 struct dpu_fetchdecode *dpu_fd_get(struct dpu_soc *dpu, int id);
 void dpu_fd_put(struct dpu_fetchdecode *fd);