summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/tuner/lv24020lp.c152
1 files changed, 109 insertions, 43 deletions
diff --git a/firmware/drivers/tuner/lv24020lp.c b/firmware/drivers/tuner/lv24020lp.c
index 9ec68f9a27..79d38443f2 100644
--- a/firmware/drivers/tuner/lv24020lp.c
+++ b/firmware/drivers/tuner/lv24020lp.c
@@ -24,6 +24,7 @@
24#include "thread.h" 24#include "thread.h"
25#include "kernel.h" 25#include "kernel.h"
26#include "tuner.h" /* tuner abstraction interface */ 26#include "tuner.h" /* tuner abstraction interface */
27#include "power.h"
27#include "fmradio.h" /* physical interface driver */ 28#include "fmradio.h" /* physical interface driver */
28#include "sound.h" 29#include "sound.h"
29#include "pp5024.h" 30#include "pp5024.h"
@@ -31,6 +32,8 @@
31 32
32#ifndef BOOTLOADER 33#ifndef BOOTLOADER
33 34
35static struct mutex tuner_mtx;
36
34#if 0 37#if 0
35/* define to enable tuner logging */ 38/* define to enable tuner logging */
36#define SANYO_TUNER_LOG 39#define SANYO_TUNER_LOG
@@ -338,6 +341,10 @@ static void lv24020lp_write(unsigned int address, unsigned int data)
338 break; 341 break;
339 } 342 }
340 343
344 /* Check if interface is turned on */
345 if (!(tuner_status & TUNER_POWERED))
346 return;
347
341 address = lv24020lp_begin_write(address); 348 address = lv24020lp_begin_write(address);
342 349
343 /* data first */ 350 /* data first */
@@ -365,6 +372,10 @@ static unsigned int lv24020lp_read(unsigned int address)
365 int i; 372 int i;
366 unsigned int toread; 373 unsigned int toread;
367 374
375 /* Check if interface is turned on */
376 if (!(tuner_status & TUNER_POWERED))
377 return 0;
378
368 address = lv24020lp_begin_write(address); 379 address = lv24020lp_begin_write(address);
369 380
370 /* address */ 381 /* address */
@@ -433,9 +444,6 @@ static int tuner_measure(unsigned char type, int scale, int duration)
433{ 444{
434 int64_t finval; 445 int64_t finval;
435 446
436 if (!tuner_awake())
437 return 0;
438
439 /* enable measuring */ 447 /* enable measuring */
440 lv24020lp_write_or(MSRC_SEL, type); 448 lv24020lp_write_or(MSRC_SEL, type);
441 lv24020lp_write_and(CNT_CTRL, ~CNT_SEL); 449 lv24020lp_write_and(CNT_CTRL, ~CNT_SEL);
@@ -463,19 +471,20 @@ static int tuner_measure(unsigned char type, int scale, int duration)
463 else 471 else
464 finval = scale*finval / duration; 472 finval = scale*finval / duration;
465 473
474 /* This function takes a loooong time and other stuff needs
475 running by now */
476 yield();
477
466 return (int)finval; 478 return (int)finval;
467} 479}
468 480
469/* set the FM oscillator frequency */ 481/* set the FM oscillator frequency */
470static void set_frequency(int freq) 482static bool set_frequency(int freq)
471{ 483{
472 int coef, cap_value, osc_value; 484 int coef, cap_value, osc_value;
473 int f1, f2, x1, x2; 485 int f1, f2, x1, x2;
474 int count; 486 int count;
475 487
476 if (!tuner_awake())
477 return;
478
479 TUNER_LOG_OPEN(); 488 TUNER_LOG_OPEN();
480 489
481 TUNER_LOG("set_frequency(%d)\n", freq); 490 TUNER_LOG("set_frequency(%d)\n", freq);
@@ -579,6 +588,8 @@ static void set_frequency(int freq)
579 TUNER_LOG("\n"); 588 TUNER_LOG("\n");
580 589
581 TUNER_LOG_SYNC(); 590 TUNER_LOG_SYNC();
591
592 return true;
582} 593}
583 594
584static void fine_step_tune(int (*setcmp)(int regval), int regval, int step) 595static void fine_step_tune(int (*setcmp)(int regval), int regval, int step)
@@ -639,10 +650,10 @@ static int if_setcmp(int regval)
639 /* This register is bounces around by a few hundred Hz and doesn't seem 650 /* This register is bounces around by a few hundred Hz and doesn't seem
640 to be precisely tuneable. Just do 110000 +/- 500 since it's not very 651 to be precisely tuneable. Just do 110000 +/- 500 since it's not very
641 critical it seems. */ 652 critical it seems. */
642 if (abs(if_set - 109500) <= 500) 653 if (abs(if_set - 110000) <= 500)
643 return 0; 654 return 0;
644 655
645 return if_set < 109500 ? -1 : 1; 656 return if_set < 110000 ? -1 : 1;
646} 657}
647 658
648static int sd_setcmp(int regval) 659static int sd_setcmp(int regval)
@@ -666,8 +677,6 @@ static void set_sleep(bool sleep)
666 (TUNER_PRESENT | TUNER_POWERED)) 677 (TUNER_PRESENT | TUNER_POWERED))
667 return; 678 return;
668 679
669 tuner_status |= TUNER_AWAKE;
670
671 enable_afc(false); 680 enable_afc(false);
672 681
673 /* 2. Calibrate the IF frequency at 110 kHz: */ 682 /* 2. Calibrate the IF frequency at 110 kHz: */
@@ -702,9 +711,79 @@ static void set_sleep(bool sleep)
702 lv24020lp_write(STEREO_CTRL, FMCS_SET(7) | AUTOSSR); 711 lv24020lp_write(STEREO_CTRL, FMCS_SET(7) | AUTOSSR);
703 lv24020lp_write(PW_SCTRL, SS_CTRL_SET(3) | SM_CTRL_SET(1) | 712 lv24020lp_write(PW_SCTRL, SS_CTRL_SET(3) | SM_CTRL_SET(1) |
704 PW_RAD); 713 PW_RAD);
714
715 tuner_status |= TUNER_AWAKE;
716}
717
718static int lp24020lp_tuned(void)
719{
720 return RSS_FS(lv24020lp_read(RADIO_STAT)) < 0x1f;
721}
722
723static int lv24020lp_debug_info(int setting)
724{
725 int val = -1;
726
727 if (setting >= LV24020LP_DEBUG_FIRST && setting <= LV24020LP_DEBUG_LAST)
728 {
729 val = 0;
730
731 if (tuner_awake())
732 {
733 switch (setting)
734 {
735 /* tuner-specific debug info */
736 case LV24020LP_CTRL_STAT:
737 val = lv24020lp_read(CTRL_STAT);
738 break;
739
740 case LV24020LP_REG_STAT:
741 val = lv24020lp_read(RADIO_STAT);
742 break;
743
744 case LV24020LP_MSS_FM:
745 val = tuner_measure(MSS_FM, 1, 16);
746 break;
747
748 case LV24020LP_MSS_IF:
749 val = tuner_measure(MSS_IF, 1000, 16);
750 break;
751
752 case LV24020LP_MSS_SD:
753 val = tuner_measure(MSS_SD, 1000, 16);
754 break;
755
756 case LV24020LP_IF_SET:
757 val = if_set;
758 break;
759
760 case LV24020LP_SD_SET:
761 val = sd_set;
762 break;
763 }
764 }
765 }
766
767 return val;
705} 768}
706 769
707/** Public interfaces **/ 770/** Public interfaces **/
771void lv24020lp_init(void)
772{
773 mutex_init(&tuner_mtx);
774}
775
776void lv24020lp_lock(void)
777{
778 mutex_lock(&tuner_mtx);
779}
780
781void lv24020lp_unlock(void)
782{
783 mutex_unlock(&tuner_mtx);
784}
785
786/* This function expects the driver to be locked externally */
708void lv24020lp_power(bool status) 787void lv24020lp_power(bool status)
709{ 788{
710 static const unsigned char tuner_defaults[][2] = 789 static const unsigned char tuner_defaults[][2] =
@@ -734,7 +813,7 @@ void lv24020lp_power(bool status)
734 813
735 if (status) 814 if (status)
736 { 815 {
737 tuner_status |= TUNER_POWERED | TUNER_PRESENCE_CHECKED; 816 tuner_status |= (TUNER_PRESENCE_CHECKED | TUNER_POWERED);
738 817
739 /* if tuner is present, CHIP ID is 0x09 */ 818 /* if tuner is present, CHIP ID is 0x09 */
740 if (lv24020lp_read(CHIP_ID) == 0x09) 819 if (lv24020lp_read(CHIP_ID) == 0x09)
@@ -750,16 +829,16 @@ void lv24020lp_power(bool status)
750 lv24020lp_write(tuner_defaults[i][0], tuner_defaults[i][1]); 829 lv24020lp_write(tuner_defaults[i][0], tuner_defaults[i][1]);
751 830
752 /* Complete the startup calibration if the tuner is woken */ 831 /* Complete the startup calibration if the tuner is woken */
753 udelay(100000); 832 sleep(HZ/10);
754 } 833 }
755 } 834 }
756 else 835 else
757 { 836 {
837 tuner_status &= ~(TUNER_POWERED | TUNER_AWAKE);
838
758 /* Power off */ 839 /* Power off */
759 if (tuner_status & TUNER_PRESENT) 840 if (tuner_status & TUNER_PRESENT)
760 lv24020lp_write_and(PW_SCTRL, ~PW_RAD); 841 lv24020lp_write_and(PW_SCTRL, ~PW_RAD);
761
762 tuner_status &= ~(TUNER_POWERED | TUNER_AWAKE);
763 } 842 }
764} 843}
765 844
@@ -767,6 +846,8 @@ int lv24020lp_set(int setting, int value)
767{ 846{
768 int val = 1; 847 int val = 1;
769 848
849 mutex_lock(&tuner_mtx);
850
770 switch(setting) 851 switch(setting)
771 { 852 {
772 case RADIO_SLEEP: 853 case RADIO_SLEEP:
@@ -780,7 +861,7 @@ int lv24020lp_set(int setting, int value)
780 case RADIO_SCAN_FREQUENCY: 861 case RADIO_SCAN_FREQUENCY:
781 /* TODO: really implement this */ 862 /* TODO: really implement this */
782 set_frequency(value); 863 set_frequency(value);
783 val = lv24020lp_get(RADIO_TUNED); 864 val = lp24020lp_tuned();
784 break; 865 break;
785 866
786 case RADIO_MUTE: 867 case RADIO_MUTE:
@@ -791,13 +872,11 @@ int lv24020lp_set(int setting, int value)
791 break; 872 break;
792 873
793 case RADIO_REGION: 874 case RADIO_REGION:
794 {
795 if (lv24020lp_region_data[value]) 875 if (lv24020lp_region_data[value])
796 lv24020lp_write_or(AUDIO_CTRL2, DEEMP); 876 lv24020lp_write_or(AUDIO_CTRL2, DEEMP);
797 else 877 else
798 lv24020lp_write_and(AUDIO_CTRL2, ~DEEMP); 878 lv24020lp_write_and(AUDIO_CTRL2, ~DEEMP);
799 break; 879 break;
800 }
801 880
802 case RADIO_FORCE_MONO: 881 case RADIO_FORCE_MONO:
803 if (value) 882 if (value)
@@ -807,9 +886,11 @@ int lv24020lp_set(int setting, int value)
807 break; 886 break;
808 887
809 default: 888 default:
810 val = -1; 889 value = -1;
811 } 890 }
812 891
892 mutex_unlock(&tuner_mtx);
893
813 return val; 894 return val;
814} 895}
815 896
@@ -817,11 +898,13 @@ int lv24020lp_get(int setting)
817{ 898{
818 int val = -1; 899 int val = -1;
819 900
901 mutex_lock(&tuner_mtx);
902
820 switch(setting) 903 switch(setting)
821 { 904 {
822 case RADIO_TUNED: 905 case RADIO_TUNED:
823 /* TODO: really implement this */ 906 /* TODO: really implement this */
824 val = RSS_FS(lv24020lp_read(RADIO_STAT)) < 0x1f; 907 val = lp24020lp_tuned();
825 break; 908 break;
826 909
827 case RADIO_STEREO: 910 case RADIO_STEREO:
@@ -833,38 +916,21 @@ int lv24020lp_get(int setting)
833 bool fmstatus = true; 916 bool fmstatus = true;
834 917
835 if (!(tuner_status & TUNER_PRESENCE_CHECKED)) 918 if (!(tuner_status & TUNER_PRESENCE_CHECKED))
836 fmstatus = tuner_power(true); 919 fmstatus = tuner_power_nolock(true);
837 920
838 val = (tuner_status & TUNER_PRESENT) != 0; 921 val = (tuner_status & TUNER_PRESENT) != 0;
839 922
840 if (!fmstatus) 923 if (!fmstatus)
841 tuner_power(false); 924 tuner_power_nolock(false);
842 break; 925 break;
843 } 926 }
844 927
845 /* tuner-specific debug info */ 928 default:
846 case LV24020LP_CTRL_STAT: 929 val = lv24020lp_debug_info(setting);
847 return lv24020lp_read(CTRL_STAT);
848
849 case LV24020LP_REG_STAT:
850 return lv24020lp_read(RADIO_STAT);
851
852 case LV24020LP_MSS_FM:
853 return tuner_measure(MSS_FM, 1, 16);
854
855 case LV24020LP_MSS_IF:
856 return tuner_measure(MSS_IF, 1000, 16);
857
858 case LV24020LP_MSS_SD:
859 return tuner_measure(MSS_SD, 1000, 16);
860
861 case LV24020LP_IF_SET:
862 return if_set;
863
864 case LV24020LP_SD_SET:
865 return sd_set;
866 } 930 }
867 931
932 mutex_unlock(&tuner_mtx);
933
868 return val; 934 return val;
869} 935}
870#endif /* BOOTLOADER */ 936#endif /* BOOTLOADER */