diff options
author | Liu Ying <victor.liu@nxp.com> | 2017-06-19 11:39:56 +0800 |
---|---|---|
committer | Leonard Crestez <leonard.crestez@nxp.com> | 2018-08-24 12:41:33 +0300 |
commit | b33d51329cb4a2eccf131858ff13d120896b6dda (patch) | |
tree | d3a2e9e4978060f6c56a90e6001dc3648516d69d | |
parent | 4358277f999d6edee93077acb63fd7409bbbb487 (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.txt | 5 | ||||
-rw-r--r-- | drivers/gpu/imx/dpu/dpu-common.c | 56 | ||||
-rw-r--r-- | drivers/gpu/imx/dpu/dpu-fetchdecode.c | 149 | ||||
-rw-r--r-- | drivers/gpu/imx/dpu/dpu-prv.h | 8 | ||||
-rw-r--r-- | include/video/dpu.h | 33 |
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); |