summaryrefslogtreecommitdiff
path: root/firmware/target/sh
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/sh')
-rw-r--r--firmware/target/sh/archos/audio-archos.c563
-rw-r--r--firmware/target/sh/archos/mascodec-archos.c485
2 files changed, 1048 insertions, 0 deletions
diff --git a/firmware/target/sh/archos/audio-archos.c b/firmware/target/sh/archos/audio-archos.c
new file mode 100644
index 0000000000..e2d8b6f157
--- /dev/null
+++ b/firmware/target/sh/archos/audio-archos.c
@@ -0,0 +1,563 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Code that has been in mpeg.c before, now creating an encapsulated play
11 * data module, to be used by other sources than file playback as well.
12 *
13 * Copyright (C) 2004 by Linus Nielsen Feltzing
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24#include <stdbool.h>
25#include "config.h"
26#include "debug.h"
27#include "panic.h"
28#include <kernel.h>
29#include "mp3_playback.h"
30#include "sound.h"
31#include "i2c.h"
32#include "system.h"
33#include "audiohw.h"
34
35/* hacking into mpeg.c, recording is still there */
36#if CONFIG_CODEC == MAS3587F
37enum
38{
39 MPEG_DECODER,
40 MPEG_ENCODER
41} mpeg_mode;
42#endif /* #ifdef MAS3587F */
43
44#if ((CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)) && !defined(SIMULATOR)
45extern unsigned long shadow_io_control_main;
46extern unsigned shadow_codec_reg0;
47#endif
48
49/**** globals ****/
50
51/* own version, independent of mpeg.c */
52static bool paused; /* playback is paused */
53static bool playing; /* We are playing an MP3 stream */
54
55/* for measuring the play time */
56static long playstart_tick;
57static long cumulative_ticks;
58
59/* the registered callback function to ask for more mp3 data */
60static void (*callback_for_more)(unsigned char**, size_t*);
61
62/* list of tracks in memory */
63#define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */
64#define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)
65
66bool audio_is_initialized = false;
67
68/* FIX: this code pretty much assumes a MAS */
69
70/* dirty calls to mpeg.c */
71extern void playback_tick(void);
72extern void rec_tick(void);
73
74unsigned long mas_version_code;
75
76#if CONFIG_CODEC == MAS3507D
77static void mas_poll_start(void)
78{
79 unsigned int count;
80
81 count = 9 * FREQ / 10000 / 8; /* 0.9 ms */
82
83 /* We are using timer 1 */
84
85 TSTR &= ~0x02; /* Stop the timer */
86 TSNC &= ~0x02; /* No synchronization */
87 TMDR &= ~0x02; /* Operate normally */
88
89 TCNT1 = 0; /* Start counting at 0 */
90 GRA1 = count;
91 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
92
93 /* Enable interrupt on level 5 */
94 IPRC = (IPRC & ~0x000f) | 0x0005;
95
96 TSR1 &= ~0x02;
97 TIER1 = 0xf9; /* Enable GRA match interrupt */
98
99 TSTR |= 0x02; /* Start timer 1 */
100}
101#elif CONFIG_CODEC != SWCODEC
102static void postpone_dma_tick(void)
103{
104 unsigned int count;
105
106 count = 8 * FREQ / 10000 / 8; /* 0.8 ms */
107
108 /* We are using timer 1 */
109
110 TSTR &= ~0x02; /* Stop the timer */
111 TSNC &= ~0x02; /* No synchronization */
112 TMDR &= ~0x02; /* Operate normally */
113
114 TCNT1 = 0; /* Start counting at 0 */
115 GRA1 = count;
116 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
117
118 /* Enable interrupt on level 5 */
119 IPRC = (IPRC & ~0x000f) | 0x0005;
120
121 TSR1 &= ~0x02;
122 TIER1 = 0xf9; /* Enable GRA match interrupt */
123
124 TSTR |= 0x02; /* Start timer 1 */
125}
126#endif
127
128#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
129void demand_irq_enable(bool on)
130{
131 int oldlevel = disable_irq_save();
132
133 if(on)
134 {
135 IPRA = (IPRA & 0xfff0) | 0x000b;
136 ICR &= ~0x0010; /* IRQ3 level sensitive */
137 }
138 else
139 IPRA &= 0xfff0;
140
141 restore_irq(oldlevel);
142}
143#endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
144
145
146static void play_tick(void)
147{
148 if(playing && !paused)
149 {
150 /* Start DMA if it is disabled and the DEMAND pin is high */
151 if(!(SCR0 & 0x80) && (PBDR & 0x4000))
152 {
153 SCR0 |= 0x80;
154 }
155
156 playback_tick(); /* dirty call to mpeg.c */
157 }
158}
159
160void DEI3(void) __attribute__((interrupt_handler));
161void DEI3(void)
162{
163 unsigned char* start;
164 size_t size = 0;
165
166 if (callback_for_more != NULL)
167 {
168 callback_for_more(&start, &size);
169 }
170
171 if (size > 0)
172 {
173 DTCR3 = size & 0xffff;
174 SAR3 = (unsigned int) start;
175 }
176 else
177 {
178 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
179 }
180
181 CHCR3 &= ~0x0002; /* Clear DMA interrupt */
182}
183
184void IMIA1(void) __attribute__((interrupt_handler));
185void IMIA1(void) /* Timer 1 interrupt */
186{
187 if(playing)
188 play_tick();
189 TSR1 &= ~0x01;
190#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
191 /* Disable interrupt */
192 IPRC &= ~0x000f;
193#endif
194}
195
196void IRQ6(void) __attribute__((interrupt_handler));
197void IRQ6(void) /* PB14: MAS stop demand IRQ */
198{
199 SCR0 &= ~0x80;
200}
201
202#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
203void IRQ3(void) __attribute__((interrupt_handler));
204void IRQ3(void) /* PA15: MAS demand IRQ */
205{
206 /* Begin with setting the IRQ to edge sensitive */
207 ICR |= 0x0010;
208
209#if CONFIG_CODEC == MAS3587F
210 if(mpeg_mode == MPEG_ENCODER)
211 rec_tick();
212 else
213#endif
214 postpone_dma_tick();
215
216 /* Workaround for sh-elf-gcc 3.3.x bug with -O2 or -Os and ISRs
217 * (invalid cross-jump optimisation) */
218 asm volatile ("");
219}
220#endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
221
222static void setup_sci0(void)
223{
224 /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0, PB9 is TxD0 */
225 PBCR1 = (PBCR1 & 0x0cff) | 0x1208;
226
227 /* Set PB12 to output */
228 or_b(0x10, &PBIORH);
229
230 /* Disable serial port */
231 SCR0 = 0x00;
232
233 /* Synchronous, no prescale */
234 SMR0 = 0x80;
235
236 /* Set baudrate 1Mbit/s */
237 BRR0 = 0x02;
238
239 /* use SCK as serial clock output */
240 SCR0 = 0x01;
241
242 /* Clear FER and PER */
243 SSR0 &= 0xe7;
244
245 /* Set interrupt ITU2 and SCI0 priority to 0 */
246 IPRD &= 0x0ff0;
247
248 /* set PB15 and PB14 to inputs */
249 and_b(~0x80, &PBIORH);
250 and_b(~0x40, &PBIORH);
251
252 /* Enable End of DMA interrupt at prio 8 */
253 IPRC = (IPRC & 0xf0ff) | 0x0800;
254
255 /* Enable Tx (only!) */
256 SCR0 |= 0x20;
257}
258
259#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
260static void init_playback(void)
261{
262 unsigned long val;
263 int rc;
264
265 mp3_play_pause(false);
266
267 mas_reset();
268
269 /* Enable the audio CODEC and the DSP core, max analog voltage range */
270 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
271 if(rc < 0)
272 panicf("mas_ctrl_w: %d", rc);
273
274 /* Stop the current application */
275 val = 0;
276 mas_writemem(MAS_BANK_D0, MAS_D0_APP_SELECT, &val, 1);
277 do
278 {
279 mas_readmem(MAS_BANK_D0, MAS_D0_APP_RUNNING, &val, 1);
280 } while(val);
281
282 /* Enable the D/A Converter */
283 shadow_codec_reg0 = 0x0001;
284 mas_codec_writereg(0x0, shadow_codec_reg0);
285
286 /* ADC scale 0%, DSP scale 100% */
287 mas_codec_writereg(6, 0x0000);
288 mas_codec_writereg(7, 0x4000);
289
290#ifdef HAVE_SPDIF_OUT
291 val = 0x09; /* Disable SDO and SDI, low impedance S/PDIF outputs */
292#else
293 val = 0x2d; /* Disable SDO and SDI, disable S/PDIF output */
294#endif
295 mas_writemem(MAS_BANK_D0, MAS_D0_INTERFACE_CONTROL, &val, 1);
296
297 /* Set Demand mode and validate all settings */
298 shadow_io_control_main = 0x25;
299 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
300
301 /* Start the Layer2/3 decoder applications */
302 val = 0x0c;
303 mas_writemem(MAS_BANK_D0, MAS_D0_APP_SELECT, &val, 1);
304 do
305 {
306 mas_readmem(MAS_BANK_D0, MAS_D0_APP_RUNNING, &val, 1);
307 } while((val & 0x0c) != 0x0c);
308
309#if CONFIG_CODEC == MAS3587F
310 mpeg_mode = MPEG_DECODER;
311#endif
312
313 /* set IRQ6 to edge detect */
314 ICR |= 0x02;
315
316 /* set IRQ6 prio 8 */
317 IPRB = ( IPRB & 0xff0f ) | 0x0080;
318
319 DEBUGF("MAS Decoding application started\n");
320}
321#endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
322
323void mp3_init(int volume, int bass, int treble, int balance, int loudness,
324 int avc, int channel_config, int stereo_width,
325 int mdb_strength, int mdb_harmonics,
326 int mdb_center, int mdb_shape, bool mdb_enable,
327 bool superbass)
328{
329#if CONFIG_CODEC == MAS3507D
330 unsigned long val;
331 (void)loudness;
332 (void)avc;
333 (void)mdb_strength;
334 (void)mdb_harmonics;
335 (void)mdb_center;
336 (void)mdb_shape;
337 (void)mdb_enable;
338 (void)superbass;
339#endif
340
341 setup_sci0();
342
343#ifdef HAVE_MAS_SIBI_CONTROL
344 and_b(~0x01, &PBDRH); /* drive SIBI low */
345 or_b(0x01, &PBIORH); /* output for PB8 */
346#endif
347
348#if CONFIG_CODEC == MAS3507D
349 mas_reset();
350#elif CONFIG_CODEC == MAS3587F
351 or_b(0x08, &PAIORH); /* output for /PR */
352 init_playback();
353
354 mas_version_code = mas_readver();
355 DEBUGF("MAS3587 derivate %d, version %c%d\n",
356 (mas_version_code & 0xf000) >> 12,
357 'A' + ((mas_version_code & 0x0f00) >> 8), mas_version_code & 0xff);
358#elif CONFIG_CODEC == MAS3539F
359 or_b(0x08, &PAIORH); /* output for /PR */
360 init_playback();
361
362 mas_version_code = mas_readver();
363 DEBUGF("MAS3539 derivate %d, version %c%d\n",
364 (mas_version_code & 0xf000) >> 12,
365 'A' + ((mas_version_code & 0x0f00) >> 8), mas_version_code & 0xff);
366#endif
367
368#ifdef HAVE_DAC3550A
369 dac_init();
370#endif
371
372#if CONFIG_CODEC == MAS3507D
373 /* set IRQ6 to edge detect */
374 ICR |= 0x02;
375
376 /* set IRQ6 prio 8 */
377 IPRB = ( IPRB & 0xff0f ) | 0x0080;
378
379 mas_readmem(MAS_BANK_D1, 0xff7, &mas_version_code, 1);
380
381 mas_writereg(0x3b, 0x20); /* Don't ask why. The data sheet doesn't say */
382 mas_run(1);
383 sleep(HZ);
384
385 /* Clear the upper 12 bits of the 32-bit samples */
386 mas_writereg(0xc5, 0);
387 mas_writereg(0xc6, 0);
388
389 /* We need to set the PLL for a 14.31818MHz crystal */
390 if(mas_version_code == 0x0601) /* Version F10? */
391 {
392 val = 0x5d9d0;
393 mas_writemem(MAS_BANK_D0, 0x32d, &val, 1);
394 val = 0xfffceceb;
395 mas_writemem(MAS_BANK_D0, 0x32e, &val, 1);
396 val = 0x0;
397 mas_writemem(MAS_BANK_D0, 0x32f, &val, 1);
398 mas_run(0x475);
399 }
400 else
401 {
402 val = 0x5d9d0;
403 mas_writemem(MAS_BANK_D0, 0x36d, &val, 1);
404 val = 0xfffceceb;
405 mas_writemem(MAS_BANK_D0, 0x36e, &val, 1);
406 val = 0x0;
407 mas_writemem(MAS_BANK_D0, 0x36f, &val, 1);
408 mas_run(0xfcb);
409 }
410
411#endif
412
413#if CONFIG_CODEC == MAS3507D
414 mas_poll_start();
415
416 mas_writereg(MAS_REG_KPRESCALE, 0xe9400);
417 dac_enable(true);
418#endif
419
420#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
421 ICR &= ~0x0010; /* IRQ3 level sensitive */
422 PACR1 = (PACR1 & 0x3fff) | 0x4000; /* PA15 is IRQ3 */
423#endif
424
425 /* Must be done before calling sound_set() */
426 audio_is_initialized = true;
427
428 sound_set(SOUND_BASS, bass);
429 sound_set(SOUND_TREBLE, treble);
430 sound_set(SOUND_BALANCE, balance);
431 sound_set(SOUND_VOLUME, volume);
432 sound_set(SOUND_CHANNELS, channel_config);
433 sound_set(SOUND_STEREO_WIDTH, stereo_width);
434
435#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
436 sound_set(SOUND_LOUDNESS, loudness);
437 sound_set(SOUND_AVC, avc);
438 sound_set(SOUND_MDB_STRENGTH, mdb_strength);
439 sound_set(SOUND_MDB_HARMONICS, mdb_harmonics);
440 sound_set(SOUND_MDB_CENTER, mdb_center);
441 sound_set(SOUND_MDB_SHAPE, mdb_shape);
442 sound_set(SOUND_MDB_ENABLE, mdb_enable);
443 sound_set(SOUND_SUPERBASS, superbass);
444#endif
445
446 playing = false;
447 paused = true;
448}
449
450void mp3_shutdown(void)
451{
452#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
453 unsigned long val = 1;
454 mas_writemem(MAS_BANK_D0, MAS_D0_SOFT_MUTE, &val, 1); /* Mute */
455#endif
456
457#if CONFIG_CODEC == MAS3507D
458 dac_volume(0, 0, false);
459#endif
460}
461
462/* new functions, to be exported to plugin API */
463
464void mp3_play_init(void)
465{
466#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
467 init_playback();
468#endif
469 playing = false;
470 paused = true;
471 callback_for_more = NULL;
472 mp3_reset_playtime();
473}
474
475void mp3_play_data(const unsigned char* start, int size,
476 void (*get_more)(unsigned char** start, size_t* size) /* callback fn */
477)
478{
479 /* init DMA */
480 DAR3 = 0x5FFFEC3;
481 CHCR3 &= ~0x0002; /* Clear interrupt */
482 CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
483 DMAOR = 0x0001; /* Enable DMA */
484
485 callback_for_more = get_more;
486
487 SAR3 = (unsigned int)start;
488 DTCR3 = size & 0xffff;
489
490 playing = true;
491 paused = true;
492
493 CHCR3 |= 0x0001; /* Enable DMA IRQ */
494
495#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
496 demand_irq_enable(true);
497#endif
498}
499
500void mp3_play_pause(bool play)
501{
502 if (paused && play)
503 { /* resume playback */
504 SCR0 |= 0x80;
505 paused = false;
506 playstart_tick = current_tick;
507 }
508 else if (!paused && !play)
509 { /* stop playback */
510 SCR0 &= 0x7f;
511 paused = true;
512 cumulative_ticks += current_tick - playstart_tick;
513 }
514}
515
516bool mp3_pause_done(void)
517{
518 unsigned long frame_count;
519
520 if (!paused)
521 return false;
522
523 mas_readmem(MAS_BANK_D0, MAS_D0_MPEG_FRAME_COUNT, &frame_count, 1);
524 /* This works because the frame counter never wraps,
525 * i.e. zero always means lost sync. */
526 return frame_count == 0;
527}
528
529void mp3_play_stop(void)
530{
531 playing = false;
532 mp3_play_pause(false);
533 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
534#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
535 demand_irq_enable(false);
536#endif
537}
538
539long mp3_get_playtime(void)
540{
541 if (paused)
542 return cumulative_ticks;
543 else
544 return cumulative_ticks + current_tick - playstart_tick;
545}
546
547void mp3_reset_playtime(void)
548{
549 cumulative_ticks = 0;
550 playstart_tick = current_tick;
551}
552
553bool mp3_is_playing(void)
554{
555 return playing;
556}
557
558
559/* returns the next byte position which would be transferred */
560unsigned char* mp3_get_pos(void)
561{
562 return (unsigned char*)SAR3;
563}
diff --git a/firmware/target/sh/archos/mascodec-archos.c b/firmware/target/sh/archos/mascodec-archos.c
new file mode 100644
index 0000000000..3f932166eb
--- /dev/null
+++ b/firmware/target/sh/archos/mascodec-archos.c
@@ -0,0 +1,485 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: mas.c 18807 2008-10-14 11:12:20Z zagor $
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "stdbool.h"
22#include "config.h"
23#include "sh7034.h"
24#include "i2c.h"
25#include "debug.h"
26#include "mas35xx.h"
27#include "kernel.h"
28#include "system.h"
29#include "hwcompat.h"
30
31static int mas_devread(unsigned long *dest, int len);
32
33int mas_default_read(unsigned short *buf)
34{
35 unsigned char *dest = (unsigned char *)buf;
36 int ret = 0;
37
38 i2c_begin();
39
40 i2c_start();
41 i2c_outb(MAS_DEV_WRITE);
42 if (i2c_getack()) {
43 i2c_outb(MAS_DATA_READ);
44 if (i2c_getack()) {
45 i2c_start();
46 i2c_outb(MAS_DEV_READ);
47 if (i2c_getack()) {
48 dest[0] = i2c_inb(0);
49 dest[1] = i2c_inb(1);
50 }
51 else
52 ret = -3;
53 }
54 else
55 ret = -2;
56 }
57 else
58 ret = -1;
59
60 i2c_stop();
61
62 i2c_end();
63 return ret;
64}
65
66int mas_run(unsigned short address)
67{
68 int ret = 0;
69 unsigned char buf[3];
70
71 i2c_begin();
72
73 buf[0] = MAS_DATA_WRITE;
74 buf[1] = address >> 8;
75 buf[2] = address & 0xff;
76
77 /* send run command */
78 if (i2c_write(MAS_DEV_WRITE,buf,3))
79 {
80 ret = -1;
81 }
82
83 i2c_end();
84 return ret;
85}
86
87/* note: 'len' is number of 32-bit words, not number of bytes! */
88int mas_readmem(int bank, int addr, unsigned long* dest, int len)
89{
90 int ret = 0;
91 unsigned char buf[7];
92
93 i2c_begin();
94
95 buf[0] = MAS_DATA_WRITE;
96 buf[1] = bank?MAS_CMD_READ_D1_MEM:MAS_CMD_READ_D0_MEM;
97 buf[2] = 0x00;
98 buf[3] = (len & 0xff00) >> 8;
99 buf[4] = len & 0xff;
100 buf[5] = (addr & 0xff00) >> 8;
101 buf[6] = addr & 0xff;
102
103 /* send read command */
104 if (i2c_write(MAS_DEV_WRITE,buf,7))
105 {
106 ret = -1;
107 }
108
109 ret = mas_devread(dest, len);
110
111 i2c_end();
112 return ret;
113}
114
115/* note: 'len' is number of 32-bit words, not number of bytes! */
116int mas_writemem(int bank, int addr, const unsigned long* src, int len)
117{
118 int ret = 0;
119 int i, j;
120 unsigned char buf[60];
121 const unsigned char* ptr = (const unsigned char*)src;
122
123 i2c_begin();
124
125 i=0;
126 buf[i++] = MAS_DATA_WRITE;
127 buf[i++] = bank?MAS_CMD_WRITE_D1_MEM:MAS_CMD_WRITE_D0_MEM;
128 buf[i++] = 0x00;
129 buf[i++] = (len & 0xff00) >> 8;
130 buf[i++] = len & 0xff;
131 buf[i++] = (addr & 0xff00) >> 8;
132 buf[i++] = addr & 0xff;
133
134 j = 0;
135 while(len--) {
136#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
137 buf[i++] = 0;
138 buf[i++] = ptr[j+1];
139 buf[i++] = ptr[j+2];
140 buf[i++] = ptr[j+3];
141#else
142 buf[i++] = ptr[j+2];
143 buf[i++] = ptr[j+3];
144 buf[i++] = 0;
145 buf[i++] = ptr[j+1];
146#endif
147 j += 4;
148 }
149
150 /* send write command */
151 if (i2c_write(MAS_DEV_WRITE,buf,i))
152 {
153 ret = -1;
154 }
155
156 i2c_end();
157 return ret;
158}
159
160int mas_readreg(int reg)
161{
162 int ret = 0;
163 unsigned char buf[16];
164 unsigned long value;
165
166 i2c_begin();
167
168 buf[0] = MAS_DATA_WRITE;
169 buf[1] = MAS_CMD_READ_REG | (reg >> 4);
170 buf[2] = (reg & 0x0f) << 4;
171
172 /* send read command */
173 if (i2c_write(MAS_DEV_WRITE,buf,3))
174 {
175 ret = -1;
176 }
177 else
178 {
179 if(mas_devread(&value, 1))
180 {
181 ret = -2;
182 }
183 else
184 {
185 ret = value;
186 }
187 }
188
189 i2c_end();
190 return ret;
191}
192
193int mas_writereg(int reg, unsigned int val)
194{
195 int ret = 0;
196 unsigned char buf[5];
197
198 i2c_begin();
199
200 buf[0] = MAS_DATA_WRITE;
201 buf[1] = MAS_CMD_WRITE_REG | (reg >> 4);
202#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
203 buf[2] = ((reg & 0x0f) << 4) | (val >> 16 & 0x0f);
204 buf[3] = (val >> 8) & 0xff;
205 buf[4] = val & 0xff;
206#else
207 buf[2] = ((reg & 0x0f) << 4) | (val & 0x0f);
208 buf[3] = (val >> 12) & 0xff;
209 buf[4] = (val >> 4) & 0xff;
210#endif
211
212 /* send write command */
213 if (i2c_write(MAS_DEV_WRITE,buf,5))
214 {
215 ret = -1;
216 }
217
218 i2c_end();
219 return ret;
220}
221
222/* note: 'len' is number of 32-bit words, not number of bytes! */
223static int mas_devread(unsigned long *dest, int len)
224{
225 int ret = 0;
226 unsigned char* ptr = (unsigned char*)dest;
227 int i;
228
229 /* handle read-back */
230 /* Remember, the MAS values are only 20 bits, so we set
231 the upper 12 bits to 0 */
232 i2c_start();
233 i2c_outb(MAS_DEV_WRITE);
234 if (i2c_getack()) {
235 i2c_outb(MAS_DATA_READ);
236 if (i2c_getack()) {
237 i2c_start();
238 i2c_outb(MAS_DEV_READ);
239 if (i2c_getack()) {
240 for (i=0;len;i++) {
241 len--;
242#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
243 i2c_inb(0); /* Dummy read */
244 ptr[i*4+0] = 0;
245 ptr[i*4+1] = i2c_inb(0) & 0x0f;
246 ptr[i*4+2] = i2c_inb(0);
247 if(len)
248 ptr[i*4+3] = i2c_inb(0);
249 else
250 ptr[i*4+3] = i2c_inb(1); /* NAK the last byte */
251#else
252 ptr[i*4+2] = i2c_inb(0);
253 ptr[i*4+3] = i2c_inb(0);
254 ptr[i*4+0] = i2c_inb(0);
255 if(len)
256 ptr[i*4+1] = i2c_inb(0);
257 else
258 ptr[i*4+1] = i2c_inb(1); /* NAK the last byte */
259#endif
260 }
261 }
262 else
263 ret = -3;
264 }
265 else
266 ret = -2;
267 }
268 else
269 ret = -1;
270
271 i2c_stop();
272
273 return ret;
274}
275
276void mas_reset(void)
277{
278 or_b(0x01, &PAIORH);
279
280#if CONFIG_CODEC == MAS3507D
281 /* PB5 is "MAS enable". make it GPIO output and high */
282 PBCR2 &= ~0x0c00;
283 or_b(0x20, &PBIORL);
284 or_b(0x20, &PBDRL);
285
286 and_b(~0x01, &PADRH);
287 sleep(HZ/100);
288 or_b(0x01, &PADRH);
289 sleep(HZ/5);
290#elif (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
291 if (HW_MASK & ATA_ADDRESS_200)
292 {
293 and_b(~0x01, &PADRH);
294 sleep(HZ/100);
295 or_b(0x01, &PADRH);
296 sleep(HZ/5);
297 }
298 else
299 {
300 /* Older recorder models don't invert the POR signal */
301 or_b(0x01, &PADRH);
302 sleep(HZ/100);
303 and_b(~0x01, &PADRH);
304 sleep(HZ/5);
305 }
306#endif
307}
308
309#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
310int mas_direct_config_read(unsigned char reg)
311{
312 int ret = 0;
313 unsigned char tmp[2];
314
315 i2c_begin();
316
317 i2c_start();
318 i2c_outb(MAS_DEV_WRITE);
319 if (i2c_getack()) {
320 i2c_outb(reg);
321 if (i2c_getack()) {
322 i2c_start();
323 i2c_outb(MAS_DEV_READ);
324 if (i2c_getack()) {
325 tmp[0] = i2c_inb(0);
326 tmp[1] = i2c_inb(1); /* NAK the last byte */
327 ret = (tmp[0] << 8) | tmp[1];
328 }
329 else
330 ret = -3;
331 }
332 else
333 ret = -2;
334 }
335 else
336 ret = -1;
337
338 i2c_stop();
339
340 i2c_end();
341 return ret;
342}
343
344int mas_direct_config_write(unsigned char reg, unsigned int val)
345{
346 int ret = 0;
347 unsigned char buf[3];
348
349 i2c_begin();
350
351 buf[0] = reg;
352 buf[1] = (val >> 8) & 0xff;
353 buf[2] = val & 0xff;
354
355 /* send write command */
356 if (i2c_write(MAS_DEV_WRITE,buf,3))
357 {
358 ret = -1;
359 }
360
361 i2c_end();
362 return ret;
363}
364
365int mas_codec_writereg(int reg, unsigned int val)
366{
367 int ret = 0;
368 unsigned char buf[5];
369
370 i2c_begin();
371
372 buf[0] = MAS_CODEC_WRITE;
373 buf[1] = (reg >> 8) & 0xff;
374 buf[2] = reg & 0xff;
375 buf[3] = (val >> 8) & 0xff;
376 buf[4] = val & 0xff;
377
378 /* send write command */
379 if (i2c_write(MAS_DEV_WRITE,buf,5))
380 {
381 ret = -1;
382 }
383
384 i2c_end();
385 return ret;
386}
387
388int mas_codec_readreg(int reg)
389{
390 int ret = 0;
391 unsigned char buf[16];
392 unsigned char tmp[2];
393
394 i2c_begin();
395
396 buf[0] = MAS_CODEC_WRITE;
397 buf[1] = (reg >> 8) & 0xff;
398 buf[2] = reg & 0xff;
399
400 /* send read command */
401 if (i2c_write(MAS_DEV_WRITE,buf,3))
402 {
403 ret = -1;
404 }
405 else
406 {
407 i2c_start();
408 i2c_outb(MAS_DEV_WRITE);
409 if (i2c_getack()) {
410 i2c_outb(MAS_CODEC_READ);
411 if (i2c_getack()) {
412 i2c_start();
413 i2c_outb(MAS_DEV_READ);
414 if (i2c_getack()) {
415 tmp[0] = i2c_inb(0);
416 tmp[1] = i2c_inb(1); /* NAK the last byte */
417 ret = (tmp[0] << 8) | tmp[1];
418 }
419 else
420 ret = -4;
421 }
422 else
423 ret = -3;
424 }
425 else
426 ret = -2;
427
428 i2c_stop();
429 }
430
431 i2c_end();
432 return ret;
433}
434
435unsigned long mas_readver(void)
436{
437 int ret = 0;
438 unsigned char buf[16];
439 unsigned long value;
440
441 i2c_begin();
442
443 buf[0] = MAS_DATA_WRITE;
444 buf[1] = MAS_CMD_READ_IC_VER;
445 buf[2] = 0;
446
447 /* send read command */
448 if (i2c_write(MAS_DEV_WRITE,buf,3))
449 {
450 ret = -1;
451 }
452 else
453 {
454 if(mas_devread(&value, 1))
455 {
456 ret = -2;
457 }
458 else
459 {
460 ret = value;
461 }
462 }
463
464 i2c_end();
465 return ret;
466}
467
468#endif
469
470#if CONFIG_TUNER & S1A0903X01
471static int pllfreq;
472
473void mas_store_pllfreq(int freq)
474{
475 pllfreq = freq;
476}
477
478int mas_get_pllfreq(void)
479{
480 return pllfreq;
481}
482#endif
483
484
485