xref: /haiku/src/add-ons/kernel/drivers/audio/ice1712/io.cpp (revision ffb788fe584e7d487fa58f2bd137435d2587ee24)
1 /*
2  * Copyright 2004-2015 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Jérôme Duval, jerome.duval@free.fr
7  *		Marcus Overhagen, marcus@overhagen.de
8  *		Jérôme Lévêque, leveque.jerome@gmail.com
9  */
10 
11 
12 #include "io.h"
13 #include "ice1712_reg.h"
14 #include "debug.h"
15 
16 extern pci_module_info *pci;
17 
18 static void ak45xx_write_gpio(ice1712 *ice, uint8 reg_addr,
19 	uint8 data, uint8 chip_select, uint8 invert_cs);
20 
21 static void cs84xx_write_gpio(ice1712 *ice, uint8 reg_addr,
22 	uint8 data, uint8 chip_select, uint8 invert_cs);
23 
ak45xx_read_gpio(ice1712 * ice,uint8 reg_addr,uint8 chip_select,uint8 invert_cs)24 static uint8 ak45xx_read_gpio(ice1712 *ice, uint8 reg_addr,
25 	uint8 chip_select, uint8 invert_cs)
26 		{return 0;} //Unimplemented
27 
28 static uint8 cs84xx_read_gpio(ice1712 *ice, uint8 reg_addr,
29 	uint8 chip_select, uint8 invert_cs);
30 
31 static void write_gpio_byte(ice1712 *ice, uint8 data, uint8 gpio_data);
32 static uint8 read_gpio_byte(ice1712 *ice, uint8 gpio_data);
33 
34 
35 //Address are [PCI_10] + xx
36 uint8
read_ccs_uint8(ice1712 * ice,int8 regno)37 read_ccs_uint8(ice1712 *ice, int8 regno)
38 {
39 	return pci->read_io_8(ice->Controller + regno);
40 };
41 
42 
43 uint16
read_ccs_uint16(ice1712 * ice,int8 regno)44 read_ccs_uint16(ice1712 *ice, int8 regno)
45 {
46 	return pci->read_io_16(ice->Controller + regno);
47 };
48 
49 
50 uint32
read_ccs_uint32(ice1712 * ice,int8 regno)51 read_ccs_uint32(ice1712 *ice, int8 regno)
52 {
53 	return pci->read_io_32(ice->Controller + regno);
54 };
55 
56 
57 void
write_ccs_uint8(ice1712 * ice,int8 regno,uint8 value)58 write_ccs_uint8(ice1712 *ice, int8 regno, uint8 value)
59 {
60 	pci->write_io_8(ice->Controller + regno, value);
61 };
62 
63 
64 void
write_ccs_uint16(ice1712 * ice,int8 regno,uint16 value)65 write_ccs_uint16(ice1712 *ice, int8 regno, uint16 value)
66 {
67 	pci->write_io_16(ice->Controller + regno, value);
68 };
69 
70 
71 void
write_ccs_uint32(ice1712 * ice,int8 regno,uint32 value)72 write_ccs_uint32(ice1712 *ice, int8 regno, uint32 value)
73 {
74 	pci->write_io_32(ice->Controller + regno, value);
75 };
76 
77 
78 uint8
read_cci_uint8(ice1712 * ice,int8 index)79 read_cci_uint8(ice1712 *ice, int8 index)
80 {
81 	write_ccs_uint8(ice, CCS_CCI_INDEX, index);
82 	return read_ccs_uint8(ice, CCS_CCI_DATA);
83 };
84 
85 
86 void
write_cci_uint8(ice1712 * ice,int8 index,uint8 value)87 write_cci_uint8(ice1712 *ice, int8 index, uint8 value)
88 {
89 	write_ccs_uint8(ice, CCS_CCI_INDEX, index);
90 	write_ccs_uint8(ice, CCS_CCI_DATA, value);
91 };
92 
93 
94 //Address are [PCI_14] + xx
95 uint8
read_ddma_uint8(ice1712 * ice,int8 regno)96 read_ddma_uint8(ice1712 *ice, int8 regno)
97 {
98 	return pci->read_io_8(ice->DDMA + regno);
99 };
100 
101 
102 uint16
read_ddma_uint16(ice1712 * ice,int8 regno)103 read_ddma_uint16(ice1712 *ice, int8 regno)
104 {
105 	return pci->read_io_16(ice->DDMA + regno);
106 };
107 
108 
109 uint32
read_ddma_uint32(ice1712 * ice,int8 regno)110 read_ddma_uint32(ice1712 *ice, int8 regno)
111 {
112 	return pci->read_io_32(ice->DDMA + regno);
113 };
114 
115 
116 void
write_ddma_uint8(ice1712 * ice,int8 regno,uint8 value)117 write_ddma_uint8(ice1712 *ice, int8 regno, uint8 value)
118 {
119 	pci->write_io_8(ice->DDMA + regno, value);
120 };
121 
122 
123 void
write_ddma_uint16(ice1712 * ice,int8 regno,uint16 value)124 write_ddma_uint16(ice1712 *ice, int8 regno, uint16 value)
125 {
126 	pci->write_io_16(ice->DDMA + regno, value);
127 };
128 
129 
130 void
write_ddma_uint32(ice1712 * ice,int8 regno,uint32 value)131 write_ddma_uint32(ice1712 *ice, int8 regno, uint32 value)
132 {
133 	pci->write_io_32(ice->DDMA + regno, value);
134 };
135 
136 
137 //Address are [PCI_18] + x
138 uint8
read_ds_uint8(ice1712 * ice,int8 regno)139 read_ds_uint8(ice1712 *ice, int8 regno)
140 {
141 	return pci->read_io_8(ice->DMA_Path + regno);
142 };
143 
144 
145 uint16
read_ds_uint16(ice1712 * ice,int8 regno)146 read_ds_uint16(ice1712 *ice, int8 regno)
147 {
148 	return pci->read_io_16(ice->DMA_Path + regno);
149 };
150 
151 
152 uint32
read_ds_uint32(ice1712 * ice,int8 regno)153 read_ds_uint32(ice1712 *ice, int8 regno)
154 {
155 	return pci->read_io_32(ice->DMA_Path + regno);
156 };
157 
158 
159 void
write_ds_uint8(ice1712 * ice,int8 regno,uint8 value)160 write_ds_uint8(ice1712 *ice, int8 regno, uint8 value)
161 {
162 	pci->write_io_8(ice->DMA_Path + regno, value);
163 };
164 
165 
166 void
write_ds_uint16(ice1712 * ice,int8 regno,uint16 value)167 write_ds_uint16(ice1712 *ice, int8 regno, uint16 value)
168 {
169 	pci->write_io_16(ice->DMA_Path + regno, value);
170 };
171 
172 
173 void
write_ds_uint32(ice1712 * ice,int8 regno,uint32 value)174 write_ds_uint32(ice1712 *ice, int8 regno, uint32 value)
175 {
176 	pci->write_io_32(ice->DMA_Path + regno, value);
177 };
178 
179 
180 uint32
read_ds_channel_data(ice1712 * ice,uint8 channel,ds8_register index)181 read_ds_channel_data(ice1712 *ice, uint8 channel, ds8_register index)
182 {
183 	uint8 ds8_channel_index = channel << 4 | index;
184 
185 	write_ds_uint8(ice, DS_CHANNEL_INDEX, ds8_channel_index);
186 	return read_ds_uint32(ice, DS_CHANNEL_DATA);
187 }
188 
189 
190 void
write_ds_channel_data(ice1712 * ice,uint8 channel,ds8_register index,uint32 data)191 write_ds_channel_data(ice1712 *ice, uint8 channel, ds8_register index,
192 	uint32 data)
193 {
194 	uint8 ds8_channel_index = channel << 4 | index;
195 
196 	write_ds_uint8(ice, DS_CHANNEL_INDEX, ds8_channel_index);
197 	write_ds_uint32(ice, DS_CHANNEL_DATA, data);
198 }
199 
200 
201 //Address are [PCI_1C] + xx
202 uint8
read_mt_uint8(ice1712 * ice,int8 regno)203 read_mt_uint8(ice1712 *ice, int8 regno)
204 {
205 	return pci->read_io_8(ice->Multi_Track + regno);
206 };
207 
208 
209 uint16
read_mt_uint16(ice1712 * ice,int8 regno)210 read_mt_uint16(ice1712 *ice, int8 regno)
211 {
212 	return pci->read_io_16(ice->Multi_Track + regno);
213 };
214 
215 
216 uint32
read_mt_uint32(ice1712 * ice,int8 regno)217 read_mt_uint32(ice1712 *ice, int8 regno)
218 {
219 	return pci->read_io_32(ice->Multi_Track + regno);
220 };
221 
222 
223 void
write_mt_uint8(ice1712 * ice,int8 regno,uint8 value)224 write_mt_uint8(ice1712 *ice, int8 regno, uint8 value)
225 {
226 	pci->write_io_8(ice->Multi_Track + regno, value);
227 };
228 
229 
230 void
write_mt_uint16(ice1712 * ice,int8 regno,uint16 value)231 write_mt_uint16(ice1712 *ice, int8 regno, uint16 value)
232 {
233 	pci->write_io_16(ice->Multi_Track + regno, value);
234 };
235 
236 
237 void
write_mt_uint32(ice1712 * ice,int8 regno,uint32 value)238 write_mt_uint32(ice1712 *ice, int8 regno, uint32 value)
239 {
240 	pci->write_io_32(ice->Multi_Track + regno, value);
241 };
242 
243 
244 /*
245  * return -1 if error else return an uint8
246  */
247 int16
read_i2c(ice1712 * ice,uint8 dev_addr,uint8 byte_addr)248 read_i2c(ice1712 *ice, uint8 dev_addr, uint8 byte_addr)
249 {
250 	if (read_ccs_uint8(ice, CCS_I2C_CONTROL_STATUS) != 0x80)
251 		return -1;
252 	write_ccs_uint8(ice, CCS_I2C_BYTE_ADDRESS, byte_addr);
253 	write_ccs_uint8(ice, CCS_I2C_DEV_ADDRESS, dev_addr);
254 	snooze(1000);
255 	return read_ccs_uint8(ice, CCS_I2C_DATA);
256 }
257 
258 
259 /*
260  * return -1 if error else return 0
261  */
262 int16
write_i2c(ice1712 * ice,uint8 dev_addr,uint8 byte_addr,uint8 value)263 write_i2c(ice1712 *ice, uint8 dev_addr, uint8 byte_addr, uint8 value)
264 {
265 	if (read_ccs_uint8(ice, CCS_I2C_CONTROL_STATUS) != 0x80)
266 		return -1;
267 
268 	write_ccs_uint8(ice, CCS_I2C_BYTE_ADDRESS, byte_addr);
269 	write_ccs_uint8(ice, CCS_I2C_DEV_ADDRESS, dev_addr);
270 	write_ccs_uint8(ice, CCS_I2C_DATA, value);
271 	return 0;
272 }
273 
274 
read_eeprom(ice1712 * ice,uint8 eeprom[32])275 int16 read_eeprom(ice1712 *ice, uint8 eeprom[32])
276 {
277 	int i;
278 	int16 tmp;
279 
280 	for (i = 0; i < 6; i++) {
281 		tmp = read_i2c(ice, I2C_EEPROM_ADDRESS_READ, i);
282 		if (tmp >= 0)
283 			eeprom[i] = (uint8)tmp;
284 		else
285 			return -1;
286 	}
287 	if (eeprom[4] > 32)
288 		return -1;
289 	for (i = 6; i < eeprom[4]; i++) {
290 		tmp = read_i2c(ice, I2C_EEPROM_ADDRESS_READ, i);
291 		if (tmp >= 0)
292 			eeprom[i] = (uint8)tmp;
293 		else
294 			return -1;
295 	}
296 	return eeprom[4];
297 }
298 
299 
300 void
codec_write(ice1712 * ice,uint8 reg_addr,uint8 data)301 codec_write(ice1712 *ice, uint8 reg_addr, uint8 data)
302 {
303 	switch (ice->config.product) {
304 		case ICE1712_SUBDEVICE_DELTA66:
305 		case ICE1712_SUBDEVICE_DELTA44:
306 			ak45xx_write_gpio(ice, reg_addr, data,
307 				DELTA66_CODEC_CS_0, 0);
308 			ak45xx_write_gpio(ice, reg_addr, data,
309 				DELTA66_CODEC_CS_1, 0);
310 			break;
311 		case ICE1712_SUBDEVICE_DELTA410:
312 		case ICE1712_SUBDEVICE_AUDIOPHILE_2496:
313 		case ICE1712_SUBDEVICE_DELTADIO2496:
314 			ak45xx_write_gpio(ice, reg_addr, data, AP2496_CODEC_CS, 0);
315 			break;
316 		case ICE1712_SUBDEVICE_DELTA1010:
317 		case ICE1712_SUBDEVICE_DELTA1010LT:
318 			ak45xx_write_gpio(ice, reg_addr, data,
319 				DELTA1010LT_CODEC_CS_0, DELTA1010LT_CS_NONE);
320 			ak45xx_write_gpio(ice, reg_addr, data,
321 				DELTA1010LT_CODEC_CS_1, DELTA1010LT_CS_NONE);
322 			ak45xx_write_gpio(ice, reg_addr, data,
323 				DELTA1010LT_CODEC_CS_2, DELTA1010LT_CS_NONE);
324 			ak45xx_write_gpio(ice, reg_addr, data,
325 				DELTA1010LT_CODEC_CS_3, DELTA1010LT_CS_NONE);
326 			break;
327 		case ICE1712_SUBDEVICE_VX442:
328 			ak45xx_write_gpio(ice, reg_addr, data, VX442_CODEC_CS_0, 0);
329 			ak45xx_write_gpio(ice, reg_addr, data, VX442_CODEC_CS_1, 0);
330 			break;
331 	}
332 }
333 
334 
335 void
spdif_write(ice1712 * ice,uint8 reg_addr,uint8 data)336 spdif_write(ice1712 *ice, uint8 reg_addr, uint8 data)
337 {
338 	switch (ice->config.product) {
339 		case ICE1712_SUBDEVICE_DELTA1010:
340 			break;
341 		case ICE1712_SUBDEVICE_DELTADIO2496:
342 			break;
343 		case ICE1712_SUBDEVICE_DELTA66:
344 			break;
345 		case ICE1712_SUBDEVICE_DELTA44:
346 			break;
347 		case ICE1712_SUBDEVICE_AUDIOPHILE_2496:
348 			cs84xx_write_gpio(ice, reg_addr, data, AP2496_SPDIF_CS, 0);
349 			break;
350 		case ICE1712_SUBDEVICE_DELTA410:
351 			break;
352 		case ICE1712_SUBDEVICE_DELTA1010LT:
353 			cs84xx_write_gpio(ice, reg_addr, data, DELTA1010LT_SPDIF_CS,
354 				DELTA1010LT_CS_NONE);
355 			break;
356 		case ICE1712_SUBDEVICE_VX442:
357 			cs84xx_write_gpio(ice, reg_addr, data, VX442_SPDIF_CS, 0);
358 			break;
359 	}
360 }
361 
362 
363 uint8
codec_read(ice1712 * ice,uint8 reg_addr)364 codec_read(ice1712 *ice, uint8 reg_addr)
365 {
366 	uint8 val = 0xFF;
367 	switch (ice->config.product) {
368 		case ICE1712_SUBDEVICE_DELTA66:
369 		case ICE1712_SUBDEVICE_DELTA44:
370 			val = ak45xx_read_gpio(ice, reg_addr, DELTA66_CODEC_CS_0, 0);
371 			break;
372 		case ICE1712_SUBDEVICE_DELTA410:
373 		case ICE1712_SUBDEVICE_AUDIOPHILE_2496:
374 		case ICE1712_SUBDEVICE_DELTADIO2496:
375 			val = ak45xx_read_gpio(ice, reg_addr, AP2496_CODEC_CS, 0);
376 			break;
377 		case ICE1712_SUBDEVICE_DELTA1010:
378 		case ICE1712_SUBDEVICE_DELTA1010LT:
379 			val = ak45xx_read_gpio(ice, reg_addr, DELTA1010LT_CODEC_CS_0,
380 				DELTA1010LT_CS_NONE);
381 			break;
382 		case ICE1712_SUBDEVICE_VX442:
383 			val = ak45xx_read_gpio(ice, reg_addr, VX442_CODEC_CS_0, 0);
384 			break;
385 	}
386 
387 	return val;
388 }
389 
390 
391 uint8
spdif_read(ice1712 * ice,uint8 reg_addr)392 spdif_read(ice1712 *ice, uint8 reg_addr)
393 {
394 	uint8 val = 0xFF;
395 	switch (ice->config.product) {
396 		case ICE1712_SUBDEVICE_DELTA1010:
397 			break;
398 		case ICE1712_SUBDEVICE_DELTADIO2496:
399 			break;
400 		case ICE1712_SUBDEVICE_DELTA66:
401 			break;
402 		case ICE1712_SUBDEVICE_DELTA44:
403 			break;
404 		case ICE1712_SUBDEVICE_AUDIOPHILE_2496:
405 			val = cs84xx_read_gpio(ice, reg_addr, AP2496_SPDIF_CS, 0);
406 			break;
407 		case ICE1712_SUBDEVICE_DELTA410:
408 			break;
409 		case ICE1712_SUBDEVICE_DELTA1010LT:
410 			val = cs84xx_read_gpio(ice, reg_addr, DELTA1010LT_SPDIF_CS,
411 				DELTA1010LT_CS_NONE);
412 			break;
413 		case ICE1712_SUBDEVICE_VX442:
414 			val = cs84xx_read_gpio(ice, reg_addr, VX442_SPDIF_CS, 0);
415 			break;
416 	}
417 
418 	return val;
419 }
420 
421 
422 void
write_gpio_byte(ice1712 * ice,uint8 data,uint8 gpio_data)423 write_gpio_byte(ice1712 *ice, uint8 data, uint8 gpio_data)
424 {
425 	int i;
426 
427 	for (i = 7; i >= 0; i--) {
428 		// drop clock and data bits
429 		gpio_data &= ~(ice->CommLines.clock | ice->CommLines.data_out);
430 
431 		// set data bit if needed
432 		if (data & (1 << i))
433 			gpio_data |= ice->CommLines.data_out;
434 
435 		write_gpio(ice, gpio_data);
436 		snooze(GPIO_I2C_DELAY);
437 
438 		// raise clock
439 		gpio_data |= ice->CommLines.clock;
440 		write_gpio(ice, gpio_data);
441 		snooze(GPIO_I2C_DELAY);
442 	}
443 }
444 
445 
446 uint8
read_gpio_byte(ice1712 * ice,uint8 gpio_data)447 read_gpio_byte(ice1712 *ice, uint8 gpio_data)
448 {
449 	int i;
450 	uint8 data = 0;
451 
452 	for (i = 7; i >= 0; i--) {
453 		// drop clock
454 		gpio_data &= ~(ice->CommLines.clock);
455 		write_gpio(ice, gpio_data);
456 		snooze(GPIO_I2C_DELAY);
457 
458 		if (read_gpio(ice) &ice->CommLines.data_in)
459 			data |= 1 << i;
460 
461 		gpio_data |= ice->CommLines.clock;
462 
463 		write_gpio(ice, gpio_data);
464 		snooze(GPIO_I2C_DELAY);
465 	}
466 
467 	return data;
468 }
469 
470 
471 void
ak45xx_write_gpio(ice1712 * ice,uint8 reg_addr,uint8 data,uint8 chip_select,uint8 invert_cs)472 ak45xx_write_gpio(ice1712 *ice, uint8 reg_addr, uint8 data,
473 	uint8 chip_select, uint8 invert_cs)
474 {
475 	uint8 tmp;
476 
477 	tmp = read_gpio(ice);
478 	tmp |= ice->CommLines.cs_mask;
479 
480 	if (invert_cs != 0) {
481 		tmp &= ~invert_cs;
482 		tmp |= chip_select;
483 	} else {
484 		tmp &= ~chip_select;
485 	}
486 
487 	write_gpio(ice, tmp);
488 	snooze(GPIO_I2C_DELAY);
489 
490 	write_gpio_byte(ice, ((AK45xx_CHIP_ADDRESS & 0x03) << 6) | 0x20
491 		| (reg_addr & 0x1F), tmp);
492 	write_gpio_byte(ice, data, tmp);
493 
494 	if (invert_cs != 0) {
495 		tmp |= invert_cs;
496 	} else {
497 		tmp |= chip_select;
498 	}
499 	write_gpio(ice, tmp);
500 	snooze(GPIO_I2C_DELAY);
501 }
502 
503 
504 void
cs84xx_write_gpio(ice1712 * ice,uint8 reg_addr,uint8 data,uint8 chip_select,uint8 invert_cs)505 cs84xx_write_gpio(ice1712 *ice, uint8 reg_addr, uint8 data,
506 	uint8 chip_select, uint8 invert_cs)
507 {
508 	uint8 tmp;
509 
510 	tmp = read_gpio(ice);
511 	tmp |= ice->CommLines.cs_mask;
512 
513 	if (invert_cs != 0) {
514 		tmp &= ~invert_cs;
515 		tmp |= chip_select;
516 	} else {
517 		tmp &= ~chip_select;
518 	}
519 
520 	write_gpio(ice, tmp);
521 	snooze(GPIO_I2C_DELAY);
522 
523 	write_gpio_byte(ice, (CS84xx_CHIP_ADDRESS & 0x7F) << 1, tmp);
524 	write_gpio_byte(ice, reg_addr & 0x7F, tmp); //Do not Increment
525 	write_gpio_byte(ice, data, tmp);
526 
527 	if (invert_cs != 0) {
528 		tmp |= invert_cs;
529 	} else {
530 		tmp |= chip_select;
531 	}
532 	write_gpio(ice, tmp);
533 	snooze(GPIO_I2C_DELAY);
534 }
535 
536 
537 uint8
cs84xx_read_gpio(ice1712 * ice,uint8 reg_addr,uint8 chip_select,uint8 invert_cs)538 cs84xx_read_gpio(ice1712 *ice, uint8 reg_addr, uint8 chip_select,
539 	uint8 invert_cs)
540 {
541 	uint8 tmp, data;
542 
543 	tmp = read_gpio(ice);
544 	tmp |= ice->CommLines.cs_mask;
545 
546 	if (invert_cs != 0) {
547 		tmp &= ~invert_cs;
548 		tmp |= chip_select;
549 	} else {
550 		tmp &= ~chip_select;
551 	}
552 
553 	write_gpio(ice, tmp);
554 	snooze(GPIO_I2C_DELAY);
555 
556 	write_gpio_byte(ice, (CS84xx_CHIP_ADDRESS & 0x7F) << 1,
557 		tmp); //For writing the MAP
558 	write_gpio_byte(ice, reg_addr & 0x7F, tmp); //Do not Increment
559 
560 	//Deselect the chip
561 	if (invert_cs != 0) {
562 		tmp |= invert_cs;
563 	} else {
564 		tmp |= chip_select;
565 	}
566 	write_gpio(ice, tmp);
567 	snooze(GPIO_I2C_DELAY);
568 
569 	if (invert_cs != 0) {
570 		tmp &= ~invert_cs;
571 		tmp |= chip_select;
572 	} else {
573 		tmp &= ~chip_select;
574 	}
575 	write_gpio(ice, tmp);
576 	snooze(GPIO_I2C_DELAY);
577 
578 	write_gpio_byte(ice, (CS84xx_CHIP_ADDRESS & 0x7F) << 1 | 1,
579 		tmp); //For writing the MAP
580 	data = read_gpio_byte(ice, tmp); //For reading
581 
582 	//Deselect the chip
583 	if (invert_cs != 0) {
584 		tmp |= invert_cs;
585 	} else {
586 		tmp |= chip_select;
587 	}
588 	write_gpio(ice, tmp);
589 
590 	return data;
591 }
592 
593 
594 /*
595  * return -1 if error else return an uint8
596  */
597 uint8
read_gpio(ice1712 * ice)598 read_gpio(ice1712 *ice)
599 {
600 	return read_cci_uint8(ice, CCI_GPIO_DATA);
601 }
602 
603 
604 /*
605  * return -1 if error else return 0
606  */
607 void
write_gpio(ice1712 * ice,uint8 value)608 write_gpio(ice1712 *ice, uint8 value)
609 {
610 	write_cci_uint8(ice, CCI_GPIO_DATA, value);
611 }
612