]> git.karo-electronics.de Git - karo-tx-linux.git/blob - sound/soc/fsl/hdmi_pcm.S
ENGR00305624-1 ASoC: imx-hdmi-dma: Use neon data copy function
[karo-tx-linux.git] / sound / soc / fsl / hdmi_pcm.S
1 /**
2  * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19 .section .text
20
21 .global hdmi_dma_copy_16_neon_lut
22 .global hdmi_dma_copy_16_neon_fast
23 .global hdmi_dma_copy_24_neon_lut
24 .global hdmi_dma_copy_24_neon_fast
25
26
27 /**
28  * hdmi_dma_copy_16_neon_lut
29  * Convert pcm sample to iec sample. Pcm sample is 16 bits.
30  * Frame index's between 0 and 47 inclusively. Channel count can be 1, 2, 4, 8.
31  * Frame count should be multipliable by 4, and Sample count by 8.
32  *
33  * C Prototype
34  *   void hdmi_dma_copy_16_neon_lut(unsigned short *src, unsigned int *dst,
35  *                      int samples, unsigned char *lookup_table);
36  * Return value
37  *   None
38  * Parameters
39  *   src                Source PCM16 samples
40  *   dst                Dest buffer to store pcm with header
41  *   samples            Contains sample count (=frame_count * channel_count)
42  *   lookup_table       Preconstructed header table. Channels interleaved.
43  */
44
45 hdmi_dma_copy_16_neon_lut:
46         mov     r12, #1         /* construct vector(1) */
47         vdup.8 d6, r12
48
49 hdmi_dma_copy_16_neon_lut_start:
50
51         /* get 8 samples to q0 */
52         vld1.16 {d0, d1}, [r0]! /* TODO: aligned */
53
54         /* pld [r1, #(64*4)] */
55
56         /* xor every bit */
57         vcnt.8     q1, q0       /* count of 1s */
58         vpadd.i8 d2, d2, d3     /* only care about the LST in every element */
59         vand       d2, d2, d6   /* clear other bits while keep the least bit */
60         vshl.u8    d2, d2, #3   /* bit p: d2 = d2 << 3 */
61
62         /* get packet header */
63         vld1.8       {d5}, [r3]!
64         veor        d4, d5, d2  /* xor bit c */
65
66         /* store: (d4 << 16 | q0) << 8 */
67         vmovl.u8  q2, d4        /* expand from char to short */
68         vzip.16     q0, q2
69         vshl.u32   q0, q0, #8
70         vshl.u32   q1, q2, #8
71         vst1.32     {d0, d1, d2, d3}, [r1]!
72
73         /* decrease sample count */
74         subs  r2, r2, #8
75         bne   hdmi_dma_copy_16_neon_lut_start
76
77         mov pc, lr
78
79 /**
80  * hdmi_dma_copy_16_neon_fast
81  * Convert pcm sample to iec sample. Pcm sample is 16 bits.
82  * Frame index's between 48 and 191 inclusively.
83  * Channel count can be 1, 2, 4 or 8.
84  * Frame count should be multipliable by 4, and Sample count by 8.
85  *
86  * C Prototype
87  * void hdmi_dma_copy_16_neon_fast(unsigned short *src,
88  *              unsigned int *dst, int samples);
89  * Return value
90  *   None
91  * Parameters
92  *   src                Source PCM16 samples
93  *   dst                Dest buffer to store pcm with header
94  *   samples            Contains sample count (=frame_count * channel_count)
95  */
96
97 hdmi_dma_copy_16_neon_fast:
98         mov     r12, #1         /* construct vector(1) */
99         vdup.8 d6, r12
100
101 hdmi_dma_copy_16_neon_fast_start:
102         /* get 8 samples to q0 */
103         vld1.16 {d0, d1}, [r0]! /* TODO: aligned */
104
105         /* pld [r1, #(64*4)] */
106
107         /* xor every bit */
108         vcnt.8     q1, q0       /* count of 1s */
109         vpadd.i8 d2, d2, d3
110         vand       d2, d2, d6   /* clear other bits while keep the LST */
111         /* finally we construct packet header */
112         vshl.u8    d4, d2, #3   /* bit p: d2 = d2 << 3 */
113
114         /* get packet header: always 0 */
115
116         /* store: (d4 << 16 | q0) << 8 */
117         vmovl.u8  q2, d4        /* expand from char to short */
118         vzip.16     q0, q2
119         vshl.u32   q0, q0, #8
120         vshl.u32   q1, q2, #8
121         vst1.32     {d0, d1, d2, d3}, [r1]!
122
123         /* decrease sample count */
124         subs  r2, r2, #8
125         bne   hdmi_dma_copy_16_neon_fast_start
126
127         mov pc, lr
128
129
130
131 /**
132  * hdmi_dma_copy_24_neon_lut
133  * Convert pcm sample to iec sample. Pcm sample is 24 bits.
134  * Frame index's between 0 and 47 inclusively. Channel count can be 1, 2, 4, 8.
135  * Frame count should be multipliable by 4, and Sample count by 8.
136  *
137  * C Prototype
138  *   void hdmi_dma_copy_24_neon_lut(unsigned int *src, unsigned int *dst,
139  *                      int samples, unsigned char *lookup_table);
140  * Return value
141  *   None
142  * Parameters
143  *   src                Source PCM24 samples
144  *   dst                Dest buffer to store pcm with header
145  *   samples            Contains sample count (=frame_count * channel_count)
146  *   lookup_table       Preconstructed header table. Channels interleaved.
147  */
148
149 hdmi_dma_copy_24_neon_lut:
150         vpush   {d8}
151
152         mov     r12, #1         /* construct vector(1) */
153         vdup.8 d8, r12
154
155 hdmi_dma_copy_24_neon_lut_start:
156
157         /* get 8 samples to q0 and q1 */
158         vld1.32 {d0, d1, d2, d3}, [r0]! /* TODO: aligned */
159
160         /* pld [r1, #(64*4)] */
161
162         /* xor every bit */
163         vcnt.8     q2, q0       /* count of 1s */
164         vpadd.i8 d4, d4, d5     /* only care about the LSB in every element */
165         vcnt.8     q3, q1
166         vpadd.i8 d6, d6, d7
167         vpadd.i8 d4, d4, d6     /* d4: contains xor result and other dirty bits */
168         vand       d4, d4, d8   /* clear other bits while keep the least bit */
169         vshl.u8    d4, d4, #3   /* bit p: d4 = d4 << 3 */
170
171         /* get packet header */
172         vld1.8       {d5}, [r3]!/* d5: original header */
173         veor        d5, d5, d4  /* fix bit p */
174
175         /* store: (d5 << 24 | q0) */
176         vmovl.u8  q3, d5        /* expand from char to short */
177         vmovl.u16 q2, d6        /* expand from short to int */
178         vmovl.u16 q3, d7
179         vshl.u32    q2, q2, #24
180         vshl.u32    q3, q3, #24
181         vorr          q0, q0, q2
182         vorr          q1, q1, q3
183         vst1.32     {d0, d1, d2, d3}, [r1]!
184
185         /* decrease sample count */
186         subs  r2, r2, #8
187         bne   hdmi_dma_copy_24_neon_lut_start
188
189         vpop {d8}
190         mov pc, lr
191
192 /**
193  * hdmi_dma_copy_24_neon_fast
194  * Convert pcm sample to iec sample. Pcm sample is 24 bits.
195  * Frame index's between 48 and 191 inclusively.
196  * Channel count can be 1, 2, 4 or 8.
197  * Frame count should be multipliable by 4, and Sample count by 8.
198  *
199  * C Prototype
200  * void hdmi_dma_copy_24_neon_fast(unsigned int *src,
201  *              unsigned int *dst, int samples);
202  * Return value
203  *   None
204  * Parameters
205  *   src                Source PCM24 samples
206  *   dst                Dest buffer to store pcm with header
207  *   samples            Contains sample count (=frame_count * channel_count)
208  */
209
210 hdmi_dma_copy_24_neon_fast:
211         vpush   {d8}
212
213         mov     r12, #1         /* construct vector(1) */
214         vdup.8 d8, r12
215
216 hdmi_dma_copy_24_neon_fast_start:
217         /* get 8 samples to q0 and q1 */
218         vld1.32 {d0, d1, d2, d3}, [r0]! /* TODO: aligned */
219
220         /* pld [r1, #(64*4)] */
221
222         /* xor every bit */
223         vcnt.8     q2, q0       /* count of 1s */
224         vpadd.i8 d4, d4, d5     /* only care about the LSB in every element */
225         vcnt.8     q3, q1
226         vpadd.i8 d6, d6, d7
227         vpadd.i8 d4, d4, d6     /* d4: contains xor result and other dirty bits */
228         vand       d4, d4, d8   /* clear other bits while keep the least bit */
229         vshl.u8    d4, d4, #3   /* bit p: d4 = d4 << 3 */
230
231         /* store: (d4 << 24 | q0)  */
232         vmovl.u8  q3, d4        /* expand from char to short */
233         vmovl.u16 q2, d6        /* expand from short to int */
234         vmovl.u16 q3, d7
235         vshl.u32    q2, q2, #24
236         vshl.u32    q3, q3, #24
237         vorr          q0, q0, q2
238         vorr          q1, q1, q3
239         vst1.32     {d0, d1, d2, d3}, [r1]!
240
241         /* decrease sample count */
242         subs  r2, r2, #8
243         bne   hdmi_dma_copy_24_neon_fast_start
244
245         vpop {d8}
246         mov pc, lr