aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Longerbeam <slongerbeam@gmail.com>2016-08-17 20:50:17 -0400
committerPhilipp Zabel <p.zabel@pengutronix.de>2016-08-29 10:30:23 -0400
commitac4708fab1422905870a1c286e69d784ddc7358c (patch)
tree3fc517d040d264e30de1138fdd6cbb0317e660af
parent2d2ead4530771de0c5f2f7f0a7924deb045c4cce (diff)
gpu: ipu-v3: Add FSU channel linking support
Adds functions to link and unlink source channels to sink channels in the FSU: int ipu_fsu_link(struct ipu_soc *ipu, int src_ch, int sink_ch); int ipu_fsu_unlink(struct ipu_soc *ipu, int src_ch, int sink_ch); The channels numbers are usually IDMAC channels, but they can also be channels that do not transfer data to or from memory. The following convenience functions can be used in place of ipu_fsu_link/unlink() when both source and sink channels are IDMAC channels: int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink); int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink); So far the following links are supported: IPUV3_CHANNEL_IC_PRP_ENC_MEM -> IPUV3_CHANNEL_MEM_ROT_ENC PUV3_CHANNEL_IC_PRP_VF_MEM -> IPUV3_CHANNEL_MEM_ROT_VF IPUV3_CHANNEL_IC_PP_MEM -> IPUV3_CHANNEL_MEM_ROT_PP IPUV3_CHANNEL_CSI_DIRECT -> IPUV3_CHANNEL_CSI_VDI_PREV More links can be added to the fsu_link_info[] array. Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
-rw-r--r--drivers/gpu/ipu-v3/ipu-common.c131
-rw-r--r--drivers/gpu/ipu-v3/ipu-prv.h27
-rw-r--r--include/video/imx-ipu-v3.h13
3 files changed, 171 insertions, 0 deletions
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index 9d3584b3b315..891cbefe2ad4 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -730,6 +730,137 @@ void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi)
730} 730}
731EXPORT_SYMBOL_GPL(ipu_set_ic_src_mux); 731EXPORT_SYMBOL_GPL(ipu_set_ic_src_mux);
732 732
733
734/* Frame Synchronization Unit Channel Linking */
735
736struct fsu_link_reg_info {
737 int chno;
738 u32 reg;
739 u32 mask;
740 u32 val;
741};
742
743struct fsu_link_info {
744 struct fsu_link_reg_info src;
745 struct fsu_link_reg_info sink;
746};
747
748static const struct fsu_link_info fsu_link_info[] = {
749 {
750 .src = { IPUV3_CHANNEL_IC_PRP_ENC_MEM, IPU_FS_PROC_FLOW2,
751 FS_PRP_ENC_DEST_SEL_MASK, FS_PRP_ENC_DEST_SEL_IRT_ENC },
752 .sink = { IPUV3_CHANNEL_MEM_ROT_ENC, IPU_FS_PROC_FLOW1,
753 FS_PRPENC_ROT_SRC_SEL_MASK, FS_PRPENC_ROT_SRC_SEL_ENC },
754 }, {
755 .src = { IPUV3_CHANNEL_IC_PRP_VF_MEM, IPU_FS_PROC_FLOW2,
756 FS_PRPVF_DEST_SEL_MASK, FS_PRPVF_DEST_SEL_IRT_VF },
757 .sink = { IPUV3_CHANNEL_MEM_ROT_VF, IPU_FS_PROC_FLOW1,
758 FS_PRPVF_ROT_SRC_SEL_MASK, FS_PRPVF_ROT_SRC_SEL_VF },
759 }, {
760 .src = { IPUV3_CHANNEL_IC_PP_MEM, IPU_FS_PROC_FLOW2,
761 FS_PP_DEST_SEL_MASK, FS_PP_DEST_SEL_IRT_PP },
762 .sink = { IPUV3_CHANNEL_MEM_ROT_PP, IPU_FS_PROC_FLOW1,
763 FS_PP_ROT_SRC_SEL_MASK, FS_PP_ROT_SRC_SEL_PP },
764 }, {
765 .src = { IPUV3_CHANNEL_CSI_DIRECT, 0 },
766 .sink = { IPUV3_CHANNEL_CSI_VDI_PREV, IPU_FS_PROC_FLOW1,
767 FS_VDI_SRC_SEL_MASK, FS_VDI_SRC_SEL_CSI_DIRECT },
768 },
769};
770
771static const struct fsu_link_info *find_fsu_link_info(int src, int sink)
772{
773 int i;
774
775 for (i = 0; i < ARRAY_SIZE(fsu_link_info); i++) {
776 if (src == fsu_link_info[i].src.chno &&
777 sink == fsu_link_info[i].sink.chno)
778 return &fsu_link_info[i];
779 }
780
781 return NULL;
782}
783
784/*
785 * Links a source channel to a sink channel in the FSU.
786 */
787int ipu_fsu_link(struct ipu_soc *ipu, int src_ch, int sink_ch)
788{
789 const struct fsu_link_info *link;
790 u32 src_reg, sink_reg;
791 unsigned long flags;
792
793 link = find_fsu_link_info(src_ch, sink_ch);
794 if (!link)
795 return -EINVAL;
796
797 spin_lock_irqsave(&ipu->lock, flags);
798
799 if (link->src.mask) {
800 src_reg = ipu_cm_read(ipu, link->src.reg);
801 src_reg &= ~link->src.mask;
802 src_reg |= link->src.val;
803 ipu_cm_write(ipu, src_reg, link->src.reg);
804 }
805
806 if (link->sink.mask) {
807 sink_reg = ipu_cm_read(ipu, link->sink.reg);
808 sink_reg &= ~link->sink.mask;
809 sink_reg |= link->sink.val;
810 ipu_cm_write(ipu, sink_reg, link->sink.reg);
811 }
812
813 spin_unlock_irqrestore(&ipu->lock, flags);
814 return 0;
815}
816EXPORT_SYMBOL_GPL(ipu_fsu_link);
817
818/*
819 * Unlinks source and sink channels in the FSU.
820 */
821int ipu_fsu_unlink(struct ipu_soc *ipu, int src_ch, int sink_ch)
822{
823 const struct fsu_link_info *link;
824 u32 src_reg, sink_reg;
825 unsigned long flags;
826
827 link = find_fsu_link_info(src_ch, sink_ch);
828 if (!link)
829 return -EINVAL;
830
831 spin_lock_irqsave(&ipu->lock, flags);
832
833 if (link->src.mask) {
834 src_reg = ipu_cm_read(ipu, link->src.reg);
835 src_reg &= ~link->src.mask;
836 ipu_cm_write(ipu, src_reg, link->src.reg);
837 }
838
839 if (link->sink.mask) {
840 sink_reg = ipu_cm_read(ipu, link->sink.reg);
841 sink_reg &= ~link->sink.mask;
842 ipu_cm_write(ipu, sink_reg, link->sink.reg);
843 }
844
845 spin_unlock_irqrestore(&ipu->lock, flags);
846 return 0;
847}
848EXPORT_SYMBOL_GPL(ipu_fsu_unlink);
849
850/* Link IDMAC channels in the FSU */
851int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink)
852{
853 return ipu_fsu_link(src->ipu, src->num, sink->num);
854}
855EXPORT_SYMBOL_GPL(ipu_idmac_link);
856
857/* Unlink IDMAC channels in the FSU */
858int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink)
859{
860 return ipu_fsu_unlink(src->ipu, src->num, sink->num);
861}
862EXPORT_SYMBOL_GPL(ipu_idmac_unlink);
863
733struct ipu_devtype { 864struct ipu_devtype {
734 const char *name; 865 const char *name;
735 unsigned long cm_ofs; 866 unsigned long cm_ofs;
diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h
index 02057d8f2732..dca2c3af1b8a 100644
--- a/drivers/gpu/ipu-v3/ipu-prv.h
+++ b/drivers/gpu/ipu-v3/ipu-prv.h
@@ -75,6 +75,33 @@ struct ipu_soc;
75#define IPU_INT_CTRL(n) IPU_CM_REG(0x003C + 4 * (n)) 75#define IPU_INT_CTRL(n) IPU_CM_REG(0x003C + 4 * (n))
76#define IPU_INT_STAT(n) IPU_CM_REG(0x0200 + 4 * (n)) 76#define IPU_INT_STAT(n) IPU_CM_REG(0x0200 + 4 * (n))
77 77
78/* FS_PROC_FLOW1 */
79#define FS_PRPENC_ROT_SRC_SEL_MASK (0xf << 0)
80#define FS_PRPENC_ROT_SRC_SEL_ENC (0x7 << 0)
81#define FS_PRPVF_ROT_SRC_SEL_MASK (0xf << 8)
82#define FS_PRPVF_ROT_SRC_SEL_VF (0x8 << 8)
83#define FS_PP_SRC_SEL_MASK (0xf << 12)
84#define FS_PP_ROT_SRC_SEL_MASK (0xf << 16)
85#define FS_PP_ROT_SRC_SEL_PP (0x5 << 16)
86#define FS_VDI1_SRC_SEL_MASK (0x3 << 20)
87#define FS_VDI3_SRC_SEL_MASK (0x3 << 20)
88#define FS_PRP_SRC_SEL_MASK (0xf << 24)
89#define FS_VDI_SRC_SEL_MASK (0x3 << 28)
90#define FS_VDI_SRC_SEL_CSI_DIRECT (0x1 << 28)
91#define FS_VDI_SRC_SEL_VDOA (0x2 << 28)
92
93/* FS_PROC_FLOW2 */
94#define FS_PRP_ENC_DEST_SEL_MASK (0xf << 0)
95#define FS_PRP_ENC_DEST_SEL_IRT_ENC (0x1 << 0)
96#define FS_PRPVF_DEST_SEL_MASK (0xf << 4)
97#define FS_PRPVF_DEST_SEL_IRT_VF (0x1 << 4)
98#define FS_PRPVF_ROT_DEST_SEL_MASK (0xf << 8)
99#define FS_PP_DEST_SEL_MASK (0xf << 12)
100#define FS_PP_DEST_SEL_IRT_PP (0x3 << 12)
101#define FS_PP_ROT_DEST_SEL_MASK (0xf << 16)
102#define FS_PRPENC_ROT_DEST_SEL_MASK (0xf << 20)
103#define FS_PRP_DEST_SEL_MASK (0xf << 24)
104
78#define IPU_DI0_COUNTER_RELEASE (1 << 24) 105#define IPU_DI0_COUNTER_RELEASE (1 << 24)
79#define IPU_DI1_COUNTER_RELEASE (1 << 25) 106#define IPU_DI1_COUNTER_RELEASE (1 << 25)
80 107
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 335d42e250a9..1a3f7d4811fc 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -107,6 +107,14 @@ enum ipu_channel_irq {
107#define IPUV3_CHANNEL_CSI2 2 107#define IPUV3_CHANNEL_CSI2 2
108#define IPUV3_CHANNEL_CSI3 3 108#define IPUV3_CHANNEL_CSI3 3
109#define IPUV3_CHANNEL_VDI_MEM_IC_VF 5 109#define IPUV3_CHANNEL_VDI_MEM_IC_VF 5
110/*
111 * NOTE: channels 6,7 are unused in the IPU and are not IDMAC channels,
112 * but the direct CSI->VDI linking is handled the same way as IDMAC
113 * channel linking in the FSU via the IPU_FS_PROC_FLOW registers, so
114 * these channel names are used to support the direct CSI->VDI link.
115 */
116#define IPUV3_CHANNEL_CSI_DIRECT 6
117#define IPUV3_CHANNEL_CSI_VDI_PREV 7
110#define IPUV3_CHANNEL_MEM_VDI_PREV 8 118#define IPUV3_CHANNEL_MEM_VDI_PREV 8
111#define IPUV3_CHANNEL_MEM_VDI_CUR 9 119#define IPUV3_CHANNEL_MEM_VDI_CUR 9
112#define IPUV3_CHANNEL_MEM_VDI_NEXT 10 120#define IPUV3_CHANNEL_MEM_VDI_NEXT 10
@@ -143,6 +151,7 @@ enum ipu_channel_irq {
143#define IPUV3_CHANNEL_ROT_PP_MEM 50 151#define IPUV3_CHANNEL_ROT_PP_MEM 50
144#define IPUV3_CHANNEL_MEM_BG_SYNC_ALPHA 51 152#define IPUV3_CHANNEL_MEM_BG_SYNC_ALPHA 51
145#define IPUV3_CHANNEL_MEM_BG_ASYNC_ALPHA 52 153#define IPUV3_CHANNEL_MEM_BG_ASYNC_ALPHA 52
154#define IPUV3_NUM_CHANNELS 64
146 155
147int ipu_map_irq(struct ipu_soc *ipu, int irq); 156int ipu_map_irq(struct ipu_soc *ipu, int irq);
148int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel, 157int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
@@ -186,6 +195,10 @@ int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel);
186bool ipu_idmac_buffer_is_ready(struct ipuv3_channel *channel, u32 buf_num); 195bool ipu_idmac_buffer_is_ready(struct ipuv3_channel *channel, u32 buf_num);
187void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num); 196void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num);
188void ipu_idmac_clear_buffer(struct ipuv3_channel *channel, u32 buf_num); 197void ipu_idmac_clear_buffer(struct ipuv3_channel *channel, u32 buf_num);
198int ipu_fsu_link(struct ipu_soc *ipu, int src_ch, int sink_ch);
199int ipu_fsu_unlink(struct ipu_soc *ipu, int src_ch, int sink_ch);
200int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink);
201int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink);
189 202
190/* 203/*
191 * IPU Channel Parameter Memory (cpmem) functions 204 * IPU Channel Parameter Memory (cpmem) functions