^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* radio-trust.c - Trust FM Radio card driver for Linux 2.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * by Eric Lammerts <eric@scintilla.utwente.nl>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Based on radio-aztech.c. Original notes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Adapted to support the Video for Linux API by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Russell Kroll <rkroll@exploits.org>. Based on original tuner code by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Quay Ly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Donald Song
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Jason Lewis (jlewis@twilight.vtc.vsc.edu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Scott McGrath (smcgrath@twilight.vtc.vsc.edu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * William McGrath (wmcgrath@twilight.vtc.vsc.edu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@kernel.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <media/v4l2-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "radio-isa.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) MODULE_DESCRIPTION("A driver for the Trust FM Radio card.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) MODULE_VERSION("0.1.99");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #ifndef CONFIG_RADIO_TRUST_PORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define CONFIG_RADIO_TRUST_PORT -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define TRUST_MAX 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static int io[TRUST_MAX] = { [0] = CONFIG_RADIO_TRUST_PORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) [1 ... (TRUST_MAX - 1)] = -1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int radio_nr[TRUST_MAX] = { [0 ... (TRUST_MAX - 1)] = -1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) module_param_array(io, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) MODULE_PARM_DESC(io, "I/O addresses of the Trust FM Radio card (0x350 or 0x358)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) module_param_array(radio_nr, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) MODULE_PARM_DESC(radio_nr, "Radio device numbers");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct trust {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct radio_isa_card isa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int ioval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static struct radio_isa_card *trust_alloc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct trust *tr = kzalloc(sizeof(*tr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return tr ? &tr->isa : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* i2c addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define TDA7318_ADDR 0x88
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define TSA6060T_ADDR 0xc4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define TR_DELAY do { inb(tr->isa.io); inb(tr->isa.io); inb(tr->isa.io); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define TR_SET_SCL outb(tr->ioval |= 2, tr->isa.io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define TR_CLR_SCL outb(tr->ioval &= 0xfd, tr->isa.io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define TR_SET_SDA outb(tr->ioval |= 1, tr->isa.io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define TR_CLR_SDA outb(tr->ioval &= 0xfe, tr->isa.io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static void write_i2c(struct trust *tr, int n, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned char val, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) va_start(args, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* start condition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) TR_SET_SDA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) TR_SET_SCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) TR_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) TR_CLR_SDA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) TR_CLR_SCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) TR_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) for (; n; n--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) val = va_arg(args, unsigned);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) for (mask = 0x80; mask; mask >>= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (val & mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) TR_SET_SDA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) TR_CLR_SDA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) TR_SET_SCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) TR_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) TR_CLR_SCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) TR_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* acknowledge bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) TR_SET_SDA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) TR_SET_SCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) TR_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) TR_CLR_SCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) TR_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* stop condition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) TR_CLR_SDA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) TR_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) TR_SET_SCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) TR_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) TR_SET_SDA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) TR_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static int trust_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct trust *tr = container_of(isa, struct trust, isa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) tr->ioval = (tr->ioval & 0xf7) | (mute << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) outb(tr->ioval, isa->io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) write_i2c(tr, 2, TDA7318_ADDR, vol ^ 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int trust_s_stereo(struct radio_isa_card *isa, bool stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct trust *tr = container_of(isa, struct trust, isa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) tr->ioval = (tr->ioval & 0xfb) | (!stereo << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) outb(tr->ioval, isa->io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static u32 trust_g_signal(struct radio_isa_card *isa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int i, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) for (i = 0, v = 0; i < 100; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) v |= inb(isa->io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return (v & 1) ? 0 : 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static int trust_s_frequency(struct radio_isa_card *isa, u32 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct trust *tr = container_of(isa, struct trust, isa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) freq /= 160; /* Convert to 10 kHz units */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) freq += 1070; /* Add 10.7 MHz IF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) write_i2c(tr, 5, TSA6060T_ADDR, (freq << 1) | 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) freq >> 7, 0x60 | ((freq >> 15) & 1), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int basstreble2chip[15] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static int trust_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct radio_isa_card *isa =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) container_of(ctrl->handler, struct radio_isa_card, hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct trust *tr = container_of(isa, struct trust, isa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) case V4L2_CID_AUDIO_BASS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) write_i2c(tr, 2, TDA7318_ADDR, 0x60 | basstreble2chip[ctrl->val]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) case V4L2_CID_AUDIO_TREBLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) write_i2c(tr, 2, TDA7318_ADDR, 0x70 | basstreble2chip[ctrl->val]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static const struct v4l2_ctrl_ops trust_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .s_ctrl = trust_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static int trust_initialize(struct radio_isa_card *isa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct trust *tr = container_of(isa, struct trust, isa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) tr->ioval = 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) write_i2c(tr, 2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) write_i2c(tr, 2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) write_i2c(tr, 2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) write_i2c(tr, 2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) write_i2c(tr, 2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) v4l2_ctrl_new_std(&isa->hdl, &trust_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) V4L2_CID_AUDIO_BASS, 0, 15, 1, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) v4l2_ctrl_new_std(&isa->hdl, &trust_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) V4L2_CID_AUDIO_TREBLE, 0, 15, 1, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return isa->hdl.error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static const struct radio_isa_ops trust_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .init = trust_initialize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .alloc = trust_alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .s_mute_volume = trust_s_mute_volume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .s_frequency = trust_s_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .s_stereo = trust_s_stereo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .g_signal = trust_g_signal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static const int trust_ioports[] = { 0x350, 0x358 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static struct radio_isa_driver trust_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .match = radio_isa_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .probe = radio_isa_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .remove = radio_isa_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .name = "radio-trust",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .io_params = io,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .radio_nr_params = radio_nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .io_ports = trust_ioports,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .num_of_io_ports = ARRAY_SIZE(trust_ioports),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .region_size = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) .card = "Trust FM Radio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) .ops = &trust_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .has_stereo = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .max_volume = 31,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static int __init trust_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return isa_register_driver(&trust_driver.driver, TRUST_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static void __exit trust_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) isa_unregister_driver(&trust_driver.driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) module_init(trust_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) module_exit(trust_exit);