aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/radio-maestro.c
diff options
context:
space:
mode:
authorJiri Slaby <xslaby@fi.muni.cz>2006-01-09 23:52:48 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-10 11:01:41 -0500
commit6a2cf8eed7f9c8dcc08785259cd179fcb317b120 (patch)
treea914e519d73f8bc4ee2033833ababec3922d56d9 /drivers/media/radio/radio-maestro.c
parent89dad8f07fa244d64459ecd9499bc314dc617598 (diff)
[PATCH] media-radio: Maestro radio Lindent
Maestro radio Lindent + some handwork Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/media/radio/radio-maestro.c')
-rw-r--r--drivers/media/radio/radio-maestro.c208
1 files changed, 105 insertions, 103 deletions
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index bf8b5929ae43..84da5ad18bda 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -29,28 +29,28 @@
29 29
30#define DRIVER_VERSION "0.05" 30#define DRIVER_VERSION "0.05"
31 31
32#define GPIO_DATA 0x60 /* port offset from ESS_IO_BASE */ 32#define GPIO_DATA 0x60 /* port offset from ESS_IO_BASE */
33 33
34#define IO_MASK 4 /* mask register offset from GPIO_DATA 34#define IO_MASK 4 /* mask register offset from GPIO_DATA
35 bits 1=unmask write to given bit */ 35 bits 1=unmask write to given bit */
36#define IO_DIR 8 /* direction register offset from GPIO_DATA 36#define IO_DIR 8 /* direction register offset from GPIO_DATA
37 bits 0/1=read/write direction */ 37 bits 0/1=read/write direction */
38 38
39#define GPIO6 0x0040 /* mask bits for GPIO lines */ 39#define GPIO6 0x0040 /* mask bits for GPIO lines */
40#define GPIO7 0x0080 40#define GPIO7 0x0080
41#define GPIO8 0x0100 41#define GPIO8 0x0100
42#define GPIO9 0x0200 42#define GPIO9 0x0200
43 43
44#define STR_DATA GPIO6 /* radio TEA5757 pins and GPIO bits */ 44#define STR_DATA GPIO6 /* radio TEA5757 pins and GPIO bits */
45#define STR_CLK GPIO7 45#define STR_CLK GPIO7
46#define STR_WREN GPIO8 46#define STR_WREN GPIO8
47#define STR_MOST GPIO9 47#define STR_MOST GPIO9
48 48
49#define FREQ_LO 50*16000 49#define FREQ_LO 50*16000
50#define FREQ_HI 150*16000 50#define FREQ_HI 150*16000
51 51
52#define FREQ_IF 171200 /* 10.7*16000 */ 52#define FREQ_IF 171200 /* 10.7*16000 */
53#define FREQ_STEP 200 /* 12.5*16 */ 53#define FREQ_STEP 200 /* 12.5*16 */
54 54
55#define FREQ2BITS(x) ((((unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1))\ 55#define FREQ2BITS(x) ((((unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1))\
56 /(FREQ_STEP<<2))<<2) /* (x==fmhz*16*1000) -> bits */ 56 /(FREQ_STEP<<2))<<2) /* (x==fmhz*16*1000) -> bits */
@@ -61,7 +61,7 @@ static int radio_nr = -1;
61module_param(radio_nr, int, 0); 61module_param(radio_nr, int, 0);
62 62
63static int radio_ioctl(struct inode *inode, struct file *file, 63static int radio_ioctl(struct inode *inode, struct file *file,
64 unsigned int cmd, unsigned long arg); 64 unsigned int cmd, unsigned long arg);
65static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent); 65static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
66static void maestro_remove(struct pci_dev *pdev); 66static void maestro_remove(struct pci_dev *pdev);
67 67
@@ -92,22 +92,20 @@ static struct file_operations maestro_fops = {
92 .llseek = no_llseek, 92 .llseek = no_llseek,
93}; 93};
94 94
95static struct video_device maestro_radio= 95static struct video_device maestro_radio = {
96{
97 .owner = THIS_MODULE, 96 .owner = THIS_MODULE,
98 .name = "Maestro radio", 97 .name = "Maestro radio",
99 .type = VID_TYPE_TUNER, 98 .type = VID_TYPE_TUNER,
100 .hardware = VID_HARDWARE_SF16MI, 99 .hardware = VID_HARDWARE_SF16MI,
101 .fops = &maestro_fops, 100 .fops = &maestro_fops,
102}; 101};
103 102
104struct radio_device 103struct radio_device {
105{
106 __u16 io, /* base of Maestro card radio io (GPIO_DATA)*/ 104 __u16 io, /* base of Maestro card radio io (GPIO_DATA)*/
107 muted, /* VIDEO_AUDIO_MUTE */ 105 muted, /* VIDEO_AUDIO_MUTE */
108 stereo, /* VIDEO_TUNER_STEREO_ON */ 106 stereo, /* VIDEO_TUNER_STEREO_ON */
109 tuned; /* signal strength (0 or 0xffff) */ 107 tuned; /* signal strength (0 or 0xffff) */
110 struct semaphore lock; 108 struct semaphore lock;
111}; 109};
112 110
113static __u32 radio_bits_get(struct radio_device *dev) 111static __u32 radio_bits_get(struct radio_device *dev)
@@ -115,6 +113,7 @@ static __u32 radio_bits_get(struct radio_device *dev)
115 register __u16 io=dev->io, l, rdata; 113 register __u16 io=dev->io, l, rdata;
116 register __u32 data=0; 114 register __u32 data=0;
117 __u16 omask; 115 __u16 omask;
116
118 omask = inw(io + IO_MASK); 117 omask = inw(io + IO_MASK);
119 outw(~(STR_CLK | STR_WREN), io + IO_MASK); 118 outw(~(STR_CLK | STR_WREN), io + IO_MASK);
120 outw(0, io); 119 outw(0, io);
@@ -137,10 +136,13 @@ static __u32 radio_bits_get(struct radio_device *dev)
137 data++; 136 data++;
138 udelay(2); 137 udelay(2);
139 } 138 }
139
140 if(dev->muted) 140 if(dev->muted)
141 outw(STR_WREN, io); 141 outw(STR_WREN, io);
142
142 udelay(4); 143 udelay(4);
143 outw(omask, io + IO_MASK); 144 outw(omask, io + IO_MASK);
145
144 return data & 0x3ffe; 146 return data & 0x3ffe;
145} 147}
146 148
@@ -148,6 +150,7 @@ static void radio_bits_set(struct radio_device *dev, __u32 data)
148{ 150{
149 register __u16 io=dev->io, l, bits; 151 register __u16 io=dev->io, l, bits;
150 __u16 omask, odir; 152 __u16 omask, odir;
153
151 omask = inw(io + IO_MASK); 154 omask = inw(io + IO_MASK);
152 odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN); 155 odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
153 outw(odir | STR_DATA, io + IO_DIR); 156 outw(odir | STR_DATA, io + IO_DIR);
@@ -163,8 +166,10 @@ static void radio_bits_set(struct radio_device *dev, __u32 data)
163 outw(bits, io); /* LO level */ 166 outw(bits, io); /* LO level */
164 udelay(4); 167 udelay(4);
165 } 168 }
169
166 if(!dev->muted) 170 if(!dev->muted)
167 outw(0, io); 171 outw(0, io);
172
168 udelay(4); 173 udelay(4);
169 outw(omask, io + IO_MASK); 174 outw(omask, io + IO_MASK);
170 outw(odir, io + IO_DIR); 175 outw(odir, io + IO_DIR);
@@ -172,108 +177,103 @@ static void radio_bits_set(struct radio_device *dev, __u32 data)
172} 177}
173 178
174static inline int radio_function(struct inode *inode, struct file *file, 179static inline int radio_function(struct inode *inode, struct file *file,
175 unsigned int cmd, void *arg) 180 unsigned int cmd, void *arg)
176{ 181{
177 struct video_device *dev = video_devdata(file); 182 struct video_device *dev = video_devdata(file);
178 struct radio_device *card=dev->priv; 183 struct radio_device *card = dev->priv;
179 184
180 switch(cmd) { 185 switch (cmd) {
181 case VIDIOCGCAP: { 186 case VIDIOCGCAP: {
182 struct video_capability *v = arg; 187 struct video_capability *v = arg;
183 memset(v,0,sizeof(*v)); 188 memset(v, 0, sizeof(*v));
184 strcpy(v->name, "Maestro radio"); 189 strcpy(v->name, "Maestro radio");
185 v->type=VID_TYPE_TUNER; 190 v->type = VID_TYPE_TUNER;
186 v->channels=v->audios=1; 191 v->channels = v->audios = 1;
187 return 0; 192 return 0;
188 } 193 } case VIDIOCGTUNER: {
189 case VIDIOCGTUNER: { 194 struct video_tuner *v = arg;
190 struct video_tuner *v = arg; 195 if (v->tuner)
191 if(v->tuner) 196 return -EINVAL;
192 return -EINVAL; 197 (void)radio_bits_get(card);
193 (void)radio_bits_get(card); 198 v->flags = VIDEO_TUNER_LOW | card->stereo;
194 v->flags = VIDEO_TUNER_LOW | card->stereo; 199 v->signal = card->tuned;
195 v->signal = card->tuned; 200 strcpy(v->name, "FM");
196 strcpy(v->name, "FM"); 201 v->rangelow = FREQ_LO;
197 v->rangelow = FREQ_LO; 202 v->rangehigh = FREQ_HI;
198 v->rangehigh = FREQ_HI; 203 v->mode = VIDEO_MODE_AUTO;
199 v->mode = VIDEO_MODE_AUTO; 204 return 0;
200 return 0; 205 } case VIDIOCSTUNER: {
201 } 206 struct video_tuner *v = arg;
202 case VIDIOCSTUNER: { 207 if (v->tuner != 0)
203 struct video_tuner *v = arg; 208 return -EINVAL;
204 if(v->tuner!=0) 209 return 0;
205 return -EINVAL; 210 } case VIDIOCGFREQ: {
206 return 0; 211 unsigned long *freq = arg;
207 } 212 *freq = BITS2FREQ(radio_bits_get(card));
208 case VIDIOCGFREQ: { 213 return 0;
209 unsigned long *freq = arg; 214 } case VIDIOCSFREQ: {
210 *freq = BITS2FREQ(radio_bits_get(card)); 215 unsigned long *freq = arg;
211 return 0; 216 if (*freq < FREQ_LO || *freq > FREQ_HI)
212 } 217 return -EINVAL;
213 case VIDIOCSFREQ: { 218 radio_bits_set(card, FREQ2BITS(*freq));
214 unsigned long *freq = arg; 219 return 0;
215 if (*freq<FREQ_LO || *freq>FREQ_HI ) 220 } case VIDIOCGAUDIO: {
216 return -EINVAL; 221 struct video_audio *v = arg;
217 radio_bits_set(card, FREQ2BITS(*freq)); 222 memset(v, 0, sizeof(*v));
223 strcpy(v->name, "Radio");
224 v->flags = VIDEO_AUDIO_MUTABLE | card->muted;
225 v->mode = VIDEO_SOUND_STEREO;
226 return 0;
227 } case VIDIOCSAUDIO: {
228 struct video_audio *v = arg;
229 if (v->audio)
230 return -EINVAL;
231 {
232 register __u16 io = card->io;
233 register __u16 omask = inw(io + IO_MASK);
234 outw(~STR_WREN, io + IO_MASK);
235 outw((card->muted = v->flags & VIDEO_AUDIO_MUTE) ?
236 STR_WREN : 0, io);
237 udelay(4);
238 outw(omask, io + IO_MASK);
239 msleep(125);
218 return 0; 240 return 0;
219 } 241 }
220 case VIDIOCGAUDIO: { 242 } case VIDIOCGUNIT: {
221 struct video_audio *v = arg; 243 struct video_unit *v = arg;
222 memset(v,0,sizeof(*v)); 244 v->video = VIDEO_NO_UNIT;
223 strcpy(v->name, "Radio"); 245 v->vbi = VIDEO_NO_UNIT;
224 v->flags=VIDEO_AUDIO_MUTABLE | card->muted; 246 v->radio = dev->minor;
225 v->mode=VIDEO_SOUND_STEREO; 247 v->audio = 0;
226 return 0; 248 v->teletext = VIDEO_NO_UNIT;
227 } 249 return 0;
228 case VIDIOCSAUDIO: { 250 } default:
229 struct video_audio *v = arg; 251 return -ENOIOCTLCMD;
230 if(v->audio)
231 return -EINVAL;
232 {
233 register __u16 io=card->io;
234 register __u16 omask = inw(io + IO_MASK);
235 outw(~STR_WREN, io + IO_MASK);
236 outw((card->muted = v->flags & VIDEO_AUDIO_MUTE)
237 ? STR_WREN : 0, io);
238 udelay(4);
239 outw(omask, io + IO_MASK);
240 msleep(125);
241 return 0;
242 }
243 }
244 case VIDIOCGUNIT: {
245 struct video_unit *v = arg;
246 v->video=VIDEO_NO_UNIT;
247 v->vbi=VIDEO_NO_UNIT;
248 v->radio=dev->minor;
249 v->audio=0;
250 v->teletext=VIDEO_NO_UNIT;
251 return 0;
252 }
253 default: return -ENOIOCTLCMD;
254 } 252 }
255} 253}
256 254
257static int radio_ioctl(struct inode *inode, struct file *file, 255static int radio_ioctl(struct inode *inode, struct file *file,
258 unsigned int cmd, unsigned long arg) 256 unsigned int cmd, unsigned long arg)
259{ 257{
260 struct video_device *dev = video_devdata(file); 258 struct video_device *dev = video_devdata(file);
261 struct radio_device *card=dev->priv; 259 struct radio_device *card = dev->priv;
262 int ret; 260 int ret;
263 261
264 down(&card->lock); 262 down(&card->lock);
265 ret = video_usercopy(inode, file, cmd, arg, radio_function); 263 ret = video_usercopy(inode, file, cmd, arg, radio_function);
266 up(&card->lock); 264 up(&card->lock);
265
267 return ret; 266 return ret;
268} 267}
269 268
270static __u16 __devinit radio_power_on(struct radio_device *dev) 269static __u16 __devinit radio_power_on(struct radio_device *dev)
271{ 270{
272 register __u16 io=dev->io; 271 register __u16 io = dev->io;
273 register __u32 ofreq; 272 register __u32 ofreq;
274 __u16 omask, odir; 273 __u16 omask, odir;
274
275 omask = inw(io + IO_MASK); 275 omask = inw(io + IO_MASK);
276 odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN); 276 odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
277 outw(odir & ~STR_WREN, io + IO_DIR); 277 outw(odir & ~STR_WREN, io + IO_DIR);
278 dev->muted = inw(io) & STR_WREN ? 0 : VIDEO_AUDIO_MUTE; 278 dev->muted = inw(io) & STR_WREN ? 0 : VIDEO_AUDIO_MUTE;
279 outw(odir, io + IO_DIR); 279 outw(odir, io + IO_DIR);
@@ -282,9 +282,11 @@ static __u16 __devinit radio_power_on(struct radio_device *dev)
282 udelay(16); 282 udelay(16);
283 outw(omask, io + IO_MASK); 283 outw(omask, io + IO_MASK);
284 ofreq = radio_bits_get(dev); 284 ofreq = radio_bits_get(dev);
285 if((ofreq<FREQ2BITS(FREQ_LO)) || (ofreq>FREQ2BITS(FREQ_HI))) 285
286 if ((ofreq < FREQ2BITS(FREQ_LO)) || (ofreq > FREQ2BITS(FREQ_HI)))
286 ofreq = FREQ2BITS(FREQ_LO); 287 ofreq = FREQ2BITS(FREQ_LO);
287 radio_bits_set(dev, ofreq); 288 radio_bits_set(dev, ofreq);
289
288 return (ofreq == radio_bits_get(dev)); 290 return (ofreq == radio_bits_get(dev));
289} 291}
290 292
@@ -335,7 +337,7 @@ static int __devinit maestro_probe(struct pci_dev *pdev,
335 } 337 }
336 338
337 dev_info(&pdev->dev, "version " DRIVER_VERSION " time " __TIME__ " " 339 dev_info(&pdev->dev, "version " DRIVER_VERSION " time " __TIME__ " "
338 __DATE__ "\n"); 340 __DATE__ "\n");
339 dev_info(&pdev->dev, "radio chip initialized\n"); 341 dev_info(&pdev->dev, "radio chip initialized\n");
340 342
341 return 0; 343 return 0;
@@ -357,10 +359,6 @@ static void __devexit maestro_remove(struct pci_dev *pdev)
357 video_unregister_device(vdev); 359 video_unregister_device(vdev);
358} 360}
359 361
360MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
361MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
362MODULE_LICENSE("GPL");
363
364static int __init maestro_radio_init(void) 362static int __init maestro_radio_init(void)
365{ 363{
366 int retval = pci_register_driver(&maestro_r_driver); 364 int retval = pci_register_driver(&maestro_r_driver);
@@ -378,3 +376,7 @@ static void __exit maestro_radio_exit(void)
378 376
379module_init(maestro_radio_init); 377module_init(maestro_radio_init);
380module_exit(maestro_radio_exit); 378module_exit(maestro_radio_exit);
379
380MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
381MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
382MODULE_LICENSE("GPL");