aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx25840
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2009-12-24 11:06:08 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-02-26 13:10:41 -0500
commit3ccc646b56a3f03029a259c6a8affd9cecc6020e (patch)
tree28acf2a154c4792a1af091d778ab39385d56f9de /drivers/media/video/cx25840
parentb6e436b263b35476da4be06e0719cb1d5c8f8eed (diff)
V4L/DVB: cx25840, v4l2-subdev, ivtv, pvrusb2: Fix ivtv/cx25840 tinny audio
This change attempts to fix the ivtv tinny audio problem by keeping digitizer to encoder audio clocks running, while disabling the video clocks as needed to avoid unpredictable PCI bus hangs. To accomplish this, for the cx25840 module enabling of audio streaming had to be separated from enabling video streaming, requiring an additional v4l2_subdev_audio_op and calls to this new op in the pvrusb2 and ivtv drivers. The cx231xx and cx23885 driver use the cx25840 module for affecting only video on s_stream calls, so those drivers needed no change. The CX23418 hardware does not exhibit either the tinny audio problem nor the PCI bus hang, so the cx18 driver did not need corresponding changes. CX2341[56] based cards that are not using the CX2584x family of chips do not seem to be affected by the tinny audio problem, and this change should not affect how they are configured. It will delay their first capture by starting by another 300 msec though. Many thanks go to Argus <pthorn-ivtvd@styx2002.no-ip.org> and Martin Dauskardt <martin.dauskardt@gmx.de> whose persistent testing and investigation of this problem will hopefully fix this problem once and for all for many ivtv users. Reported-by: Martin Dauskardt <martin.dauskardt@gmx.de> Reported-by: Argus <pthorn-ivtvd@styx2002.no-ip.org> Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx25840')
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c48
1 files changed, 39 insertions, 9 deletions
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 385ecd58f1c..796f12d59da 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -1347,30 +1347,59 @@ static int cx25840_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *
1347} 1347}
1348#endif 1348#endif
1349 1349
1350static int cx25840_s_audio_stream(struct v4l2_subdev *sd, int enable)
1351{
1352 struct cx25840_state *state = to_state(sd);
1353 struct i2c_client *client = v4l2_get_subdevdata(sd);
1354 u8 v;
1355
1356 if (is_cx2583x(state) || is_cx2388x(state) || is_cx231xx(state))
1357 return 0;
1358
1359 v4l_dbg(1, cx25840_debug, client, "%s audio output\n",
1360 enable ? "enable" : "disable");
1361
1362 if (enable) {
1363 v = cx25840_read(client, 0x115) | 0x80;
1364 cx25840_write(client, 0x115, v);
1365 v = cx25840_read(client, 0x116) | 0x03;
1366 cx25840_write(client, 0x116, v);
1367 } else {
1368 v = cx25840_read(client, 0x115) & ~(0x80);
1369 cx25840_write(client, 0x115, v);
1370 v = cx25840_read(client, 0x116) & ~(0x03);
1371 cx25840_write(client, 0x116, v);
1372 }
1373 return 0;
1374}
1375
1350static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) 1376static int cx25840_s_stream(struct v4l2_subdev *sd, int enable)
1351{ 1377{
1352 struct cx25840_state *state = to_state(sd); 1378 struct cx25840_state *state = to_state(sd);
1353 struct i2c_client *client = v4l2_get_subdevdata(sd); 1379 struct i2c_client *client = v4l2_get_subdevdata(sd);
1380 u8 v;
1354 1381
1355 v4l_dbg(1, cx25840_debug, client, "%s output\n", 1382 v4l_dbg(1, cx25840_debug, client, "%s video output\n",
1356 enable ? "enable" : "disable"); 1383 enable ? "enable" : "disable");
1357 if (enable) { 1384 if (enable) {
1358 if (is_cx2388x(state) || is_cx231xx(state)) { 1385 if (is_cx2388x(state) || is_cx231xx(state)) {
1359 u8 v = (cx25840_read(client, 0x421) | 0x0b); 1386 v = cx25840_read(client, 0x421) | 0x0b;
1360 cx25840_write(client, 0x421, v); 1387 cx25840_write(client, 0x421, v);
1361 } else { 1388 } else {
1362 cx25840_write(client, 0x115, 1389 v = cx25840_read(client, 0x115) | 0x0c;
1363 is_cx2583x(state) ? 0x0c : 0x8c); 1390 cx25840_write(client, 0x115, v);
1364 cx25840_write(client, 0x116, 1391 v = cx25840_read(client, 0x116) | 0x04;
1365 is_cx2583x(state) ? 0x04 : 0x07); 1392 cx25840_write(client, 0x116, v);
1366 } 1393 }
1367 } else { 1394 } else {
1368 if (is_cx2388x(state) || is_cx231xx(state)) { 1395 if (is_cx2388x(state) || is_cx231xx(state)) {
1369 u8 v = cx25840_read(client, 0x421) & ~(0x0b); 1396 v = cx25840_read(client, 0x421) & ~(0x0b);
1370 cx25840_write(client, 0x421, v); 1397 cx25840_write(client, 0x421, v);
1371 } else { 1398 } else {
1372 cx25840_write(client, 0x115, 0x00); 1399 v = cx25840_read(client, 0x115) & ~(0x0c);
1373 cx25840_write(client, 0x116, 0x00); 1400 cx25840_write(client, 0x115, v);
1401 v = cx25840_read(client, 0x116) & ~(0x04);
1402 cx25840_write(client, 0x116, v);
1374 } 1403 }
1375 } 1404 }
1376 return 0; 1405 return 0;
@@ -1601,6 +1630,7 @@ static const struct v4l2_subdev_tuner_ops cx25840_tuner_ops = {
1601static const struct v4l2_subdev_audio_ops cx25840_audio_ops = { 1630static const struct v4l2_subdev_audio_ops cx25840_audio_ops = {
1602 .s_clock_freq = cx25840_s_clock_freq, 1631 .s_clock_freq = cx25840_s_clock_freq,
1603 .s_routing = cx25840_s_audio_routing, 1632 .s_routing = cx25840_s_audio_routing,
1633 .s_stream = cx25840_s_audio_stream,
1604}; 1634};
1605 1635
1606static const struct v4l2_subdev_video_ops cx25840_video_ops = { 1636static const struct v4l2_subdev_video_ops cx25840_video_ops = {