diff options
Diffstat (limited to 'drivers/media/radio/radio-gemtek.c')
-rw-r--r-- | drivers/media/radio/radio-gemtek.c | 124 |
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); | |||
114 | struct gemtek_device { | 113 | struct 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 | ||
120 | enum { | 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 | |
132 | struct 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 | ||
137 | static struct gemtek_device gemtek_unit; | 154 | static struct gemtek_device gemtek_unit; |
138 | 155 | ||
139 | static 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 | |||
162 | static spinlock_t lock; | 156 | static 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 | */ |
167 | static 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 | */ |
613 | static int __init gemtek_init(void) | 580 | static 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); |