1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
7 #include <linux/dma-mapping.h>
8 #include <linux/kernel.h>
13 #define PT3_ACCESS_UNIT (TS_PACKET_SZ * 128)
14 #define PT3_BUF_CANARY (0x74)
16 static u32
get_dma_base(int idx
)
20 i
= (idx
== 1 || idx
== 2) ? 3 - idx
: idx
;
21 return REG_DMA_BASE
+ 0x18 * i
;
24 int pt3_stop_dma(struct pt3_adapter
*adap
)
26 struct pt3_board
*pt3
= adap
->dvb_adap
.priv
;
31 base
= get_dma_base(adap
->adap_idx
);
32 stat
= ioread32(pt3
->regs
[0] + base
+ OFST_STATUS
);
36 iowrite32(0x02, pt3
->regs
[0] + base
+ OFST_DMA_CTL
);
37 for (retry
= 0; retry
< 5; retry
++) {
38 stat
= ioread32(pt3
->regs
[0] + base
+ OFST_STATUS
);
46 int pt3_start_dma(struct pt3_adapter
*adap
)
48 struct pt3_board
*pt3
= adap
->dvb_adap
.priv
;
49 u32 base
= get_dma_base(adap
->adap_idx
);
51 iowrite32(0x02, pt3
->regs
[0] + base
+ OFST_DMA_CTL
);
52 iowrite32(lower_32_bits(adap
->desc_buf
[0].b_addr
),
53 pt3
->regs
[0] + base
+ OFST_DMA_DESC_L
);
54 iowrite32(upper_32_bits(adap
->desc_buf
[0].b_addr
),
55 pt3
->regs
[0] + base
+ OFST_DMA_DESC_H
);
56 iowrite32(0x01, pt3
->regs
[0] + base
+ OFST_DMA_CTL
);
61 static u8
*next_unit(struct pt3_adapter
*adap
, int *idx
, int *ofs
)
63 *ofs
+= PT3_ACCESS_UNIT
;
64 if (*ofs
>= DATA_BUF_SZ
) {
67 if (*idx
== adap
->num_bufs
)
70 return &adap
->buffer
[*idx
].data
[*ofs
];
73 int pt3_proc_dma(struct pt3_adapter
*adap
)
80 if (adap
->buffer
[idx
].data
[ofs
] == PT3_BUF_CANARY
)
83 while (*next_unit(adap
, &idx
, &ofs
) != PT3_BUF_CANARY
) {
86 p
= &adap
->buffer
[adap
->buf_idx
].data
[adap
->buf_ofs
];
87 if (adap
->num_discard
> 0)
89 else if (adap
->buf_ofs
+ PT3_ACCESS_UNIT
> DATA_BUF_SZ
) {
90 dvb_dmx_swfilter_packets(&adap
->demux
, p
,
91 (DATA_BUF_SZ
- adap
->buf_ofs
) / TS_PACKET_SZ
);
92 dvb_dmx_swfilter_packets(&adap
->demux
,
93 adap
->buffer
[idx
].data
, ofs
/ TS_PACKET_SZ
);
95 dvb_dmx_swfilter_packets(&adap
->demux
, p
,
96 PT3_ACCESS_UNIT
/ TS_PACKET_SZ
);
105 void pt3_init_dmabuf(struct pt3_adapter
*adap
)
112 p
= adap
->buffer
[0].data
;
113 /* mark the whole buffers as "not written yet" */
114 while (idx
< adap
->num_bufs
) {
115 p
[ofs
] = PT3_BUF_CANARY
;
116 ofs
+= PT3_ACCESS_UNIT
;
117 if (ofs
>= DATA_BUF_SZ
) {
120 p
= adap
->buffer
[idx
].data
;
127 void pt3_free_dmabuf(struct pt3_adapter
*adap
)
129 struct pt3_board
*pt3
;
132 pt3
= adap
->dvb_adap
.priv
;
133 for (i
= 0; i
< adap
->num_bufs
; i
++)
134 dma_free_coherent(&pt3
->pdev
->dev
, DATA_BUF_SZ
,
135 adap
->buffer
[i
].data
, adap
->buffer
[i
].b_addr
);
138 for (i
= 0; i
< adap
->num_desc_bufs
; i
++)
139 dma_free_coherent(&pt3
->pdev
->dev
, PAGE_SIZE
,
140 adap
->desc_buf
[i
].descs
, adap
->desc_buf
[i
].b_addr
);
141 adap
->num_desc_bufs
= 0;
145 int pt3_alloc_dmabuf(struct pt3_adapter
*adap
)
147 struct pt3_board
*pt3
;
152 dma_addr_t data_addr
, desc_addr
;
155 pt3
= adap
->dvb_adap
.priv
;
157 adap
->num_desc_bufs
= 0;
158 for (i
= 0; i
< pt3
->num_bufs
; i
++) {
159 p
= dma_alloc_coherent(&pt3
->pdev
->dev
, DATA_BUF_SZ
,
160 &adap
->buffer
[i
].b_addr
, GFP_KERNEL
);
163 adap
->buffer
[i
].data
= p
;
166 pt3_init_dmabuf(adap
);
168 /* build circular-linked pointers (xfer_desc) to the data buffers*/
172 DIV_ROUND_UP(adap
->num_bufs
* DATA_BUF_XFERS
, DESCS_IN_PAGE
);
173 for (i
= 0; i
< num_desc_bufs
; i
++) {
174 p
= dma_alloc_coherent(&pt3
->pdev
->dev
, PAGE_SIZE
,
175 &desc_addr
, GFP_KERNEL
);
178 adap
->num_desc_bufs
++;
179 adap
->desc_buf
[i
].descs
= p
;
180 adap
->desc_buf
[i
].b_addr
= desc_addr
;
183 d
= &adap
->desc_buf
[i
- 1].descs
[DESCS_IN_PAGE
- 1];
184 d
->next_l
= lower_32_bits(desc_addr
);
185 d
->next_h
= upper_32_bits(desc_addr
);
187 for (j
= 0; j
< DESCS_IN_PAGE
; j
++) {
188 data_addr
= adap
->buffer
[idx
].b_addr
+ ofs
;
189 d
= &adap
->desc_buf
[i
].descs
[j
];
190 d
->addr_l
= lower_32_bits(data_addr
);
191 d
->addr_h
= upper_32_bits(data_addr
);
192 d
->size
= DATA_XFER_SZ
;
194 desc_addr
+= sizeof(struct xfer_desc
);
195 d
->next_l
= lower_32_bits(desc_addr
);
196 d
->next_h
= upper_32_bits(desc_addr
);
199 if (ofs
>= DATA_BUF_SZ
) {
202 if (idx
>= adap
->num_bufs
) {
203 desc_addr
= adap
->desc_buf
[0].b_addr
;
204 d
->next_l
= lower_32_bits(desc_addr
);
205 d
->next_h
= upper_32_bits(desc_addr
);
214 pt3_free_dmabuf(adap
);