static int jzcodec_soc_dev_setup(struct snd_soc_device *socdev, struct snd_soc_codec *codec) { int ret; u16 reg_val; socdev->card->codec = codec; mutex_init(&codec->mutex); /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { printk(KERN_ERR "jzcodec: failed to create pcms\n"); return ret; } /* power on device */ jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3hot); /* clear suspend bit of jz4740 internal codec */ reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); reg_val = reg_val & ~(0x2); jzcodec_write(codec, ICODEC_1_LOW, reg_val); /* set vol bits */ reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); reg_val = reg_val | 0x3; jzcodec_write(codec, ICODEC_2_LOW, reg_val); /* set line in capture gain bits */ reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_HIGH); reg_val = reg_val | 0x1f; jzcodec_write(codec, ICODEC_2_HIGH, reg_val); /* set mic boost gain bits */ reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); reg_val = reg_val | (0x3 << 4); jzcodec_write(codec, ICODEC_2_LOW, reg_val); mdelay(5); reg_val = 0x3300; jzcodec_write(codec, ICODEC_1_LOW, reg_val); reg_val = 0x0003; jzcodec_write(codec, ICODEC_1_HIGH, reg_val); jzcodec_add_controls(codec); jzcodec_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { printk(KERN_ERR "jzcodec: failed to register card\n"); goto card_err; } return ret; card_err: snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); return ret; }
static int jzcodec_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec = socdev->codec; jzcodec_reg_pm[ICODEC_1_LOW] = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); jzcodec_reg_pm[ICODEC_1_HIGH] = jzcodec_read_reg_cache(codec, ICODEC_1_HIGH); jzcodec_reg_pm[ICODEC_2_LOW] = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); jzcodec_reg_pm[ICODEC_2_HIGH] = jzcodec_read_reg_cache(codec, ICODEC_2_HIGH); jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3cold); return 0; }
static int jzcodec_reset(struct snd_soc_codec *codec) { u16 val; val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); val = val | 0x1; jzcodec_write(codec, ICODEC_1_LOW, val); mdelay(1); val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); val = val & ~0x1; jzcodec_write(codec, ICODEC_1_LOW, val); mdelay(1); return 0; }
static int jzcodec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; u16 reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); /* bit size. codec side */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: break; } /* sample rate */ reg_val = reg_val & ~(0xf << 8); switch (params_rate(params)) { case 8000: reg_val |= (0x0 << 8); break; case 11025: reg_val |= (0x1 << 8); break; case 12000: reg_val |= (0x2 << 8); break; case 16000: reg_val |= (0x3 << 8); break; case 22050: reg_val |= (0x4 << 8); break; case 24000: reg_val |= (0x5 << 8); break; case 32000: reg_val |= (0x6 << 8); break; case 44100: reg_val |= (0x7 << 8); break; case 48000: reg_val |= (0x8 << 8); break; default: printk(" invalid rate :0x%08x\n",params_rate(params)); } jzcodec_write(codec, ICODEC_2_LOW, reg_val); return 0; }
static int jzcodec_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; u16 reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); if (mute != 0) mute = 1; if (mute) reg_val = reg_val | (0x1 << 14); else reg_val = reg_val & ~(0x1 << 14); jzcodec_write(codec, ICODEC_1_LOW, reg_val); return 0; }
/* * initialise the JZCODEC driver * register the mixer and dsp interfaces with the kernel */ static int jzcodec_init(struct snd_soc_device *socdev) { struct snd_soc_codec *codec = socdev->codec; int reg, ret = 0; u16 reg_val; for (reg = 0; reg < JZCODEC_CACHEREGNUM / 2; reg++) { switch (reg) { case 0: jzcodec_reg[reg] = REG_ICDC_CDCCR1; jzcodec_reg_LH[ICODEC_1_LOW] = jzcodec_reg[reg] & 0xffff; jzcodec_reg_LH[ICODEC_1_HIGH] = (jzcodec_reg[reg] & 0xffff0000) >> 16; break; case 1: jzcodec_reg[reg] = REG_ICDC_CDCCR2; jzcodec_reg_LH[ICODEC_2_LOW] = jzcodec_reg[reg] & 0xffff; jzcodec_reg_LH[ICODEC_2_HIGH] = (jzcodec_reg[reg] & 0xffff0000) >> 16; break; } } codec->name = "JZCODEC"; codec->owner = THIS_MODULE; codec->read = jzcodec_read_reg_cache; codec->write = jzcodec_write; codec->dapm_event = jzcodec_dapm_event; codec->dai = &jzcodec_dai; codec->num_dai = 1; codec->reg_cache_size = sizeof(jzcodec_reg_LH); codec->reg_cache = kmemdup(jzcodec_reg_LH, sizeof(jzcodec_reg_LH), GFP_KERNEL); if (codec->reg_cache == NULL) return -ENOMEM; jzcodec_reset(codec); /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { printk(KERN_ERR "jzcodec: failed to create pcms\n"); goto pcm_err; } /* power on device */ jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3hot); /* clear suspend bit of jz4740 internal codec */ reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); reg_val = reg_val & ~(0x2); jzcodec_write(codec, ICODEC_1_LOW, reg_val); /* set vol bits */ reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); reg_val = reg_val | 0x3; jzcodec_write(codec, ICODEC_2_LOW, reg_val); /* set line in capture gain bits */ reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_HIGH); reg_val = reg_val | 0x1f; jzcodec_write(codec, ICODEC_2_HIGH, reg_val); /* set mic boost gain bits */ reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); reg_val = reg_val | (0x3 << 4); jzcodec_write(codec, ICODEC_2_LOW, reg_val); mdelay(5); reg_val = 0x3300; jzcodec_write(codec, ICODEC_1_LOW, reg_val); reg_val = 0x0003; jzcodec_write(codec, ICODEC_1_HIGH, reg_val); jzcodec_add_controls(codec); jzcodec_add_widgets(codec); ret = snd_soc_register_card(socdev); if (ret < 0) { printk(KERN_ERR "jzcodec: failed to register card\n"); goto card_err; } return ret; card_err: snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); pcm_err: kfree(codec->reg_cache); return ret; }