~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux-2.6.17/drivers/media/radio/miropcm20-rds-core.c

Version: ~ [ 2.6.16 ] ~ [ 2.6.17 ] ~
Architecture: ~ [ ia64 ] ~ [ i386 ] ~ [ arm ] ~ [ ppc ] ~ [ sparc64 ] ~

  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 <linux/mutex.h>
 22 
 23 #include <asm/io.h>
 24 #include "../../../sound/oss/aci.h"
 25 #include "miropcm20-rds-core.h"
 26 
 27 #define DEBUG 0
 28 
 29 static struct mutex aci_rds_mutex;
 30 
 31 #define RDS_DATASHIFT          2   /* Bit 2 */
 32 #define RDS_DATAMASK        (1 << RDS_DATASHIFT)
 33 #define RDS_BUSYMASK        0x10   /* Bit 4 */
 34 #define RDS_CLOCKMASK       0x08   /* Bit 3 */
 35 
 36 #define RDS_DATA(x)         (((x) >> RDS_DATASHIFT) & 1) 
 37 
 38 
 39 #if DEBUG
 40 static void print_matrix(char array[], unsigned int length)
 41 {
 42         int i, j;
 43 
 44         for (i=0; i<length; i++) {
 45                 printk(KERN_DEBUG "aci-rds: ");
 46                 for (j=7; j>=0; j--) {
 47                         printk("%d", (array[i] >> j) & 0x1);
 48                 }
 49                 if (i%8 == 0)
 50                         printk(" byte-border\n");
 51                 else
 52                         printk("\n");
 53         }
 54 }
 55 #endif /* DEBUG */
 56 
 57 static int byte2trans(unsigned char byte, unsigned char sendbuffer[], int size)
 58 {
 59         int i;
 60 
 61         if (size != 8)
 62                 return -1;
 63         for (i = 7; i >= 0; i--)
 64                 sendbuffer[7-i] = (byte & (1 << i)) ? RDS_DATAMASK : 0;
 65         sendbuffer[0] |= RDS_CLOCKMASK;
 66 
 67         return 0;
 68 }
 69 
 70 static int rds_waitread(void)
 71 {
 72         unsigned char byte;
 73         int i=2000;
 74 
 75         do {
 76                 byte=inb(RDS_REGISTER);
 77                 i--;
 78         }
 79         while ((byte & RDS_BUSYMASK) && i);
 80 
 81         if (i) {
 82                 #if DEBUG
 83                 printk(KERN_DEBUG "rds_waitread()");
 84                 print_matrix(&byte, 1);
 85                 #endif
 86                 return (byte);
 87         } else {
 88                 printk(KERN_WARNING "aci-rds: rds_waitread() timeout...\n");
 89                 return -1;
 90         }
 91 }
 92 
 93 /* don't use any ..._nowait() function if you are not sure what you do... */
 94 
 95 static inline void rds_rawwrite_nowait(unsigned char byte)
 96 {
 97         #if DEBUG
 98         printk(KERN_DEBUG "rds_rawwrite()");
 99         print_matrix(&byte, 1);
100         #endif
101         outb(byte, RDS_REGISTER);
102 }
103 
104 static int rds_rawwrite(unsigned char byte)
105 {
106         if (rds_waitread() >= 0) {
107                 rds_rawwrite_nowait(byte);
108                 return 0;
109         } else
110                 return -1;
111 }
112 
113 static int rds_write(unsigned char cmd)
114 {
115         unsigned char sendbuffer[8];
116         int i;
117         
118         if (byte2trans(cmd, sendbuffer, 8) != 0){
119                 return -1;
120         } else {
121                 for (i=0; i<8; i++) {
122                         rds_rawwrite(sendbuffer[i]);
123                 }
124         }
125         return 0;
126 }
127 
128 static int rds_readcycle_nowait(void)
129 {
130         rds_rawwrite_nowait(0);
131         return rds_waitread();
132 }
133 
134 static int rds_readcycle(void)
135 {
136         if (rds_rawwrite(0) < 0)
137                 return -1;
138         return rds_waitread();
139 }
140 
141 static int rds_read(unsigned char databuffer[], int datasize)
142 {
143         #define READSIZE (8*datasize)
144 
145         int i,j;
146 
147         if (datasize < 1)  /* nothing to read */
148                 return 0;
149 
150         /* to be able to use rds_readcycle_nowait()
151            I have to waitread() here */
152         if (rds_waitread() < 0)
153                 return -1;
154         
155         memset(databuffer, 0, datasize);
156 
157         for (i=0; i< READSIZE; i++)
158                 if((j=rds_readcycle_nowait()) < 0) {
159                         return -1;
160                 } else {
161                         databuffer[i/8]|=(RDS_DATA(j) << (7-(i%8)));
162                 }
163 
164         return 0;
165 }
166 
167 static int rds_ack(void)
168 {
169         int i=rds_readcycle();
170 
171         if (i < 0)
172                 return -1;
173         if (i & RDS_DATAMASK) {
174                 return 0;  /* ACK  */
175         } else {
176                 printk(KERN_DEBUG "aci-rds: NACK\n");
177                 return 1;  /* NACK */
178         }
179 }
180 
181 int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize)
182 {
183         int ret;
184 
185         if (mutex_lock_interruptible(&aci_rds_mutex))
186                 return -EINTR;
187 
188         rds_write(cmd);
189 
190         /* RDS_RESET doesn't need further processing */
191         if (cmd!=RDS_RESET && (rds_ack() || rds_read(databuffer, datasize)))
192                 ret = -1;
193         else
194                 ret = 0;
195 
196         mutex_unlock(&aci_rds_mutex);
197         
198         return ret;
199 }
200 EXPORT_SYMBOL(aci_rds_cmd);
201 
202 int __init attach_aci_rds(void)
203 {
204         mutex_init(&aci_rds_mutex);
205         return 0;
206 }
207 
208 void __exit unload_aci_rds(void)
209 {
210 }
211 MODULE_LICENSE("GPL");
212 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.