aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalph Metzler <rjkm@metzlerbros.de>2017-06-25 17:37:08 -0400
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2017-06-26 07:17:49 -0400
commitdd3c5d0086e0285ba5f1fc4ce3abde0f5a4092bc (patch)
tree1782e80223629257b5e7baca94d96e636e467d15
parentf894165cb57922361a8cbe339e29b8c78ad4036a (diff)
media: staging: cxd2099: Fixed buffer mode
The buffer mode was already implemented in this driver, but it did not work as expected. This has been fixed now, but it is still deactivated and can be activated by removing a comment at the begin of the file. Original code change by Ralph Metzler, modified by Jasmin Jessich and Daniel Scheller to match Kernel code style. Signed-off-by: Ralph Metzler <rjkm@metzlerbros.de> Signed-off-by: Daniel Scheller <d.scheller@gmx.net> Signed-off-by: Jasmin Jessich <jasmin@anw.at> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-core.c1
-rw-r--r--drivers/staging/media/cxd2099/cxd2099.c162
-rw-r--r--drivers/staging/media/cxd2099/cxd2099.h6
3 files changed, 123 insertions, 46 deletions
diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
index 32f4d3746c8e..cd1723e79a07 100644
--- a/drivers/media/pci/ddbridge/ddbridge-core.c
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -1305,6 +1305,7 @@ static struct cxd2099_cfg cxd_cfg = {
1305 .adr = 0x40, 1305 .adr = 0x40,
1306 .polarity = 1, 1306 .polarity = 1,
1307 .clock_mode = 1, 1307 .clock_mode = 1,
1308 .max_i2c = 512,
1308}; 1309};
1309 1310
1310static int ddb_ci_attach(struct ddb_port *port) 1311static int ddb_ci_attach(struct ddb_port *port)
diff --git a/drivers/staging/media/cxd2099/cxd2099.c b/drivers/staging/media/cxd2099/cxd2099.c
index 370ecb959543..60d8dd03e7ff 100644
--- a/drivers/staging/media/cxd2099/cxd2099.c
+++ b/drivers/staging/media/cxd2099/cxd2099.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * cxd2099.c: Driver for the CXD2099AR Common Interface Controller 2 * cxd2099.c: Driver for the CXD2099AR Common Interface Controller
3 * 3 *
4 * Copyright (C) 2010-2011 Digital Devices GmbH 4 * Copyright (C) 2010-2013 Digital Devices GmbH
5 * 5 *
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
@@ -33,7 +33,9 @@
33 33
34#include "cxd2099.h" 34#include "cxd2099.h"
35 35
36#define MAX_BUFFER_SIZE 248 36/* #define BUFFER_MODE 1 */
37
38static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount);
37 39
38struct cxd { 40struct cxd {
39 struct dvb_ca_en50221 en; 41 struct dvb_ca_en50221 en;
@@ -48,6 +50,7 @@ struct cxd {
48 int mode; 50 int mode;
49 int ready; 51 int ready;
50 int dr; 52 int dr;
53 int write_busy;
51 int slot_stat; 54 int slot_stat;
52 55
53 u8 amem[1024]; 56 u8 amem[1024];
@@ -55,6 +58,9 @@ struct cxd {
55 58
56 int cammode; 59 int cammode;
57 struct mutex lock; 60 struct mutex lock;
61
62 u8 rbuf[1028];
63 u8 wbuf[1028];
58}; 64};
59 65
60static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr, 66static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr,
@@ -73,7 +79,7 @@ static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr,
73} 79}
74 80
75static int i2c_write(struct i2c_adapter *adapter, u8 adr, 81static int i2c_write(struct i2c_adapter *adapter, u8 adr,
76 u8 *data, u8 len) 82 u8 *data, u16 len)
77{ 83{
78 struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len}; 84 struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len};
79 85
@@ -100,12 +106,12 @@ static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr,
100} 106}
101 107
102static int i2c_read(struct i2c_adapter *adapter, u8 adr, 108static int i2c_read(struct i2c_adapter *adapter, u8 adr,
103 u8 reg, u8 *data, u8 n) 109 u8 reg, u8 *data, u16 n)
104{ 110{
105 struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, 111 struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
106 .buf = &reg, .len = 1}, 112 .buf = &reg, .len = 1},
107 {.addr = adr, .flags = I2C_M_RD, 113 {.addr = adr, .flags = I2C_M_RD,
108 .buf = data, .len = n} }; 114 .buf = data, .len = n} };
109 115
110 if (i2c_transfer(adapter, msgs, 2) != 2) { 116 if (i2c_transfer(adapter, msgs, 2) != 2) {
111 dev_err(&adapter->dev, "error in i2c_read\n"); 117 dev_err(&adapter->dev, "error in i2c_read\n");
@@ -114,14 +120,26 @@ static int i2c_read(struct i2c_adapter *adapter, u8 adr,
114 return 0; 120 return 0;
115} 121}
116 122
117static int read_block(struct cxd *ci, u8 adr, u8 *data, u8 n) 123static int read_block(struct cxd *ci, u8 adr, u8 *data, u16 n)
118{ 124{
119 int status; 125 int status = 0;
120 126
121 status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr); 127 if (ci->lastaddress != adr)
128 status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr);
122 if (!status) { 129 if (!status) {
123 ci->lastaddress = adr; 130 ci->lastaddress = adr;
124 status = i2c_read(ci->i2c, ci->cfg.adr, 1, data, n); 131
132 while (n) {
133 int len = n;
134
135 if (ci->cfg.max_i2c && (len > ci->cfg.max_i2c))
136 len = ci->cfg.max_i2c;
137 status = i2c_read(ci->i2c, ci->cfg.adr, 1, data, len);
138 if (status)
139 return status;
140 data += len;
141 n -= len;
142 }
125 } 143 }
126 return status; 144 return status;
127} 145}
@@ -182,16 +200,16 @@ static int write_io(struct cxd *ci, u16 address, u8 val)
182 200
183static int write_regm(struct cxd *ci, u8 reg, u8 val, u8 mask) 201static int write_regm(struct cxd *ci, u8 reg, u8 val, u8 mask)
184{ 202{
185 int status; 203 int status = 0;
186 204
187 status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, reg); 205 if (ci->lastaddress != reg)
206 status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, reg);
188 if (!status && reg >= 6 && reg <= 8 && mask != 0xff) 207 if (!status && reg >= 6 && reg <= 8 && mask != 0xff)
189 status = i2c_read_reg(ci->i2c, ci->cfg.adr, 1, &ci->regs[reg]); 208 status = i2c_read_reg(ci->i2c, ci->cfg.adr, 1, &ci->regs[reg]);
209 ci->lastaddress = reg;
190 ci->regs[reg] = (ci->regs[reg] & (~mask)) | val; 210 ci->regs[reg] = (ci->regs[reg] & (~mask)) | val;
191 if (!status) { 211 if (!status)
192 ci->lastaddress = reg;
193 status = i2c_write_reg(ci->i2c, ci->cfg.adr, 1, ci->regs[reg]); 212 status = i2c_write_reg(ci->i2c, ci->cfg.adr, 1, ci->regs[reg]);
194 }
195 if (reg == 0x20) 213 if (reg == 0x20)
196 ci->regs[reg] &= 0x7f; 214 ci->regs[reg] &= 0x7f;
197 return status; 215 return status;
@@ -203,16 +221,31 @@ static int write_reg(struct cxd *ci, u8 reg, u8 val)
203} 221}
204 222
205#ifdef BUFFER_MODE 223#ifdef BUFFER_MODE
206static int write_block(struct cxd *ci, u8 adr, u8 *data, int n) 224static int write_block(struct cxd *ci, u8 adr, u8 *data, u16 n)
207{ 225{
208 int status; 226 int status = 0;
209 u8 buf[256] = {1}; 227 u8 *buf = ci->wbuf;
210 228
211 status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr); 229 if (ci->lastaddress != adr)
212 if (!status) { 230 status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr);
213 ci->lastaddress = adr; 231 if (status)
214 memcpy(buf + 1, data, n); 232 return status;
215 status = i2c_write(ci->i2c, ci->cfg.adr, buf, n + 1); 233 dev_info(&ci->i2c->dev, "write_block %d\n", n);
234
235 ci->lastaddress = adr;
236 buf[0] = 1;
237 while (n) {
238 int len = n;
239
240 if (ci->cfg.max_i2c && (len + 1 > ci->cfg.max_i2c))
241 len = ci->cfg.max_i2c - 1;
242 dev_info(&ci->i2c->dev, "write %d\n", len);
243 memcpy(buf + 1, data, len);
244 status = i2c_write(ci->i2c, ci->cfg.adr, buf, len + 1);
245 if (status)
246 return status;
247 n -= len;
248 data += len;
216 } 249 }
217 return status; 250 return status;
218} 251}
@@ -238,6 +271,8 @@ static void set_mode(struct cxd *ci, int mode)
238 271
239static void cam_mode(struct cxd *ci, int mode) 272static void cam_mode(struct cxd *ci, int mode)
240{ 273{
274 u8 dummy;
275
241 if (mode == ci->cammode) 276 if (mode == ci->cammode)
242 return; 277 return;
243 278
@@ -246,16 +281,15 @@ static void cam_mode(struct cxd *ci, int mode)
246 write_regm(ci, 0x20, 0x80, 0x80); 281 write_regm(ci, 0x20, 0x80, 0x80);
247 break; 282 break;
248 case 0x01: 283 case 0x01:
249#ifdef BUFFER_MODE
250 if (!ci->en.read_data) 284 if (!ci->en.read_data)
251 return; 285 return;
286 ci->write_busy = 0;
252 dev_info(&ci->i2c->dev, "enable cam buffer mode\n"); 287 dev_info(&ci->i2c->dev, "enable cam buffer mode\n");
253 /* write_reg(ci, 0x0d, 0x00); */ 288 write_reg(ci, 0x0d, 0x00);
254 /* write_reg(ci, 0x0e, 0x01); */ 289 write_reg(ci, 0x0e, 0x01);
255 write_regm(ci, 0x08, 0x40, 0x40); 290 write_regm(ci, 0x08, 0x40, 0x40);
256 /* read_reg(ci, 0x12, &dummy); */ 291 read_reg(ci, 0x12, &dummy);
257 write_regm(ci, 0x08, 0x80, 0x80); 292 write_regm(ci, 0x08, 0x80, 0x80);
258#endif
259 break; 293 break;
260 default: 294 default:
261 break; 295 break;
@@ -325,7 +359,10 @@ static int init(struct cxd *ci)
325 if (status < 0) 359 if (status < 0)
326 break; 360 break;
327 361
328 if (ci->cfg.clock_mode) { 362 if (ci->cfg.clock_mode == 2) {
363 /* bitrate*2^13/ 72000 */
364 u32 reg = ((ci->cfg.bitrate << 13) + 71999) / 72000;
365
329 if (ci->cfg.polarity) { 366 if (ci->cfg.polarity) {
330 status = write_reg(ci, 0x09, 0x6f); 367 status = write_reg(ci, 0x09, 0x6f);
331 if (status < 0) 368 if (status < 0)
@@ -335,6 +372,25 @@ static int init(struct cxd *ci)
335 if (status < 0) 372 if (status < 0)
336 break; 373 break;
337 } 374 }
375 status = write_reg(ci, 0x20, 0x08);
376 if (status < 0)
377 break;
378 status = write_reg(ci, 0x21, (reg >> 8) & 0xff);
379 if (status < 0)
380 break;
381 status = write_reg(ci, 0x22, reg & 0xff);
382 if (status < 0)
383 break;
384 } else if (ci->cfg.clock_mode == 1) {
385 if (ci->cfg.polarity) {
386 status = write_reg(ci, 0x09, 0x6f); /* D */
387 if (status < 0)
388 break;
389 } else {
390 status = write_reg(ci, 0x09, 0x6d);
391 if (status < 0)
392 break;
393 }
338 status = write_reg(ci, 0x20, 0x68); 394 status = write_reg(ci, 0x20, 0x68);
339 if (status < 0) 395 if (status < 0)
340 break; 396 break;
@@ -346,7 +402,7 @@ static int init(struct cxd *ci)
346 break; 402 break;
347 } else { 403 } else {
348 if (ci->cfg.polarity) { 404 if (ci->cfg.polarity) {
349 status = write_reg(ci, 0x09, 0x4f); 405 status = write_reg(ci, 0x09, 0x4f); /* C */
350 if (status < 0) 406 if (status < 0)
351 break; 407 break;
352 } else { 408 } else {
@@ -354,7 +410,6 @@ static int init(struct cxd *ci)
354 if (status < 0) 410 if (status < 0)
355 break; 411 break;
356 } 412 }
357
358 status = write_reg(ci, 0x20, 0x28); 413 status = write_reg(ci, 0x20, 0x28);
359 if (status < 0) 414 if (status < 0)
360 break; 415 break;
@@ -401,7 +456,6 @@ static int read_attribute_mem(struct dvb_ca_en50221 *ca,
401 set_mode(ci, 1); 456 set_mode(ci, 1);
402 read_pccard(ci, address, &val, 1); 457 read_pccard(ci, address, &val, 1);
403 mutex_unlock(&ci->lock); 458 mutex_unlock(&ci->lock);
404 /* printk(KERN_INFO "%02x:%02x\n", address,val); */
405 return val; 459 return val;
406} 460}
407 461
@@ -446,6 +500,9 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
446{ 500{
447 struct cxd *ci = ca->data; 501 struct cxd *ci = ca->data;
448 502
503 if (ci->cammode)
504 read_data(ca, slot, ci->rbuf, 0);
505
449 mutex_lock(&ci->lock); 506 mutex_lock(&ci->lock);
450 cam_mode(ci, 0); 507 cam_mode(ci, 0);
451 write_reg(ci, 0x00, 0x21); 508 write_reg(ci, 0x00, 0x21);
@@ -465,7 +522,6 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
465 } 522 }
466 } 523 }
467 mutex_unlock(&ci->lock); 524 mutex_unlock(&ci->lock);
468 /* msleep(500); */
469 return 0; 525 return 0;
470} 526}
471 527
@@ -474,11 +530,19 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
474 struct cxd *ci = ca->data; 530 struct cxd *ci = ca->data;
475 531
476 dev_info(&ci->i2c->dev, "%s\n", __func__); 532 dev_info(&ci->i2c->dev, "%s\n", __func__);
533 if (ci->cammode)
534 read_data(ca, slot, ci->rbuf, 0);
477 mutex_lock(&ci->lock); 535 mutex_lock(&ci->lock);
536 write_reg(ci, 0x00, 0x21);
537 write_reg(ci, 0x06, 0x1F);
538 msleep(300);
539
478 write_regm(ci, 0x09, 0x08, 0x08); 540 write_regm(ci, 0x09, 0x08, 0x08);
479 write_regm(ci, 0x20, 0x80, 0x80); /* Reset CAM Mode */ 541 write_regm(ci, 0x20, 0x80, 0x80); /* Reset CAM Mode */
480 write_regm(ci, 0x06, 0x07, 0x07); /* Clear IO Mode */ 542 write_regm(ci, 0x06, 0x07, 0x07); /* Clear IO Mode */
543
481 ci->mode = -1; 544 ci->mode = -1;
545 ci->write_busy = 0;
482 mutex_unlock(&ci->lock); 546 mutex_unlock(&ci->lock);
483 return 0; 547 return 0;
484} 548}
@@ -490,9 +554,7 @@ static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
490 mutex_lock(&ci->lock); 554 mutex_lock(&ci->lock);
491 write_regm(ci, 0x09, 0x00, 0x08); 555 write_regm(ci, 0x09, 0x00, 0x08);
492 set_mode(ci, 0); 556 set_mode(ci, 0);
493#ifdef BUFFER_MODE
494 cam_mode(ci, 1); 557 cam_mode(ci, 1);
495#endif
496 mutex_unlock(&ci->lock); 558 mutex_unlock(&ci->lock);
497 return 0; 559 return 0;
498} 560}
@@ -510,8 +572,10 @@ static int campoll(struct cxd *ci)
510 ci->dr = 1; 572 ci->dr = 1;
511 dev_info(&ci->i2c->dev, "DR\n"); 573 dev_info(&ci->i2c->dev, "DR\n");
512 } 574 }
513 if (istat & 0x20) 575 if (istat & 0x20) {
576 ci->write_busy = 0;
514 dev_info(&ci->i2c->dev, "WC\n"); 577 dev_info(&ci->i2c->dev, "WC\n");
578 }
515 579
516 if (istat & 2) { 580 if (istat & 2) {
517 u8 slotstat; 581 u8 slotstat;
@@ -519,7 +583,8 @@ static int campoll(struct cxd *ci)
519 read_reg(ci, 0x01, &slotstat); 583 read_reg(ci, 0x01, &slotstat);
520 if (!(2 & slotstat)) { 584 if (!(2 & slotstat)) {
521 if (!ci->slot_stat) { 585 if (!ci->slot_stat) {
522 ci->slot_stat = DVB_CA_EN50221_POLL_CAM_PRESENT; 586 ci->slot_stat |=
587 DVB_CA_EN50221_POLL_CAM_PRESENT;
523 write_regm(ci, 0x03, 0x08, 0x08); 588 write_regm(ci, 0x03, 0x08, 0x08);
524 } 589 }
525 590
@@ -531,8 +596,8 @@ static int campoll(struct cxd *ci)
531 ci->ready = 0; 596 ci->ready = 0;
532 } 597 }
533 } 598 }
534 if (istat & 8 && 599 if ((istat & 8) &&
535 ci->slot_stat == DVB_CA_EN50221_POLL_CAM_PRESENT) { 600 (ci->slot_stat == DVB_CA_EN50221_POLL_CAM_PRESENT)) {
536 ci->ready = 1; 601 ci->ready = 1;
537 ci->slot_stat |= DVB_CA_EN50221_POLL_CAM_READY; 602 ci->slot_stat |= DVB_CA_EN50221_POLL_CAM_READY;
538 } 603 }
@@ -553,7 +618,6 @@ static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
553 return ci->slot_stat; 618 return ci->slot_stat;
554} 619}
555 620
556#ifdef BUFFER_MODE
557static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount) 621static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
558{ 622{
559 struct cxd *ci = ca->data; 623 struct cxd *ci = ca->data;
@@ -571,23 +635,33 @@ static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
571 mutex_lock(&ci->lock); 635 mutex_lock(&ci->lock);
572 read_reg(ci, 0x0f, &msb); 636 read_reg(ci, 0x0f, &msb);
573 read_reg(ci, 0x10, &lsb); 637 read_reg(ci, 0x10, &lsb);
574 len = (msb << 8) | lsb; 638 len = ((u16)msb << 8) | lsb;
639 if (len > ecount || len < 2) {
640 /* read it anyway or cxd may hang */
641 read_block(ci, 0x12, ci->rbuf, len);
642 mutex_unlock(&ci->lock);
643 return -EIO;
644 }
575 read_block(ci, 0x12, ebuf, len); 645 read_block(ci, 0x12, ebuf, len);
576 ci->dr = 0; 646 ci->dr = 0;
577 mutex_unlock(&ci->lock); 647 mutex_unlock(&ci->lock);
578
579 return len; 648 return len;
580} 649}
581 650
651#ifdef BUFFER_MODE
652
582static int write_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount) 653static int write_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
583{ 654{
584 struct cxd *ci = ca->data; 655 struct cxd *ci = ca->data;
585 656
657 if (ci->write_busy)
658 return -EAGAIN;
586 mutex_lock(&ci->lock); 659 mutex_lock(&ci->lock);
587 dev_info(&ci->i2c->dev, "%s %d\n", __func__, ecount); 660 dev_info(&ci->i2c->dev, "%s %d\n", __func__, ecount);
588 write_reg(ci, 0x0d, ecount >> 8); 661 write_reg(ci, 0x0d, ecount >> 8);
589 write_reg(ci, 0x0e, ecount & 0xff); 662 write_reg(ci, 0x0e, ecount & 0xff);
590 write_block(ci, 0x11, ebuf, ecount); 663 write_block(ci, 0x11, ebuf, ecount);
664 ci->write_busy = 1;
591 mutex_unlock(&ci->lock); 665 mutex_unlock(&ci->lock);
592 return ecount; 666 return ecount;
593} 667}
diff --git a/drivers/staging/media/cxd2099/cxd2099.h b/drivers/staging/media/cxd2099/cxd2099.h
index 0eb607c5b423..f4b29b1d6eb8 100644
--- a/drivers/staging/media/cxd2099/cxd2099.h
+++ b/drivers/staging/media/cxd2099/cxd2099.h
@@ -30,8 +30,10 @@
30struct cxd2099_cfg { 30struct cxd2099_cfg {
31 u32 bitrate; 31 u32 bitrate;
32 u8 adr; 32 u8 adr;
33 u8 polarity:1; 33 u8 polarity;
34 u8 clock_mode:1; 34 u8 clock_mode;
35
36 u32 max_i2c;
35}; 37};
36 38
37#if defined(CONFIG_DVB_CXD2099) || \ 39#if defined(CONFIG_DVB_CXD2099) || \