wm8960 linux codec 代码,修改过了,支持录音

/*
* wm8960.c  --  WM8960 ALSA SoC Audio driver
*
* Copyright 2007-11 Wolfson Microelectronics, plc
*
* Author: Liam Girdwood
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include <sound/wm8960.h>
#include "wm8960.h"
/* R25 - Power 1 */
#define WM8960_VMID_MASK 0x180
#define WM8960_VREF      0x40
/* R26 - Power 2 */
#define WM8960_PWR2_LOUT1    0x40
#define WM8960_PWR2_ROUT1    0x20
#define WM8960_PWR2_OUT3    0x02
/* R28 - Anti-pop 1 */
#define WM8960_POBCTRL  0x80
#define WM8960_BUFDCOPEN 0x10
#define WM8960_BUFIOEN  0x08
#define WM8960_SOFT_ST  0x04
#define WM8960_HPSTBY    0x01
/* R29 - Anti-pop 2 */
#define WM8960_DISOP    0x40
#define WM8960_DRES_MASK 0x30
/*
* wm8960 register cache
* We can't read the WM8960 register space when we are
* using 2 wire for device control, so we cache them instead.
*/
static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {
    0x0097, 0x0097, 0x0000, 0x0000,
    0x0000, 0x0008, 0x0000, 0x000a,
    0x01c0, 0x0000, 0x00ff, 0x00ff,
    0x0000, 0x0000, 0x0000, 0x0000,
    0x0000, 0x007b, 0x0100, 0x0032,
    0x0000, 0x00c3, 0x00c3, 0x01c0,
    0x0000, 0x0000, 0x0000, 0x0000,
    0x0000, 0x0000, 0x0000, 0x0000,
    0x0100, 0x0100, 0x0050, 0x0050,
    0x0050, 0x0050, 0x0000, 0x0000,
    0x0000, 0x0000, 0x0040, 0x0000,
    0x0000, 0x0050, 0x0050, 0x0000,
    0x0002, 0x0037, 0x004d, 0x0080,
    0x0008, 0x0031, 0x0026, 0x00e9,
};
struct wm8960_priv {
    enum snd_soc_control_type control_type;
    int (*set_bias_level)(struct snd_soc_codec *,
                  enum snd_soc_bias_level level);
    struct snd_soc_dapm_widget *lout1;
    struct snd_soc_dapm_widget *rout1;
    struct snd_soc_dapm_widget *out3;
    bool deemph;
    int playback_fs;
};
#define wm8960_reset(c)    snd_soc_write(c, WM8960_RESET, 0)
/* enumerated controls */
static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted",
    "Right Inverted", "Stereo Inversion"};
static const char *wm8960_3d_upper_cutoff[] = {"High", "Low"};
static const char *wm8960_3d_lower_cutoff[] = {"Low", "High"};
static const char *wm8960_alcfunc[] = {"Off", "Right", "Left", "Stereo"};
static const char *wm8960_alcmode[] = {"ALC", "Limiter"};
static const struct soc_enum wm8960_enum[] = {
    SOC_ENUM_SINGLE(WM8960_DACCTL1, 5, 4, wm8960_polarity),
    SOC_ENUM_SINGLE(WM8960_DACCTL2, 5, 4, wm8960_polarity),
    SOC_ENUM_SINGLE(WM8960_3D, 6, 2, wm8960_3d_upper_cutoff),
    SOC_ENUM_SINGLE(WM8960_3D, 5, 2, wm8960_3d_lower_cutoff),
    SOC_ENUM_SINGLE(WM8960_ALC1, 7, 4, wm8960_alcfunc),
    SOC_ENUM_SINGLE(WM8960_ALC3, 8, 2, wm8960_alcmode),
};
static const int deemph_settings[] = { 0, 32000, 44100, 48000 };
static int wm8960_set_deemph(struct snd_soc_codec *codec)
{
    struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
    int val, i, best;
    /* If we're using deemphasis select the nearest available sample
    * rate.
    */
    if (wm8960->deemph) {
        best = 1;
        for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) {
            if (abs(deemph_settings[i] - wm8960->playback_fs) <
                abs(deemph_settings[best] - wm8960->playback_fs))
                best = i;
        }
        val = best << 1;
    } else {
        val = 0;
    }
    dev_dbg(codec->dev, "Set deemphasis %d\n", val);
    return snd_soc_update_bits(codec, WM8960_DACCTL1,
                  0x6, val);
}
static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,
                struct snd_ctl_elem_value *ucontrol)
{
    struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
    struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
    ucontrol-&umerated.item[0] = wm8960->deemph;
    return 0;
}
static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,
                struct snd_ctl_elem_value *ucontrol)
{
    struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
    struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
    int deemph = ucontrol-&umerated.item[0];
    if (deemph > 1)
        return -EINVAL;
    wm8960->deemph = deemph;
    return wm8960_set_deemph(codec);
}
static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0);

本文发布于:2024-09-22 19:33:06,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/4/90865.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议