summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiu Ying <victor.liu@nxp.com>2017-06-19 11:39:56 +0800
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-24 12:41:33 +0300
commitb33d51329cb4a2eccf131858ff13d120896b6dda (patch)
treed3a2e9e4978060f6c56a90e6001dc3648516d69d
parent4358277f999d6edee93077acb63fd7409bbbb487 (diff)
MLK-15110-15 gpu: imx: dpu: fetchdecode: Add DPR support
This patch adds DPR support for fetchdecode in the DPU base driver. Signed-off-by: Liu Ying <victor.liu@nxp.com>
-rw-r--r--Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt5
-rw-r--r--drivers/gpu/imx/dpu/dpu-common.c56
-rw-r--r--drivers/gpu/imx/dpu/dpu-fetchdecode.c149
-rw-r--r--drivers/gpu/imx/dpu/dpu-prv.h8
-rw-r--r--include/video/dpu.h33
5 files changed, 251 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
index 9365b54c7c29..de3616775fa1 100644
--- a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
+++ b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
@@ -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>;
diff --git a/drivers/gpu/imx/dpu/dpu-common.c b/drivers/gpu/imx/dpu/dpu-common.c
index 4328301edec2..b2fc8835b016 100644
--- a/drivers/gpu/imx/dpu/dpu-common.c
+++ b/drivers/gpu/imx/dpu/dpu-common.c
@@ -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);
diff --git a/drivers/gpu/imx/dpu/dpu-fetchdecode.c b/drivers/gpu/imx/dpu/dpu-fetchdecode.c
index fe5dd37dbedf..b4ec261d1688 100644
--- a/drivers/gpu/imx/dpu/dpu-fetchdecode.c
+++ b/drivers/gpu/imx/dpu/dpu-fetchdecode.c
@@ -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;
+}
diff --git a/drivers/gpu/imx/dpu/dpu-prv.h b/drivers/gpu/imx/dpu/dpu-prv.h
index b18e5b628b41..d6111b933e4a 100644
--- a/drivers/gpu/imx/dpu/dpu-prv.h
+++ b/drivers/gpu/imx/dpu/dpu-prv.h
@@ -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;
diff --git a/include/video/dpu.h b/include/video/dpu.h
index 71bb34632783..45d253e210dc 100644
--- a/include/video/dpu.h
+++ b/include/video/dpu.h
@@ -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);