diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2007-11-04 09:03:36 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-01-25 16:02:00 -0500 |
commit | 9dd659de9fbd1687c6175053c6453db5b932f152 (patch) | |
tree | 5e07d228f4eaff3ae66bb96fd56792463adcc261 /drivers/media/video/tuner-core.c | |
parent | 92de1f16d15a30831d1685949aeb76c99032ef23 (diff) |
V4L/DVB (6556): tuner: convert to bus-based I2C API
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/tuner-core.c')
-rw-r--r-- | drivers/media/video/tuner-core.c | 99 |
1 files changed, 32 insertions, 67 deletions
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 48b2d46048ab..1b0d28a0ca78 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <media/tuner.h> | 19 | #include <media/tuner.h> |
20 | #include <media/tuner-types.h> | 20 | #include <media/tuner-types.h> |
21 | #include <media/v4l2-common.h> | 21 | #include <media/v4l2-common.h> |
22 | #include <media/v4l2-i2c-drv-legacy.h> | ||
22 | #include "tuner-driver.h" | 23 | #include "tuner-driver.h" |
23 | #include "mt20xx.h" | 24 | #include "mt20xx.h" |
24 | #include "tda8290.h" | 25 | #include "tda8290.h" |
@@ -30,7 +31,7 @@ | |||
30 | 31 | ||
31 | #define UNSET (-1U) | 32 | #define UNSET (-1U) |
32 | 33 | ||
33 | #define PREFIX "tuner " | 34 | #define PREFIX t->i2c->driver->driver.name |
34 | 35 | ||
35 | /* standard i2c insmod options */ | 36 | /* standard i2c insmod options */ |
36 | static unsigned short normal_i2c[] = { | 37 | static unsigned short normal_i2c[] = { |
@@ -75,9 +76,6 @@ MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners"); | |||
75 | MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); | 76 | MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); |
76 | MODULE_LICENSE("GPL"); | 77 | MODULE_LICENSE("GPL"); |
77 | 78 | ||
78 | static struct i2c_driver driver; | ||
79 | static struct i2c_client client_template; | ||
80 | |||
81 | /* ---------------------------------------------------------------------- */ | 79 | /* ---------------------------------------------------------------------- */ |
82 | 80 | ||
83 | static void fe_set_freq(struct dvb_frontend *fe, unsigned int freq) | 81 | static void fe_set_freq(struct dvb_frontend *fe, unsigned int freq) |
@@ -919,18 +917,18 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
919 | 917 | ||
920 | static int tuner_suspend(struct i2c_client *c, pm_message_t state) | 918 | static int tuner_suspend(struct i2c_client *c, pm_message_t state) |
921 | { | 919 | { |
922 | struct tuner *t = i2c_get_clientdata (c); | 920 | struct tuner *t = i2c_get_clientdata(c); |
923 | 921 | ||
924 | tuner_dbg ("suspend\n"); | 922 | tuner_dbg("suspend\n"); |
925 | /* FIXME: power down ??? */ | 923 | /* FIXME: power down ??? */ |
926 | return 0; | 924 | return 0; |
927 | } | 925 | } |
928 | 926 | ||
929 | static int tuner_resume(struct i2c_client *c) | 927 | static int tuner_resume(struct i2c_client *c) |
930 | { | 928 | { |
931 | struct tuner *t = i2c_get_clientdata (c); | 929 | struct tuner *t = i2c_get_clientdata(c); |
932 | 930 | ||
933 | tuner_dbg ("resume\n"); | 931 | tuner_dbg("resume\n"); |
934 | if (V4L2_TUNER_RADIO == t->mode) { | 932 | if (V4L2_TUNER_RADIO == t->mode) { |
935 | if (t->radio_freq) | 933 | if (t->radio_freq) |
936 | set_freq(c, t->radio_freq); | 934 | set_freq(c, t->radio_freq); |
@@ -946,7 +944,7 @@ static int tuner_resume(struct i2c_client *c) | |||
946 | LIST_HEAD(tuner_list); | 944 | LIST_HEAD(tuner_list); |
947 | 945 | ||
948 | /* Search for existing radio and/or TV tuners on the given I2C adapter. | 946 | /* Search for existing radio and/or TV tuners on the given I2C adapter. |
949 | Note that when this function is called from tuner_attach you can be | 947 | Note that when this function is called from tuner_probe you can be |
950 | certain no other devices will be added/deleted at the same time, I2C | 948 | certain no other devices will be added/deleted at the same time, I2C |
951 | core protects against that. */ | 949 | core protects against that. */ |
952 | static void tuner_lookup(struct i2c_adapter *adap, | 950 | static void tuner_lookup(struct i2c_adapter *adap, |
@@ -977,28 +975,19 @@ static void tuner_lookup(struct i2c_adapter *adap, | |||
977 | } | 975 | } |
978 | 976 | ||
979 | /* During client attach, set_type is called by adapter's attach_inform callback. | 977 | /* During client attach, set_type is called by adapter's attach_inform callback. |
980 | set_type must then be completed by tuner_attach. | 978 | set_type must then be completed by tuner_probe. |
981 | */ | 979 | */ |
982 | static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | 980 | static int tuner_probe(struct i2c_client *client) |
983 | { | 981 | { |
984 | struct i2c_client *client; | ||
985 | struct tuner *t; | 982 | struct tuner *t; |
986 | struct tuner *radio; | 983 | struct tuner *radio; |
987 | struct tuner *tv; | 984 | struct tuner *tv; |
988 | 985 | ||
989 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
990 | if (NULL == client) | ||
991 | return -ENOMEM; | ||
992 | |||
993 | t = kzalloc(sizeof(struct tuner), GFP_KERNEL); | 986 | t = kzalloc(sizeof(struct tuner), GFP_KERNEL); |
994 | if (NULL == t) { | 987 | if (NULL == t) |
995 | kfree(client); | ||
996 | return -ENOMEM; | 988 | return -ENOMEM; |
997 | } | ||
998 | t->i2c = client; | 989 | t->i2c = client; |
999 | client_template.adapter = adap; | 990 | strlcpy(client->name, "(tuner unset)", sizeof(client->name)); |
1000 | client_template.addr = addr; | ||
1001 | memcpy(client, &client_template, sizeof(struct i2c_client)); | ||
1002 | i2c_set_clientdata(client, t); | 991 | i2c_set_clientdata(client, t); |
1003 | t->type = UNSET; | 992 | t->type = UNSET; |
1004 | t->audmode = V4L2_TUNER_MODE_STEREO; | 993 | t->audmode = V4L2_TUNER_MODE_STEREO; |
@@ -1015,14 +1004,16 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | |||
1015 | printk(KERN_CONT "%02x ", buffer[i]); | 1004 | printk(KERN_CONT "%02x ", buffer[i]); |
1016 | printk("\n"); | 1005 | printk("\n"); |
1017 | } | 1006 | } |
1018 | /* HACK: This test were added to avoid tuner to probe tda9840 and | 1007 | /* HACK: This test was added to avoid tuner to probe tda9840 and |
1019 | tea6415c on the MXB card */ | 1008 | tea6415c on the MXB card */ |
1020 | if (adap->id == I2C_HW_SAA7146 && addr < 0x4a) | 1009 | if (client->adapter->id == I2C_HW_SAA7146 && client->addr < 0x4a) { |
1010 | kfree(t); | ||
1021 | return -ENODEV; | 1011 | return -ENODEV; |
1012 | } | ||
1022 | 1013 | ||
1023 | /* autodetection code based on the i2c addr */ | 1014 | /* autodetection code based on the i2c addr */ |
1024 | if (!no_autodetect) { | 1015 | if (!no_autodetect) { |
1025 | switch (addr) { | 1016 | switch (client->addr) { |
1026 | case 0x10: | 1017 | case 0x10: |
1027 | if (tea5761_autodetection(t->i2c->adapter, t->i2c->addr) | 1018 | if (tea5761_autodetection(t->i2c->adapter, t->i2c->addr) |
1028 | != EINVAL) { | 1019 | != EINVAL) { |
@@ -1092,7 +1083,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | |||
1092 | 1083 | ||
1093 | /* Should be just before return */ | 1084 | /* Should be just before return */ |
1094 | register_client: | 1085 | register_client: |
1095 | tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); | 1086 | tuner_info("chip found @ 0x%x (%s)\n", client->addr << 1, |
1087 | client->adapter->name); | ||
1096 | 1088 | ||
1097 | /* Sets a default mode */ | 1089 | /* Sets a default mode */ |
1098 | if (t->mode_mask & T_ANALOG_TV) { | 1090 | if (t->mode_mask & T_ANALOG_TV) { |
@@ -1102,19 +1094,21 @@ register_client: | |||
1102 | } else { | 1094 | } else { |
1103 | t->mode = T_DIGITAL_TV; | 1095 | t->mode = T_DIGITAL_TV; |
1104 | } | 1096 | } |
1105 | |||
1106 | i2c_attach_client(client); | ||
1107 | set_type(client, t->type, t->mode_mask, t->config, t->tuner_callback); | 1097 | set_type(client, t->type, t->mode_mask, t->config, t->tuner_callback); |
1098 | list_add_tail(&t->list, &tuner_list); | ||
1108 | return 0; | 1099 | return 0; |
1109 | } | 1100 | } |
1110 | 1101 | ||
1111 | static int tuner_probe(struct i2c_adapter *adap) | 1102 | static int tuner_legacy_probe(struct i2c_adapter *adap) |
1112 | { | 1103 | { |
1113 | if (0 != addr) { | 1104 | if (0 != addr) { |
1114 | normal_i2c[0] = addr; | 1105 | normal_i2c[0] = addr; |
1115 | normal_i2c[1] = I2C_CLIENT_END; | 1106 | normal_i2c[1] = I2C_CLIENT_END; |
1116 | } | 1107 | } |
1117 | 1108 | ||
1109 | if ((adap->class & I2C_CLASS_TV_ANALOG) == 0) | ||
1110 | return 0; | ||
1111 | |||
1118 | /* HACK: Ignore 0x6b and 0x6f on cx88 boards. | 1112 | /* HACK: Ignore 0x6b and 0x6f on cx88 boards. |
1119 | * FusionHDTV5 RT Gold has an ir receiver at 0x6b | 1113 | * FusionHDTV5 RT Gold has an ir receiver at 0x6b |
1120 | * and an RTC at 0x6f which can get corrupted if probed. | 1114 | * and an RTC at 0x6f which can get corrupted if probed. |
@@ -1136,64 +1130,35 @@ static int tuner_probe(struct i2c_adapter *adap) | |||
1136 | "too many options specified " | 1130 | "too many options specified " |
1137 | "in i2c probe ignore list!\n"); | 1131 | "in i2c probe ignore list!\n"); |
1138 | } | 1132 | } |
1139 | 1133 | return 1; | |
1140 | if (adap->class & I2C_CLASS_TV_ANALOG) | ||
1141 | return i2c_probe(adap, &addr_data, tuner_attach); | ||
1142 | return 0; | ||
1143 | } | 1134 | } |
1144 | 1135 | ||
1145 | static int tuner_detach(struct i2c_client *client) | 1136 | static int tuner_remove(struct i2c_client *client) |
1146 | { | 1137 | { |
1147 | struct tuner *t = i2c_get_clientdata(client); | 1138 | struct tuner *t = i2c_get_clientdata(client); |
1148 | struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; | 1139 | struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; |
1149 | int err; | ||
1150 | |||
1151 | err = i2c_detach_client(t->i2c); | ||
1152 | if (err) { | ||
1153 | tuner_warn | ||
1154 | ("Client deregistration failed, client not detached.\n"); | ||
1155 | return err; | ||
1156 | } | ||
1157 | 1140 | ||
1158 | if (ops && ops->release) | 1141 | if (ops && ops->release) |
1159 | ops->release(&t->fe); | 1142 | ops->release(&t->fe); |
1160 | 1143 | ||
1161 | list_del(&t->list); | 1144 | list_del(&t->list); |
1162 | kfree(t); | 1145 | kfree(t); |
1163 | kfree(client); | ||
1164 | return 0; | 1146 | return 0; |
1165 | } | 1147 | } |
1166 | 1148 | ||
1167 | /* ----------------------------------------------------------------------- */ | 1149 | /* ----------------------------------------------------------------------- */ |
1168 | 1150 | ||
1169 | static struct i2c_driver driver = { | 1151 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
1170 | .id = I2C_DRIVERID_TUNER, | 1152 | .name = "tuner", |
1171 | .attach_adapter = tuner_probe, | 1153 | .driverid = I2C_DRIVERID_TUNER, |
1172 | .detach_client = tuner_detach, | ||
1173 | .command = tuner_command, | 1154 | .command = tuner_command, |
1155 | .probe = tuner_probe, | ||
1156 | .remove = tuner_remove, | ||
1174 | .suspend = tuner_suspend, | 1157 | .suspend = tuner_suspend, |
1175 | .resume = tuner_resume, | 1158 | .resume = tuner_resume, |
1176 | .driver = { | 1159 | .legacy_probe = tuner_legacy_probe, |
1177 | .name = "tuner", | ||
1178 | }, | ||
1179 | }; | 1160 | }; |
1180 | static struct i2c_client client_template = { | ||
1181 | .name = "(tuner unset)", | ||
1182 | .driver = &driver, | ||
1183 | }; | ||
1184 | |||
1185 | static int __init tuner_init_module(void) | ||
1186 | { | ||
1187 | return i2c_add_driver(&driver); | ||
1188 | } | ||
1189 | |||
1190 | static void __exit tuner_cleanup_module(void) | ||
1191 | { | ||
1192 | i2c_del_driver(&driver); | ||
1193 | } | ||
1194 | 1161 | ||
1195 | module_init(tuner_init_module); | ||
1196 | module_exit(tuner_cleanup_module); | ||
1197 | 1162 | ||
1198 | /* | 1163 | /* |
1199 | * Overrides for Emacs so that we follow Linus's tabbing style. | 1164 | * Overrides for Emacs so that we follow Linus's tabbing style. |