diff options
Diffstat (limited to 'firmware/drivers/tuner')
-rw-r--r-- | firmware/drivers/tuner/tea5760uk.c | 111 |
1 files changed, 73 insertions, 38 deletions
diff --git a/firmware/drivers/tuner/tea5760uk.c b/firmware/drivers/tuner/tea5760uk.c index 781e51967c..db07e20cf4 100644 --- a/firmware/drivers/tuner/tea5760uk.c +++ b/firmware/drivers/tuner/tea5760uk.c | |||
@@ -28,10 +28,20 @@ | |||
28 | #include "fmradio.h" | 28 | #include "fmradio.h" |
29 | #include "fmradio_i2c.h" /* physical interface driver */ | 29 | #include "fmradio_i2c.h" /* physical interface driver */ |
30 | 30 | ||
31 | #define I2C_ADR 0xC0 | 31 | #define I2C_ADR 0x22 |
32 | static unsigned char write_bytes[7] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | 32 | |
33 | 33 | static bool tuner_present = false; | |
34 | static void tea5760uk_set_clear(int byte, unsigned char bits, int set) | 34 | static unsigned char write_bytes[7] = { |
35 | 0x00, /* INTREG LSB */ | ||
36 | 0x80, /* FRQSET MSB */ | ||
37 | 0x00, /* FRQSET LSB */ | ||
38 | 0x08, /* TNCTRL MSB */ | ||
39 | 0xD2, /* TNCTRL LSB */ | ||
40 | 0x00, /* TESTREG MSB */ | ||
41 | 0x40 /* TESTREG LSB */ | ||
42 | }; | ||
43 | |||
44 | static void tea5760_set_clear(int byte, unsigned char bits, int set) | ||
35 | { | 45 | { |
36 | write_bytes[byte] &= ~bits; | 46 | write_bytes[byte] &= ~bits; |
37 | if (set) | 47 | if (set) |
@@ -39,58 +49,60 @@ static void tea5760uk_set_clear(int byte, unsigned char bits, int set) | |||
39 | } | 49 | } |
40 | 50 | ||
41 | /* tuner abstraction layer: set something to the tuner */ | 51 | /* tuner abstraction layer: set something to the tuner */ |
42 | int tea5760uk_set(int setting, int value) | 52 | int tea5760_set(int setting, int value) |
43 | { | 53 | { |
44 | switch(setting) | 54 | switch(setting) |
45 | { | 55 | { |
46 | case RADIO_SLEEP: | 56 | case RADIO_SLEEP: |
47 | /* init values */ | 57 | if (value) { |
48 | write_bytes[0] |= (1<<7); /* mute */ | 58 | /* sleep / standby mode */ |
49 | #if CONFIG_TUNER_XTAL == 32768 | 59 | tea5760_set_clear(3, (1<<6), 0); |
50 | /* 32.768kHz, soft mute, stereo noise cancelling */ | 60 | } |
51 | write_bytes[3] |= (1<<4) | (1<<3) | (1<<1); | 61 | else { |
52 | #else | 62 | /* active mode */ |
53 | /* soft mute, stereo noise cancelling */ | 63 | tea5760_set_clear(3, (1<<6), 1); |
54 | write_bytes[3] |= (1<<3) | (1<<1); | 64 | /* disable hard mute */ |
55 | #endif | 65 | tea5760_set_clear(4, (1<<7), 0); |
56 | /* sleep / standby mode */ | 66 | } |
57 | tea5760uk_set_clear(3, (1<<6), value); | ||
58 | break; | 67 | break; |
59 | 68 | ||
60 | case RADIO_FREQUENCY: | 69 | case RADIO_FREQUENCY: |
61 | { | 70 | { |
62 | int n; | 71 | int n; |
63 | #if CONFIG_TUNER_XTAL == 32768 | 72 | |
73 | /* low side injection */ | ||
74 | tea5760_set_clear(4, (1<<4), 0); | ||
64 | n = (4 * (value - 225000) + 16384) / 32768; | 75 | n = (4 * (value - 225000) + 16384) / 32768; |
65 | #else | 76 | |
66 | n = (4 * (value - 225000)) / 50000; | 77 | /* set frequency in preset mode */ |
67 | #endif | 78 | write_bytes[1] = (n >> 8) & 0x3F; |
68 | write_bytes[6] = (write_bytes[6] & 0xC0) | (n >> 8); | 79 | write_bytes[2] = n; |
69 | write_bytes[7] = n; | ||
70 | } | 80 | } |
71 | break; | 81 | break; |
72 | 82 | ||
73 | case RADIO_SCAN_FREQUENCY: | 83 | case RADIO_SCAN_FREQUENCY: |
74 | tea5760uk_set(RADIO_FREQUENCY, value); | 84 | tea5760_set(RADIO_FREQUENCY, value); |
75 | sleep(HZ/30); | 85 | sleep(40*HZ/1000); |
76 | return tea5760uk_get(RADIO_TUNED); | 86 | return tea5760_get(RADIO_TUNED); |
77 | 87 | ||
78 | case RADIO_MUTE: | 88 | case RADIO_MUTE: |
79 | tea5760uk_set_clear(3, (1<<2), value); | 89 | tea5760_set_clear(3, (1<<2), value); |
80 | break; | 90 | break; |
81 | 91 | ||
82 | case RADIO_REGION: | 92 | case RADIO_REGION: |
83 | { | 93 | { |
84 | const struct tea5760uk_region_data *rd = | 94 | const struct tea5760_region_data *rd = |
85 | &tea5760uk_region_data[value]; | 95 | &tea5760_region_data[value]; |
86 | 96 | ||
87 | tea5760uk_set_clear(4, (1<<1), rd->deemphasis); | 97 | tea5760_set_clear(4, (1<<1), rd->deemphasis); |
88 | tea5760uk_set_clear(3, (1<<5), rd->band); | 98 | tea5760_set_clear(3, (1<<5), rd->band); |
89 | break; | ||
90 | } | 99 | } |
100 | break; | ||
101 | |||
91 | case RADIO_FORCE_MONO: | 102 | case RADIO_FORCE_MONO: |
92 | tea5760uk_set_clear(4, (1<<3), value); | 103 | tea5760_set_clear(4, (1<<3), value); |
93 | break; | 104 | break; |
105 | |||
94 | default: | 106 | default: |
95 | return -1; | 107 | return -1; |
96 | } | 108 | } |
@@ -100,7 +112,7 @@ int tea5760uk_set(int setting, int value) | |||
100 | } | 112 | } |
101 | 113 | ||
102 | /* tuner abstraction layer: read something from the tuner */ | 114 | /* tuner abstraction layer: read something from the tuner */ |
103 | int tea5760uk_get(int setting) | 115 | int tea5760_get(int setting) |
104 | { | 116 | { |
105 | unsigned char read_bytes[16]; | 117 | unsigned char read_bytes[16]; |
106 | int val = -1; /* default for unsupported query */ | 118 | int val = -1; /* default for unsupported query */ |
@@ -110,7 +122,7 @@ int tea5760uk_get(int setting) | |||
110 | switch(setting) | 122 | switch(setting) |
111 | { | 123 | { |
112 | case RADIO_PRESENT: | 124 | case RADIO_PRESENT: |
113 | val = 1; /* true */ | 125 | val = tuner_present ? 1 : 0; |
114 | break; | 126 | break; |
115 | 127 | ||
116 | case RADIO_TUNED: | 128 | case RADIO_TUNED: |
@@ -130,8 +142,31 @@ int tea5760uk_get(int setting) | |||
130 | return val; | 142 | return val; |
131 | } | 143 | } |
132 | 144 | ||
133 | void tea5760uk_dbg_info(struct tea5760uk_dbg_info *info) | 145 | void tea5760_init(void) |
134 | { | 146 | { |
135 | fmradio_i2c_read(I2C_ADR, info->read_regs, 5); | 147 | unsigned char buf[16]; |
136 | memcpy(info->write_regs, write_bytes, 5); | 148 | unsigned short manid, chipid; |
149 | |||
150 | /* read all registers */ | ||
151 | fmradio_i2c_read(I2C_ADR, buf, sizeof(buf)); | ||
152 | |||
153 | /* check device id */ | ||
154 | manid = (buf[12] << 8) | buf[13]; | ||
155 | chipid = (buf[14] << 8) | buf[15]; | ||
156 | if ((manid == 0x202B) && (chipid == 0x5760)) | ||
157 | { | ||
158 | tuner_present = true; | ||
159 | } | ||
160 | |||
161 | /* write initial values */ | ||
162 | tea5760_set_clear(3, (1<<1), 1); /* soft mute on */ | ||
163 | tea5760_set_clear(3, (1<<0), 1); /* stereo noise cancellation on */ | ||
164 | fmradio_i2c_write(I2C_ADR, write_bytes, sizeof(write_bytes)); | ||
137 | } | 165 | } |
166 | |||
167 | void tea5760_dbg_info(struct tea5760_dbg_info *info) | ||
168 | { | ||
169 | fmradio_i2c_read(I2C_ADR, info->read_regs, sizeof(info->read_regs)); | ||
170 | memcpy(info->write_regs, write_bytes, sizeof(info->write_regs)); | ||
171 | } | ||
172 | |||