4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "pvrusb2-i2c-track.h"
22 #include "pvrusb2-hdw-internal.h"
23 #include "pvrusb2-debug.h"
24 #include "pvrusb2-fx2-cmd.h"
27 #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
32 This module implements the foundation of a rather large architecture for
33 tracking state in all the various V4L I2C modules. This is obsolete with
34 kernels later than roughly 2.6.24, but it is still present in the
35 standalone pvrusb2 driver to allow continued operation with older
40 static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
42 char *buf,unsigned int maxlen);
44 static int pvr2_i2c_core_singleton(struct i2c_client *cp,
45 unsigned int cmd,void *arg)
48 if (!cp) return -EINVAL;
49 if (!(cp->driver)) return -EINVAL;
50 if (!(cp->driver->command)) return -EINVAL;
51 if (!try_module_get(cp->driver->driver.owner)) return -EAGAIN;
52 stat = cp->driver->command(cp,cmd,arg);
53 module_put(cp->driver->driver.owner);
57 int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg)
60 if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) {
63 cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG,
65 pvr2_trace(PVR2_TRACE_I2C_CMD,
66 "i2c COMMAND (code=%u 0x%x) to %.*s",
69 stat = pvr2_i2c_core_singleton(cp->client,cmd,arg);
70 if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) {
73 cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG,
75 pvr2_trace(PVR2_TRACE_I2C_CMD,
76 "i2c COMMAND to %.*s (ret=%d)",cnt,buf,stat);
81 int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg)
83 struct pvr2_i2c_client *cp, *ncp;
86 if (!hdw) return stat;
88 mutex_lock(&hdw->i2c_list_lock);
89 list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
90 if (!cp->recv_enable) continue;
91 mutex_unlock(&hdw->i2c_list_lock);
92 stat = pvr2_i2c_client_cmd(cp,cmd,arg);
93 mutex_lock(&hdw->i2c_list_lock);
95 mutex_unlock(&hdw->i2c_list_lock);
100 static int handler_check(struct pvr2_i2c_client *cp)
102 struct pvr2_i2c_handler *hp = cp->handler;
104 if (!hp->func_table->check) return 0;
105 return hp->func_table->check(hp->func_data) != 0;
111 void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw)
113 struct pvr2_i2c_client *cp;
114 mutex_lock(&hdw->i2c_list_lock); do {
115 list_for_each_entry(cp, &hdw->i2c_clients, list) {
116 if (!cp->detected_flag) continue;
117 if (!cp->status_poll) continue;
120 hdw->tuner_signal_stale = 0;
121 } while (0); mutex_unlock(&hdw->i2c_list_lock);
125 /* Issue various I2C operations to bring chip-level drivers into sync with
126 state stored in this driver. */
127 void pvr2_i2c_core_sync(struct pvr2_hdw *hdw)
131 struct pvr2_i2c_client *cp, *ncp;
133 if (!hdw->i2c_linked) return;
134 if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) {
137 mutex_lock(&hdw->i2c_list_lock); do {
138 pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync BEGIN");
139 if (hdw->i2c_pend_types & PVR2_I2C_PEND_DETECT) {
140 /* One or more I2C clients have attached since we
141 last synced. So scan the list and identify the
145 unsigned long amask = 0;
146 buf = kmalloc(BUFSIZE,GFP_KERNEL);
147 pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT");
148 hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT;
149 list_for_each_entry(cp, &hdw->i2c_clients, list) {
150 if (!cp->detected_flag) {
152 pvr2_i2c_probe(hdw,cp);
153 cp->detected_flag = !0;
157 cnt = pvr2_i2c_client_describe(
162 trace_i2c("Probed: %.*s",cnt,buf);
163 if (handler_check(cp)) {
164 hdw->i2c_pend_types |=
165 PVR2_I2C_PEND_CLIENT;
168 hdw->i2c_pend_mask |= msk;
169 hdw->i2c_pend_types |=
170 PVR2_I2C_PEND_REFRESH;
172 amask |= cp->ctl_mask;
174 hdw->i2c_active_mask = amask;
177 if (hdw->i2c_pend_types & PVR2_I2C_PEND_STALE) {
178 /* Need to do one or more global updates. Arrange
179 for this to happen. */
181 pvr2_trace(PVR2_TRACE_I2C_CORE,
182 "i2c: PEND_STALE (0x%lx)",
183 hdw->i2c_stale_mask);
184 hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE;
185 list_for_each_entry(cp, &hdw->i2c_clients, list) {
186 m2 = hdw->i2c_stale_mask;
188 m2 &= ~cp->pend_mask;
190 pvr2_trace(PVR2_TRACE_I2C_CORE,
191 "i2c: cp=%p setting 0x%lx",
196 hdw->i2c_pend_mask |= hdw->i2c_stale_mask;
197 hdw->i2c_stale_mask = 0;
198 hdw->i2c_pend_types |= PVR2_I2C_PEND_REFRESH;
200 if (hdw->i2c_pend_types & PVR2_I2C_PEND_CLIENT) {
201 /* One or more client handlers are asking for an
202 update. Run through the list of known clients
203 and update each one. */
204 pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT");
205 hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT;
206 list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients,
208 if (!cp->handler) continue;
209 if (!cp->handler->func_table->update) continue;
210 pvr2_trace(PVR2_TRACE_I2C_CORE,
211 "i2c: cp=%p update",cp);
212 mutex_unlock(&hdw->i2c_list_lock);
213 cp->handler->func_table->update(
214 cp->handler->func_data);
215 mutex_lock(&hdw->i2c_list_lock);
216 /* If client's update function set some
217 additional pending bits, account for that
219 if (cp->pend_mask & ~hdw->i2c_pend_mask) {
220 hdw->i2c_pend_mask |= cp->pend_mask;
221 hdw->i2c_pend_types |=
222 PVR2_I2C_PEND_REFRESH;
226 if (hdw->i2c_pend_types & PVR2_I2C_PEND_REFRESH) {
227 const struct pvr2_i2c_op *opf;
229 /* Some actual updates are pending. Walk through
230 each update type and perform it. */
231 pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_REFRESH"
232 " (0x%lx)",hdw->i2c_pend_mask);
233 hdw->i2c_pend_types &= ~PVR2_I2C_PEND_REFRESH;
234 pm = hdw->i2c_pend_mask;
235 hdw->i2c_pend_mask = 0;
236 for (idx = 0, msk = 1; pm; idx++, msk <<= 1) {
237 if (!(pm & msk)) continue;
239 list_for_each_entry(cp, &hdw->i2c_clients,
241 if (cp->pend_mask & msk) {
242 cp->pend_mask &= ~msk;
243 cp->recv_enable = !0;
248 opf = pvr2_i2c_get_op(idx);
250 mutex_unlock(&hdw->i2c_list_lock);
252 mutex_lock(&hdw->i2c_list_lock);
255 pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync END");
256 } while (0); mutex_unlock(&hdw->i2c_list_lock);
259 int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw)
261 unsigned long msk,sm,pm;
263 const struct pvr2_i2c_op *opf;
264 struct pvr2_i2c_client *cp;
267 pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale BEGIN");
269 pm = hdw->i2c_active_mask;
271 for (idx = 0, msk = 1; pm; idx++, msk <<= 1) {
272 if (!(msk & pm)) continue;
274 opf = pvr2_i2c_get_op(idx);
275 if (!(opf && opf->check)) continue;
276 if (opf->check(hdw)) {
280 if (sm) pt |= PVR2_I2C_PEND_STALE;
282 list_for_each_entry(cp, &hdw->i2c_clients, list)
283 if (handler_check(cp))
284 pt |= PVR2_I2C_PEND_CLIENT;
287 mutex_lock(&hdw->i2c_list_lock); do {
288 hdw->i2c_pend_types |= pt;
289 hdw->i2c_stale_mask |= sm;
290 hdw->i2c_pend_mask |= hdw->i2c_stale_mask;
291 } while (0); mutex_unlock(&hdw->i2c_list_lock);
294 pvr2_trace(PVR2_TRACE_I2C_CORE,
295 "i2c: types=0x%x stale=0x%lx pend=0x%lx",
299 pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale END");
301 return (hdw->i2c_pend_types & PVR2_I2C_PEND_ALL) != 0;
304 static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
306 char *buf,unsigned int maxlen)
308 unsigned int ccnt,bcnt;
310 const struct pvr2_i2c_op *opf;
313 if (detail & PVR2_I2C_DETAIL_DEBUG) {
314 bcnt = scnprintf(buf,maxlen,
315 "ctxt=%p ctl_mask=0x%lx",
317 ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
320 bcnt = scnprintf(buf,maxlen,
325 ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
326 if ((detail & PVR2_I2C_DETAIL_HANDLER) &&
327 cp->handler && cp->handler->func_table->describe) {
328 bcnt = scnprintf(buf,maxlen," (");
329 ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
330 bcnt = cp->handler->func_table->describe(
331 cp->handler->func_data,buf,maxlen);
332 ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
333 bcnt = scnprintf(buf,maxlen,")");
334 ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
336 if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) {
338 unsigned long msk,sm;
340 bcnt = scnprintf(buf,maxlen," [");
341 ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
344 for (idx = 0, msk = 1; msk; idx++, msk <<= 1) {
345 if (!(cp->ctl_mask & msk)) continue;
346 opf = pvr2_i2c_get_op(idx);
348 bcnt = scnprintf(buf,maxlen,"%s%s",
351 ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
358 bcnt = scnprintf(buf,maxlen,"%s%lx",
359 idx != 0 ? " " : "",sm);
360 ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
362 bcnt = scnprintf(buf,maxlen,"]");
363 ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
368 unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw,
369 char *buf,unsigned int maxlen)
371 unsigned int ccnt,bcnt;
372 struct pvr2_i2c_client *cp;
374 mutex_lock(&hdw->i2c_list_lock); do {
375 list_for_each_entry(cp, &hdw->i2c_clients, list) {
376 bcnt = pvr2_i2c_client_describe(
378 (PVR2_I2C_DETAIL_HANDLER|
379 PVR2_I2C_DETAIL_CTLMASK),
381 ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
382 bcnt = scnprintf(buf,maxlen,"\n");
383 ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
385 } while (0); mutex_unlock(&hdw->i2c_list_lock);
389 void pvr2_i2c_track_attach_inform(struct i2c_client *client)
391 struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
392 struct pvr2_i2c_client *cp;
393 int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL);
394 cp = kzalloc(sizeof(*cp),GFP_KERNEL);
395 trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]",
399 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
400 "Unable to allocate tracking memory for incoming"
401 " i2c module; ignoring module. This is likely"
402 " going to be a problem.");
406 INIT_LIST_HEAD(&cp->list);
408 mutex_lock(&hdw->i2c_list_lock); do {
409 hdw->cropcap_stale = !0;
410 list_add_tail(&cp->list,&hdw->i2c_clients);
411 hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT;
412 } while (0); mutex_unlock(&hdw->i2c_list_lock);
413 if (fl) queue_work(hdw->workqueue,&hdw->worki2csync);
416 static void pvr2_i2c_client_disconnect(struct pvr2_i2c_client *cp)
418 if (cp->handler && cp->handler->func_table->detach) {
419 cp->handler->func_table->detach(cp->handler->func_data);
425 void pvr2_i2c_track_detach_inform(struct i2c_client *client)
427 struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
428 struct pvr2_i2c_client *cp, *ncp;
429 unsigned long amask = 0;
431 mutex_lock(&hdw->i2c_list_lock);
432 hdw->cropcap_stale = !0;
433 list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
434 if (cp->client == client) {
435 trace_i2c("pvr2_i2c_detach"
436 " [client=%s @ 0x%x ctxt=%p]",
439 pvr2_i2c_client_disconnect(cp);
443 amask |= cp->ctl_mask;
445 hdw->i2c_active_mask = amask;
446 mutex_unlock(&hdw->i2c_list_lock);
448 trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=<unknown>]",
449 client->name, client->addr);
453 /* This function is used to remove an i2c client from our tracking
454 structure if the client happens to be the specified v4l2 sub-device.
455 The idea here is to ensure that sub-devices are not also tracked with
456 the old tracking mechanism - it's one or the other not both. This is
457 only for debugging. In a "real" environment, only one of these two
458 mechanisms should even be compiled in. But by enabling both we can
459 incrementally test control of each sub-device. */
460 void pvr2_i2c_untrack_subdev(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
462 struct i2c_client *client;
463 struct pvr2_i2c_client *cp, *ncp;
464 unsigned long amask = 0;
465 mutex_lock(&hdw->i2c_list_lock);
466 list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
468 if (i2c_get_clientdata(client) == sd) {
469 trace_i2c("pvr2_i2c_detach (subdev active)"
470 " [client=%s @ 0x%x ctxt=%p]",
471 client->name, client->addr, cp);
472 pvr2_i2c_client_disconnect(cp);
475 amask |= cp->ctl_mask;
477 hdw->i2c_active_mask = amask;
478 mutex_unlock(&hdw->i2c_list_lock);
481 void pvr2_i2c_track_init(struct pvr2_hdw *hdw)
483 hdw->i2c_pend_mask = 0;
484 hdw->i2c_stale_mask = 0;
485 hdw->i2c_active_mask = 0;
486 INIT_LIST_HEAD(&hdw->i2c_clients);
487 mutex_init(&hdw->i2c_list_lock);
490 void pvr2_i2c_track_done(struct pvr2_hdw *hdw)
497 Stuff for Emacs to see, in order to encourage consistent editing style:
498 *** Local Variables: ***
500 *** fill-column: 75 ***
502 *** c-basic-offset: 8 ***