1 /* SF16-FMR2 radio driver for Linux 2 * Copyright (c) 2011 Ondrej Zary 3 * 4 * Original driver was (c) 2000-2002 Ziglio Frediano, freddy77@angelfire.com 5 * but almost nothing remained here after conversion to generic TEA575x 6 * implementation 7 */ 8 9 #include <linux/delay.h> 10 #include <linux/module.h> /* Modules */ 11 #include <linux/init.h> /* Initdata */ 12 #include <linux/slab.h> 13 #include <linux/ioport.h> /* request_region */ 14 #include <linux/io.h> /* outb, outb_p */ 15 #include <linux/isa.h> 16 #include <sound/tea575x-tuner.h> 17 18 MODULE_AUTHOR("Ondrej Zary"); 19 MODULE_DESCRIPTION("MediaForte SF16-FMR2 FM radio card driver"); 20 MODULE_LICENSE("GPL"); 21 22 static int radio_nr = -1; 23 module_param(radio_nr, int, 0444); 24 MODULE_PARM_DESC(radio_nr, "Radio device number"); 25 26 struct fmr2 { 27 int io; 28 struct v4l2_device v4l2_dev; 29 struct snd_tea575x tea; 30 struct v4l2_ctrl *volume; 31 struct v4l2_ctrl *balance; 32 }; 33 34 /* the port is hardwired so no need to support multiple cards */ 35 #define FMR2_PORT 0x384 36 37 /* TEA575x tuner pins */ 38 #define STR_DATA (1 << 0) 39 #define STR_CLK (1 << 1) 40 #define STR_WREN (1 << 2) 41 #define STR_MOST (1 << 3) 42 /* PT2254A/TC9154A volume control pins */ 43 #define PT_ST (1 << 4) 44 #define PT_CK (1 << 5) 45 #define PT_DATA (1 << 6) 46 /* volume control presence pin */ 47 #define FMR2_HASVOL (1 << 7) 48 49 static void fmr2_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) 50 { 51 struct fmr2 *fmr2 = tea->private_data; 52 u8 bits = 0; 53 54 bits |= (pins & TEA575X_DATA) ? STR_DATA : 0; 55 bits |= (pins & TEA575X_CLK) ? STR_CLK : 0; 56 /* WRITE_ENABLE is inverted, DATA must be high during read */ 57 bits |= (pins & TEA575X_WREN) ? 0 : STR_WREN | STR_DATA; 58 59 outb(bits, fmr2->io); 60 } 61 62 static u8 fmr2_tea575x_get_pins(struct snd_tea575x *tea) 63 { 64 struct fmr2 *fmr2 = tea->private_data; 65 u8 bits = inb(fmr2->io); 66 67 return (bits & STR_DATA) ? TEA575X_DATA : 0 | 68 (bits & STR_MOST) ? TEA575X_MOST : 0; 69 } 70 71 static void fmr2_tea575x_set_direction(struct snd_tea575x *tea, bool output) 72 { 73 } 74 75 static struct snd_tea575x_ops fmr2_tea_ops = { 76 .set_pins = fmr2_tea575x_set_pins, 77 .get_pins = fmr2_tea575x_get_pins, 78 .set_direction = fmr2_tea575x_set_direction, 79 }; 80 81 /* TC9154A/PT2254A volume control */ 82 83 /* 18-bit shift register bit definitions */ 84 #define TC9154A_ATT_MAJ_0DB (1 << 0) 85 #define TC9154A_ATT_MAJ_10DB (1 << 1) 86 #define TC9154A_ATT_MAJ_20DB (1 << 2) 87 #define TC9154A_ATT_MAJ_30DB (1 << 3) 88 #define TC9154A_ATT_MAJ_40DB (1 << 4) 89 #define TC9154A_ATT_MAJ_50DB (1 << 5) 90 #define TC9154A_ATT_MAJ_60DB (1 << 6) 91 92 #define TC9154A_ATT_MIN_0DB (1 << 7) 93 #define TC9154A_ATT_MIN_2DB (1 << 8) 94 #define TC9154A_ATT_MIN_4DB (1 << 9) 95 #define TC9154A_ATT_MIN_6DB (1 << 10) 96 #define TC9154A_ATT_MIN_8DB (1 << 11) 97 /* bit 12 is ignored */ 98 #define TC9154A_CHANNEL_LEFT (1 << 13) 99 #define TC9154A_CHANNEL_RIGHT (1 << 14) 100 /* bits 15, 16, 17 must be 0 */ 101 102 #define TC9154A_ATT_MAJ(x) (1 << x) 103 #define TC9154A_ATT_MIN(x) (1 << (7 + x)) 104 105 static void tc9154a_set_pins(struct fmr2 *fmr2, u8 pins) 106 { 107 if (!fmr2->tea.mute) 108 pins |= STR_WREN; 109 110 outb(pins, fmr2->io); 111 } 112 113 static void tc9154a_set_attenuation(struct fmr2 *fmr2, int att, u32 channel) 114 { 115 int i; 116 u32 reg; 117 u8 bit; 118 119 reg = TC9154A_ATT_MAJ(att / 10) | TC9154A_ATT_MIN((att % 10) / 2); 120 reg |= channel; 121 /* write 18-bit shift register, LSB first */ 122 for (i = 0; i < 18; i++) { 123 bit = reg & (1 << i) ? PT_DATA : 0; 124 tc9154a_set_pins(fmr2, bit); 125 udelay(5); 126 tc9154a_set_pins(fmr2, bit | PT_CK); 127 udelay(5); 128 tc9154a_set_pins(fmr2, bit); 129 } 130 131 /* latch register data */ 132 udelay(5); 133 tc9154a_set_pins(fmr2, PT_ST); 134 udelay(5); 135 tc9154a_set_pins(fmr2, 0); 136 } 137 138 static int fmr2_s_ctrl(struct v4l2_ctrl *ctrl) 139 { 140 struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler); 141 struct fmr2 *fmr2 = tea->private_data; 142 int volume, balance, left, right; 143 144 switch (ctrl->id) { 145 case V4L2_CID_AUDIO_VOLUME: 146 volume = ctrl->val; 147 balance = fmr2->balance->cur.val; 148 break; 149 case V4L2_CID_AUDIO_BALANCE: 150 balance = ctrl->val; 151 volume = fmr2->volume->cur.val; 152 break; 153 default: 154 return -EINVAL; 155 } 156 157 left = right = volume; 158 if (balance < 0) 159 right = max(0, right + balance); 160 if (balance > 0) 161 left = max(0, left - balance); 162 163 tc9154a_set_attenuation(fmr2, abs(left - 68), TC9154A_CHANNEL_LEFT); 164 tc9154a_set_attenuation(fmr2, abs(right - 68), TC9154A_CHANNEL_RIGHT); 165 166 return 0; 167 } 168 169 static const struct v4l2_ctrl_ops fmr2_ctrl_ops = { 170 .s_ctrl = fmr2_s_ctrl, 171 }; 172 173 static int fmr2_tea_ext_init(struct snd_tea575x *tea) 174 { 175 struct fmr2 *fmr2 = tea->private_data; 176 177 if (inb(fmr2->io) & FMR2_HASVOL) { 178 fmr2->volume = v4l2_ctrl_new_std(&tea->ctrl_handler, &fmr2_ctrl_ops, V4L2_CID_AUDIO_VOLUME, 0, 68, 2, 56); 179 fmr2->balance = v4l2_ctrl_new_std(&tea->ctrl_handler, &fmr2_ctrl_ops, V4L2_CID_AUDIO_BALANCE, -68, 68, 2, 0); 180 if (tea->ctrl_handler.error) { 181 printk(KERN_ERR "radio-sf16fmr2: can't initialize controls\n"); 182 return tea->ctrl_handler.error; 183 } 184 } 185 186 return 0; 187 } 188 189 static int __devinit fmr2_probe(struct device *pdev, unsigned int dev) 190 { 191 struct fmr2 *fmr2; 192 int err; 193 194 fmr2 = kzalloc(sizeof(*fmr2), GFP_KERNEL); 195 if (fmr2 == NULL) 196 return -ENOMEM; 197 198 strlcpy(fmr2->v4l2_dev.name, dev_name(pdev), 199 sizeof(fmr2->v4l2_dev.name)); 200 fmr2->io = FMR2_PORT; 201 202 if (!request_region(fmr2->io, 2, fmr2->v4l2_dev.name)) { 203 printk(KERN_ERR "radio-sf16fmr2: I/O port 0x%x already in use\n", fmr2->io); 204 kfree(fmr2); 205 return -EBUSY; 206 } 207 208 dev_set_drvdata(pdev, fmr2); 209 err = v4l2_device_register(pdev, &fmr2->v4l2_dev); 210 if (err < 0) { 211 v4l2_err(&fmr2->v4l2_dev, "Could not register v4l2_device\n"); 212 release_region(fmr2->io, 2); 213 kfree(fmr2); 214 return err; 215 } 216 fmr2->tea.v4l2_dev = &fmr2->v4l2_dev; 217 fmr2->tea.private_data = fmr2; 218 fmr2->tea.radio_nr = radio_nr; 219 fmr2->tea.ops = &fmr2_tea_ops; 220 fmr2->tea.ext_init = fmr2_tea_ext_init; 221 strlcpy(fmr2->tea.card, "SF16-FMR2", sizeof(fmr2->tea.card)); 222 snprintf(fmr2->tea.bus_info, sizeof(fmr2->tea.bus_info), "ISA:%s", 223 fmr2->v4l2_dev.name); 224 225 if (snd_tea575x_init(&fmr2->tea)) { 226 printk(KERN_ERR "radio-sf16fmr2: Unable to detect TEA575x tuner\n"); 227 release_region(fmr2->io, 2); 228 kfree(fmr2); 229 return -ENODEV; 230 } 231 232 printk(KERN_INFO "radio-sf16fmr2: SF16-FMR2 radio card at 0x%x.\n", fmr2->io); 233 return 0; 234 } 235 236 static int __exit fmr2_remove(struct device *pdev, unsigned int dev) 237 { 238 struct fmr2 *fmr2 = dev_get_drvdata(pdev); 239 240 snd_tea575x_exit(&fmr2->tea); 241 release_region(fmr2->io, 2); 242 v4l2_device_unregister(&fmr2->v4l2_dev); 243 kfree(fmr2); 244 return 0; 245 } 246 247 struct isa_driver fmr2_driver = { 248 .probe = fmr2_probe, 249 .remove = fmr2_remove, 250 .driver = { 251 .name = "radio-sf16fmr2", 252 }, 253 }; 254 255 static int __init fmr2_init(void) 256 { 257 return isa_register_driver(&fmr2_driver, 1); 258 } 259 260 static void __exit fmr2_exit(void) 261 { 262 isa_unregister_driver(&fmr2_driver); 263 } 264 265 module_init(fmr2_init); 266 module_exit(fmr2_exit); 267