diff options
Diffstat (limited to 'sound/soc/codecs/cx20442.c')
| -rw-r--r-- | sound/soc/codecs/cx20442.c | 173 | 
1 files changed, 49 insertions, 124 deletions
| diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index f07a415c753f..e8d27c8f9ba3 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -24,7 +24,8 @@  struct cx20442_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type; +	void *control_data;  	u8 reg_cache[1];  }; @@ -102,7 +103,7 @@ static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec,  {  	u8 *reg_cache = codec->reg_cache; -	if (reg >= codec->reg_cache_size) +	if (reg >= codec->driver->reg_cache_size)  		return -EINVAL;  	return reg_cache[reg]; @@ -164,16 +165,17 @@ static int cx20442_pm_to_v253_vsp(u8 value)  static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,  							unsigned int value)  { +	struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);  	u8 *reg_cache = codec->reg_cache;  	int vls, vsp, old, len;  	char buf[18]; -	if (reg >= codec->reg_cache_size) +	if (reg >= codec->driver->reg_cache_size)  		return -EINVAL;  	/* hw_write and control_data pointers required for talking to the modem  	 * are expected to be set by the line discipline initialization code */ -	if (!codec->hw_write || !codec->control_data) +	if (!codec->hw_write || !cx20442->control_data)  		return -EIO;  	old = reg_cache[reg]; @@ -202,17 +204,13 @@ static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,  		return -ENOMEM;  	dev_dbg(codec->dev, "%s: %s\n", __func__, buf); -	if (codec->hw_write(codec->control_data, buf, len) != len) +	if (codec->hw_write(cx20442->control_data, buf, len) != len)  		return -EIO;  	return 0;  } -/* Moved up here as line discipline referres it during initialization */ -static struct snd_soc_codec *cx20442_codec; - -  /*   * Line discpline related code   * @@ -228,15 +226,15 @@ static const char *v253_init = "ate0m0q0+fclass=8\r";  /* Line discipline .open() */  static int v253_open(struct tty_struct *tty)  { -	struct snd_soc_codec *codec = cx20442_codec;  	int ret, len = strlen(v253_init);  	/* Doesn't make sense without write callback */  	if (!tty->ops->write)  		return -EINVAL; -	/* Pass the codec structure address for use by other ldisc callbacks */ -	tty->disc_data = codec; +	/* Won't work if no codec pointer has been passed by a card driver */ +	if (!tty->disc_data) +		return -ENODEV;  	if (tty->ops->write(tty, v253_init, len) != len) {  		ret = -EIO; @@ -253,15 +251,18 @@ err:  static void v253_close(struct tty_struct *tty)  {  	struct snd_soc_codec *codec = tty->disc_data; +	struct cx20442_priv *cx20442;  	tty->disc_data = NULL;  	if (!codec)  		return; +	cx20442 = snd_soc_codec_get_drvdata(codec); +  	/* Prevent the codec driver from further accessing the modem */  	codec->hw_write = NULL; -	codec->control_data = NULL; +	cx20442->control_data = NULL;  	codec->pop_time = 0;  } @@ -277,15 +278,18 @@ static void v253_receive(struct tty_struct *tty,  				const unsigned char *cp, char *fp, int count)  {  	struct snd_soc_codec *codec = tty->disc_data; +	struct cx20442_priv *cx20442;  	if (!codec)  		return; -	if (!codec->control_data) { +	cx20442 = snd_soc_codec_get_drvdata(codec); + +	if (!cx20442->control_data) {  		/* First modem response, complete setup procedure */  		/* Set up codec driver access to modem controls */ -		codec->control_data = tty; +		cx20442->control_data = tty;  		codec->hw_write = (hw_write_t)tty->ops->write;  		codec->pop_time = 1;  	} @@ -313,8 +317,8 @@ EXPORT_SYMBOL_GPL(v253_ops);   * Codec DAI   */ -struct snd_soc_dai cx20442_dai = { -	.name = "CX20442", +static struct snd_soc_dai_driver cx20442_dai = { +	.name = "cx20442-voice",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -330,142 +334,63 @@ struct snd_soc_dai cx20442_dai = {  		.formats = SNDRV_PCM_FMTBIT_S16_LE,  	},  }; -EXPORT_SYMBOL_GPL(cx20442_dai); -static int cx20442_codec_probe(struct platform_device *pdev) +static int cx20442_codec_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret; - -	if (!cx20442_codec) { -		dev_err(&pdev->dev, "cx20442 not yet discovered\n"); -		return -ENODEV; -	} -	codec = cx20442_codec; - -	socdev->card->codec = codec; +	struct cx20442_priv *cx20442; -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		dev_err(&pdev->dev, "failed to create pcms\n"); -		goto pcm_err; -	} +	cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL); +	if (cx20442 == NULL) +		return -ENOMEM; +	snd_soc_codec_set_drvdata(codec, cx20442);  	cx20442_add_widgets(codec); -pcm_err: -	return ret; +	cx20442->control_data = NULL; +	codec->hw_write = NULL; +	codec->pop_time = 0; + +	return 0;  }  /* power down chip */ -static int cx20442_codec_remove(struct platform_device *pdev) +static int cx20442_codec_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); +	struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); +	if (cx20442->control_data) { +			struct tty_struct *tty = cx20442->control_data; +			tty_hangup(tty); +	} +	kfree(cx20442);  	return 0;  } -struct snd_soc_codec_device cx20442_codec_dev = { +static struct snd_soc_codec_driver cx20442_codec_dev = {  	.probe = 	cx20442_codec_probe,  	.remove = 	cx20442_codec_remove, +	.reg_cache_size = 1, +	.reg_word_size = sizeof(u8), +	.read = cx20442_read_reg_cache, +	.write = cx20442_write,  }; -EXPORT_SYMBOL_GPL(cx20442_codec_dev); - -static int cx20442_register(struct cx20442_priv *cx20442) -{ -	struct snd_soc_codec *codec = &cx20442->codec; -	int ret; - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->name = "CX20442"; -	codec->owner = THIS_MODULE; -	snd_soc_codec_set_drvdata(codec, cx20442); - -	codec->dai = &cx20442_dai; -	codec->num_dai = 1; - -	codec->reg_cache = &cx20442->reg_cache; -	codec->reg_cache_size = ARRAY_SIZE(cx20442->reg_cache); -	codec->read = cx20442_read_reg_cache; -	codec->write = cx20442_write; - -	codec->bias_level = SND_SOC_BIAS_OFF; - -	cx20442_dai.dev = codec->dev; - -	cx20442_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err; -	} - -	ret = snd_soc_register_dai(&cx20442_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} - -	return 0; - -err_codec: -	snd_soc_unregister_codec(codec); -err: -	cx20442_codec = NULL; -	kfree(cx20442); -	return ret; -} - -static void cx20442_unregister(struct cx20442_priv *cx20442) -{ -	snd_soc_unregister_dai(&cx20442_dai); -	snd_soc_unregister_codec(&cx20442->codec); - -	cx20442_codec = NULL; -	kfree(cx20442); -}  static int cx20442_platform_probe(struct platform_device *pdev)  { -	struct cx20442_priv *cx20442; -	struct snd_soc_codec *codec; - -	cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL); -	if (cx20442 == NULL) -		return -ENOMEM; - -	codec = &cx20442->codec; - -	codec->control_data = NULL; -	codec->hw_write = NULL; -	codec->pop_time = 0; - -	codec->dev = &pdev->dev; -	platform_set_drvdata(pdev, cx20442); - -	return cx20442_register(cx20442); +	return snd_soc_register_codec(&pdev->dev, +			&cx20442_codec_dev, &cx20442_dai, 1);  }  static int __exit cx20442_platform_remove(struct platform_device *pdev)  { -	struct cx20442_priv *cx20442 = platform_get_drvdata(pdev); - -	cx20442_unregister(cx20442); +	snd_soc_unregister_codec(&pdev->dev);  	return 0;  }  static struct platform_driver cx20442_platform_driver = {  	.driver = { -		.name = "cx20442", +		.name = "cx20442-codec",  		.owner = THIS_MODULE,  		},  	.probe = cx20442_platform_probe, @@ -487,4 +412,4 @@ module_exit(cx20442_exit);  MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver");  MODULE_AUTHOR("Janusz Krzysztofik");  MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:cx20442"); +MODULE_ALIAS("platform:cx20442-codec"); |