mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
rk3368 codec : add support for headset detection of es8316
Signed-off-by: smj <smj@rock-chips.com>
This commit is contained in:
@@ -170,7 +170,9 @@
|
||||
gpio0_c2: gpio0-c2 {
|
||||
rockchip,pins = <0 GPIO_C2 RK_FUNC_GPIO &pcfg_pull_down>;
|
||||
};
|
||||
|
||||
gpio0_c3: gpio0-c3{
|
||||
rockchip,pins = <0 GPIO_C3 RK_FUNC_GPIO &pcfg_pull_down>;
|
||||
};
|
||||
//to add
|
||||
};
|
||||
|
||||
@@ -329,6 +331,8 @@
|
||||
es8316: es8316@10 {
|
||||
compatible = "es8316";
|
||||
reg = <0x10>;
|
||||
spk-con-gpio = <&gpio0 GPIO_C3 GPIO_ACTIVE_HIGH>;
|
||||
hp-det-gpio = <&gpio0 GPIO_C7 GPIO_ACTIVE_HIGH>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -45,9 +45,11 @@
|
||||
#define amic_used 0
|
||||
|
||||
#define INVALID_GPIO -1
|
||||
int es8316_spk_con_gpio = INVALID_GPIO;
|
||||
int es8316_hp_con_gpio = INVALID_GPIO;
|
||||
int es8316_hp_det_gpio = INVALID_GPIO;
|
||||
|
||||
#define ES8316_CODEC_SET_SPK 1
|
||||
#define ES8316_CODEC_SET_HP 2
|
||||
|
||||
|
||||
int HP_IRQ = 0;
|
||||
int hp_irq_flag = 0;
|
||||
int es8316_init_reg = 0;
|
||||
@@ -107,8 +109,73 @@ struct es8316_priv {
|
||||
unsigned int dmic_amic;
|
||||
unsigned int sysclk;
|
||||
struct snd_pcm_hw_constraint_list *sysclk_constraints;
|
||||
|
||||
int spk_ctl_gpio;
|
||||
int hp_ctl_gpio;
|
||||
int hp_det_gpio;
|
||||
|
||||
bool spk_gpio_level;
|
||||
bool hp_gpio_level;
|
||||
bool hp_det_level;
|
||||
};
|
||||
|
||||
struct es8316_priv *es8316_private;
|
||||
static int es8316_set_gpio(int gpio, bool level)
|
||||
{
|
||||
struct es8316_priv *es8316 = es8316_private;
|
||||
|
||||
if (!es8316) {
|
||||
DBG("%s : es8316_priv is NULL\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
DBG("%s : set %s %s ctl gpio %s\n", __func__,
|
||||
gpio & ES8316_CODEC_SET_SPK ? "spk" : "",
|
||||
gpio & ES8316_CODEC_SET_HP ? "hp" : "",
|
||||
level ? "HIGH" : "LOW");
|
||||
if ((gpio & ES8316_CODEC_SET_SPK)
|
||||
&& es8316 && es8316->spk_ctl_gpio != INVALID_GPIO) {
|
||||
DBG("%d,set_value%s\n", es8316->spk_ctl_gpio, level ?
|
||||
"HIGH" : "LOW");
|
||||
gpio_set_value(es8316->spk_ctl_gpio, level);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char mute_flag = 1;
|
||||
static irqreturn_t hp_det_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
int ret;
|
||||
unsigned int type;
|
||||
struct es8316_priv *es8316 = es8316_private;
|
||||
|
||||
disable_irq_nosync(irq);
|
||||
|
||||
type = gpio_get_value(es8316->hp_det_gpio) ?
|
||||
IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
|
||||
ret = irq_set_irq_type(irq, type);
|
||||
if (ret < 0) {
|
||||
DBG("%s: irq_set_irq_type(%d, %d) failed\n",
|
||||
__func__, irq, type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (type == IRQ_TYPE_EDGE_FALLING)
|
||||
hp_irq_flag = 0;
|
||||
else
|
||||
hp_irq_flag = 1;
|
||||
if (mute_flag == 0) {
|
||||
if (es8316->hp_det_level == gpio_get_value(es8316->hp_det_gpio))
|
||||
es8316_set_gpio(ES8316_CODEC_SET_SPK,
|
||||
!es8316->spk_gpio_level);
|
||||
else
|
||||
es8316_set_gpio(ES8316_CODEC_SET_SPK,
|
||||
es8316->spk_gpio_level);
|
||||
}
|
||||
enable_irq(irq);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* es8316S Controls
|
||||
*/
|
||||
@@ -795,12 +862,21 @@ static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
static int es8316_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct es8316_priv *es8316 = es8316_private;
|
||||
|
||||
dev_dbg(codec->dev, "%s %d\n", __func__, mute);
|
||||
if (mute)
|
||||
mute_flag = mute;
|
||||
if (mute) {
|
||||
es8316_set_gpio(ES8316_CODEC_SET_SPK, !es8316->spk_gpio_level);
|
||||
msleep(100);
|
||||
snd_soc_write(codec, ES8316_DAC_SET1_REG30, 0x20);
|
||||
else if (dai->playback_active)
|
||||
} else if (dai->playback_active) {
|
||||
snd_soc_write(codec, ES8316_DAC_SET1_REG30, 0x00);
|
||||
msleep(130);
|
||||
if (hp_irq_flag == 0)
|
||||
es8316_set_gpio(ES8316_CODEC_SET_SPK,
|
||||
es8316->spk_gpio_level);
|
||||
msleep(150);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1092,9 +1168,15 @@ static struct spi_driver es8316_spi_driver = {
|
||||
static void es8316_i2c_shutdown(struct i2c_client *i2c)
|
||||
{
|
||||
struct snd_soc_codec *codec;
|
||||
struct es8316_priv *es8316 = es8316_private;
|
||||
|
||||
if (!es8316_codec)
|
||||
goto err;
|
||||
|
||||
es8316_set_gpio(ES8316_CODEC_SET_SPK, !es8316->spk_gpio_level);
|
||||
mdelay(150);
|
||||
|
||||
|
||||
codec = es8316_codec;
|
||||
snd_soc_write(codec, ES8316_CPHP_ICAL_VOL_REG18, 0x33);
|
||||
snd_soc_write(codec, ES8316_CPHP_OUTEN_REG17, 0x00);
|
||||
@@ -1118,14 +1200,68 @@ static int es8316_i2c_probe(struct i2c_client *i2c_client,
|
||||
{
|
||||
struct es8316_priv *es8316;
|
||||
int ret = -1;
|
||||
unsigned long irq_flag = 0;
|
||||
int hp_irq = 0;
|
||||
enum of_gpio_flags flags;
|
||||
struct device_node *np = i2c_client->dev.of_node;
|
||||
|
||||
DBG("---%s---probe start\n", __func__);
|
||||
|
||||
es8316 = kzalloc(sizeof(*es8316), GFP_KERNEL);
|
||||
if (es8316 == NULL)
|
||||
return -ENOMEM;
|
||||
else
|
||||
es8316_private = es8316;
|
||||
|
||||
es8316->dmic_amic = amic_used; /*if internal mic is amic*/
|
||||
i2c_set_clientdata(i2c_client, es8316);
|
||||
|
||||
|
||||
es8316->spk_ctl_gpio = of_get_named_gpio_flags(np,
|
||||
"spk-con-gpio", 0, &flags);
|
||||
if (es8316->spk_ctl_gpio < 0) {
|
||||
DBG("%s() Can not read property spk codec-en-gpio\n", __func__);
|
||||
es8316->spk_ctl_gpio = INVALID_GPIO;
|
||||
} else {
|
||||
es8316->spk_gpio_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1;
|
||||
ret = gpio_request(es8316->spk_ctl_gpio, NULL);
|
||||
gpio_direction_output(es8316->spk_ctl_gpio,
|
||||
!es8316->spk_gpio_level);
|
||||
}
|
||||
|
||||
es8316->hp_ctl_gpio = of_get_named_gpio_flags(np,
|
||||
"hp-con-gpio", 0, &flags);
|
||||
if (es8316->hp_ctl_gpio < 0) {
|
||||
DBG("%s() Can not read property hp codec-en-gpio\n", __func__);
|
||||
es8316->hp_ctl_gpio = INVALID_GPIO;
|
||||
} else {
|
||||
es8316->hp_gpio_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1;
|
||||
ret = gpio_request(es8316->hp_ctl_gpio, NULL);
|
||||
gpio_direction_output(es8316->hp_ctl_gpio, !es8316->hp_gpio_level);
|
||||
}
|
||||
|
||||
es8316->hp_det_gpio = of_get_named_gpio_flags(np,
|
||||
"hp-det-gpio", 0, &flags);
|
||||
if (es8316->hp_det_gpio < 0) {
|
||||
DBG("%s() Can not read property hp_det gpio\n", __func__);
|
||||
es8316->hp_det_gpio = INVALID_GPIO;
|
||||
} else {
|
||||
es8316->hp_det_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1;
|
||||
ret = gpio_request(es8316->hp_det_gpio, NULL);
|
||||
if (ret != 0) {
|
||||
DBG("%s request HP_DET error", __func__);
|
||||
return ret;
|
||||
}
|
||||
gpio_direction_input(es8316->hp_det_gpio);
|
||||
|
||||
irq_flag = IRQF_TRIGGER_LOW | IRQF_ONESHOT;
|
||||
hp_irq = gpio_to_irq(es8316->hp_det_gpio);
|
||||
|
||||
if (hp_irq)
|
||||
ret = request_threaded_irq(hp_irq, NULL,
|
||||
hp_det_irq_handler, irq_flag, "ES8316", NULL);
|
||||
}
|
||||
|
||||
ret = snd_soc_register_codec(&i2c_client->dev,
|
||||
&soc_codec_dev_es8316,
|
||||
&es8316_dai, 1);
|
||||
@@ -1134,6 +1270,8 @@ static int es8316_i2c_probe(struct i2c_client *i2c_client,
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user