[alsa-devel] [PATCH] ASoC: AK4671: add ak4671 codec driver
Joonyoung Shim
jy0922.shim at samsung.com
Fri Sep 4 03:30:29 CEST 2009
On 9/3/2009 11:02 PM, Mark Brown wrote:
> On Thu, Sep 03, 2009 at 09:25:43PM +0900, Joonyoung Shim wrote:
>> The AK4671 is a stereo CODEC with a built-in Microphone-Amplifier,
>> Receiver-Amplifier and Headphone-Amplifier.
>>
>> The datasheet for the ak4671 can find at the following url:
>> http://www.asahi-kasei.co.jp/akm/en/product/ak4671/ak4671_f01e.pdf
>>
>> Signed-off-by: Joonyoung Shim <jy0922.shim at samsung.com>
>
> This looks very good, everything below is relatively minor.
>
>> +/* write to the ak4671 register space */
>> +static int ak4671_write(struct snd_soc_codec *codec, unsigned int reg,
>> + unsigned int value)
>> +{
>> + u8 data[2];
>> +
>> + /* data is
>> + * D15..D8 AK4671 register offset
>> + * D7...D0 register data
>> + */
>> + data[0] = reg & 0xff;
>> + data[1] = value & 0xff;
>> +
>> + ak4671_write_reg_cache(codec, reg, value);
>> + if (codec->hw_write(codec->control_data, data, 2) == 2)
>> + return 0;
>> + else
>> + return -EIO;
>> +}
>
> It would be nice (but not essential) to move over to soc-cache if
> possible - see the current for-2.6.32 code.
>
I saw the soc-cache code. Ok, i will move to soc-cache, test it.
>> +static const struct snd_kcontrol_new ak4671_snd_controls[] = {
>> + /* Common playback gain controls */
>> + SOC_SINGLE_TLV("Stereo Line Output1 Playback Volume",
>> + AK4671_OUTPUT_VOLUME_CONTROL, 0, 0x6, 0, out1_tlv),
>> + SOC_SINGLE_TLV("Headphone Output2 Playback Volume",
>> + AK4671_OUTPUT_VOLUME_CONTROL, 4, 0xd, 0, out2_tlv),
>> + SOC_SINGLE_TLV("Stereo Line Output3 Playback Volume",
>> + AK4671_LOUT3_POWER_MANAGERMENT, 6, 0x3, 0, out3_tlv),
>
> Could drop the "Stereo" from the control names - it'll probably read
> better in applications.
>
Ok.
>> + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
>> + case SND_SOC_DAIFMT_CBM_CFM:
>> + ak4671->pll_on = 1;
>> + mode |= AK4671_M_S;
>> + break;
>> + case SND_SOC_DAIFMT_CBM_CFS:
>> + ak4671->pll_on = 1;
>> + mode &= ~(AK4671_M_S);
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>
> Looks like pll_on is always set? If that's true then there's not much
> gain from keeping track of it.
>
The ak4671 supports four mode.
1. PLL Master Mode
2. PLL Slave Mode
3. EXT Slave Mode
4. EXT Master Mode
The 1 and 2 mode need pll_on set but the 3 and 4 mode don't need pll_on
set, but i didn't implemented EXT mode yet.
Ok, I will remove the pll_on keeping until implementing the EXT mode.
>> +/* event handlers */
>> +static int ak4671_set_bias_level(struct snd_soc_codec *codec,
>> + enum snd_soc_bias_level level)
>> +{
>> + struct ak4671_priv *ak4671 = codec->private_data;
>> + u8 reg;
>> +
>> + switch (level) {
>> + case SND_SOC_BIAS_ON:
>> + case SND_SOC_BIAS_PREPARE:
>> + case SND_SOC_BIAS_STANDBY:
>> + if (ak4671->pll_on) {
>> + reg = ak4671_read_reg_cache(codec,
>> + AK4671_PLL_MODE_SELECT1);
>> + reg |= AK4671_PMPLL;
>> + ak4671_write(codec, AK4671_PLL_MODE_SELECT1, reg);
>> + /* pll lock time: max 40ms */
>> + mdelay(40);
>> + }
>
> I suspect this will run into trouble with bypass paths (which do appear
> to exist if I read the DAPM routes correctly). If a bypass path is
> active then the CODEC will be brought up to full bias out of sync with
> any configuration of pll_on by the DAI format configuration.
>
A bypass path should operate regardless pll_on.
> I've not looked at the datasheet but I think what you need here is to
> make the PLL a SND_SOC_DAPM_SUPPLY for the DACs and ADCs, then use an
> event on that to turn on and off the PLL. DAPM will then keep the PLL
> powered so long as one of the DACs or ADCs is in use.
>
I'll check about this.
>> +static struct snd_soc_dai_ops ak4671_dai_ops = {
>> + .hw_params = ak4671_hw_params,
>> + .set_sysclk = ak4671_set_dai_sysclk,
>> + .set_fmt = ak4671_set_dai_fmt,
>> +
>> + /* TODO */
>
> Could just remove the comment here.
>
This is my fault. I will remove the comment.
>> +#ifdef CONFIG_PM
>> +static int ak4671_suspend(struct platform_device *pdev, pm_message_t state)
>> +{
>> + /* TODO */
>> +
>> + return 0;
>> +}
>> +
>> +static int ak4671_resume(struct platform_device *pdev)
>> +{
>> + /* TODO */
>> +
>> + return 0;
>> +}
>> +#else
>> +#define ak4671_suspend NULL
>> +#define ak4671_resume NULL
>> +#endif
>
> May as well just remove these completely if they're not implemented.
>
I will remove it.
Thanks.
More information about the Alsa-devel
mailing list