fuzev2: prevent button light flickering when accessing µSD
[kugel-rb.git] / firmware / drivers / tuner / tea5767.c
blob7c6d5b59ef9b1c8d4c3bfd1787d7385e35bc74a2
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 * Tuner "middleware" for Philips TEA5767 chip
11 * Copyright (C) 2004 Jörg Hohensohn
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
22 #include "config.h"
23 #include <stdbool.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include "kernel.h"
27 #include "tuner.h" /* tuner abstraction interface */
28 #include "fmradio.h"
29 #include "fmradio_i2c.h" /* physical interface driver */
31 #if defined(PHILIPS_HDD1630) || defined(ONDA_VX747) || defined(ONDA_VX777)
32 #define I2C_ADR 0x60
33 #else
34 #define I2C_ADR 0xC0
35 #endif
37 static unsigned char write_bytes[5] = { 0x00, 0x00, 0x00, 0x00, 0x00 };
39 static void tea5767_set_clear(int byte, unsigned char bits, int set)
41 write_bytes[byte] &= ~bits;
42 if (set)
43 write_bytes[byte] |= bits;
46 /* tuner abstraction layer: set something to the tuner */
47 int tea5767_set(int setting, int value)
49 switch(setting)
51 case RADIO_SLEEP:
52 /* init values */
53 write_bytes[0] |= (1<<7); /* mute */
54 #if CONFIG_TUNER_XTAL == 32768
55 /* 32.768kHz, soft mute, stereo noise cancelling */
56 write_bytes[3] |= (1<<4) | (1<<3) | (1<<1);
57 #else
58 /* soft mute, stereo noise cancelling */
59 write_bytes[3] |= (1<<3) | (1<<1);
60 #endif
61 /* sleep / standby mode */
62 tea5767_set_clear(3, (1<<6), value);
63 break;
65 case RADIO_FREQUENCY:
67 int n;
68 #if CONFIG_TUNER_XTAL == 32768
69 n = (4 * (value - 225000) + 16384) / 32768;
70 #else
71 n = (4 * (value - 225000)) / 50000;
72 #endif
73 write_bytes[0] = (write_bytes[0] & 0xC0) | (n >> 8);
74 write_bytes[1] = n;
76 break;
78 case RADIO_SCAN_FREQUENCY:
79 tea5767_set(RADIO_FREQUENCY, value);
80 sleep(HZ/30);
81 return tea5767_get(RADIO_TUNED);
83 case RADIO_MUTE:
84 tea5767_set_clear(0, 0x80, value);
85 break;
87 case RADIO_REGION:
89 const struct tea5767_region_data *rd =
90 &tea5767_region_data[value];
92 tea5767_set_clear(4, (1<<6), rd->deemphasis);
93 tea5767_set_clear(3, (1<<5), rd->band);
94 break;
96 case RADIO_FORCE_MONO:
97 tea5767_set_clear(2, 0x08, value);
98 break;
99 default:
100 return -1;
103 fmradio_i2c_write(I2C_ADR, write_bytes, sizeof(write_bytes));
104 return 1;
107 /* tuner abstraction layer: read something from the tuner */
108 int tea5767_get(int setting)
110 unsigned char read_bytes[5];
111 int val = -1; /* default for unsupported query */
113 fmradio_i2c_read(I2C_ADR, read_bytes, sizeof(read_bytes));
115 switch(setting)
117 case RADIO_PRESENT:
118 val = 1; /* true */
119 break;
121 case RADIO_TUNED:
122 val = 0;
123 if (read_bytes[0] & 0x80) /* ready */
125 val = read_bytes[2] & 0x7F; /* IF counter */
126 val = (abs(val - 0x36) < 2); /* close match */
128 break;
130 case RADIO_STEREO:
131 val = read_bytes[2] >> 7;
132 break;
135 return val;
138 void tea5767_dbg_info(struct tea5767_dbg_info *info)
140 fmradio_i2c_read(I2C_ADR, info->read_regs, 5);
141 memcpy(info->write_regs, write_bytes, 5);