aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/pci
diff options
context:
space:
mode:
authorOlli Salonen <olli.salonen@iki.fi>2014-10-04 02:59:30 -0400
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2014-10-30 09:50:49 -0400
commit24e774092fa639823f677f9f69ca0d9f3deb62f6 (patch)
treedcffd8c67e93cd33a2d9a8af51534e71e8c426a6 /drivers/media/pci
parente450de45f4ab9325c8d5d68f3984d6c4d8961d1a (diff)
[media] cx23855: add CI support for DVBSky T980C
Add CI support for DVBSky T980C card. The new host device independent CIMaX SP2 I2C driver was used to implement it. IRQ handling is not implemented at this point. It could be used to detect the CAM insertion/removal instantly. Signed-off-by: Olli Salonen <olli.salonen@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers/media/pci')
-rw-r--r--drivers/media/pci/cx23885/cx23885-dvb.c106
1 files changed, 104 insertions, 2 deletions
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index 5ea1027878ba..757854914781 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -71,6 +71,7 @@
71#include "si2165.h" 71#include "si2165.h"
72#include "si2168.h" 72#include "si2168.h"
73#include "si2157.h" 73#include "si2157.h"
74#include "sp2.h"
74#include "m88ds3103.h" 75#include "m88ds3103.h"
75#include "m88ts2022.h" 76#include "m88ts2022.h"
76 77
@@ -616,6 +617,77 @@ static int dvbsky_t9580_set_voltage(struct dvb_frontend *fe,
616 return 0; 617 return 0;
617} 618}
618 619
620static int cx23885_sp2_ci_ctrl(void *priv, u8 read, int addr,
621 u8 data, int *mem)
622{
623 /* MC417 */
624 #define SP2_DATA 0x000000ff
625 #define SP2_WR 0x00008000
626 #define SP2_RD 0x00004000
627 #define SP2_ACK 0x00001000
628 #define SP2_ADHI 0x00000800
629 #define SP2_ADLO 0x00000400
630 #define SP2_CS1 0x00000200
631 #define SP2_CS0 0x00000100
632 #define SP2_EN_ALL 0x00001000
633 #define SP2_CTRL_OFF (SP2_CS1 | SP2_CS0 | SP2_WR | SP2_RD)
634
635 struct cx23885_tsport *port = priv;
636 struct cx23885_dev *dev = port->dev;
637 int ret;
638 int tmp;
639 unsigned long timeout;
640
641 mutex_lock(&dev->gpio_lock);
642
643 /* write addr */
644 cx_write(MC417_OEN, SP2_EN_ALL);
645 cx_write(MC417_RWD, SP2_CTRL_OFF |
646 SP2_ADLO | (0xff & addr));
647 cx_clear(MC417_RWD, SP2_ADLO);
648 cx_write(MC417_RWD, SP2_CTRL_OFF |
649 SP2_ADHI | (0xff & (addr >> 8)));
650 cx_clear(MC417_RWD, SP2_ADHI);
651
652 if (read)
653 /* data in */
654 cx_write(MC417_OEN, SP2_EN_ALL | SP2_DATA);
655 else
656 /* data out */
657 cx_write(MC417_RWD, SP2_CTRL_OFF | data);
658
659 /* chip select 0 */
660 cx_clear(MC417_RWD, SP2_CS0);
661
662 /* read/write */
663 cx_clear(MC417_RWD, (read) ? SP2_RD : SP2_WR);
664
665 /* wait for a maximum of 1 msec */
666 timeout = jiffies + msecs_to_jiffies(1);
667 while (!time_after(jiffies, timeout)) {
668 tmp = cx_read(MC417_RWD);
669 if ((tmp & SP2_ACK) == 0)
670 break;
671 usleep_range(50, 100);
672 }
673
674 cx_set(MC417_RWD, SP2_CTRL_OFF);
675 *mem = tmp & 0xff;
676
677 mutex_unlock(&dev->gpio_lock);
678
679 if (!read) {
680 if (*mem < 0) {
681 ret = -EREMOTEIO;
682 goto err;
683 }
684 }
685
686 return 0;
687err:
688 return ret;
689}
690
619static int cx23885_dvb_set_frontend(struct dvb_frontend *fe) 691static int cx23885_dvb_set_frontend(struct dvb_frontend *fe)
620{ 692{
621 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 693 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
@@ -944,11 +1016,11 @@ static int dvb_register(struct cx23885_tsport *port)
944 struct vb2_dvb_frontend *fe0, *fe1 = NULL; 1016 struct vb2_dvb_frontend *fe0, *fe1 = NULL;
945 struct si2168_config si2168_config; 1017 struct si2168_config si2168_config;
946 struct si2157_config si2157_config; 1018 struct si2157_config si2157_config;
1019 struct sp2_config sp2_config;
947 struct m88ts2022_config m88ts2022_config; 1020 struct m88ts2022_config m88ts2022_config;
948 struct i2c_board_info info; 1021 struct i2c_board_info info;
949 struct i2c_adapter *adapter; 1022 struct i2c_adapter *adapter;
950 struct i2c_client *client_demod; 1023 struct i2c_client *client_demod, *client_tuner, *client_ci;
951 struct i2c_client *client_tuner;
952 int mfe_shared = 0; /* bus not shared by default */ 1024 int mfe_shared = 0; /* bus not shared by default */
953 int ret; 1025 int ret;
954 1026
@@ -1682,6 +1754,7 @@ static int dvb_register(struct cx23885_tsport *port)
1682 break; 1754 break;
1683 case CX23885_BOARD_DVBSKY_T980C: 1755 case CX23885_BOARD_DVBSKY_T980C:
1684 i2c_bus = &dev->i2c_bus[1]; 1756 i2c_bus = &dev->i2c_bus[1];
1757 i2c_bus2 = &dev->i2c_bus[0];
1685 1758
1686 /* attach frontend */ 1759 /* attach frontend */
1687 memset(&si2168_config, 0, sizeof(si2168_config)); 1760 memset(&si2168_config, 0, sizeof(si2168_config));
@@ -1819,6 +1892,35 @@ static int dvb_register(struct cx23885_tsport *port)
1819 case CX23885_BOARD_DVBSKY_T980C: { 1892 case CX23885_BOARD_DVBSKY_T980C: {
1820 u8 eeprom[256]; /* 24C02 i2c eeprom */ 1893 u8 eeprom[256]; /* 24C02 i2c eeprom */
1821 1894
1895 /* attach CI */
1896 memset(&sp2_config, 0, sizeof(sp2_config));
1897 sp2_config.dvb_adap = &port->frontends.adapter;
1898 sp2_config.priv = port;
1899 sp2_config.ci_control = cx23885_sp2_ci_ctrl;
1900 memset(&info, 0, sizeof(struct i2c_board_info));
1901 strlcpy(info.type, "sp2", I2C_NAME_SIZE);
1902 info.addr = 0x40;
1903 info.platform_data = &sp2_config;
1904 request_module(info.type);
1905 client_ci = i2c_new_device(&i2c_bus2->i2c_adap, &info);
1906 if (client_ci == NULL ||
1907 client_ci->dev.driver == NULL) {
1908 module_put(client_tuner->dev.driver->owner);
1909 i2c_unregister_device(client_tuner);
1910 module_put(client_demod->dev.driver->owner);
1911 i2c_unregister_device(client_demod);
1912 goto frontend_detach;
1913 }
1914 if (!try_module_get(client_ci->dev.driver->owner)) {
1915 i2c_unregister_device(client_ci);
1916 module_put(client_tuner->dev.driver->owner);
1917 i2c_unregister_device(client_tuner);
1918 module_put(client_demod->dev.driver->owner);
1919 i2c_unregister_device(client_demod);
1920 goto frontend_detach;
1921 }
1922 port->i2c_client_ci = client_ci;
1923
1822 if (port->nr != 1) 1924 if (port->nr != 1)
1823 break; 1925 break;
1824 1926