diff options
Diffstat (limited to 'firmware/drivers/tuner')
-rw-r--r-- | firmware/drivers/tuner/ipod_remote_tuner.c | 76 |
1 files changed, 59 insertions, 17 deletions
diff --git a/firmware/drivers/tuner/ipod_remote_tuner.c b/firmware/drivers/tuner/ipod_remote_tuner.c index 9595939f1d..5539b09721 100644 --- a/firmware/drivers/tuner/ipod_remote_tuner.c +++ b/firmware/drivers/tuner/ipod_remote_tuner.c | |||
@@ -69,7 +69,7 @@ static void rmt_tuner_set_freq(int curr_freq) | |||
69 | rds_reset(); | 69 | rds_reset(); |
70 | /* ex: 00 01 63 14 = 90.9MHz */ | 70 | /* ex: 00 01 63 14 = 90.9MHz */ |
71 | unsigned char data[] = {0x07, 0x0B, 0x00, 0x01, 0x63, 0x14}; | 71 | unsigned char data[] = {0x07, 0x0B, 0x00, 0x01, 0x63, 0x14}; |
72 | 72 | ||
73 | if (curr_freq != 0) | 73 | if (curr_freq != 0) |
74 | { | 74 | { |
75 | unsigned int khz = curr_freq / 1000; | 75 | unsigned int khz = curr_freq / 1000; |
@@ -93,20 +93,23 @@ static void rmt_tuner_sleep(int state) | |||
93 | old_region = -1; | 93 | old_region = -1; |
94 | tuner_frequency = 0; | 94 | tuner_frequency = 0; |
95 | radio_tuned = false; | 95 | radio_tuned = false; |
96 | 96 | ||
97 | /* tuner HW on */ | 97 | /* tuner HW on */ |
98 | const unsigned char data[] = {0x07, 0x05, 0x01}; | 98 | const unsigned char data[] = {0x07, 0x05, 0x01}; |
99 | iap_send_pkt(data, sizeof(data)); | 99 | iap_send_pkt(data, sizeof(data)); |
100 | /* set rds on */ | ||
101 | const unsigned char data3[] = {0x07, 0x20, 0x40, 0x00, 0x00, 0x10 }; | ||
102 | iap_send_pkt(data3, sizeof(data3)); | ||
100 | /* boost gain */ | 103 | /* boost gain */ |
101 | const unsigned char data1[] = {0x07, 0x24, 0x06 }; | 104 | const unsigned char data1[] = {0x07, 0x24, 0x06 }; |
102 | iap_send_pkt(data1, sizeof(data1)); | 105 | iap_send_pkt(data1, sizeof(data1)); |
106 | /* tuner mode */ | ||
107 | const unsigned char data4[] = {0x07, 0x0E, 0x00 }; | ||
108 | iap_send_pkt(data4, sizeof(data3)); | ||
103 | /* set volume */ | 109 | /* set volume */ |
104 | unsigned char data2[] = {0x03, 0x09, 0x04, 0x00, 0x00 }; | 110 | unsigned char data2[] = {0x03, 0x09, 0x04, 0x00, 0x00 }; |
105 | data2[4] = (char)((global_settings.volume+58) * 4); | 111 | data2[4] = (char)((global_settings.volume+58) * 4); |
106 | iap_send_pkt(data2, sizeof(data2)); | 112 | iap_send_pkt(data2, sizeof(data2)); |
107 | /* set rds on */ | ||
108 | const unsigned char data3[] = {0x07, 0x20, 0x40, 0x00, 0x00, 0x10 }; | ||
109 | iap_send_pkt(data3, sizeof(data3)); | ||
110 | } | 113 | } |
111 | else | 114 | else |
112 | { | 115 | { |
@@ -115,14 +118,14 @@ static void rmt_tuner_sleep(int state) | |||
115 | iap_send_pkt(data, sizeof(data)); | 118 | iap_send_pkt(data, sizeof(data)); |
116 | /* set rds off */ | 119 | /* set rds off */ |
117 | const unsigned char data1[] = {0x07, 0x20, 0x00, 0x00, 0x00, 0x00 }; | 120 | const unsigned char data1[] = {0x07, 0x20, 0x00, 0x00, 0x00, 0x00 }; |
118 | iap_send_pkt(data1, sizeof(data1)); | 121 | iap_send_pkt(data1, sizeof(data1)); |
119 | /* stop tuner HW */ | 122 | /* stop tuner HW */ |
120 | const unsigned char data2[] = {0x07, 0x05, 0x00}; | 123 | const unsigned char data2[] = {0x07, 0x05, 0x00}; |
121 | iap_send_pkt(data2, sizeof(data2)); | 124 | iap_send_pkt(data2, sizeof(data2)); |
122 | } | 125 | } |
123 | } | 126 | } |
124 | 127 | ||
125 | static void rmt_tuner_scan(int param) | 128 | void rmt_tuner_scan(int param) |
126 | { | 129 | { |
127 | const unsigned char data[] = {0x07, 0x11, 0x08}; /* RSSI level */ | 130 | const unsigned char data[] = {0x07, 0x11, 0x08}; /* RSSI level */ |
128 | unsigned char updown = 0x00; | 131 | unsigned char updown = 0x00; |
@@ -148,13 +151,23 @@ static void rmt_tuner_scan(int param) | |||
148 | static void rmt_tuner_mute(int value) | 151 | static void rmt_tuner_mute(int value) |
149 | { | 152 | { |
150 | /* mute flag off (play) */ | 153 | /* mute flag off (play) */ |
151 | unsigned char data[] = {0x03, 0x09, 0x03, 0x01}; | 154 | /* The Apple Tuner does NOT appear to support muting. The Apple |
155 | * firmware turns the power off when pressing pause on the iPod | ||
156 | * or on the Tuner Remote. | ||
157 | */ | ||
152 | if (value) | 158 | if (value) |
153 | { | 159 | { |
154 | /* mute flag on (pause) */ | 160 | /* mute flag on (pause) */ |
155 | data[3] = 0x02; | 161 | unsigned char data[] = {0x03, 0x09, 0x03, 0x02}; |
162 | iap_send_pkt(data, sizeof(data)); | ||
163 | rmt_tuner_sleep(1); | ||
164 | } | ||
165 | else | ||
166 | { | ||
167 | unsigned char data[] = {0x03, 0x09, 0x03, 0x01}; | ||
168 | iap_send_pkt(data, sizeof(data)); | ||
169 | rmt_tuner_sleep(0); | ||
156 | } | 170 | } |
157 | iap_send_pkt(data, sizeof(data)); | ||
158 | } | 171 | } |
159 | 172 | ||
160 | static void rmt_tuner_region(int region) | 173 | static void rmt_tuner_region(int region) |
@@ -163,13 +176,20 @@ static void rmt_tuner_region(int region) | |||
163 | { | 176 | { |
164 | const struct fm_region_data *rd = &fm_region_data[region]; | 177 | const struct fm_region_data *rd = &fm_region_data[region]; |
165 | unsigned char data[] = {0x07, 0x08, 0x00}; | 178 | unsigned char data[] = {0x07, 0x08, 0x00}; |
179 | /* Apple MFi Accessory Firmware Spec R46 now lists | ||
180 | * the following bands | ||
181 | * ID00 AM 520-1710Khz Not Supported | ||
182 | * ID02 Japan 76-90Mkz 100Khz 50/75uS | ||
183 | * ID01 87.5-108Mhz US 200Khz 75uS, EU 100Kz 50uS | ||
184 | * ID03 76-108Mhz Wideband. Not Supported | ||
185 | */ | ||
166 | if (rd->freq_min == 76000000) | 186 | if (rd->freq_min == 76000000) |
167 | { | 187 | { |
168 | data[2] = 0x02; /* japan band */ | 188 | data[2] = 0x02; /* japan band */ |
169 | } | 189 | } |
170 | else | 190 | else |
171 | { | 191 | { |
172 | data[2] = 0x01; /* us eur band */ | 192 | data[2] = 0x01; /* us/europe band */ |
173 | } | 193 | } |
174 | iap_send_pkt(data, sizeof(data)); | 194 | iap_send_pkt(data, sizeof(data)); |
175 | sleep(HZ/100); | 195 | sleep(HZ/100); |
@@ -225,11 +245,13 @@ static void set_deemphasis(int deemphasis) | |||
225 | case 1: | 245 | case 1: |
226 | { | 246 | { |
227 | tuner_param |= 0x40; | 247 | tuner_param |= 0x40; |
248 | /* 50uS */ | ||
228 | break; | 249 | break; |
229 | } | 250 | } |
230 | default: | 251 | default: |
231 | { | 252 | { |
232 | tuner_param |= 0x00; | 253 | tuner_param |= 0x00; |
254 | /* 75uS */ | ||
233 | break; | 255 | break; |
234 | } | 256 | } |
235 | } | 257 | } |
@@ -253,16 +275,15 @@ static void set_mono(int value) | |||
253 | static bool reply_timeout(void) | 275 | static bool reply_timeout(void) |
254 | { | 276 | { |
255 | int timeout = 0; | 277 | int timeout = 0; |
256 | 278 | ||
257 | sleep(HZ/50); | 279 | sleep(HZ/50); |
258 | do | 280 | do |
259 | { | 281 | { |
260 | iap_handlepkt(); | ||
261 | sleep(HZ/50); | 282 | sleep(HZ/50); |
262 | timeout++; | 283 | timeout++; |
263 | } | 284 | } |
264 | while((ipod_rmt_tuner_get(RADIO_TUNED) == 0) && (timeout < TIMEOUT_VALUE)); | 285 | while((ipod_rmt_tuner_get(RADIO_TUNED) == 0) && (timeout < TIMEOUT_VALUE)); |
265 | 286 | ||
266 | return (timeout >= TIMEOUT_VALUE); | 287 | return (timeout >= TIMEOUT_VALUE); |
267 | } | 288 | } |
268 | 289 | ||
@@ -277,7 +298,7 @@ void rmt_tuner_rds_data(unsigned int len, const unsigned char *buf) | |||
277 | rds_push_info(RDS_INFO_RT, (uintptr_t)(buf+4), len-4); | 298 | rds_push_info(RDS_INFO_RT, (uintptr_t)(buf+4), len-4); |
278 | } | 299 | } |
279 | } | 300 | } |
280 | 301 | ||
281 | /* tuner abstraction layer: set something to the tuner */ | 302 | /* tuner abstraction layer: set something to the tuner */ |
282 | int ipod_rmt_tuner_set(int setting, int value) | 303 | int ipod_rmt_tuner_set(int setting, int value) |
283 | { | 304 | { |
@@ -327,7 +348,7 @@ int ipod_rmt_tuner_set(int setting, int value) | |||
327 | /* scan up */ | 348 | /* scan up */ |
328 | else | 349 | else |
329 | rmt_tuner_scan(1); | 350 | rmt_tuner_scan(1); |
330 | 351 | ||
331 | sleep(HZ/10); | 352 | sleep(HZ/10); |
332 | if (reply_timeout()) | 353 | if (reply_timeout()) |
333 | { | 354 | { |
@@ -337,7 +358,7 @@ int ipod_rmt_tuner_set(int setting, int value) | |||
337 | return 0; | 358 | return 0; |
338 | } | 359 | } |
339 | radio_tuned = false; | 360 | radio_tuned = false; |
340 | } | 361 | } |
341 | 362 | ||
342 | if (tuner_frequency == value) | 363 | if (tuner_frequency == value) |
343 | { | 364 | { |
@@ -360,6 +381,27 @@ int ipod_rmt_tuner_set(int setting, int value) | |||
360 | 381 | ||
361 | case RADIO_REGION: | 382 | case RADIO_REGION: |
362 | { | 383 | { |
384 | /* The latest MFi Accessory Firmware Document I have lists the | ||
385 | * following regions | ||
386 | * US 87.5-108Mhz 200Khz 75uS | ||
387 | * US/EU 87.5-108Mhz 100Khz 75/50uS | ||
388 | * JP 76.0-90Mhz 100Mhz 50/75uS | ||
389 | * | ||
390 | * with the following bands | ||
391 | * 0x00 AM WordlWide 520-1710Khz | ||
392 | * 0x01 FM EU 87.5-108.0Mhz | ||
393 | * 0x02 FM JP 76.0-90.0Mhz | ||
394 | * 0x03 FM Wide 76.0-108.0Mhz | ||
395 | * | ||
396 | * | ||
397 | * A 7G Classic with the latest Apple Firmware returns the following | ||
398 | * regions with the settings listed | ||
399 | * Americas 87.5-108 200Khz 75uS | ||
400 | * Asia 87.5-108 100Khz 75uS | ||
401 | * Australia 87.5-108 200Khz 75uS | ||
402 | * Europe 87.5-108 100Khz 75uS | ||
403 | * Japan 76.0-90. 100Kz 75uS | ||
404 | */ | ||
363 | const struct fm_region_data *rd = &fm_region_data[value]; | 405 | const struct fm_region_data *rd = &fm_region_data[value]; |
364 | int band = (rd->freq_min == 76000000) ? 2 : 0; | 406 | int band = (rd->freq_min == 76000000) ? 2 : 0; |
365 | int spacing = (100000 / rd->freq_step); | 407 | int spacing = (100000 / rd->freq_step); |