aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2014-04-25 09:44:56 -0400
committerTakashi Iwai <tiwai@suse.de>2014-05-26 08:22:37 -0400
commit44aff6980af107cccda4d6677995c88b9dad3482 (patch)
tree6ffea09a63a7e1457df1373b66a72b2f65170f63
parentc68a1c6584d066d0f2b7aa2117d2eddce2d01def (diff)
ALSA: firewire-lib: Add handling output connection by CMP
This patch adds some macros, codes with condition of direction and new functions to handle output connection. Once cmp_connection_init() is executed with its direction, CMP input and output connection can be handled by the same way. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/firewire/cmp.c99
1 files changed, 90 insertions, 9 deletions
diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c
index c7f7a3164390..9da40d9e79da 100644
--- a/sound/firewire/cmp.c
+++ b/sound/firewire/cmp.c
@@ -29,6 +29,14 @@
29#define PCR_CHANNEL_MASK 0x003f0000 29#define PCR_CHANNEL_MASK 0x003f0000
30#define PCR_CHANNEL_SHIFT 16 30#define PCR_CHANNEL_SHIFT 16
31 31
32/* oPCR specific fields */
33#define OPCR_XSPEED_MASK 0x00C00000
34#define OPCR_XSPEED_SHIFT 22
35#define OPCR_SPEED_MASK 0x0000C000
36#define OPCR_SPEED_SHIFT 14
37#define OPCR_OVERHEAD_ID_MASK 0x00003C00
38#define OPCR_OVERHEAD_ID_SHIFT 10
39
32enum bus_reset_handling { 40enum bus_reset_handling {
33 ABORT_ON_BUS_RESET, 41 ABORT_ON_BUS_RESET,
34 SUCCEED_ON_BUS_RESET, 42 SUCCEED_ON_BUS_RESET,
@@ -41,10 +49,27 @@ void cmp_error(struct cmp_connection *c, const char *fmt, ...)
41 49
42 va_start(va, fmt); 50 va_start(va, fmt);
43 dev_err(&c->resources.unit->device, "%cPCR%u: %pV", 51 dev_err(&c->resources.unit->device, "%cPCR%u: %pV",
44 'i', c->pcr_index, &(struct va_format){ fmt, &va }); 52 (c->direction == CMP_INPUT) ? 'i' : 'o',
53 c->pcr_index, &(struct va_format){ fmt, &va });
45 va_end(va); 54 va_end(va);
46} 55}
47 56
57static u64 mpr_address(struct cmp_connection *c)
58{
59 if (c->direction == CMP_INPUT)
60 return CSR_REGISTER_BASE + CSR_IMPR;
61 else
62 return CSR_REGISTER_BASE + CSR_OMPR;
63}
64
65static u64 pcr_address(struct cmp_connection *c)
66{
67 if (c->direction == CMP_INPUT)
68 return CSR_REGISTER_BASE + CSR_IPCR(c->pcr_index);
69 else
70 return CSR_REGISTER_BASE + CSR_OPCR(c->pcr_index);
71}
72
48static int pcr_modify(struct cmp_connection *c, 73static int pcr_modify(struct cmp_connection *c,
49 __be32 (*modify)(struct cmp_connection *c, __be32 old), 74 __be32 (*modify)(struct cmp_connection *c, __be32 old),
50 int (*check)(struct cmp_connection *c, __be32 pcr), 75 int (*check)(struct cmp_connection *c, __be32 pcr),
@@ -60,8 +85,7 @@ static int pcr_modify(struct cmp_connection *c,
60 85
61 err = snd_fw_transaction( 86 err = snd_fw_transaction(
62 c->resources.unit, TCODE_LOCK_COMPARE_SWAP, 87 c->resources.unit, TCODE_LOCK_COMPARE_SWAP,
63 CSR_REGISTER_BASE + CSR_IPCR(c->pcr_index), 88 pcr_address(c), buffer, 8,
64 buffer, 8,
65 FW_FIXED_GENERATION | c->resources.generation); 89 FW_FIXED_GENERATION | c->resources.generation);
66 90
67 if (err < 0) { 91 if (err < 0) {
@@ -101,9 +125,9 @@ int cmp_connection_init(struct cmp_connection *c,
101 u32 mpr; 125 u32 mpr;
102 int err; 126 int err;
103 127
128 c->direction = direction;
104 err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, 129 err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
105 CSR_REGISTER_BASE + CSR_IMPR, 130 mpr_address(c), &mpr_be, 4, 0);
106 &mpr_be, 4, 0);
107 if (err < 0) 131 if (err < 0)
108 return err; 132 return err;
109 mpr = be32_to_cpu(mpr_be); 133 mpr = be32_to_cpu(mpr_be);
@@ -151,6 +175,53 @@ static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr)
151 return ipcr; 175 return ipcr;
152} 176}
153 177
178static int get_overhead_id(struct cmp_connection *c)
179{
180 int id;
181
182 /*
183 * apply "oPCR overhead ID encoding"
184 * the encoding table can convert up to 512.
185 * here the value over 512 is converted as the same way as 512.
186 */
187 for (id = 1; id < 16; id++) {
188 if (c->resources.bandwidth_overhead < (id << 5))
189 break;
190 }
191 if (id == 16)
192 id = 0;
193
194 return id;
195}
196
197static __be32 opcr_set_modify(struct cmp_connection *c, __be32 opcr)
198{
199 unsigned int spd, xspd;
200
201 /* generate speed and extended speed field value */
202 if (c->speed > SCODE_400) {
203 spd = SCODE_800;
204 xspd = c->speed - SCODE_800;
205 } else {
206 spd = c->speed;
207 xspd = 0;
208 }
209
210 opcr &= ~cpu_to_be32(PCR_BCAST_CONN |
211 PCR_P2P_CONN_MASK |
212 OPCR_XSPEED_MASK |
213 PCR_CHANNEL_MASK |
214 OPCR_SPEED_MASK |
215 OPCR_OVERHEAD_ID_MASK);
216 opcr |= cpu_to_be32(1 << PCR_P2P_CONN_SHIFT);
217 opcr |= cpu_to_be32(xspd << OPCR_XSPEED_SHIFT);
218 opcr |= cpu_to_be32(c->resources.channel << PCR_CHANNEL_SHIFT);
219 opcr |= cpu_to_be32(spd << OPCR_SPEED_SHIFT);
220 opcr |= cpu_to_be32(get_overhead_id(c) << OPCR_OVERHEAD_ID_SHIFT);
221
222 return opcr;
223}
224
154static int pcr_set_check(struct cmp_connection *c, __be32 pcr) 225static int pcr_set_check(struct cmp_connection *c, __be32 pcr)
155{ 226{
156 if (pcr & cpu_to_be32(PCR_BCAST_CONN | 227 if (pcr & cpu_to_be32(PCR_BCAST_CONN |
@@ -196,8 +267,13 @@ retry_after_bus_reset:
196 if (err < 0) 267 if (err < 0)
197 goto err_mutex; 268 goto err_mutex;
198 269
199 err = pcr_modify(c, ipcr_set_modify, pcr_set_check, 270 if (c->direction == CMP_OUTPUT)
200 ABORT_ON_BUS_RESET); 271 err = pcr_modify(c, opcr_set_modify, pcr_set_check,
272 ABORT_ON_BUS_RESET);
273 else
274 err = pcr_modify(c, ipcr_set_modify, pcr_set_check,
275 ABORT_ON_BUS_RESET);
276
201 if (err == -EAGAIN) { 277 if (err == -EAGAIN) {
202 fw_iso_resources_free(&c->resources); 278 fw_iso_resources_free(&c->resources);
203 goto retry_after_bus_reset; 279 goto retry_after_bus_reset;
@@ -245,8 +321,13 @@ int cmp_connection_update(struct cmp_connection *c)
245 if (err < 0) 321 if (err < 0)
246 goto err_unconnect; 322 goto err_unconnect;
247 323
248 err = pcr_modify(c, ipcr_set_modify, pcr_set_check, 324 if (c->direction == CMP_OUTPUT)
249 SUCCEED_ON_BUS_RESET); 325 err = pcr_modify(c, opcr_set_modify, pcr_set_check,
326 SUCCEED_ON_BUS_RESET);
327 else
328 err = pcr_modify(c, ipcr_set_modify, pcr_set_check,
329 SUCCEED_ON_BUS_RESET);
330
250 if (err < 0) 331 if (err < 0)
251 goto err_resources; 332 goto err_resources;
252 333