mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	ASoC: rt5659: Add the support of Intel HDA Header
The patch adds the support of Intel HDA Header. Signed-off-by: Oder Chiou <oder_chiou@realtek.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
		
							parent
							
								
									7928b2cbe5
								
							
						
					
					
						commit
						041e74b714
					
				
					 3 changed files with 117 additions and 5 deletions
				
			
		| 
						 | 
					@ -30,6 +30,7 @@ enum rt5659_dmic2_data_pin {
 | 
				
			||||||
enum rt5659_jd_src {
 | 
					enum rt5659_jd_src {
 | 
				
			||||||
	RT5659_JD_NULL,
 | 
						RT5659_JD_NULL,
 | 
				
			||||||
	RT5659_JD3,
 | 
						RT5659_JD3,
 | 
				
			||||||
 | 
						RT5659_JD_HDA_HEADER,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct rt5659_platform_data {
 | 
					struct rt5659_platform_data {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1461,6 +1461,61 @@ static void rt5659_jack_detect_work(struct work_struct *work)
 | 
				
			||||||
			    SND_JACK_BTN_2 | SND_JACK_BTN_3);
 | 
								    SND_JACK_BTN_2 | SND_JACK_BTN_3);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void rt5659_jack_detect_intel_hd_header(struct work_struct *work)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct rt5659_priv *rt5659 =
 | 
				
			||||||
 | 
							container_of(work, struct rt5659_priv, jack_detect_work.work);
 | 
				
			||||||
 | 
						unsigned int value;
 | 
				
			||||||
 | 
						bool hp_flag, mic_flag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!rt5659->hs_jack)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* headphone jack */
 | 
				
			||||||
 | 
						regmap_read(rt5659->regmap, RT5659_GPIO_STA, &value);
 | 
				
			||||||
 | 
						hp_flag = (!(value & 0x8)) ? true : false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (hp_flag != rt5659->hda_hp_plugged) {
 | 
				
			||||||
 | 
							rt5659->hda_hp_plugged = hp_flag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (hp_flag) {
 | 
				
			||||||
 | 
								regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_1,
 | 
				
			||||||
 | 
									0x10, 0x0);
 | 
				
			||||||
 | 
								rt5659->jack_type |= SND_JACK_HEADPHONE;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_1,
 | 
				
			||||||
 | 
									0x10, 0x10);
 | 
				
			||||||
 | 
								rt5659->jack_type = rt5659->jack_type &
 | 
				
			||||||
 | 
									(~SND_JACK_HEADPHONE);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							snd_soc_jack_report(rt5659->hs_jack, rt5659->jack_type,
 | 
				
			||||||
 | 
								SND_JACK_HEADPHONE);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* mic jack */
 | 
				
			||||||
 | 
						regmap_read(rt5659->regmap, RT5659_4BTN_IL_CMD_1, &value);
 | 
				
			||||||
 | 
						regmap_write(rt5659->regmap, RT5659_4BTN_IL_CMD_1, value);
 | 
				
			||||||
 | 
						mic_flag = (value & 0x2000) ? true : false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mic_flag != rt5659->hda_mic_plugged) {
 | 
				
			||||||
 | 
							rt5659->hda_mic_plugged = mic_flag;
 | 
				
			||||||
 | 
							if (mic_flag) {
 | 
				
			||||||
 | 
								regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_2,
 | 
				
			||||||
 | 
									0x2, 0x2);
 | 
				
			||||||
 | 
								rt5659->jack_type |= SND_JACK_MICROPHONE;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_2,
 | 
				
			||||||
 | 
									0x2, 0x0);
 | 
				
			||||||
 | 
								rt5659->jack_type = rt5659->jack_type
 | 
				
			||||||
 | 
									& (~SND_JACK_MICROPHONE);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							snd_soc_jack_report(rt5659->hs_jack, rt5659->jack_type,
 | 
				
			||||||
 | 
								SND_JACK_MICROPHONE);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct snd_kcontrol_new rt5659_snd_controls[] = {
 | 
					static const struct snd_kcontrol_new rt5659_snd_controls[] = {
 | 
				
			||||||
	/* Speaker Output Volume */
 | 
						/* Speaker Output Volume */
 | 
				
			||||||
	SOC_DOUBLE_TLV("Speaker Playback Volume", RT5659_SPO_VOL,
 | 
						SOC_DOUBLE_TLV("Speaker Playback Volume", RT5659_SPO_VOL,
 | 
				
			||||||
| 
						 | 
					@ -3990,6 +4045,54 @@ static void rt5659_calibrate(struct rt5659_priv *rt5659)
 | 
				
			||||||
	regmap_write(rt5659->regmap, RT5659_HP_CHARGE_PUMP_1, 0x0c16);
 | 
						regmap_write(rt5659->regmap, RT5659_HP_CHARGE_PUMP_1, 0x0c16);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rt5659_intel_hd_header_probe_setup(struct rt5659_priv *rt5659)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						regmap_read(rt5659->regmap, RT5659_GPIO_STA, &value);
 | 
				
			||||||
 | 
						if (!(value & 0x8)) {
 | 
				
			||||||
 | 
							rt5659->hda_hp_plugged = true;
 | 
				
			||||||
 | 
							regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_1,
 | 
				
			||||||
 | 
								0x10, 0x0);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_1,
 | 
				
			||||||
 | 
								0x10, 0x10);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						regmap_update_bits(rt5659->regmap, RT5659_PWR_ANLG_1,
 | 
				
			||||||
 | 
							RT5659_PWR_VREF2 | RT5659_PWR_MB,
 | 
				
			||||||
 | 
							RT5659_PWR_VREF2 | RT5659_PWR_MB);
 | 
				
			||||||
 | 
						msleep(20);
 | 
				
			||||||
 | 
						regmap_update_bits(rt5659->regmap, RT5659_PWR_ANLG_1,
 | 
				
			||||||
 | 
							RT5659_PWR_FV2, RT5659_PWR_FV2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						regmap_update_bits(rt5659->regmap, RT5659_PWR_ANLG_3, RT5659_PWR_LDO2,
 | 
				
			||||||
 | 
							RT5659_PWR_LDO2);
 | 
				
			||||||
 | 
						regmap_update_bits(rt5659->regmap, RT5659_PWR_ANLG_2, RT5659_PWR_MB1,
 | 
				
			||||||
 | 
							RT5659_PWR_MB1);
 | 
				
			||||||
 | 
						regmap_update_bits(rt5659->regmap, RT5659_PWR_VOL, RT5659_PWR_MIC_DET,
 | 
				
			||||||
 | 
							RT5659_PWR_MIC_DET);
 | 
				
			||||||
 | 
						msleep(20);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						regmap_update_bits(rt5659->regmap, RT5659_4BTN_IL_CMD_2,
 | 
				
			||||||
 | 
							RT5659_4BTN_IL_MASK, RT5659_4BTN_IL_EN);
 | 
				
			||||||
 | 
						regmap_read(rt5659->regmap, RT5659_4BTN_IL_CMD_1, &value);
 | 
				
			||||||
 | 
						regmap_write(rt5659->regmap, RT5659_4BTN_IL_CMD_1, value);
 | 
				
			||||||
 | 
						regmap_read(rt5659->regmap, RT5659_4BTN_IL_CMD_1, &value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (value & 0x2000) {
 | 
				
			||||||
 | 
							rt5659->hda_mic_plugged = true;
 | 
				
			||||||
 | 
							regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_2,
 | 
				
			||||||
 | 
								0x2, 0x2);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_2,
 | 
				
			||||||
 | 
								0x2, 0x0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_2,
 | 
				
			||||||
 | 
							RT5659_IL_IRQ_MASK, RT5659_IL_IRQ_EN);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int rt5659_i2c_probe(struct i2c_client *i2c,
 | 
					static int rt5659_i2c_probe(struct i2c_client *i2c,
 | 
				
			||||||
		    const struct i2c_device_id *id)
 | 
							    const struct i2c_device_id *id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -4174,16 +4277,23 @@ static int rt5659_i2c_probe(struct i2c_client *i2c,
 | 
				
			||||||
				RT5659_PWR_MB, RT5659_PWR_MB);
 | 
									RT5659_PWR_MB, RT5659_PWR_MB);
 | 
				
			||||||
		regmap_write(rt5659->regmap, RT5659_PWR_ANLG_2, 0x0001);
 | 
							regmap_write(rt5659->regmap, RT5659_PWR_ANLG_2, 0x0001);
 | 
				
			||||||
		regmap_write(rt5659->regmap, RT5659_IRQ_CTRL_2, 0x0040);
 | 
							regmap_write(rt5659->regmap, RT5659_IRQ_CTRL_2, 0x0040);
 | 
				
			||||||
 | 
							INIT_DELAYED_WORK(&rt5659->jack_detect_work,
 | 
				
			||||||
 | 
								rt5659_jack_detect_work);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case RT5659_JD_NULL:
 | 
						case RT5659_JD_HDA_HEADER:
 | 
				
			||||||
 | 
							regmap_write(rt5659->regmap, RT5659_GPIO_CTRL_3, 0x8000);
 | 
				
			||||||
 | 
							regmap_write(rt5659->regmap, RT5659_RC_CLK_CTRL, 0x0900);
 | 
				
			||||||
 | 
							regmap_write(rt5659->regmap, RT5659_EJD_CTRL_1,  0x70c0);
 | 
				
			||||||
 | 
							regmap_write(rt5659->regmap, RT5659_JD_CTRL_1,   0x2000);
 | 
				
			||||||
 | 
							regmap_write(rt5659->regmap, RT5659_IRQ_CTRL_1,  0x0040);
 | 
				
			||||||
 | 
							INIT_DELAYED_WORK(&rt5659->jack_detect_work,
 | 
				
			||||||
 | 
								rt5659_jack_detect_intel_hd_header);
 | 
				
			||||||
 | 
							rt5659_intel_hd_header_probe_setup(rt5659);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		dev_warn(&i2c->dev, "Currently, support JD3 only\n");
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	INIT_DELAYED_WORK(&rt5659->jack_detect_work, rt5659_jack_detect_work);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (i2c->irq) {
 | 
						if (i2c->irq) {
 | 
				
			||||||
		ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
 | 
							ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
 | 
				
			||||||
			rt5659_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
 | 
								rt5659_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1810,7 +1810,8 @@ struct rt5659_priv {
 | 
				
			||||||
	int pll_out;
 | 
						int pll_out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int jack_type;
 | 
						int jack_type;
 | 
				
			||||||
 | 
						bool hda_hp_plugged;
 | 
				
			||||||
 | 
						bool hda_mic_plugged;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int rt5659_set_jack_detect(struct snd_soc_codec *codec,
 | 
					int rt5659_set_jack_detect(struct snd_soc_codec *codec,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue