aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/radio-gemtek.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio/radio-gemtek.c')
-rw-r--r--drivers/media/radio/radio-gemtek.c124
1 files changed, 44 insertions, 80 deletions
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 0fcd2b09218d..0c963db03614 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -106,7 +106,6 @@ module_param(radio_nr, int, 0444);
106#define GEMTEK_PLL_OFF 0x07 /* PLL off */ 106#define GEMTEK_PLL_OFF 0x07 /* PLL off */
107 107
108#define BU2614_BUS_SIZE 32 /* BU2614 / BU2614FS bus size */ 108#define BU2614_BUS_SIZE 32 /* BU2614 / BU2614FS bus size */
109#define BU2614_NOPS 8 /* Number of supported operations */
110 109
111#define SHORT_DELAY 5 /* usec */ 110#define SHORT_DELAY 5 /* usec */
112#define LONG_DELAY 75 /* usec */ 111#define LONG_DELAY 75 /* usec */
@@ -114,72 +113,53 @@ module_param(radio_nr, int, 0444);
114struct gemtek_device { 113struct gemtek_device {
115 unsigned long lastfreq; 114 unsigned long lastfreq;
116 int muted; 115 int muted;
117 unsigned long bu2614data[BU2614_NOPS]; 116 u32 bu2614data;
118}; 117};
119 118
120enum { 119#define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */
121 BU2614_VOID, 120#define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */
122 BU2614_FREQ, /* D0..D15, Frequency data */ 121#define BU2614_VOID_BITS 4 /* unused */
123 BU2614_PORT, /* P0..P2, Output port control data */ 122#define BU2614_FMES_BITS 1 /* CT, Frequency measurement beginning data */
124 BU2614_FMES, /* CT, Frequency measurement beginning data */ 123#define BU2614_STDF_BITS 3 /* R0..R2, Standard frequency data */
125 BU2614_STDF, /* R0..R2, Standard frequency data */ 124#define BU2614_SWIN_BITS 1 /* S, Switch between FMIN / AMIN */
126 BU2614_SWIN, /* S, Switch between FMIN / AMIN */ 125#define BU2614_SWAL_BITS 1 /* PS, Swallow counter division (AMIN only)*/
127 BU2614_SWAL, /* PS, Swallow counter division (AMIN only) */ 126#define BU2614_VOID2_BITS 1 /* unused */
128 BU2614_FMUN, /* GT, Frequency measurement time and unlock */ 127#define BU2614_FMUN_BITS 1 /* GT, Frequency measurement time & unlock */
129 BU2614_TEST /* TS, Test data is input */ 128#define BU2614_TEST_BITS 1 /* TS, Test data is input */
130}; 129
131 130#define BU2614_FREQ_SHIFT 0
132struct bu2614_op { 131#define BU2614_PORT_SHIFT (BU2614_FREQ_BITS + BU2614_FREQ_SHIFT)
133 int op; /* Operation */ 132#define BU2614_VOID_SHIFT (BU2614_PORT_BITS + BU2614_PORT_SHIFT)
134 int size; /* Data size */ 133#define BU2614_FMES_SHIFT (BU2614_VOID_BITS + BU2614_VOID_SHIFT)
135}; 134#define BU2614_STDF_SHIFT (BU2614_FMES_BITS + BU2614_FMES_SHIFT)
135#define BU2614_SWIN_SHIFT (BU2614_STDF_BITS + BU2614_STDF_SHIFT)
136#define BU2614_SWAL_SHIFT (BU2614_SWIN_BITS + BU2614_SWIN_SHIFT)
137#define BU2614_VOID2_SHIFT (BU2614_SWAL_BITS + BU2614_SWAL_SHIFT)
138#define BU2614_FMUN_SHIFT (BU2614_VOID2_BITS + BU2614_VOID2_SHIFT)
139#define BU2614_TEST_SHIFT (BU2614_FMUN_BITS + BU2614_FMUN_SHIFT)
140
141#define MKMASK(field) (((1<<BU2614_##field##_BITS) - 1) << \
142 BU2614_##field##_SHIFT)
143#define BU2614_PORT_MASK MKMASK(PORT)
144#define BU2614_FREQ_MASK MKMASK(FREQ)
145#define BU2614_VOID_MASK MKMASK(VOID)
146#define BU2614_FMES_MASK MKMASK(FMES)
147#define BU2614_STDF_MASK MKMASK(STDF)
148#define BU2614_SWIN_MASK MKMASK(SWIN)
149#define BU2614_SWAL_MASK MKMASK(SWAL)
150#define BU2614_VOID2_MASK MKMASK(VOID2)
151#define BU2614_FMUN_MASK MKMASK(FMUN)
152#define BU2614_TEST_MASK MKMASK(TEST)
136 153
137static struct gemtek_device gemtek_unit; 154static struct gemtek_device gemtek_unit;
138 155
139static struct bu2614_op bu2614ops[] = {
140 {.op = BU2614_FREQ,
141 .size = 0x10},
142 {.op = BU2614_PORT,
143 .size = 0x03},
144 {.op = BU2614_VOID,
145 .size = 0x04},
146 {.op = BU2614_FMES,
147 .size = 0x01},
148 {.op = BU2614_STDF,
149 .size = 0x03},
150 {.op = BU2614_SWIN,
151 .size = 0x01},
152 {.op = BU2614_SWAL,
153 .size = 0x01},
154 {.op = BU2614_VOID,
155 .size = 0x01},
156 {.op = BU2614_FMUN,
157 .size = 0x01},
158 {.op = BU2614_TEST,
159 .size = 0x01}
160};
161
162static spinlock_t lock; 156static spinlock_t lock;
163 157
164/* 158/*
165 * Set data which will be sent to BU2614FS. 159 * Set data which will be sent to BU2614FS.
166 */ 160 */
167static void gemtek_bu2614_set(struct gemtek_device *dev, int op, 161#define gemtek_bu2614_set(dev, field, data) ((dev)->bu2614data = \
168 unsigned long data) 162 ((dev)->bu2614data & ~field##_MASK) | ((data) << field##_SHIFT))
169{
170 int i, q;
171
172 for (i = 0, q = 0; q < ARRAY_SIZE(dev->bu2614data); ++i) {
173 if (bu2614ops[i].op == op) {
174 dev->bu2614data[q] =
175 data & ((1 << bu2614ops[i].size) - 1);
176 return;
177 }
178
179 if (bu2614ops[i].op != BU2614_VOID)
180 ++q;
181 }
182}
183 163
184/* 164/*
185 * Transmit settings to BU2614FS over GemTek IC. 165 * Transmit settings to BU2614FS over GemTek IC.
@@ -197,25 +177,12 @@ static void gemtek_bu2614_transmit(struct gemtek_device *dev)
197 outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io); 177 outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io);
198 udelay(LONG_DELAY); 178 udelay(LONG_DELAY);
199 179
200 for (i = 0, q = 0; q < ARRAY_SIZE(dev->bu2614data); ++i) { 180 for (i = 0, q = dev->bu2614data; i < 32; i++, q >>= 1) {
201 for (bit = 0; bit < bu2614ops[i].size; ++bit) { 181 bit = (q & 1) ? GEMTEK_DA : 0;
202 if (bu2614ops[i].op != BU2614_VOID && 182 outb_p(mute | GEMTEK_CE | bit, io);
203 dev->bu2614data[q] & (1 << bit)) { 183 udelay(SHORT_DELAY);
204 outb_p(mute | GEMTEK_CE | GEMTEK_DA, io); 184 outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, io);
205 udelay(SHORT_DELAY); 185 udelay(SHORT_DELAY);
206 outb_p(mute | GEMTEK_CE | GEMTEK_DA |
207 GEMTEK_CK, io);
208 udelay(SHORT_DELAY);
209 } else {
210 outb_p(mute | GEMTEK_CE, io);
211 udelay(SHORT_DELAY);
212 outb_p(mute | GEMTEK_CE | GEMTEK_CK, io);
213 udelay(SHORT_DELAY);
214 }
215 }
216
217 if (bu2614ops[i].op != BU2614_VOID)
218 ++q;
219 } 186 }
220 187
221 outb_p(mute | GEMTEK_DA | GEMTEK_CK, io); 188 outb_p(mute | GEMTEK_DA | GEMTEK_CK, io);
@@ -612,8 +579,6 @@ static struct video_device gemtek_radio = {
612 */ 579 */
613static int __init gemtek_init(void) 580static int __init gemtek_init(void)
614{ 581{
615 int i;
616
617 printk(KERN_INFO RADIO_BANNER "\n"); 582 printk(KERN_INFO RADIO_BANNER "\n");
618 583
619 spin_lock_init(&lock); 584 spin_lock_init(&lock);
@@ -651,8 +616,7 @@ static int __init gemtek_init(void)
651 616
652 /* Set defaults */ 617 /* Set defaults */
653 gemtek_unit.lastfreq = GEMTEK_LOWFREQ; 618 gemtek_unit.lastfreq = GEMTEK_LOWFREQ;
654 for (i = 0; i < ARRAY_SIZE(gemtek_unit.bu2614data); ++i) 619 gemtek_unit.bu2614data = 0;
655 gemtek_unit.bu2614data[i] = 0;
656 620
657 if (initmute) 621 if (initmute)
658 gemtek_mute(&gemtek_unit); 622 gemtek_mute(&gemtek_unit);