diff options
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/audio/mas35xx.c | 285 | ||||
-rw-r--r-- | firmware/drivers/audio/sdl.c | 22 | ||||
-rw-r--r-- | firmware/drivers/button.c | 9 | ||||
-rw-r--r-- | firmware/drivers/fmradio.c | 121 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_m41st84w.c | 296 | ||||
-rw-r--r-- | firmware/drivers/tuner/s1a0903x01.c | 179 |
6 files changed, 0 insertions, 912 deletions
diff --git a/firmware/drivers/audio/mas35xx.c b/firmware/drivers/audio/mas35xx.c deleted file mode 100644 index 65c582c79c..0000000000 --- a/firmware/drivers/audio/mas35xx.c +++ /dev/null @@ -1,285 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Driver for MAS35xx audio codec - * - * - * Copyright (c) 2007 by Christian Gmeiner - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "system.h" /* MAX MIN macros */ -#include "sound.h" - -int channel_configuration = SOUND_CHAN_STEREO; -int stereo_width = 100; - -#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) -unsigned long mdb_shape_shadow = 0; -unsigned long loudness_shadow = 0; -unsigned long shadow_io_control_main; -#endif - -static void set_channel_config(void) -{ - /* default values: stereo */ - unsigned long val_ll = 0x80000; - unsigned long val_lr = 0; - unsigned long val_rl = 0; - unsigned long val_rr = 0x80000; - int bank; - - switch(channel_configuration) - { - /* case SOUND_CHAN_STEREO unnecessary */ - - case SOUND_CHAN_MONO: - val_ll = 0xc0000; - val_lr = 0xc0000; - val_rl = 0xc0000; - val_rr = 0xc0000; - break; - - case SOUND_CHAN_CUSTOM: - { - /* fixed point variables (matching MAS internal format) - integer part: upper 13 bits (inlcuding sign) - fractional part: lower 19 bits */ - long fp_width, fp_straight, fp_cross; - - fp_width = (stereo_width << 19) / 100; - if (stereo_width <= 100) - { - fp_straight = - ((1<<19) + fp_width) / 2; - fp_cross = fp_straight + fp_width; - } - else - { - /* straight = - (1 + width) / (2 * width) */ - fp_straight = - ((((1<<19) + fp_width) / (fp_width >> 9)) << 9); - fp_cross = (1<<19) + fp_straight; - } - val_ll = val_rr = fp_straight & 0xfffff; - val_lr = val_rl = fp_cross & 0xfffff; - } - break; - - case SOUND_CHAN_MONO_LEFT: - val_ll = 0x80000; - val_lr = 0x80000; - val_rl = 0; - val_rr = 0; - break; - - case SOUND_CHAN_MONO_RIGHT: - val_ll = 0; - val_lr = 0; - val_rl = 0x80000; - val_rr = 0x80000; - break; - - case SOUND_CHAN_KARAOKE: - val_ll = 0xc0000; - val_lr = 0x40000; - val_rl = 0x40000; - val_rr = 0xc0000; - break; - } - -#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) - bank = MAS_BANK_D0; -#elif CONFIG_CODEC == MAS3507D - bank = MAS_BANK_D1; -#endif - - mas_writemem(bank, MAS_D0_OUT_LL, &val_ll, 1); /* LL */ - mas_writemem(bank, MAS_D0_OUT_LR, &val_lr, 1); /* LR */ - mas_writemem(bank, MAS_D0_OUT_RL, &val_rl, 1); /* RL */ - mas_writemem(bank, MAS_D0_OUT_RR, &val_rr, 1); /* RR */ -} - -void audiohw_set_channel(int val) -{ - channel_configuration = val; - set_channel_config(); -} - -void audiohw_set_stereo_width(int val) -{ - stereo_width = val; - if (channel_configuration == SOUND_CHAN_CUSTOM) { - set_channel_config(); - } -} - -void audiohw_set_bass(int val) -{ -#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) - unsigned tmp = ((unsigned)(val * 8) & 0xff) << 8; - mas_codec_writereg(MAS_REG_KBASS, tmp); -#elif CONFIG_CODEC == MAS3507D - mas_writereg(MAS_REG_KBASS, bass_table[val+15]); -#endif -} - -#if CONFIG_CODEC == MAS3507D -void audiohw_set_prescaler(int val) -{ - mas_writereg(MAS_REG_KPRESCALE, prescale_table[val/10]); -} -#endif - -void audiohw_set_treble(int val) -{ -#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) - unsigned tmp = ((unsigned)(val * 8) & 0xff) << 8; - mas_codec_writereg(MAS_REG_KTREBLE, tmp); -#elif CONFIG_CODEC == MAS3507D - mas_writereg(MAS_REG_KTREBLE, treble_table[val+15]); -#endif -} - -#if (CONFIG_CODEC == MAS3507D) -/* convert tenth of dB volume (-780..+180) to dac3550 register value */ -static unsigned int tenthdb2reg(int db) -{ - if (db < -540) /* 3 dB steps */ - return (db + 780) / 30; - else /* 1.5 dB steps */ - return (db + 660) / 15; -} - -void audiohw_set_volume(int vol_l, int vol_r) -{ - dac_volume(tenthdb2reg(vol_l), tenthdb2reg(vol_r), false); -} -#endif /* CONFIG_CODEC == MAS3507D */ - -#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) -void audiohw_set_volume(int val) -{ - unsigned tmp = ((unsigned)(val + 115) & 0xff) << 8; - mas_codec_writereg(MAS_REG_VOLUME_CONTROL, tmp); -} - -void audiohw_set_loudness(int value) -{ - loudness_shadow = (loudness_shadow & 0x04) | - (MAX(MIN(value * 4, 0x44), 0) << 8); - mas_codec_writereg(MAS_REG_KLOUDNESS, loudness_shadow); -} - -void audiohw_set_avc(int value) -{ - int tmp; - - static const uint16_t avc_vals[] = - { - (0x1 << 8) | (0x8 << 12), /* 20ms */ - (0x2 << 8) | (0x8 << 12), /* 2s */ - (0x4 << 8) | (0x8 << 12), /* 4s */ - (0x8 << 8) | (0x8 << 12), /* 8s */ - }; - switch (value) { - case 1: - case 2: - case 3: - case 4: - tmp = avc_vals[value -1]; - break; - case -1: /* turn off and then turn on again to decay quickly */ - tmp = mas_codec_readreg(MAS_REG_KAVC); - mas_codec_writereg(MAS_REG_KAVC, 0); - break; - default: /* off */ - tmp = 0; - break; - } - mas_codec_writereg(MAS_REG_KAVC, tmp); -} - -void audiohw_set_mdb_strength(int value) -{ - mas_codec_writereg(MAS_REG_KMDB_STR, (value & 0x7f) << 8); -} - -void audiohw_set_mdb_harmonics(int value) -{ - int tmp = value * 127 / 100; - mas_codec_writereg(MAS_REG_KMDB_HAR, (tmp & 0x7f) << 8); -} - -void audiohw_set_mdb_center(int value) -{ - mas_codec_writereg(MAS_REG_KMDB_FC, (value/10) << 8); -} - -void audiohw_set_mdb_shape(int value) -{ - mdb_shape_shadow = (mdb_shape_shadow & 0x02) | ((value/10) << 8); - mas_codec_writereg(MAS_REG_KMDB_SWITCH, mdb_shape_shadow); -} - -void audiohw_set_mdb_enable(int value) -{ - mdb_shape_shadow = (mdb_shape_shadow & ~0x02) | (value?2:0); - mas_codec_writereg(MAS_REG_KMDB_SWITCH, mdb_shape_shadow); -} - -void audiohw_set_superbass(int value) -{ - loudness_shadow = (loudness_shadow & ~0x04) | (value?4:0); - mas_codec_writereg(MAS_REG_KLOUDNESS, loudness_shadow); -} - -void audiohw_set_balance(int val) -{ - unsigned tmp = ((unsigned)(val * 127 / 100) & 0xff) << 8; - mas_codec_writereg(MAS_REG_BALANCE, tmp); -} - -/* This functionality works by telling the decoder that we have another - crystal frequency than we actually have. It will adjust its internal - parameters and the result is that the audio is played at another pitch. -*/ -static int32_t last_pitch = PITCH_SPEED_100; - -void audiohw_set_pitch(int32_t val) -{ - if (val == last_pitch) - return; - - /* Calculate the new (bogus) frequency */ - unsigned long reg = 18432 * PITCH_SPEED_100 / val; - mas_writemem(MAS_BANK_D0, MAS_D0_OFREQ_CONTROL, ®, 1); - - /* We must tell the MAS that the frequency has changed. - * This will unfortunately cause a short silence. */ - mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, - &shadow_io_control_main, 1); - - last_pitch = val; -} - -int32_t audiohw_get_pitch(void) -{ - return last_pitch; -} - -#endif /* CONFIG_CODEC == MAS3587F || CONFIG_CODEC == MAS3539F */ - diff --git a/firmware/drivers/audio/sdl.c b/firmware/drivers/audio/sdl.c index a8fd2ffa07..d701665889 100644 --- a/firmware/drivers/audio/sdl.c +++ b/firmware/drivers/audio/sdl.c @@ -134,25 +134,3 @@ unsigned int pcm_sampr_to_hw_sampr(unsigned int samplerate, unsigned int type) { return samplerate; (void)type; } #endif /* CONFIG_SAMPR_TYPES */ -#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) -int mas_codec_readreg(int reg) -{ - (void)reg; - return 0; -} - -int mas_codec_writereg(int reg, unsigned int val) -{ - (void)reg; - (void)val; - return 0; -} -int mas_writemem(int bank, int addr, const unsigned long* src, int len) -{ - (void)bank; - (void)addr; - (void)src; - (void)len; - return 0; -} -#endif diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c index 626afc415f..c81b629f6d 100644 --- a/firmware/drivers/button.c +++ b/firmware/drivers/button.c @@ -575,9 +575,6 @@ static int button_flip(int button) #if defined(BUTTON_SCROLL_BACK) && defined(BUTTON_SCROLL_FWD) | BUTTON_SCROLL_BACK | BUTTON_SCROLL_FWD #endif -#if CONFIG_KEYPAD == RECORDER_PAD - | BUTTON_F1 | BUTTON_F3 -#endif #if (CONFIG_KEYPAD == SANSA_C200_PAD) || (CONFIG_KEYPAD == SANSA_CLIP_PAD) ||\ (CONFIG_KEYPAD == GIGABEAT_PAD) || (CONFIG_KEYPAD == GIGABEAT_S_PAD) | BUTTON_VOL_UP | BUTTON_VOL_DOWN @@ -604,12 +601,6 @@ static int button_flip(int button) if (button & BUTTON_SCROLL_FWD) newbutton |= BUTTON_SCROLL_BACK; #endif -#if CONFIG_KEYPAD == RECORDER_PAD - if (button & BUTTON_F1) - newbutton |= BUTTON_F3; - if (button & BUTTON_F3) - newbutton |= BUTTON_F1; -#endif #if (CONFIG_KEYPAD == SANSA_C200_PAD) || (CONFIG_KEYPAD == SANSA_CLIP_PAD) ||\ (CONFIG_KEYPAD == GIGABEAT_PAD) || (CONFIG_KEYPAD == GIGABEAT_S_PAD) if (button & BUTTON_VOL_UP) diff --git a/firmware/drivers/fmradio.c b/firmware/drivers/fmradio.c deleted file mode 100644 index a6d2e799cb..0000000000 --- a/firmware/drivers/fmradio.c +++ /dev/null @@ -1,121 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Linus Nielsen Feltzing - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "lcd.h" -#include "sh7034.h" -#include "kernel.h" -#include "thread.h" -#include "debug.h" -#include "system.h" -#include "fmradio.h" - -#if CONFIG_TUNER - -/* Signals: - DI (Data In) - PB0 (doubles as data pin for the LCD) - CL (Clock) - PB1 (doubles as clock for the LCD) - CE (Chip Enable) - PB3 (also chip select for the LCD, but active low) - DO (Data Out) - PB4 -*/ - -/* cute little functions */ -#define CE_LO and_b(~0x08, PBDRL_ADDR) -#define CE_HI or_b(0x08, PBDRL_ADDR) -#define CL_LO and_b(~0x02, PBDRL_ADDR) -#define CL_HI or_b(0x02, PBDRL_ADDR) -#define DO (PBDR & 0x10) -#define DI_LO and_b(~0x01, PBDRL_ADDR) -#define DI_HI or_b(0x01, PBDRL_ADDR) - -#define START or_b((0x08 | 0x02), PBDRL_ADDR) - -/* delay loop */ -#define DELAY do { int _x; for(_x=0;_x<10;_x++);} while (0) - - -int fmradio_read(int addr) -{ - int i; - int data = 0; - - START; - - /* First address bit */ - CL_LO; - if(addr & 2) - DI_HI; - else - DI_LO; - DELAY; - CL_HI; - DELAY; - - /* Second address bit */ - CL_LO; - if(addr & 1) - DI_HI; - else - DI_LO; - DELAY; - CL_HI; - DELAY; - - for(i = 0; i < 21;i++) - { - CL_LO; - DELAY; - data <<= 1; - data |= (DO)?1:0; - CL_HI; - DELAY; - } - - CE_LO; - - return data; -} - -void fmradio_set(int addr, int data) -{ - int i; - - /* Include the address in the data */ - data |= addr << 21; - - START; - - for(i = 0; i < 23;i++) - { - CL_LO; - DELAY; - if(data & (1 << 22)) - DI_HI; - else - DI_LO; - - data <<= 1; - CL_HI; - DELAY; - } - - CE_LO; -} - -#endif diff --git a/firmware/drivers/rtc/rtc_m41st84w.c b/firmware/drivers/rtc/rtc_m41st84w.c deleted file mode 100644 index 621e650f68..0000000000 --- a/firmware/drivers/rtc/rtc_m41st84w.c +++ /dev/null @@ -1,296 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Linus Nielsen Feltzing, Uwe Freese, Laurent Baum - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" -#include "i2c.h" -#include "rtc.h" -#include "kernel.h" -#include "system.h" -#include "timefuncs.h" - -#define RTC_ADR 0xd0 -#define RTC_DEV_WRITE (RTC_ADR | 0x00) -#define RTC_DEV_READ (RTC_ADR | 0x01) - -void rtc_init(void) -{ - unsigned char data; - -#ifdef HAVE_RTC_ALARM - /* Check + save alarm bit first, before the power thread starts watching */ - rtc_check_alarm_started(false); -#endif - - /* Clear the Stop bit if it is set */ - data = rtc_read(0x01); - if(data & 0x80) - rtc_write(0x01, 0x00); - - /* Clear the HT bit if it is set */ - data = rtc_read(0x0c); - - if(data & 0x40) - { - data &= ~0x40; - rtc_write(0x0c,data); - } - -#ifdef HAVE_RTC_ALARM - - /* Clear Trec bit, write-protecting the RTC for 200ms when shutting off */ - /* without this, the alarm won't work! */ - - data = rtc_read(0x04); - if (data & 0x80) - { - data &= ~0x80; - rtc_write(0x04, data); - } - - /* Also, make sure that the OUT bit in register 8 is 1, - otherwise the player can't be turned off. */ - rtc_write(8, rtc_read(8) | 0x80); - -#endif -} - -#ifdef HAVE_RTC_ALARM - -/* check whether the unit has been started by the RTC alarm function */ -/* (check for AF, which => started using wakeup alarm) */ -bool rtc_check_alarm_started(bool release_alarm) -{ - static bool alarm_state, run_before; - bool rc; - - if (run_before) { - rc = alarm_state; - alarm_state &= ~release_alarm; - } else { - /* This call resets AF, so we store the state for later recall */ - rc = alarm_state = rtc_check_alarm_flag(); - run_before = true; - } - - return rc; -} -/* - * Checks the AL register. This call resets AL once read. - * - * We're only interested if ABE is set. AL is still raised regardless - * even if the unit is off when the alarm occurs. - */ -bool rtc_check_alarm_flag(void) -{ - return ( ( (rtc_read(0x0f) & 0x40) != 0) && - (rtc_read(0x0a) & 0x20) ); -} - -/* set alarm time registers to the given time (repeat once per day) */ -void rtc_set_alarm(int h, int m) -{ - unsigned char data; - - /* for daily alarm, RPT5=RPT4=on, RPT1=RPT2=RPT3=off */ - - rtc_write(0x0e, 0x00); /* seconds 0 and RTP1 */ - rtc_write(0x0d, DEC2BCD(m)); /* minutes and RPT2 */ - rtc_write(0x0c, DEC2BCD(h)); /* hour and RPT3 */ - rtc_write(0x0b, 0xc1); /* set date 01 and RPT4 and RTP5 */ - - /* set month to 1, if it's invalid, the rtc does an alarm every second instead */ - data = rtc_read(0x0a); - data &= 0xe0; - data |= 0x01; - rtc_write(0x0a, data); -} - -/* read out the current alarm time */ -void rtc_get_alarm(int *h, int *m) -{ - unsigned char data; - - data = rtc_read(0x0c); - *h = BCD2DEC(data & 0x3f); - - data = rtc_read(0x0d); - *m = BCD2DEC(data & 0x7f); -} - -/* turn alarm on or off by setting the alarm flag enable */ -/* the alarm is automatically disabled when the RTC gets Vcc power at startup */ -/* avoid that an alarm occurs when the device is on because this locks the ON key forever */ -void rtc_enable_alarm(bool enable) -{ - unsigned char data = rtc_read(0x0a); - if (enable) - { - data |= 0xa0; /* turn bit d7=AFE and d5=ABE on */ - } - else - data &= 0x5f; /* turn bit d7=AFE and d5=ABE off */ - rtc_write(0x0a, data); - - /* check if alarm flag AF is off (as it should be) */ - /* in some cases enabling the alarm results in an activated AF flag */ - /* this should not happen, but it does */ - /* if you know why, tell me! */ - /* for now, we try again forever in this case */ - while (rtc_check_alarm_flag()) /* on */ - { - data &= 0x5f; /* turn bit d7=AFE and d5=ABE off */ - rtc_write(0x0a, data); - sleep(HZ / 10); - rtc_check_alarm_flag(); - data |= 0xa0; /* turn bit d7=AFE and d5=ABE on */ - rtc_write(0x0a, data); - } -} - -#endif /* HAVE_RTC_ALARM */ - -int rtc_write(unsigned char address, unsigned char value) -{ - int ret = 0; - unsigned char buf[2]; - - i2c_begin(); - - buf[0] = address; - buf[1] = value; - - /* send run command */ - if (i2c_write(RTC_DEV_WRITE,buf,2)) - { - ret = -1; - } - - i2c_end(); - return ret; -} - -int rtc_read(unsigned char address) -{ - int value = -1; - unsigned char buf[1]; - - i2c_begin(); - - buf[0] = address; - - /* send read command */ - if (i2c_write(RTC_DEV_READ,buf,1) >= 0) - { - i2c_start(); - i2c_outb(RTC_DEV_READ); - if (i2c_getack()) - { - value = i2c_inb(1); - } - } - - i2c_stop(); - - i2c_end(); - return value; -} - -int rtc_read_multiple(unsigned char address, unsigned char *buf, int numbytes) -{ - int ret = 0; - unsigned char obuf[1]; - int i; - - i2c_begin(); - - obuf[0] = address; - - /* send read command */ - if (i2c_write(RTC_DEV_READ, obuf, 1) >= 0) - { - i2c_start(); - i2c_outb(RTC_DEV_READ); - if (i2c_getack()) - { - for(i = 0;i < numbytes-1;i++) - buf[i] = i2c_inb(0); - - buf[i] = i2c_inb(1); - } - else - { - ret = -1; - } - } - - i2c_stop(); - - i2c_end(); - return ret; -} - -int rtc_read_datetime(struct tm *tm) -{ - int rc; - unsigned char buf[7]; - - rc = rtc_read_multiple(1, buf, sizeof(buf)); - - /* convert from bcd, avoid getting extra bits */ - tm->tm_sec = BCD2DEC(buf[0] & 0x7f); - tm->tm_min = BCD2DEC(buf[1] & 0x7f); - tm->tm_hour = BCD2DEC(buf[2] & 0x3f); - tm->tm_mday = BCD2DEC(buf[4] & 0x3f); - tm->tm_mon = BCD2DEC(buf[5] & 0x1f) - 1; - tm->tm_year = BCD2DEC(buf[6]) + 100; - tm->tm_yday = 0; /* Not implemented for now */ - - set_day_of_week(tm); - - return rc; -} - -int rtc_write_datetime(const struct tm *tm) -{ - unsigned int i; - int rc = 0; - unsigned char buf[7]; - - buf[0] = tm->tm_sec; - buf[1] = tm->tm_min; - buf[2] = tm->tm_hour; - buf[3] = tm->tm_wday; - buf[4] = tm->tm_mday; - buf[5] = tm->tm_mon + 1; - buf[6] = tm->tm_year - 100; - - /* Adjust weekday */ - if (buf[3] == 0) - buf[3] = 7; - - for (i = 0; i < sizeof(buf) ;i++) - { - rc |= rtc_write(i + 1, DEC2BCD(buf[i])); - } - rc |= rtc_write(8, 0x80); /* Out=1, calibration = 0 */ - - return rc; -} - diff --git a/firmware/drivers/tuner/s1a0903x01.c b/firmware/drivers/tuner/s1a0903x01.c deleted file mode 100644 index 91d1319fb5..0000000000 --- a/firmware/drivers/tuner/s1a0903x01.c +++ /dev/null @@ -1,179 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * Tuner "middleware" for Samsung S1A0903X01 chip - * - * Copyright (C) 2003 Linus Nielsen Feltzing - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include <stdbool.h> -#include <stdlib.h> -#include "config.h" -#include "kernel.h" -#include "tuner.h" /* tuner abstraction interface */ -#include "fmradio.h" /* physical interface driver */ -#include "sound.h" -#include "mas35xx.h" -#include "power.h" - -#define DEFAULT_IN1 0x100003 /* Mute */ -#define DEFAULT_IN2 0x140884 /* 5kHz, 7.2MHz crystal */ -#define PLL_FREQ_STEP 10000 - -static int fm_in1; -static int fm_in2; -static int fm_present = -1; /* unknown */ - -/* tuner abstraction layer: set something to the tuner */ -int s1a0903x01_set(int setting, int value) -{ - int val = 1; - - switch(setting) - { - case RADIO_SLEEP: - if (!value) - { - tuner_power(true); - /* wakeup: just unit */ - fm_in1 = DEFAULT_IN1; - fm_in2 = DEFAULT_IN2; - fmradio_set(1, fm_in1); - fmradio_set(2, fm_in2); - } - else - tuner_power(false); - /* else we have no sleep mode? */ - break; - - case RADIO_FREQUENCY: - { - int pll_cnt; -#if CONFIG_CODEC == MAS3587F - /* Shift the MAS internal clock away for certain frequencies to - * avoid interference. */ - int pitch = 1000; - - /* 4th harmonic falls in the FM frequency range */ - int if_freq = 4 * mas_get_pllfreq(); - - /* shift the mas harmonic >= 300 kHz away using the direction - * which needs less shifting. */ - if (value < if_freq) - { - if (if_freq - value < 300000) - pitch = 1003 - (if_freq - value) / 100000; - } - else - { - if (value - if_freq < 300000) - pitch = 997 + (value - if_freq) / 100000; - } - sound_set_pitch(pitch); -#endif - /* We add the standard Intermediate Frequency 10.7MHz - ** before calculating the divisor - ** The reference frequency is set to 50kHz, and the VCO - ** output is prescaled by 2. - */ - - pll_cnt = (value + 10700000) / (PLL_FREQ_STEP/2) / 2; - - /* 0x100000 == FM mode - ** 0x000002 == Microprocessor controlled Mute - */ - fm_in1 = (fm_in1 & 0xfff00007) | (pll_cnt << 3); - fmradio_set(1, fm_in1); - break; - } - - case RADIO_SCAN_FREQUENCY: - /* Tune in and delay */ - s1a0903x01_set(RADIO_FREQUENCY, value); - sleep(1); - /* Start IF measurement */ - fm_in1 |= 4; - fmradio_set(1, fm_in1); - sleep(1); - val = s1a0903x01_get(RADIO_TUNED); - break; - - case RADIO_MUTE: - fm_in1 = (fm_in1 & 0xfffffffe) | (value?1:0); - fmradio_set(1, fm_in1); - break; - - case RADIO_FORCE_MONO: - fm_in2 = (fm_in2 & 0xfffffffb) | (value?0:4); - fmradio_set(2, fm_in2); - break; - /* NOTE: These were only zeroed when starting the tuner from OFF - but the default values already set them to 0. */ -#if 0 - case S1A0903X01_IF_MEASUREMENT: - fm_in1 = (fm_in1 & 0xfffffffb) | (value?4:0); - fmradio_set(1, fm_in1); - break; - - case S1A0903X01_SENSITIVITY: - fm_in2 = (fm_in2 & 0xffff9fff) | ((value & 3) << 13); - fmradio_set(2, fm_in2); - break; -#endif - default: - val = -1; - } - - return val; -} - -/* tuner abstraction layer: read something from the tuner */ -int s1a0903x01_get(int setting) -{ - int val = -1; - switch(setting) - { - case RADIO_PRESENT: - if (fm_present == -1) - { -#ifdef HAVE_TUNER_PWR_CTRL - bool fmstatus = tuner_power(true); -#endif - /* 5kHz, 7.2MHz crystal, test mode 1 */ - fmradio_set(2, 0x140885); - fm_present = (fmradio_read(0) == 0x140885); -#ifdef HAVE_TUNER_PWR_CTRL - if (!fmstatus) - tuner_power(false); -#endif - } - - val = fm_present; - break; - - case RADIO_TUNED: - val = fmradio_read(3); - val = abs(10700 - ((val & 0x7ffff) / 8)) < 50; /* convert to kHz */ - break; - - case RADIO_STEREO: - val = fmradio_read(3); - val = ((val & 0x100000) ? true : false); - break; - } - return val; -} |