From 440eed43e2a95bb842488755683716814da10f2b Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Fri, 30 Jul 2010 09:51:52 +0200 Subject: pcmcia: introduce autoconfiguration feature Introduce an autoconfiguration feature to set certain values in pcmcia_loop_config(), instead of copying the same code over and over in each PCMCIA driver. At first, introduce the following options: CONF_AUTO_CHECK_VCC check or matching Vcc entry CONF_AUTO_SET_VPP set Vpp CONF_AUTO_AUDIO enable the speaker line CC: netdev@vger.kernel.org CC: linux-wireless@vger.kernel.org CC: linux-ide@vger.kernel.org CC: linux-usb@vger.kernel.org CC: laforge@gnumonks.org CC: linux-mtd@lists.infradead.org CC: alsa-devel@alsa-project.org CC: linux-serial@vger.kernel.org CC: Jiri Kosina CC: linux-scsi@vger.kernel.org Acked-by: Gustavo F. Padovan (for drivers/bluetooth) Tested-by: Wolfram Sang Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_cis.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'drivers/pcmcia') diff --git a/drivers/pcmcia/pcmcia_cis.c b/drivers/pcmcia/pcmcia_cis.c index ce8b94a3b675..160da0697335 100644 --- a/drivers/pcmcia/pcmcia_cis.c +++ b/drivers/pcmcia/pcmcia_cis.c @@ -131,7 +131,6 @@ struct pcmcia_cfg_mem { int (*conf_check) (struct pcmcia_device *p_dev, cistpl_cftable_entry_t *cfg, cistpl_cftable_entry_t *dflt, - unsigned int vcc, void *priv_data); cisparse_t parse; cistpl_cftable_entry_t dflt; @@ -146,16 +145,46 @@ struct pcmcia_cfg_mem { */ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv) { - cistpl_cftable_entry_t *cfg = &parse->cftable_entry; struct pcmcia_cfg_mem *cfg_mem = priv; + struct pcmcia_device *p_dev = cfg_mem->p_dev; + cistpl_cftable_entry_t *cfg = &parse->cftable_entry; + cistpl_cftable_entry_t *dflt = &cfg_mem->dflt; + unsigned int flags = p_dev->config_flags; + unsigned int vcc = p_dev->socket->socket.Vcc; + + dev_dbg(&p_dev->dev, "testing configuration %x, autoconf %x\n", + cfg->index, flags); /* default values */ cfg_mem->p_dev->config_index = cfg->index; if (cfg->flags & CISTPL_CFTABLE_DEFAULT) cfg_mem->dflt = *cfg; + /* check for matching Vcc? */ + if (flags & CONF_AUTO_CHECK_VCC) { + if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) + return -ENODEV; + } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) + return -ENODEV; + } + } + + /* set Vpp? */ + if (flags & CONF_AUTO_SET_VPP) { + if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) + p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; + else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) + p_dev->vpp = + dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; + } + + /* enable audio? */ + if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO)) + p_dev->config_flags |= CONF_ENABLE_SPKR; + return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt, - cfg_mem->p_dev->socket->socket.Vcc, cfg_mem->priv_data); } @@ -176,7 +205,6 @@ int pcmcia_loop_config(struct pcmcia_device *p_dev, int (*conf_check) (struct pcmcia_device *p_dev, cistpl_cftable_entry_t *cfg, cistpl_cftable_entry_t *dflt, - unsigned int vcc, void *priv_data), void *priv_data) { -- cgit v1.2.3