diff mbox series

[v2,4/7] media: uniphier: add TS common file of HSC

Message ID 20180808052519.14528-5-suzuki.katsuhiro@socionext.com
State New
Headers show
Series [v2,1/7] media: uniphier: add DT bindings documentation for UniPhier HSC | expand

Commit Message

Katsuhiro Suzuki Aug. 8, 2018, 5:25 a.m. UTC
Add TS input/output code to start/stop configure the MPEG2-TS ports
of HSC for Socionext UniPhier SoCs.

Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>


---

Changes from v1:
  - Split from large patches
  - Fix include lines
---
 drivers/media/platform/uniphier/Makefile  |   2 +-
 drivers/media/platform/uniphier/hsc-reg.h |  41 +++++++
 drivers/media/platform/uniphier/hsc-ts.c  | 127 ++++++++++++++++++++++
 drivers/media/platform/uniphier/hsc.h     |   6 +
 4 files changed, 175 insertions(+), 1 deletion(-)
 create mode 100644 drivers/media/platform/uniphier/hsc-ts.c

-- 
2.18.0
diff mbox series

Patch

diff --git a/drivers/media/platform/uniphier/Makefile b/drivers/media/platform/uniphier/Makefile
index 59be2edf0c53..2ba03067644d 100644
--- a/drivers/media/platform/uniphier/Makefile
+++ b/drivers/media/platform/uniphier/Makefile
@@ -1,4 +1,4 @@ 
 # SPDX-License-Identifier: GPL-2.0
-uniphier-dvb-y += hsc-dma.o hsc-css.o
+uniphier-dvb-y += hsc-dma.o hsc-css.o hsc-ts.o
 
 obj-$(CONFIG_DVB_UNIPHIER) += uniphier-dvb.o
diff --git a/drivers/media/platform/uniphier/hsc-reg.h b/drivers/media/platform/uniphier/hsc-reg.h
index e5bc87658361..26f04b79178b 100644
--- a/drivers/media/platform/uniphier/hsc-reg.h
+++ b/drivers/media/platform/uniphier/hsc-reg.h
@@ -144,4 +144,45 @@ 
 #define   CSS_DPCTRL_DPSEL_TSI1            BIT(1)
 #define   CSS_DPCTRL_DPSEL_TSI0            BIT(0)
 
+/* TSI */
+#define TSI_SYNCCNTROL(i)                (0x7100 + (i) * 0x70)
+#define   TSI_SYNCCNTROL_FRAME_MASK        GENMASK(18, 16)
+#define   TSI_SYNCCNTROL_FRAME_EXTSYNC1    (0x0 << 16)
+#define   TSI_SYNCCNTROL_FRAME_EXTSYNC2    (0x1 << 16)
+#define TSI_CONFIG(i)                    (0x7104 + (i) * 0x70)
+#define   TSI_CONFIG_ATSMD_MASK            GENMASK(22, 21)
+#define   TSI_CONFIG_ATSMD_PCRPLL0         (0x0 << 21)
+#define   TSI_CONFIG_ATSMD_PCRPLL1         (0x1 << 21)
+#define   TSI_CONFIG_ATSMD_DPLL            (0x3 << 21)
+#define   TSI_CONFIG_ATSADD_ON             BIT(20)
+#define   TSI_CONFIG_STCMD_MASK            GENMASK(7, 6)
+#define   TSI_CONFIG_STCMD_PCRPLL0         (0x0 << 6)
+#define   TSI_CONFIG_STCMD_PCRPLL1         (0x1 << 6)
+#define   TSI_CONFIG_STCMD_DPLL            (0x3 << 6)
+#define   TSI_CONFIG_CHEN_START            BIT(0)
+#define TSI_RATEUPLMT(i)                 (0x7108 + (i) * 0x70)
+#define TSI_RATELOWLMT(i)                (0x710c + (i) * 0x70)
+#define TSI_CNTINTR(i)                   (0x7110 + (i) * 0x70)
+#define TSI_INTREN(i)                    (0x7114 + (i) * 0x70)
+#define   TSI_INTR_NTP                     BIT(13)
+#define   TSI_INTR_NTPCNT                  BIT(12)
+#define   TSI_INTR_PKTEND                  BIT(11)
+#define   TSI_INTR_PCR                     BIT(9)
+#define   TSI_INTR_LOAD                    BIT(8)
+#define   TSI_INTR_SERR                    BIT(7)
+#define   TSI_INTR_SOF                     BIT(6)
+#define   TSI_INTR_TOF                     BIT(5)
+#define   TSI_INTR_UL                      BIT(4)
+#define   TSI_INTR_LL                      BIT(3)
+#define   TSI_INTR_CNT                     BIT(2)
+#define   TSI_INTR_LOST                    BIT(1)
+#define   TSI_INTR_LOCK                    BIT(0)
+#define TSI_SYNCSTATUS(i)                (0x7118 + (i) * 0x70)
+#define   TSI_STAT_PKTST_ERR               BIT(21)
+#define   TSI_STAT_LARGE_ERR               BIT(20)
+#define   TSI_STAT_SMALL_ERR               BIT(19)
+#define   TSI_STAT_LOCK                    BIT(18)
+#define   TSI_STAT_SYNC                    BIT(17)
+#define   TSI_STAT_SEARCH                  BIT(16)
+
 #endif /* DVB_UNIPHIER_HSC_REG_H__ */
