cxd2099: convert to regmap API and move out of staging
Subsystems (4)
cover cxd2099: convert to regmap API and move out of staging
From: Daniel Scheller <[email protected]>
Patch series done by Jasmin and me.
This patch series, besides one little cosmetic fix in ddbridge, converts the cxd2099 CI controller driver to the regmap API and thus makes it a proper I2C client driver. This not only moves it away from the legacy/ "proprietary" DVB attach way of using I2C drivers, but also adds a cleanup function through the I2C remove callback (such functionality is seemingly currently missing from the DVB EN50221 API). Both ddbridge and ngene (as users of the driver) are updated separately. No regressions were spotted when used in conjuntion with VDR's and TVHeadend's CI support.
In addition, this series moves the cxd2099 driver out of staging right into dvb-frontends/ as it serves as a DVB (EN50221) frontend driver. What's written in the TODO file in the staging dir simply doesn't apply to the driver (see the commit message of that specific patch for details) and it got quite polished up lately, so it's just inappropriate to keep it in staging.
Lastly, Jasmin opted to take over maintainership of the driver, so the last patch adds her into the MAINTAINERS file for the cxd2099 driver.
Please pick this series up in this (upcoming) merge window so it'll be part of the 4.17 kernel release.
Daniel Scheller (6):
[media] ddbridge/ci: further deduplicate code/logic in ddb_ci_attach() [media] staging/cxd2099: convert to regmap API
[media] ddbridge: adapt cxd2099 attach to new i2c_client way [media] ngene: adapt cxd2099 attach to the new i2c_client way [media] staging/cxd2099: remove remainders from old attach way [media] cxd2099: move driver out of staging into dvb-frontends
Jasmin Jessich (1):
[media] MAINTAINERS: add entry for cxd2099
MAINTAINERS | 8 +
drivers/media/dvb-frontends/Kconfig | 12 ++
drivers/media/dvb-frontends/Makefile | 1 +
.../cxd2099 => media/dvb-frontends}/cxd2099.c | 209 ++++++++++-----------
.../cxd2099 => media/dvb-frontends}/cxd2099.h | 19 +-
drivers/media/pci/ddbridge/Kconfig | 1 +
drivers/media/pci/ddbridge/Makefile | 3 -
drivers/media/pci/ddbridge/ddbridge-ci.c | 72 +++++--
drivers/media/pci/ddbridge/ddbridge.h | 1 +
drivers/media/pci/ngene/Kconfig | 1 +
drivers/media/pci/ngene/Makefile | 3 -
drivers/media/pci/ngene/ngene-core.c | 41 +++-
drivers/media/pci/ngene/ngene.h | 1 +
drivers/staging/media/Kconfig | 2 -
drivers/staging/media/Makefile | 1 -
drivers/staging/media/cxd2099/Kconfig | 12 --
drivers/staging/media/cxd2099/Makefile | 4 -
drivers/staging/media/cxd2099/TODO | 12 --
18 files changed, 229 insertions(+), 174 deletions(-)
rename drivers/{staging/media/cxd2099 => media/dvb-frontends}/cxd2099.c (78%)
rename drivers/{staging/media/cxd2099 => media/dvb-frontends}/cxd2099.h (62%)
delete mode 100644 drivers/staging/media/cxd2099/Kconfig
delete mode 100644 drivers/staging/media/cxd2099/Makefile
delete mode 100644 drivers/staging/media/cxd2099/TODOSignature · 1 line
2.13.6
PATCH 1/7 ddbridge/ci: further deduplicate code/logic in ddb_ci_attach()
From: Daniel Scheller <[email protected]>
Deduplicate the checks for a valid ptr in port->en, and also handle the default case to also catch eventually yet unsupported CI hardware.
--- drivers/media/pci/ddbridge/ddbridge-ci.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-)
drivers/media/pci/ddbridge/ddbridge-ci.c +4 -8
@@ -325,24 +325,20 @@ int ddb_ci_attach(struct ddb_port *port, u32 bitrate)case DDB_CI_EXTERNAL_SONY : cxd_cfg.bitrate = bitrate; port->en =cxd2099_attach (&cxd_cfg, port, &port->i2c->adap); -if (!port->en) -return -ENODEV ;break ; -case DDB_CI_EXTERNAL_XO2 :case DDB_CI_EXTERNAL_XO2_B :ci_xo2_attach (port); -if (!port->en) -return -ENODEV ;break ; -case DDB_CI_INTERNAL :ci_attach (port); -if (!port->en) -return -ENODEV ;break ; +default : +return -ENODEV ; } +if (!port->en) +return -ENODEV ;dvb_ca_en50221_init (port->dvb[0 ].adap, port->en,0 ,1 );return 0 ; }
Signature · 1 line
2.13.6
PATCH 2/7 staging/cxd2099: convert to regmap API
In reply to Daniel SchellerFrom: Daniel Scheller <[email protected]>
Convert the cxd2099 driver to use regmap for I2C accesses, removing all own i2c_*() functions. With that, make the driver a proper I2C client driver. This also adds the benefit of having a proper cleanup function (cxd2099_remove() in this case) that takes care of resource cleanup upon I2C client deregistration.
At this point, keep the static inline declared cxd2099_attach() function so that drivers using the legacy/proprietary style attach way still compile, albeit lacking the cxd2099 driver functionality. This is taken care of in the next two patches.
--- drivers/staging/media/cxd2099/cxd2099.c | 209 ++++++++++++++++---------------- drivers/staging/media/cxd2099/cxd2099.h | 11 +- 2 files changed, 108 insertions(+), 112 deletions(-)
drivers/staging/media/cxd2099/cxd2099.c +104 -105
@@ -17,6 +17,7 @@#include <linux/kernel.h> #include <linux/module.h> #include <linux/i2c.h> +#include <linux/regmap.h> #include <linux/wait.h> #include <linux/delay.h> #include <linux/mutex.h>
@@ -33,8 +34,9 @@ static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount);struct cxd {struct dvb_ca_en50221 en; -struct i2c_adapter *i2c;struct cxd2099_cfg cfg; +struct i2c_client *client; +struct regmap *regmap;u8 regs[0x23 ];u8 lastaddress;
@@ -56,69 +58,12 @@ struct cxd {u8 wbuf[1028 ]; }; -static int i2c_write_reg (struct i2c_adapter *adapter,u8 adr, -u8 reg,u8 data) -{ -u8 m[2 ] = {reg, data}; -struct i2c_msg msg = {.addr = adr, .flags =0 , .buf = m, .len =2 }; - -if (i2c_transfer (adapter, &msg,1 ) !=1 ) { -dev_err (&adapter->dev, -"Failed to write to I2C register %02x@%02x!\n" , - reg, adr); -return -1 ; - } -return 0 ; -} - -static int i2c_write (struct i2c_adapter *adapter,u8 adr, -u8 *data,u16 len) -{ -struct i2c_msg msg = {.addr = adr, .flags =0 , .buf = data, .len = len}; - -if (i2c_transfer (adapter, &msg,1 ) !=1 ) { -dev_err (&adapter->dev,"Failed to write to I2C!\n" ); -return -1 ; - } -return 0 ; -} - -static int i2c_read_reg (struct i2c_adapter *adapter,u8 adr, -u8 reg,u8 *val) -{ -struct i2c_msg msgs[2 ] = {{.addr = adr, .flags =0 , - .buf = ®, .len =1 }, - {.addr = adr, .flags =I2C_M_RD , - .buf = val, .len =1 } }; - -if (i2c_transfer (adapter, msgs,2 ) !=2 ) { -dev_err (&adapter->dev,"error in %s()\n" , __func__); -return -1 ; - } -return 0 ; -} - -static int i2c_read (struct i2c_adapter *adapter,u8 adr, -u8 reg,u8 *data,u16 n) -{ -struct i2c_msg msgs[2 ] = {{.addr = adr, .flags =0 , - .buf = ®, .len =1 }, - {.addr = adr, .flags =I2C_M_RD , - .buf = data, .len = n} }; - -if (i2c_transfer (adapter, msgs,2 ) !=2 ) { -dev_err (&adapter->dev,"error in %s()\n" , __func__); -return -1 ; - } -return 0 ; -} -static int read_block (struct cxd *ci,u8 adr,u8 *data,u16 n) {int status =0 ;if (ci->lastaddress != adr) - status =i2c_write_reg (ci->i2c, ci->cfg.adr,0 , adr); + status =regmap_write (ci->regmap,0 , adr);if (!status) { ci->lastaddress = adr;
@@ -127,7 +72,7 @@ static int read_block(struct cxd *ci, u8 adr, u8 *data, u16 n)if (ci->cfg.max_i2c && len > ci->cfg.max_i2c) len = ci->cfg.max_i2c; - status =i2c_read (ci->i2c, ci->cfg.adr,1 , data, len); + status =regmap_raw_read (ci->regmap,1 , data, len);if (status)return status; data += len;
@@ -145,64 +90,66 @@ static int read_reg(struct cxd *ci, u8 reg, u8 *val)static int read_pccard (struct cxd *ci,u16 address,u8 *data,u8 n) {int status; -u8 addr[3 ] = {2 , address &0xff , address >>8 }; +u8 addr[2 ] = {address &0xff , address >>8 }; - status =i2c_write (ci->i2c, ci->cfg.adr, addr,3 ); + status =regmap_raw_write (ci->regmap,2 , addr,2 );if (!status) - status =i2c_read (ci->i2c, ci->cfg.adr,3 , data, n); + status =regmap_raw_read (ci->regmap,3 , data, n);return status; }static int write_pccard (struct cxd *ci,u16 address,u8 *data,u8 n) {int status; -u8 addr[3 ] = {2 , address &0xff , address >>8 }; +u8 addr[2 ] = {address &0xff , address >>8 }; - status =i2c_write (ci->i2c, ci->cfg.adr, addr,3 ); + status =regmap_raw_write (ci->regmap,2 , addr,2 );if (!status) { -u8 buf[256 ] = {3 }; +u8 buf[256 ]; -memcpy (buf +1 , data, n); - status =i2c_write (ci->i2c, ci->cfg.adr, buf, n +1 ); +memcpy (buf, data, n); + status =regmap_raw_write (ci->regmap,3 , buf, n); }return status; } -static int read_io (struct cxd *ci,u16 address,u8 *val) +static int read_io (struct cxd *ci,u16 address,unsigned int *val) {int status; -u8 addr[3 ] = {2 , address &0xff , address >>8 }; +u8 addr[2 ] = {address &0xff , address >>8 }; - status =i2c_write (ci->i2c, ci->cfg.adr, addr,3 ); + status =regmap_raw_write (ci->regmap,2 , addr,2 );if (!status) - status =i2c_read (ci->i2c, ci->cfg.adr,3 , val,1 ); + status =regmap_read (ci->regmap,3 , val);return status; }static int write_io (struct cxd *ci,u16 address,u8 val) {int status; -u8 addr[3 ] = {2 , address &0xff , address >>8 }; -u8 buf[2 ] = {3 , val}; +u8 addr[2 ] = {address &0xff , address >>8 }; - status =i2c_write (ci->i2c, ci->cfg.adr, addr,3 ); + status =regmap_raw_write (ci->regmap,2 , addr,2 );if (!status) - status =i2c_write (ci->i2c, ci->cfg.adr, buf,2 ); + status =regmap_write (ci->regmap,3 , val);return status; }static int write_regm (struct cxd *ci,u8 reg,u8 val,u8 mask) {int status =0 ; +unsigned int regval;if (ci->lastaddress != reg) - status =i2c_write_reg (ci->i2c, ci->cfg.adr,0 , reg); -if (!status && reg >=6 && reg <=8 && mask !=0xff ) - status =i2c_read_reg (ci->i2c, ci->cfg.adr,1 , &ci->regs[reg]); + status =regmap_write (ci->regmap,0 , reg); +if (!status && reg >=6 && reg <=8 && mask !=0xff ) { + status =regmap_read (ci->regmap,1 , ®val); + ci->regs[reg] = regval; + } ci->lastaddress = reg; ci->regs[reg] = (ci->regs[reg] & (~mask)) | val;if (!status) - status =i2c_write_reg (ci->i2c, ci->cfg.adr,1 , ci->regs[reg]); + status =regmap_write (ci->regmap,1 , ci->regs[reg]);if (reg ==0x20 ) ci->regs[reg] &=0x7f ;return status;
@@ -219,19 +166,18 @@ static int write_block(struct cxd *ci, u8 adr, u8 *data, u16 n)u8 *buf = ci->wbuf;if (ci->lastaddress != adr) - status =i2c_write_reg (ci->i2c, ci->cfg.adr,0 , adr); + status =regmap_write (ci->regmap,0 , adr);if (status)return status; ci->lastaddress = adr; - buf[0 ] =1 ;while (n) {int len = n;if (ci->cfg.max_i2c && (len +1 > ci->cfg.max_i2c)) len = ci->cfg.max_i2c -1 ; -memcpy (buf +1 , data, len); - status =i2c_write (ci->i2c, ci->cfg.adr, buf, len +1 ); +memcpy (buf, data, len); + status =regmap_raw_write (ci->regmap,1 , buf, len);if (status)return status; n -= len;
@@ -273,7 +219,7 @@ static void cam_mode(struct cxd *ci, int mode)if (!ci->en.read_data)return ; ci->write_busy =0 ; -dev_info (&ci->i2c->dev,"enable cam buffer mode\n" ); +dev_info (&ci->client->dev,"enable cam buffer mode\n" );write_reg (ci,0x0d ,0x00 );write_reg (ci,0x0e ,0x01 );write_regm (ci,0x08 ,0x40 ,0x40 );
@@ -464,7 +410,7 @@ static int read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address) {struct cxd *ci = ca->data; -u8 val; +unsigned int val;mutex_lock (&ci->lock);set_mode (ci,0 );
@@ -518,7 +464,7 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) {struct cxd *ci = ca->data; -dev_dbg (&ci->i2c->dev,"%s\n" , __func__); +dev_dbg (&ci->client->dev,"%s\n" , __func__);if (ci->cammode)read_data (ca, slot, ci->rbuf,0 );mutex_lock (&ci->lock);
@@ -577,7 +523,7 @@ static int campoll(struct cxd *ci)if (ci->slot_stat) { ci->slot_stat =0 ;write_regm (ci,0x03 ,0x00 ,0x08 ); -dev_info (&ci->i2c->dev,"NO CAM\n" ); +dev_info (&ci->client->dev,"NO CAM\n" ); ci->ready =0 ; } }
@@ -660,26 +606,41 @@ static struct dvb_ca_en50221 en_templ = { .write_data = write_data, }; -struct dvb_ca_en50221 *cxd2099_attach (struct cxd2099_cfg *cfg, -void *priv, -struct i2c_adapter *i2c) +static int cxd2099_probe (struct i2c_client *client, +const struct i2c_device_id *id) {struct cxd *ci; -u8 val; +struct cxd2099_cfg *cfg = client->dev.platform_data; +static const struct regmap_config rm_cfg = { + .reg_bits =8 , + .val_bits =8 , + }; +unsigned int val; +int ret; -if (i2c_read_reg (i2c, cfg->adr,0 , &val) <0 ) { -dev_info (&i2c->dev,"No CXD2099AR detected at 0x%02x\n" , - cfg->adr); -return NULL ; + ci =kzalloc (sizeof (*ci),GFP_KERNEL ); +if (!ci) { + ret = -ENOMEM ; + goto err; } - ci =kzalloc (sizeof (*ci),GFP_KERNEL ); -if (!ci) -return NULL ; + ci->client = client; +memcpy (&ci->cfg, cfg,sizeof (ci->cfg)); + + ci->regmap =regmap_init_i2c (client, &rm_cfg); +if (IS_ERR (ci->regmap)) { + ret =PTR_ERR (ci->regmap); + goto err_kfree; + } + + ret =regmap_read (ci->regmap,0x00 , &val); +if (ret <0 ) { +dev_info (&client->dev,"No CXD2099AR detected at 0x%02x\n" , + client->addr); + goto err_rmexit; + }mutex_init (&ci->lock); - ci->cfg = *cfg; - ci->i2c = i2c; ci->lastaddress =0xff ; ci->clk_reg_b =0x4a ; ci->clk_reg_f =0x1b ;
@@ -687,18 +648,56 @@ struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg, ci->en = en_templ; ci->en.data = ci;init (ci); -dev_info (&i2c->dev,"Attached CXD2099AR at 0x%02x\n" , ci->cfg.adr); +dev_info (&client->dev,"Attached CXD2099AR at 0x%02x\n" , client->addr); + + *cfg->en = &ci->en;if (!buffermode) { ci->en.read_data =NULL ; ci->en.write_data =NULL ; }else { -dev_info (&i2c->dev,"Using CXD2099AR buffer mode" ); +dev_info (&client->dev,"Using CXD2099AR buffer mode" ); } -return &ci->en; +i2c_set_clientdata (client, ci); + +return 0 ; + +err_rmexit: +regmap_exit (ci->regmap); +err_kfree: +kfree (ci); +err: + +return ret; } -EXPORT_SYMBOL (cxd2099_attach); + +static int cxd2099_remove (struct i2c_client *client) +{ +struct cxd *ci =i2c_get_clientdata (client); + +regmap_exit (ci->regmap); +kfree (ci); + +return 0 ; +} + +static const struct i2c_device_id cxd2099_id[] = { + {"cxd2099" ,0 }, + {} +}; +MODULE_DEVICE_TABLE (i2c, cxd2099_id); + +static struct i2c_driver cxd2099_driver = { + .driver = { + .name ="cxd2099" , + }, + .probe = cxd2099_probe, + .remove = cxd2099_remove, + .id_table = cxd2099_id, +}; + +module_i2c_driver (cxd2099_driver);MODULE_DESCRIPTION ("CXD2099AR Common Interface controller driver" );MODULE_AUTHOR ("Ralph Metzler" );
drivers/staging/media/cxd2099/cxd2099.h +4 -7
@@ -25,14 +25,12 @@ struct cxd2099_cfg {u8 clock_mode;u32 max_i2c; -}; -#if defined(CONFIG_DVB_CXD2099 ) || \ - (defined(CONFIG_DVB_CXD2099_MODULE ) && defined(MODULE )) -struct dvb_ca_en50221 *cxd2099_attach (struct cxd2099_cfg *cfg, -void *priv,struct i2c_adapter *i2c); -#else +/* ptr to DVB CA struct */ +struct dvb_ca_en50221 **en; +}; +/* TODO: remove when done */ static inline struct dvb_ca_en50221 *cxd2099_attach (struct cxd2099_cfg *cfg,void *priv,struct i2c_adapter *i2c)
@@ -40,6 +38,5 @@ dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg, void *priv,dev_warn (&i2c->dev,"%s: driver disabled by Kconfig\n" , __func__); return NULL; } -#endif #endif
Signature · 1 line
2.13.6
PATCH 3/7 ddbridge: adapt cxd2099 attach to new i2c_client way
In reply to Daniel SchellerFrom: Daniel Scheller <[email protected]>
Change the way the cxd2099 hardware is being attached to the new I2C client interface way.
--- drivers/media/pci/ddbridge/ddbridge-ci.c | 62 +++++++++++++++++++++++++++++--- drivers/media/pci/ddbridge/ddbridge.h | 1 + 2 files changed, 58 insertions(+), 5 deletions(-)
drivers/media/pci/ddbridge/ddbridge-ci.c +57 -5
@@ -172,6 +172,7 @@ static void ci_attach(struct ddb_port *port)memcpy (&ci->en, &en_templ,sizeof (en_templ)); ci->en.data = ci; port->en = &ci->en; + port->en_freedata =1 ; ci->port = port; ci->nr = port->nr -2 ; }
@@ -304,6 +305,7 @@ static void ci_xo2_attach(struct ddb_port *port)memcpy (&ci->en, &en_xo2_templ,sizeof (en_xo2_templ)); ci->en.data = ci; port->en = &ci->en; + port->en_freedata =1 ; ci->port = port; ci->nr = port->nr -2 ; ci->port->creg =0 ;
@@ -311,20 +313,58 @@ static void ci_xo2_attach(struct ddb_port *port)write_creg (ci,0x08 ,0x08 ); } -static struct cxd2099_cfg cxd_cfg = { +static const struct cxd2099_cfg cxd_cfgtmpl = { .bitrate =72000 , - .adr =0x40 , .polarity =1 , .clock_mode =1 , .max_i2c =512 , }; +static int ci_cxd2099_attach (struct ddb_port *port,u32 bitrate) +{ +struct cxd2099_cfg cxd_cfg = cxd_cfgtmpl; +struct i2c_client *client; +struct i2c_board_info board_info = { + .type ="cxd2099" , + .addr =0x40 , + .platform_data = &cxd_cfg, + }; + + cxd_cfg.bitrate = bitrate; + cxd_cfg.en = &port->en; + +request_module (board_info.type); + + client =i2c_new_device (&port->i2c->adap, &board_info); +if (!client || !client->dev.driver) + goto err_ret; + +if (!try_module_get (client->dev.driver->owner)) + goto err_i2c; + +if (!port->en) + goto err_i2c; + + port->dvb[0 ].i2c_client[0 ] = client; + port->en_freedata =0 ; +return 0 ; + +err_i2c: +i2c_unregister_device (client); +err_ret: +dev_err (port->dev->dev,"CXD2099AR attach failed\n" ); +return -ENODEV ; +} +int ddb_ci_attach (struct ddb_port *port,u32 bitrate) { +int ret; +switch (port->type) {case DDB_CI_EXTERNAL_SONY : - cxd_cfg.bitrate = bitrate; - port->en =cxd2099_attach (&cxd_cfg, port, &port->i2c->adap); + ret =ci_cxd2099_attach (port, bitrate); +if (ret) +return -ENODEV ;break ;case DDB_CI_EXTERNAL_XO2 :case DDB_CI_EXTERNAL_XO2_B :
@@ -345,11 +385,23 @@ int ddb_ci_attach(struct ddb_port *port, u32 bitrate)void ddb_ci_detach (struct ddb_port *port) { +struct i2c_client *client; +if (port->dvb[0 ].dev)dvb_unregister_device (port->dvb[0 ].dev);if (port->en) {dvb_ca_en50221_release (port->en); -kfree (port->en->data); + + client = port->dvb[0 ].i2c_client[0 ]; +if (client) { +module_put (client->dev.driver->owner); +i2c_unregister_device (client); + } + +/* free alloc'ed memory if needed */ +if (port->en_freedata) +kfree (port->en->data); + port->en =NULL ; } }
drivers/media/pci/ddbridge/ddbridge.h +1 -0
@@ -276,6 +276,7 @@ struct ddb_port {struct ddb_input *input[2 ];struct ddb_output *output;struct dvb_ca_en50221 *en; +u8 en_freedata;struct ddb_dvb dvb[2 ];u32 gap;u32 obr;
Signature · 1 line
2.13.6
PATCH 4/7 ngene: adapt cxd2099 attach to the new i2c_client way
In reply to Daniel SchellerFrom: Daniel Scheller <[email protected]>
Change the way the cxd2099 hardware is being attached to the new I2C client interface way.
--- drivers/media/pci/ngene/ngene-core.c | 41 ++++++++++++++++++++++++++++++++---- drivers/media/pci/ngene/ngene.h | 1 + 2 files changed, 38 insertions(+), 4 deletions(-)
drivers/media/pci/ngene/ngene-core.c +37 -4
@@ -1562,9 +1562,8 @@ static int init_channels(struct ngene *dev)return 0 ; } -static struct cxd2099_cfg cxd_cfg = { +static const struct cxd2099_cfg cxd_cfgtmpl = { .bitrate =62000 , - .adr =0x40 , .polarity =0 , .clock_mode =0 , };
@@ -1572,18 +1571,52 @@ static struct cxd2099_cfg cxd_cfg = {static void cxd_attach (struct ngene *dev) {struct ngene_ci *ci = &dev->ci; +struct cxd2099_cfg cxd_cfg = cxd_cfgtmpl; +struct i2c_client *client; +struct i2c_board_info board_info = { + .type ="cxd2099" , + .addr =0x40 , + .platform_data = &cxd_cfg, + }; + + cxd_cfg.en = &ci->en; + +request_module (board_info.type); + + client =i2c_new_device (&dev->channel[0 ].i2c_adapter, &board_info); +if (!client || !client->dev.driver) + goto err_ret; + +if (!try_module_get (client->dev.driver->owner)) + goto err_i2c; + +if (!ci->en) + goto err_i2c; - ci->en =cxd2099_attach (&cxd_cfg, dev, &dev->channel[0 ].i2c_adapter); ci->dev = dev; + dev->channel[0 ].i2c_client[0 ] = client; +return ; + +err_i2c: +i2c_unregister_device (client); +err_ret: + printk(KERN_ERR DEVICE_NAME ": CXD2099AR attach failed\n");return ; }static void cxd_detach (struct ngene *dev) {struct ngene_ci *ci = &dev->ci; +struct i2c_client *client;dvb_ca_en50221_release (ci->en); -kfree (ci->en); + + client = dev->channel[0 ].i2c_client[0 ]; +if (client) { +module_put (client->dev.driver->owner); +i2c_unregister_device (client); + } + ci->en =NULL ; }
drivers/media/pci/ngene/ngene.h +1 -0
@@ -630,6 +630,7 @@ struct ngene_vopen {struct ngene_channel {struct device device;struct i2c_adapter i2c_adapter; +struct i2c_client *i2c_client[1 ];struct ngene *dev;int number;
Signature · 1 line
2.13.6
PATCH 5/7 staging/cxd2099: remove remainders from old attach way
In reply to Daniel SchellerFrom: Daniel Scheller <[email protected]>
As all drivers using the cxd2099 are converted to handle attach/detach the generic I2C client way, the static inline cxd2099_attach isn't required anymore. Thus cleanup cxd2099.h from the remainders, the adr struct member isn't used anymore aswell.
--- drivers/staging/media/cxd2099/cxd2099.h | 10 ---------- 1 file changed, 10 deletions(-)
drivers/staging/media/cxd2099/cxd2099.h +0 -10
@@ -20,7 +20,6 @@struct cxd2099_cfg {u32 bitrate; -u8 adr;u8 polarity;u8 clock_mode;
@@ -30,13 +29,4 @@ struct cxd2099_cfg { struct dvb_ca_en50221 **en; }; -/* TODO: remove when done */ -static inline struct -dvb_ca_en50221 *cxd2099_attach (struct cxd2099_cfg *cfg,void *priv, -struct i2c_adapter *i2c) -{ -dev_warn (&i2c->dev,"%s: driver disabled by Kconfig\n" , __func__); -return NULL ; -} -#endif
Signature · 1 line
2.13.6
PATCH 6/7 cxd2099: move driver out of staging into dvb-frontends
In reply to Daniel SchellerFrom: Daniel Scheller <[email protected]>
According to the TODO file, this driver only landed in staging because of the way device nodes and data transfers are handled. Besides that this way (use of secX devices) has become sort of standard to date (ie. VDR supports this literally since ages via the ddci plugin, TVHeadend received this functionality lately, and minisatip being currently worked on regarding this), most importantly this I2C client only driver isn't even responsible for setting up device nodes, not for handling data transfer and so on, but only serves as interface for the dvb_ca_en50221 subsystem, just like every other DVB card out in the wild, with hard-wired or such flexible CA interfaces. And, it would even work with cards having the cxd2099 controller hard-wired.
Also, this driver received quite some love and even is a proper I2C client driver by now. So, as this driver acts as a EN50221 frontend device, move it to dvb-frontends. There is no need to keep it buried in staging.
This commit also updates all affected Kconfig and Makefile's, and adds MEDIA_AUTOSELECT depends to ddbridge and ngene.
---
drivers/media/dvb-frontends/Kconfig | 12 ++++++++++++
drivers/media/dvb-frontends/Makefile | 1 +
.../{staging/media/cxd2099 => media/dvb-frontends}/cxd2099.c | 0
.../{staging/media/cxd2099 => media/dvb-frontends}/cxd2099.h | 0
drivers/media/pci/ddbridge/Kconfig | 1 +
drivers/media/pci/ddbridge/Makefile | 3 ---
drivers/media/pci/ngene/Kconfig | 1 +
drivers/media/pci/ngene/Makefile | 3 ---
drivers/staging/media/Kconfig | 2 --
drivers/staging/media/Makefile | 1 -
drivers/staging/media/cxd2099/Kconfig | 12 ------------
drivers/staging/media/cxd2099/Makefile | 4 ----
drivers/staging/media/cxd2099/TODO | 12 ------------
13 files changed, 15 insertions(+), 37 deletions(-)
rename drivers/{staging/media/cxd2099 => media/dvb-frontends}/cxd2099.c (100%)
rename drivers/{staging/media/cxd2099 => media/dvb-frontends}/cxd2099.h (100%)
delete mode 100644 drivers/staging/media/cxd2099/Kconfig
delete mode 100644 drivers/staging/media/cxd2099/Makefile
delete mode 100644 drivers/staging/media/cxd2099/TODOdrivers/media/dvb-frontends/Kconfig +12 -0
@@ -904,6 +904,18 @@ config DVB_HELENE help Say Y when you want to support this frontend. +comment "Common Interface (EN50221) controller drivers" + depends on DVB_CORE + +config DVB_CXD2099 + tristate "CXD2099AR Common Interface driver" + depends on DVB_CORE && I2C + ---help--- + A driver for the CI controller currently found mostly on + Digital Devices DuoFlex CI (single) addon modules. + + Say Y when you want to support these devices. + comment "Tools to develop new frontends" config DVB_DUMMY_FE
drivers/media/dvb-frontends/Makefile +1 -0
@@ -129,3 +129,4 @@ obj-$(CONFIG_DVB_HORUS3A) += horus3a.o obj-$(CONFIG_DVB_ASCOT2E) += ascot2e.o obj-$(CONFIG_DVB_HELENE) += helene.o obj-$(CONFIG_DVB_ZD1301_DEMOD) += zd1301_demod.o +obj-$(CONFIG_DVB_CXD2099) += cxd2099.o
drivers/media/dvb-frontends/cxd2099.c renamed from drivers/staging/media/cxd2099/cxd2099.c +0 -0
drivers/media/dvb-frontends/cxd2099.h renamed from drivers/staging/media/cxd2099/cxd2099.h +0 -0
drivers/media/pci/ddbridge/Kconfig +1 -0
@@ -13,6 +13,7 @@ config DVB_DDBRIDGE select DVB_LNBH25 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT select DVB_MXL5XX if MEDIA_SUBDRV_AUTOSELECT + select DVB_CXD2099 if MEDIA_SUBDRV_AUTOSELECT ---help--- Support for cards with the Digital Devices PCI express bridge: - Octopus PCIe Bridge
drivers/media/pci/ddbridge/Makefile +0 -3
@@ -10,6 +10,3 @@ obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o ccflags-y += -Idrivers/media/dvb-frontends/ ccflags-y += -Idrivers/media/tuners/ - -# For the staging CI driver cxd2099 -ccflags-y += -Idrivers/staging/media/cxd2099/
drivers/media/pci/ngene/Kconfig +1 -0
@@ -8,6 +8,7 @@ config DVB_NGENE select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT + select DVB_CXD2099 if MEDIA_SUBDRV_AUTOSELECT ---help--- Support for Micronas PCI express cards with nGene bridge.
drivers/media/pci/ngene/Makefile +0 -3
@@ -9,6 +9,3 @@ obj-$(CONFIG_DVB_NGENE) += ngene.o ccflags-y += -Idrivers/media/dvb-frontends/ ccflags-y += -Idrivers/media/tuners/ - -# For the staging CI driver cxd2099 -ccflags-y += -Idrivers/staging/media/cxd2099/
drivers/staging/media/Kconfig +0 -2
@@ -23,8 +23,6 @@ source "drivers/staging/media/atomisp/Kconfig" source "drivers/staging/media/bcm2048/Kconfig" -source "drivers/staging/media/cxd2099/Kconfig" - source "drivers/staging/media/davinci_vpfe/Kconfig" source "drivers/staging/media/imx/Kconfig"
drivers/staging/media/Makefile +0 -1
@@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_I2C_BCM2048) += bcm2048/ -obj-$(CONFIG_DVB_CXD2099) += cxd2099/ obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx/ obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
drivers/staging/media/cxd2099/Kconfig deleted +0 -12
@@ -1,12 +0,0 @@ -config DVB_CXD2099 - tristate "CXD2099AR Common Interface driver" - depends on DVB_CORE && PCI && I2C - ---help--- - Support for the CI module found on cards based on - - Micronas ngene PCIe bridge: cineS2 etc. - - Digital Devices PCIe bridge: Octopus series - - For now, data is passed through '/dev/dvb/adapterX/sec0': - - Encrypted data must be written to 'sec0'. - - Decrypted data can be read from 'sec0'. - - Setup the CAM using device 'ca0'.
drivers/staging/media/cxd2099/Makefile deleted +0 -4
@@ -1,4 +0,0 @@ -obj-$(CONFIG_DVB_CXD2099) += cxd2099.o - -ccflags-y += -Idrivers/media/dvb-frontends/ -ccflags-y += -Idrivers/media/tuners/
drivers/staging/media/cxd2099/TODO deleted +0 -12
@@ -1,12 +0,0 @@ -For now, data is passed through '/dev/dvb/adapterX/sec0': - - Encrypted data must be written to 'sec0'. - - Decrypted data can be read from 'sec0'. - - Setup the CAM using device 'ca0'. - -But this is wrong. There are some discussions about the proper way for -doing it, as seen at: - http://www.mail-archive.com/[email protected]/msg22196.html - -While there's no proper fix for it, the driver should be kept in staging. - -Patches should be submitted to: [email protected].
Signature · 1 line
2.13.6
PATCH 7/7 MAINTAINERS: add entry for cxd2099
In reply to Daniel SchellerFrom: Jasmin Jessich <[email protected]>
The cxd2099 driver is now maintained and being taken care of by
* Jasmin Jessich <[email protected]>
--- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+)
MAINTAINERS +8 -0
@@ -8540,6 +8540,14 @@ T: git git://linuxtv.org/media_tree.git S: Supported F: drivers/media/dvb-frontends/ascot2e* +MEDIA DRIVERS FOR CXD2099AR CI CONTROLLERS +M: Jasmin Jessich <[email protected]> +L: [email protected] +W: https://linuxtv.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/dvb-frontends/cxd2099* + MEDIA DRIVERS FOR CXD2841ER M: Sergey Kozlov <[email protected]> M: Abylay Ospan <[email protected]>
Signature · 1 line
2.13.6