diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2008-12-18 11:21:57 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-30 06:39:32 -0500 |
commit | 973909e816baa85a969d2edd5ac12a1ca8669cec (patch) | |
tree | ed495bc687811bd75c011b3cce90e9658e69e743 /drivers/media/video/tda9840.c | |
parent | d531305ae148d5a401f34cd64434824f5cb8c2b1 (diff) |
V4L/DVB (9965): tda9840: convert to v4l2_subdev.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/tda9840.c')
-rw-r--r-- | drivers/media/video/tda9840.c | 188 |
1 files changed, 116 insertions, 72 deletions
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index 1c391f0328fd..2644e0dc9251 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/ioctl.h> | 30 | #include <linux/ioctl.h> |
31 | #include <linux/i2c.h> | 31 | #include <linux/i2c.h> |
32 | #include <media/v4l2-common.h> | 32 | #include <media/v4l2-device.h> |
33 | #include <media/v4l2-i2c-drv-legacy.h> | 33 | #include <media/v4l2-i2c-drv-legacy.h> |
34 | #include "tda9840.h" | 34 | #include "tda9840.h" |
35 | 35 | ||
@@ -62,85 +62,89 @@ static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END }; | |||
62 | /* magic definition of all other variables and things */ | 62 | /* magic definition of all other variables and things */ |
63 | I2C_CLIENT_INSMOD; | 63 | I2C_CLIENT_INSMOD; |
64 | 64 | ||
65 | static void tda9840_write(struct i2c_client *client, u8 reg, u8 val) | 65 | static void tda9840_write(struct v4l2_subdev *sd, u8 reg, u8 val) |
66 | { | 66 | { |
67 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
68 | |||
67 | if (i2c_smbus_write_byte_data(client, reg, val)) | 69 | if (i2c_smbus_write_byte_data(client, reg, val)) |
68 | v4l_dbg(1, debug, client, "error writing %02x to %02x\n", | 70 | v4l2_dbg(1, debug, sd, "error writing %02x to %02x\n", |
69 | val, reg); | 71 | val, reg); |
70 | } | 72 | } |
71 | 73 | ||
72 | static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) | 74 | static int tda9840_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t) |
73 | { | 75 | { |
74 | int byte = *(int *)arg; | 76 | int byte; |
75 | |||
76 | switch (cmd) { | ||
77 | case VIDIOC_S_TUNER: { | ||
78 | struct v4l2_tuner *t = arg; | ||
79 | int byte; | ||
80 | 77 | ||
81 | if (t->index) | 78 | if (t->index) |
82 | return -EINVAL; | 79 | return -EINVAL; |
83 | 80 | ||
84 | switch (t->audmode) { | 81 | switch (t->audmode) { |
85 | case V4L2_TUNER_MODE_STEREO: | 82 | case V4L2_TUNER_MODE_STEREO: |
86 | byte = TDA9840_SET_STEREO; | 83 | byte = TDA9840_SET_STEREO; |
87 | break; | ||
88 | case V4L2_TUNER_MODE_LANG1_LANG2: | ||
89 | byte = TDA9840_SET_BOTH; | ||
90 | break; | ||
91 | case V4L2_TUNER_MODE_LANG1: | ||
92 | byte = TDA9840_SET_LANG1; | ||
93 | break; | ||
94 | case V4L2_TUNER_MODE_LANG2: | ||
95 | byte = TDA9840_SET_LANG2; | ||
96 | break; | ||
97 | default: | ||
98 | byte = TDA9840_SET_MONO; | ||
99 | break; | ||
100 | } | ||
101 | v4l_dbg(1, debug, client, "TDA9840_SWITCH: 0x%02x\n", byte); | ||
102 | tda9840_write(client, SWITCH, byte); | ||
103 | break; | 84 | break; |
85 | case V4L2_TUNER_MODE_LANG1_LANG2: | ||
86 | byte = TDA9840_SET_BOTH; | ||
87 | break; | ||
88 | case V4L2_TUNER_MODE_LANG1: | ||
89 | byte = TDA9840_SET_LANG1; | ||
90 | break; | ||
91 | case V4L2_TUNER_MODE_LANG2: | ||
92 | byte = TDA9840_SET_LANG2; | ||
93 | break; | ||
94 | default: | ||
95 | byte = TDA9840_SET_MONO; | ||
96 | break; | ||
97 | } | ||
98 | v4l2_dbg(1, debug, sd, "TDA9840_SWITCH: 0x%02x\n", byte); | ||
99 | tda9840_write(sd, SWITCH, byte); | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int tda9840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t) | ||
104 | { | ||
105 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
106 | u8 byte; | ||
107 | |||
108 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
109 | if (1 != i2c_master_recv(client, &byte, 1)) { | ||
110 | v4l2_dbg(1, debug, sd, | ||
111 | "i2c_master_recv() failed\n"); | ||
112 | return -EIO; | ||
113 | } | ||
114 | |||
115 | if (byte & 0x80) { | ||
116 | v4l2_dbg(1, debug, sd, | ||
117 | "TDA9840_DETECT: register contents invalid\n"); | ||
118 | return -EINVAL; | ||
104 | } | 119 | } |
105 | 120 | ||
106 | case VIDIOC_G_TUNER: { | 121 | v4l2_dbg(1, debug, sd, "TDA9840_DETECT: byte: 0x%02x\n", byte); |
107 | struct v4l2_tuner *t = arg; | ||
108 | u8 byte; | ||
109 | 122 | ||
123 | switch (byte & 0x60) { | ||
124 | case 0x00: | ||
110 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | 125 | t->rxsubchans = V4L2_TUNER_SUB_MONO; |
111 | if (1 != i2c_master_recv(client, &byte, 1)) { | 126 | break; |
112 | v4l_dbg(1, debug, client, | 127 | case 0x20: |
113 | "i2c_master_recv() failed\n"); | 128 | t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; |
114 | return -EIO; | 129 | break; |
115 | } | 130 | case 0x40: |
116 | 131 | t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; | |
117 | if (byte & 0x80) { | 132 | break; |
118 | v4l_dbg(1, debug, client, | 133 | default: /* Incorrect detect */ |
119 | "TDA9840_DETECT: register contents invalid\n"); | 134 | t->rxsubchans = V4L2_TUNER_MODE_MONO; |
120 | return -EINVAL; | ||
121 | } | ||
122 | |||
123 | v4l_dbg(1, debug, client, "TDA9840_DETECT: byte: 0x%02x\n", byte); | ||
124 | |||
125 | switch (byte & 0x60) { | ||
126 | case 0x00: | ||
127 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
128 | break; | ||
129 | case 0x20: | ||
130 | t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | ||
131 | break; | ||
132 | case 0x40: | ||
133 | t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; | ||
134 | break; | ||
135 | default: /* Incorrect detect */ | ||
136 | t->rxsubchans = V4L2_TUNER_MODE_MONO; | ||
137 | break; | ||
138 | } | ||
139 | break; | 135 | break; |
140 | } | 136 | } |
137 | return 0; | ||
138 | } | ||
141 | 139 | ||
140 | static int tda9840_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) | ||
141 | { | ||
142 | int byte; | ||
143 | |||
144 | switch (cmd) { | ||
142 | case TDA9840_LEVEL_ADJUST: | 145 | case TDA9840_LEVEL_ADJUST: |
143 | v4l_dbg(1, debug, client, "TDA9840_LEVEL_ADJUST: %d\n", byte); | 146 | byte = *(int *)arg; |
147 | v4l2_dbg(1, debug, sd, "TDA9840_LEVEL_ADJUST: %d\n", byte); | ||
144 | 148 | ||
145 | /* check for correct range */ | 149 | /* check for correct range */ |
146 | if (byte > 25 || byte < -20) | 150 | if (byte > 25 || byte < -20) |
@@ -152,11 +156,12 @@ static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) | |||
152 | byte += 0x8; | 156 | byte += 0x8; |
153 | else | 157 | else |
154 | byte = -byte; | 158 | byte = -byte; |
155 | tda9840_write(client, LEVEL_ADJUST, byte); | 159 | tda9840_write(sd, LEVEL_ADJUST, byte); |
156 | break; | 160 | break; |
157 | 161 | ||
158 | case TDA9840_STEREO_ADJUST: | 162 | case TDA9840_STEREO_ADJUST: |
159 | v4l_dbg(1, debug, client, "TDA9840_STEREO_ADJUST: %d\n", byte); | 163 | byte = *(int *)arg; |
164 | v4l2_dbg(1, debug, sd, "TDA9840_STEREO_ADJUST: %d\n", byte); | ||
160 | 165 | ||
161 | /* check for correct range */ | 166 | /* check for correct range */ |
162 | if (byte > 25 || byte < -24) | 167 | if (byte > 25 || byte < -24) |
@@ -169,18 +174,41 @@ static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) | |||
169 | else | 174 | else |
170 | byte = -byte; | 175 | byte = -byte; |
171 | 176 | ||
172 | tda9840_write(client, STEREO_ADJUST, byte); | 177 | tda9840_write(sd, STEREO_ADJUST, byte); |
173 | break; | 178 | break; |
174 | default: | 179 | default: |
175 | return -ENOIOCTLCMD; | 180 | return -ENOIOCTLCMD; |
176 | } | 181 | } |
177 | |||
178 | return 0; | 182 | return 0; |
179 | } | 183 | } |
180 | 184 | ||
185 | static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) | ||
186 | { | ||
187 | return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); | ||
188 | } | ||
189 | |||
190 | /* ----------------------------------------------------------------------- */ | ||
191 | |||
192 | static const struct v4l2_subdev_core_ops tda9840_core_ops = { | ||
193 | .ioctl = tda9840_ioctl, | ||
194 | }; | ||
195 | |||
196 | static const struct v4l2_subdev_tuner_ops tda9840_tuner_ops = { | ||
197 | .s_tuner = tda9840_s_tuner, | ||
198 | .g_tuner = tda9840_g_tuner, | ||
199 | }; | ||
200 | |||
201 | static const struct v4l2_subdev_ops tda9840_ops = { | ||
202 | .core = &tda9840_core_ops, | ||
203 | .tuner = &tda9840_tuner_ops, | ||
204 | }; | ||
205 | |||
206 | /* ----------------------------------------------------------------------- */ | ||
207 | |||
181 | static int tda9840_probe(struct i2c_client *client, | 208 | static int tda9840_probe(struct i2c_client *client, |
182 | const struct i2c_device_id *id) | 209 | const struct i2c_device_id *id) |
183 | { | 210 | { |
211 | struct v4l2_subdev *sd; | ||
184 | int result; | 212 | int result; |
185 | int byte; | 213 | int byte; |
186 | 214 | ||
@@ -188,23 +216,38 @@ static int tda9840_probe(struct i2c_client *client, | |||
188 | if (!i2c_check_functionality(client->adapter, | 216 | if (!i2c_check_functionality(client->adapter, |
189 | I2C_FUNC_SMBUS_READ_BYTE_DATA | | 217 | I2C_FUNC_SMBUS_READ_BYTE_DATA | |
190 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) | 218 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) |
191 | return 0; | 219 | return -EIO; |
192 | 220 | ||
193 | v4l_info(client, "chip found @ 0x%x (%s)\n", | 221 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
194 | client->addr << 1, client->adapter->name); | 222 | client->addr << 1, client->adapter->name); |
195 | 223 | ||
224 | sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); | ||
225 | if (sd == NULL) | ||
226 | return -ENOMEM; | ||
227 | v4l2_i2c_subdev_init(sd, client, &tda9840_ops); | ||
228 | |||
196 | /* set initial values for level & stereo - adjustment, mode */ | 229 | /* set initial values for level & stereo - adjustment, mode */ |
197 | byte = 0; | 230 | byte = 0; |
198 | result = tda9840_command(client, TDA9840_LEVEL_ADJUST, &byte); | 231 | result = tda9840_ioctl(sd, TDA9840_LEVEL_ADJUST, &byte); |
199 | result += tda9840_command(client, TDA9840_STEREO_ADJUST, &byte); | 232 | result |= tda9840_ioctl(sd, TDA9840_STEREO_ADJUST, &byte); |
200 | tda9840_write(client, SWITCH, TDA9840_SET_STEREO); | 233 | tda9840_write(sd, SWITCH, TDA9840_SET_STEREO); |
201 | if (result) { | 234 | if (result) { |
202 | v4l_dbg(1, debug, client, "could not initialize tda9840\n"); | 235 | v4l2_dbg(1, debug, sd, "could not initialize tda9840\n"); |
236 | kfree(sd); | ||
203 | return -ENODEV; | 237 | return -ENODEV; |
204 | } | 238 | } |
205 | return 0; | 239 | return 0; |
206 | } | 240 | } |
207 | 241 | ||
242 | static int tda9840_remove(struct i2c_client *client) | ||
243 | { | ||
244 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
245 | |||
246 | v4l2_device_unregister_subdev(sd); | ||
247 | kfree(sd); | ||
248 | return 0; | ||
249 | } | ||
250 | |||
208 | static int tda9840_legacy_probe(struct i2c_adapter *adapter) | 251 | static int tda9840_legacy_probe(struct i2c_adapter *adapter) |
209 | { | 252 | { |
210 | /* Let's see whether this is a known adapter we can attach to. | 253 | /* Let's see whether this is a known adapter we can attach to. |
@@ -222,6 +265,7 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { | |||
222 | .driverid = I2C_DRIVERID_TDA9840, | 265 | .driverid = I2C_DRIVERID_TDA9840, |
223 | .command = tda9840_command, | 266 | .command = tda9840_command, |
224 | .probe = tda9840_probe, | 267 | .probe = tda9840_probe, |
268 | .remove = tda9840_remove, | ||
225 | .legacy_probe = tda9840_legacy_probe, | 269 | .legacy_probe = tda9840_legacy_probe, |
226 | .id_table = tda9840_id, | 270 | .id_table = tda9840_id, |
227 | }; | 271 | }; |