diff --git a/drivers/media/platform/uniphier/hsc-ts.c b/drivers/media/platform/uniphier/hsc-ts.c
new file mode 100644
index 000000000000..bb70429301ad
--- /dev/null
+++ b/drivers/media/platform/uniphier/hsc-ts.c
@@ -0,0 +1,127 @@ 
+// SPDX-License-Identifier: GPL-2.0
+//
+// Socionext UniPhier DVB driver for High-speed Stream Controller (HSC).
+// MPEG2-TS input/output port setting.
+//
+// Copyright (c) 2018 Socionext Inc.
+
+#include <linux/bitfield.h>
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+
+#include "hsc.h"
+#include "hsc-reg.h"
+
+/* SBC1, 2 */
+#define SBC_ACE_DMA_EN                0x6000
+#define SBC_DMAPARAM21                0x6004
+#define SBC_ACE_INTREN                0x6008
+#define SBC_ACE_INTRST                0x600c
+#define SBC_DMA_STATUS0               0x6010
+#define SBC_DMA_STATUS1               0x6014
+#define SBC_DMAPARAMA(i)              (0x6018 + (i) * 0x04)
+#define   SBC_DMAPARAMA_OFFSET_MASK     GENMASK(31, 29)
+#define   SBC_DMAPARAMA_LOOPADDR_MASK   GENMASK(28, 23)
+#define   SBC_DMAPARAMA_COUNT_MASK      GENMASK(7, 0)
+#define SBC_DMAPARAMB(i)              (0x6038 + (i) * 0x04)
+
+#define PARAMA_OFFSET_TS      0x02
+#define PARAMA_LOOPADDR_TS    0x31
+#define PARAMA_COUNT_TS       0xc4
+
+static bool ts_in_is_valid(struct hsc_chip *chip, int tsi)
+{
+	return tsi < chip->spec->num_ts_in && chip->spec->ts_in[tsi].intr.valid;
+}
+
+static const struct hsc_spec_ts *ts_in_get_spec(struct hsc_chip *chip, int tsi)
+{
+	const struct hsc_spec_ts *spec = chip->spec->ts_in;
+
+	if (!ts_in_is_valid(chip, tsi))
+		return NULL;
+
+	return &spec[tsi];
+}
+
+int hsc_ts_in_set_enable(struct hsc_chip *chip, int tsi, bool en)
+{
+	struct regmap *r = chip->regmap;
+	const struct hsc_spec_ts *speci = ts_in_get_spec(chip, tsi);
+	u32 m, v;
+
+	if (!speci)
+		return -EINVAL;
+
+	m = TSI_SYNCCNTROL_FRAME_MASK;
+	v = TSI_SYNCCNTROL_FRAME_EXTSYNC2;
+	regmap_update_bits(r, TSI_SYNCCNTROL(tsi), m, v);
+
+	m = TSI_CONFIG_ATSMD_MASK | TSI_CONFIG_STCMD_MASK |
+		TSI_CONFIG_CHEN_START;
+	v = TSI_CONFIG_ATSMD_DPLL | TSI_CONFIG_STCMD_DPLL;
+	if (en)
+		v |= TSI_CONFIG_CHEN_START;
+	regmap_update_bits(r, TSI_CONFIG(tsi), m, v);
+
+	v = (en) ? ~0 : 0;
+	regmap_update_bits(r, TSI_INTREN(tsi),
+			   TSI_INTR_SERR | TSI_INTR_LOST, v);
+	regmap_update_bits(r, speci->intr.reg, BIT(speci->intr.sft), v);
+
+	return 0;
+}
+
+int hsc_ts_in_set_dmaparam(struct hsc_chip *chip, int tsi, int ifmt)
+{
+	struct regmap *r = chip->regmap;
+	u32 v, ats, offset, loop, cnt;
+
+	if (!ts_in_is_valid(chip, tsi))
+		return -EINVAL;
+
+	switch (ifmt) {
+	case HSC_TSIF_MPEG2_TS:
+		ats = 0;
+		offset = PARAMA_OFFSET_TS;
+		loop = PARAMA_LOOPADDR_TS;
+		cnt = PARAMA_COUNT_TS;
+		break;
+	case HSC_TSIF_MPEG2_TS_ATS:
+		ats = TSI_CONFIG_ATSADD_ON;
+		offset = PARAMA_OFFSET_TS;
+		loop = PARAMA_LOOPADDR_TS;
+		cnt = PARAMA_COUNT_TS;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_update_bits(r, TSI_CONFIG(tsi), TSI_CONFIG_ATSADD_ON, ats);
+
+	v = FIELD_PREP(SBC_DMAPARAMA_OFFSET_MASK, offset) |
+		FIELD_PREP(SBC_DMAPARAMA_LOOPADDR_MASK, loop) |
+		FIELD_PREP(SBC_DMAPARAMA_COUNT_MASK, cnt);
+	regmap_write(r, SBC_DMAPARAMA(tsi), v);
+
+	return 0;
+}
+
+int hsc_ts_in_get_intr(struct hsc_chip *chip, int tsi, u32 *stat)
+{
+	struct regmap *r = chip->regmap;
+
+	if (!stat)
+		return -EINVAL;
+
+	regmap_read(r, TSI_SYNCSTATUS(tsi), stat);
+
+	return 0;
+}
+
+void hsc_ts_in_clear_intr(struct hsc_chip *chip, int tsi, u32 clear)
+{
+	struct regmap *r = chip->regmap;
+
+	regmap_write(r, TSI_SYNCSTATUS(tsi), clear);
+}
diff --git a/drivers/media/platform/uniphier/hsc.h b/drivers/media/platform/uniphier/hsc.h
index 1cbd17b475bf..a10b7a480193 100644
--- a/drivers/media/platform/uniphier/hsc.h
+++ b/drivers/media/platform/uniphier/hsc.h
@@ -346,6 +346,12 @@  int hsc_css_out_set_polarity(struct hsc_chip *chip, int out,
 int hsc_css_out_get_src(struct hsc_chip *chip, int *in, int out, bool *en);
 int hsc_css_out_set_src(struct hsc_chip *chip, int in, int out, bool en);
 
+/* TS */
+int hsc_ts_in_set_enable(struct hsc_chip *chip, int tsi, bool en);
+int hsc_ts_in_set_dmaparam(struct hsc_chip *chip, int tsi, int ifmt);
+int hsc_ts_in_get_intr(struct hsc_chip *chip, int tsi, u32 *st);
+void hsc_ts_in_clear_intr(struct hsc_chip *chip, int tsi, u32 clear);
+
 /* DMA */
 u64 hsc_rb_cnt(struct hsc_dma_buf *buf);
 u64 hsc_rb_cnt_to_end(struct hsc_dma_buf *buf);