Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.12 210 lines 4.1 kB view raw
1/* 2 * Many thanks to Fred Seidel <seidel@metabox.de>, the 3 * designer of the RDS decoder hardware. With his help 4 * I was able to code this driver. 5 * Thanks also to Norberto Pellicci, Dominic Mounteney 6 * <DMounteney@pinnaclesys.com> and www.teleauskunft.de 7 * for good hints on finding Fred. It was somewhat hard 8 * to locate him here in Germany... [: 9 * 10 * Revision history: 11 * 12 * 2000-08-09 Robert Siemer <Robert.Siemer@gmx.de> 13 * RDS support for MiroSound PCM20 radio 14 */ 15 16#include <linux/module.h> 17#include <linux/errno.h> 18#include <linux/string.h> 19#include <linux/init.h> 20#include <linux/slab.h> 21#include <asm/semaphore.h> 22#include <asm/io.h> 23#include "../../../sound/oss/aci.h" 24#include "miropcm20-rds-core.h" 25 26#define DEBUG 0 27 28static struct semaphore aci_rds_sem; 29 30#define RDS_DATASHIFT 2 /* Bit 2 */ 31#define RDS_DATAMASK (1 << RDS_DATASHIFT) 32#define RDS_BUSYMASK 0x10 /* Bit 4 */ 33#define RDS_CLOCKMASK 0x08 /* Bit 3 */ 34 35#define RDS_DATA(x) (((x) >> RDS_DATASHIFT) & 1) 36 37 38#if DEBUG 39static void print_matrix(char array[], unsigned int length) 40{ 41 int i, j; 42 43 for (i=0; i<length; i++) { 44 printk(KERN_DEBUG "aci-rds: "); 45 for (j=7; j>=0; j--) { 46 printk("%d", (array[i] >> j) & 0x1); 47 } 48 if (i%8 == 0) 49 printk(" byte-border\n"); 50 else 51 printk("\n"); 52 } 53} 54#endif /* DEBUG */ 55 56static int byte2trans(unsigned char byte, unsigned char sendbuffer[], int size) 57{ 58 int i; 59 60 if (size != 8) 61 return -1; 62 for (i = 7; i >= 0; i--) 63 sendbuffer[7-i] = (byte & (1 << i)) ? RDS_DATAMASK : 0; 64 sendbuffer[0] |= RDS_CLOCKMASK; 65 66 return 0; 67} 68 69static int rds_waitread(void) 70{ 71 unsigned char byte; 72 int i=2000; 73 74 do { 75 byte=inb(RDS_REGISTER); 76 i--; 77 } 78 while ((byte & RDS_BUSYMASK) && i); 79 80 if (i) { 81 #if DEBUG 82 printk(KERN_DEBUG "rds_waitread()"); 83 print_matrix(&byte, 1); 84 #endif 85 return (byte); 86 } else { 87 printk(KERN_WARNING "aci-rds: rds_waitread() timeout...\n"); 88 return -1; 89 } 90} 91 92/* don't use any ..._nowait() function if you are not sure what you do... */ 93 94static inline void rds_rawwrite_nowait(unsigned char byte) 95{ 96 #if DEBUG 97 printk(KERN_DEBUG "rds_rawwrite()"); 98 print_matrix(&byte, 1); 99 #endif 100 outb(byte, RDS_REGISTER); 101} 102 103static int rds_rawwrite(unsigned char byte) 104{ 105 if (rds_waitread() >= 0) { 106 rds_rawwrite_nowait(byte); 107 return 0; 108 } else 109 return -1; 110} 111 112static int rds_write(unsigned char cmd) 113{ 114 unsigned char sendbuffer[8]; 115 int i; 116 117 if (byte2trans(cmd, sendbuffer, 8) != 0){ 118 return -1; 119 } else { 120 for (i=0; i<8; i++) { 121 rds_rawwrite(sendbuffer[i]); 122 } 123 } 124 return 0; 125} 126 127static int rds_readcycle_nowait(void) 128{ 129 rds_rawwrite_nowait(0); 130 return rds_waitread(); 131} 132 133static int rds_readcycle(void) 134{ 135 if (rds_rawwrite(0) < 0) 136 return -1; 137 return rds_waitread(); 138} 139 140static int rds_read(unsigned char databuffer[], int datasize) 141{ 142 #define READSIZE (8*datasize) 143 144 int i,j; 145 146 if (datasize < 1) /* nothing to read */ 147 return 0; 148 149 /* to be able to use rds_readcycle_nowait() 150 I have to waitread() here */ 151 if (rds_waitread() < 0) 152 return -1; 153 154 memset(databuffer, 0, datasize); 155 156 for (i=0; i< READSIZE; i++) 157 if((j=rds_readcycle_nowait()) < 0) { 158 return -1; 159 } else { 160 databuffer[i/8]|=(RDS_DATA(j) << (7-(i%8))); 161 } 162 163 return 0; 164} 165 166static int rds_ack(void) 167{ 168 int i=rds_readcycle(); 169 170 if (i < 0) 171 return -1; 172 if (i & RDS_DATAMASK) { 173 return 0; /* ACK */ 174 } else { 175 printk(KERN_DEBUG "aci-rds: NACK\n"); 176 return 1; /* NACK */ 177 } 178} 179 180int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize) 181{ 182 int ret; 183 184 if (down_interruptible(&aci_rds_sem)) 185 return -EINTR; 186 187 rds_write(cmd); 188 189 /* RDS_RESET doesn't need further processing */ 190 if (cmd!=RDS_RESET && (rds_ack() || rds_read(databuffer, datasize))) 191 ret = -1; 192 else 193 ret = 0; 194 195 up(&aci_rds_sem); 196 197 return ret; 198} 199EXPORT_SYMBOL(aci_rds_cmd); 200 201int __init attach_aci_rds(void) 202{ 203 init_MUTEX(&aci_rds_sem); 204 return 0; 205} 206 207void __exit unload_aci_rds(void) 208{ 209} 210MODULE_LICENSE("GPL");