1/* $OpenBSD: tea5757.c,v 1.4 2021/11/23 00:17:59 jsg Exp $ */ 2 3/* 4 * Copyright (c) 2001 Vladimir Popov <jumbo@narod.ru> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28/* Implementation of most common TEA5757 routines */ 29 30/* 31 * Philips TEA5757H Self Tuned Radio 32 * http://www.semiconductors.philips.com/pip/TEA5757H 33 * 34 * The TEA5757; TEA5759 is a 44-pin integrated AM/FM stereo radio circuit. 35 * The radio part is based on the TEA5712. 36 * 37 * The TEA5757 is used in FM-standards in which the local oscillator 38 * frequency is above the radio frequency (e.g. European and American 39 * standards). The TEA5759 is the version in which the oscillator frequency 40 * is below the radio frequency (e.g. Japanese standard). 41 * 42 * The TEA5757; TEA5759 radio has a bus which consists of three wires: 43 * BUS-CLOCK: software driven clock input 44 * DATA: data input/output 45 * WRITE-ENABLE: write/read input 46 * 47 * The TEA5757; TEA5759 has a 25-bit shift register. 48 * 49 * The chips are used in Radiotrack II, Guillemot Maxi Radio FM 2000, 50 * Gemtek PCI cards and most Mediaforte FM tuners and sound cards with 51 * integrated FM tuners. 52 */ 53 54#include <sys/param.h> 55#include <sys/radioio.h> 56 57#include <dev/ic/tea5757.h> 58 59/* 60 * Convert frequency to hardware representation 61 */ 62u_int32_t 63tea5757_encode_freq(u_int32_t freq, int tea5759) 64{ 65 if (tea5759) 66 freq -= IF_FREQ; 67 else 68 freq += IF_FREQ; 69 70 /* 71 * NO FLOATING POINT! 72 */ 73 freq *= 10; 74 freq /= 125; 75 76 return freq & TEA5757_FREQ; 77} 78 79/* 80 * Convert frequency from hardware representation 81 */ 82u_int32_t 83tea5757_decode_freq(u_int32_t freq, int tea5759) 84{ 85 freq &= TEA5757_FREQ; 86 freq *= 125; /* 12.5 kHz */ 87 freq /= 10; 88 89 if (tea5759) 90 freq += IF_FREQ; 91 else 92 freq -= IF_FREQ; 93 94 return freq; 95} 96 97/* 98 * Hardware search 99 */ 100void 101tea5757_search(struct tea5757_t *tea, u_int32_t stereo, u_int32_t lock, int dir) 102{ 103 u_int32_t reg; 104 u_int co = 0; 105 106 reg = stereo | lock | TEA5757_SEARCH_START; 107 reg |= dir ? TEA5757_SEARCH_UP : TEA5757_SEARCH_DOWN; 108 tea5757_hardware_write(tea, reg); 109 110 DELAY(TEA5757_ACQUISITION_DELAY); 111 112 do { 113 DELAY(TEA5757_WAIT_DELAY); 114 reg = tea->read(tea->iot, tea->ioh, tea->offset); 115 } while ((reg & TEA5757_FREQ) == 0 && ++co < 200); 116} 117 118void 119tea5757_hardware_write(struct tea5757_t *tea, u_int32_t data) 120{ 121 int i = TEA5757_REGISTER_LENGTH; 122 123 tea->init(tea->iot, tea->ioh, tea->offset, 0); 124 125 while (i--) 126 if (data & (1 << i)) 127 tea->write_bit(tea->iot, tea->ioh, tea->offset, 1); 128 else 129 tea->write_bit(tea->iot, tea->ioh, tea->offset, 0); 130 131 tea->rset(tea->iot, tea->ioh, tea->offset, 0); 132} 133 134u_int32_t 135tea5757_set_freq(struct tea5757_t *tea, u_int32_t stereo, u_int32_t lock, u_int32_t freq) 136{ 137 u_int32_t data = 0ul; 138 139 if (freq < MIN_FM_FREQ) 140 freq = MIN_FM_FREQ; 141 if (freq > MAX_FM_FREQ) 142 freq = MAX_FM_FREQ; 143 144 data |= tea5757_encode_freq(freq, tea->flags & TEA5757_TEA5759); 145 data |= stereo | lock | TEA5757_SEARCH_END; 146 tea5757_hardware_write(tea, data); 147 148 return freq; 149} 150 151u_int32_t 152tea5757_encode_lock(u_int8_t lock) 153{ 154 u_int32_t ret; 155 156 if (lock < 8) 157 ret = TEA5757_S005; 158 else if (lock > 7 && lock < 15) 159 ret = TEA5757_S010; 160 else if (lock > 14 && lock < 51) 161 ret = TEA5757_S030; 162 else 163 ret = TEA5757_S150; 164 165 return ret; 166} 167 168u_int8_t 169tea5757_decode_lock(u_int32_t lock) 170{ 171 u_int8_t ret = 150; 172 173 switch (lock) { 174 case TEA5757_S005: 175 ret = 5; 176 break; 177 case TEA5757_S010: 178 ret = 10; 179 break; 180 case TEA5757_S030: 181 ret = 30; 182 break; 183 case TEA5757_S150: 184 ret = 150; 185 break; 186 } 187 188 return ret; 189} 190