适配新七寸屏和AW83791芯片
This commit is contained in:
+14
-1
@@ -1290,6 +1290,12 @@ static int aw87xxx_acf_bin_load(struct aw87xxx *aw87xxx)
|
||||
ret = request_firmware(&cont, aw87xxx->fw_name, aw87xxx->dev);
|
||||
if ((ret) || (!cont)) {
|
||||
AW_DEV_LOGD(aw87xxx->dev, "load [%s] failed!", aw87xxx->fw_name);
|
||||
if (aw87xxx->aw_dev.chipid == AW_DEV_CHIPID_C1) {
|
||||
AW_DEV_LOGI(aw87xxx->dev,
|
||||
"no ACF for AW87391, use safe built-in defaults");
|
||||
return aw87391_acf_load_builtin(aw87xxx->dev,
|
||||
&aw87xxx->acf_info);
|
||||
}
|
||||
if (acf_info->load_count == AW_READ_CHIPID_RETRIES) {
|
||||
acf_info->load_count = 0;
|
||||
} else {
|
||||
@@ -1319,7 +1325,14 @@ static int aw87xxx_acf_bin_load(struct aw87xxx *aw87xxx)
|
||||
|
||||
ret = aw87xxx_acf_parse(aw87xxx->dev, &aw87xxx->acf_info);
|
||||
if (ret < 0) {
|
||||
AW_DEV_LOGE(aw87xxx->dev, "fw_data parse failed");
|
||||
if (aw87xxx->aw_dev.chipid == AW_DEV_CHIPID_C1) {
|
||||
AW_DEV_LOGI(aw87xxx->dev,
|
||||
"ACF has no AW87391 profile, use safe built-in defaults");
|
||||
ret = aw87391_acf_load_builtin(aw87xxx->dev,
|
||||
&aw87xxx->acf_info);
|
||||
} else {
|
||||
AW_DEV_LOGE(aw87xxx->dev, "fw_data parse failed");
|
||||
}
|
||||
goto exit_acf_parse_failed;
|
||||
}
|
||||
|
||||
|
||||
+90
@@ -80,6 +80,55 @@ static char *g_profile_name[] = {"Music", "Voice", "Voip",
|
||||
|
||||
static char *g_power_off_name[] = {"Off", "OFF", "off", "oFF", "power_down"};
|
||||
|
||||
/*
|
||||
* Safe AW87391 fallback profiles derived from the public register definitions
|
||||
* in the AW87391 V1.2 data sheet. The board's legacy ACF contains AW87390
|
||||
* (chip-id 0x76) data only; those values must never be written to AW87391
|
||||
* (chip-id 0xc1), whose public register map is different.
|
||||
*
|
||||
* Keep EN_SW clear while programming and write it last when powering on.
|
||||
* Only public registers 0x00..0x05 are touched. Keep the board's legacy 8.0 V
|
||||
* charge-pump limit (0x06 on AW87391) and use the conservative default AGC2
|
||||
* limit of 1.2 W into 8 ohm. A product-specific ACF, when supplied, is still
|
||||
* preferred and bypasses this fallback entirely.
|
||||
*/
|
||||
static uint8_t g_aw87391_music_profile[] = {
|
||||
0x00, 0xaa,
|
||||
AW87XXX_DELAY_REG_ADDR, 0x01,
|
||||
0x02, 0x06,
|
||||
0x03, 0x02,
|
||||
0x04, 0x47,
|
||||
0x05, 0x4e,
|
||||
0x01, 0x3f,
|
||||
};
|
||||
|
||||
static uint8_t g_aw87391_off_profile[] = {
|
||||
0x01, 0x3e,
|
||||
};
|
||||
|
||||
static uint8_t g_aw87391_receiver_profile[] = {
|
||||
0x00, 0xaa,
|
||||
AW87XXX_DELAY_REG_ADDR, 0x01,
|
||||
0x02, 0x06,
|
||||
0x03, 0x00,
|
||||
0x04, 0x47,
|
||||
0x05, 0x4e,
|
||||
0x01, 0x37,
|
||||
};
|
||||
|
||||
struct aw87391_builtin_profile {
|
||||
const char *name;
|
||||
uint8_t *data;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
static const struct aw87391_builtin_profile g_aw87391_builtin_profiles[] = {
|
||||
{ "Music", g_aw87391_music_profile, ARRAY_SIZE(g_aw87391_music_profile) },
|
||||
{ "Off", g_aw87391_off_profile, ARRAY_SIZE(g_aw87391_off_profile) },
|
||||
{ "Receiver", g_aw87391_receiver_profile,
|
||||
ARRAY_SIZE(g_aw87391_receiver_profile) },
|
||||
};
|
||||
|
||||
static char *aw_get_prof_name(int profile)
|
||||
{
|
||||
if (profile < 0 || profile >= AW_PROFILE_MAX)
|
||||
@@ -1464,6 +1513,47 @@ void aw87xxx_acf_profile_free(struct device *dev, struct acf_bin_info *acf_info)
|
||||
}
|
||||
}
|
||||
|
||||
int aw87391_acf_load_builtin(struct device *dev,
|
||||
struct acf_bin_info *acf_info)
|
||||
{
|
||||
struct aw_prof_info *prof_info = &acf_info->prof_info;
|
||||
int count = ARRAY_SIZE(g_aw87391_builtin_profiles);
|
||||
int i;
|
||||
|
||||
aw87xxx_acf_profile_free(dev, acf_info);
|
||||
|
||||
prof_info->prof_name_list = devm_kcalloc(dev, count,
|
||||
AW_PROFILE_STR_MAX, GFP_KERNEL);
|
||||
if (!prof_info->prof_name_list)
|
||||
return -ENOMEM;
|
||||
|
||||
prof_info->prof_desc = devm_kcalloc(dev, count,
|
||||
sizeof(*prof_info->prof_desc), GFP_KERNEL);
|
||||
if (!prof_info->prof_desc) {
|
||||
devm_kfree(dev, prof_info->prof_name_list);
|
||||
prof_info->prof_name_list = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
snprintf(prof_info->prof_name_list[i], AW_PROFILE_STR_MAX, "%s",
|
||||
g_aw87391_builtin_profiles[i].name);
|
||||
prof_info->prof_desc[i].prof_name = prof_info->prof_name_list[i];
|
||||
prof_info->prof_desc[i].prof_st = AW_PROFILE_OK;
|
||||
prof_info->prof_desc[i].data_container.data =
|
||||
g_aw87391_builtin_profiles[i].data;
|
||||
prof_info->prof_desc[i].data_container.len =
|
||||
g_aw87391_builtin_profiles[i].len;
|
||||
}
|
||||
|
||||
prof_info->count = count;
|
||||
prof_info->prof_type = AW_DDE_DEV_DEFAULT_TYPE_ID;
|
||||
prof_info->status = AW_ACF_UPDATE;
|
||||
AW_DEV_LOGI(dev, "loaded built-in AW87391 safe profiles");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aw_parse_single_bin(struct device *dev, struct acf_bin_info *acf_info,
|
||||
struct aw_data_container aw_fw_data, int prof_index)
|
||||
{
|
||||
|
||||
+2
@@ -193,6 +193,8 @@ char *aw87xxx_ctos_get_prof_name(int profile_id);
|
||||
void aw87xxx_acf_profile_free(struct device *dev,
|
||||
struct acf_bin_info *acf_info);
|
||||
int aw87xxx_acf_parse(struct device *dev, struct acf_bin_info *acf_info);
|
||||
int aw87391_acf_load_builtin(struct device *dev,
|
||||
struct acf_bin_info *acf_info);
|
||||
struct aw_prof_desc *aw87xxx_acf_get_prof_desc_form_name(struct device *dev,
|
||||
struct acf_bin_info *acf_info, char *profile_name);
|
||||
int aw87xxx_acf_get_prof_index_form_name(struct device *dev,
|
||||
|
||||
+4
-3
@@ -226,8 +226,9 @@ static struct sprd_headset *sprd_hdst;
|
||||
|
||||
static void sprd_enable_hmicbias_polling(bool enable, bool force_disable);
|
||||
/*
|
||||
* When remove headphone, disconnect the headphone
|
||||
* dapm DA path in codec driver.
|
||||
* Keep the UMP9620 "HP Virt" DAPM path in sync with jack state.
|
||||
* SND_SOC_DAPM_SWITCH_E("HP Virt", ...) exposes the mixer control as
|
||||
* "HP Virt Switch".
|
||||
*/
|
||||
static int dapm_jack_switch_control(struct snd_soc_component *codec, bool on)
|
||||
{
|
||||
@@ -235,7 +236,7 @@ static int dapm_jack_switch_control(struct snd_soc_component *codec, bool on)
|
||||
struct snd_soc_card *card = codec ? codec->card : NULL;
|
||||
struct snd_ctl_elem_id id = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.name = "Virt HP Jack Switch",
|
||||
.name = "HP Virt Switch",
|
||||
};
|
||||
struct snd_ctl_elem_value ucontrol = {
|
||||
.value.integer.value[0] = on,
|
||||
|
||||
Reference in New Issue
Block a user