diff options
Diffstat (limited to 'meta-amdfalconx86/recipes-kernel/linux/files/1136-ALSA-Soc-RT286Codec-Modifications-to-ALSA-SOC-Audio.patch')
-rw-r--r-- | meta-amdfalconx86/recipes-kernel/linux/files/1136-ALSA-Soc-RT286Codec-Modifications-to-ALSA-SOC-Audio.patch | 370 |
1 files changed, 370 insertions, 0 deletions
diff --git a/meta-amdfalconx86/recipes-kernel/linux/files/1136-ALSA-Soc-RT286Codec-Modifications-to-ALSA-SOC-Audio.patch b/meta-amdfalconx86/recipes-kernel/linux/files/1136-ALSA-Soc-RT286Codec-Modifications-to-ALSA-SOC-Audio.patch new file mode 100644 index 00000000..8e1a80c0 --- /dev/null +++ b/meta-amdfalconx86/recipes-kernel/linux/files/1136-ALSA-Soc-RT286Codec-Modifications-to-ALSA-SOC-Audio.patch @@ -0,0 +1,370 @@ +From b4b235644a4e6a1d81da5c40dc492f1be70dcaeb Mon Sep 17 00:00:00 2001 +From: Maruthi Srinivas Bayyavarapu <Maruthi.Bayyavarapu@amd.com> +Date: Fri, 1 Jul 2016 13:33:43 +0530 +Subject: [PATCH 11/17] ALSA:Soc:RT286Codec :Modifications to ALSA SOC Audio + +Codec Driver. + +Signed-off-by: Maruthi Bayyavarapu <maruthi.bayyavarapu@amd.com> +Signed-off-by: Kalyan Alle <kalyan.alle@amd.com> +--- + sound/soc/codecs/rt286.c | 197 ++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 169 insertions(+), 28 deletions(-) + +diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c +index af2ed77..c67317b 100644 +--- a/sound/soc/codecs/rt286.c ++++ b/sound/soc/codecs/rt286.c +@@ -19,6 +19,7 @@ + #include <linux/spi/spi.h> + #include <linux/dmi.h> + #include <linux/acpi.h> ++#include <linux/gpio.h> + #include <sound/core.h> + #include <sound/pcm.h> + #include <sound/pcm_params.h> +@@ -29,16 +30,14 @@ + #include <sound/jack.h> + #include <linux/workqueue.h> + #include <sound/rt286.h> ++#include <sound/hda_verbs.h> + +-#include "rl6347a.h" + #include "rt286.h" + + #define RT286_VENDOR_ID 0x10ec0286 + #define RT288_VENDOR_ID 0x10ec0288 + + struct rt286_priv { +- struct reg_default *index_cache; +- int index_cache_size; + struct regmap *regmap; + struct snd_soc_codec *codec; + struct rt286_platform_data pdata; +@@ -47,9 +46,10 @@ struct rt286_priv { + struct delayed_work jack_detect_work; + int sys_clk; + int clk_id; ++ struct reg_default *index_cache; + }; + +-static const struct reg_default rt286_index_def[] = { ++static struct reg_default rt286_index_def[] = { + { 0x01, 0xaaaa }, + { 0x02, 0x8aaa }, + { 0x03, 0x0002 }, +@@ -186,6 +186,94 @@ static bool rt286_readable_register(struct device *dev, unsigned int reg) + } + } + ++static int rt286_hw_write(void *context, unsigned int reg, unsigned int value) ++{ ++ struct i2c_client *client = context; ++ struct rt286_priv *rt286 = i2c_get_clientdata(client); ++ u8 data[4]; ++ int ret, i; ++ ++ /* handle index registers */ ++ if (reg <= 0xff) { ++ rt286_hw_write(client, RT286_COEF_INDEX, reg); ++ for (i = 0; i < INDEX_CACHE_SIZE; i++) { ++ if (reg == rt286->index_cache[i].reg) { ++ rt286->index_cache[i].def = value; ++ break; ++ } ++ ++ } ++ reg = RT286_PROC_COEF; ++ } ++ ++ data[0] = (reg >> 24) & 0xff; ++ data[1] = (reg >> 16) & 0xff; ++ /* ++ * 4 bit VID: reg should be 0 ++ * 12 bit VID: value should be 0 ++ * So we use an OR operator to handle it rather than use if condition. ++ */ ++ data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff); ++ data[3] = value & 0xff; ++ ++ ret = i2c_master_send(client, data, 4); ++ ++ if (ret == 4) ++ return 0; ++ else ++ pr_err("ret=%d\n", ret); ++ if (ret < 0) ++ return ret; ++ else ++ return -EIO; ++} ++ ++static int rt286_hw_read(void *context, unsigned int reg, unsigned int *value) ++{ ++ struct i2c_client *client = context; ++ struct i2c_msg xfer[2]; ++ int ret; ++ __be32 be_reg; ++ unsigned int index, vid, buf = 0x0; ++ ++ /* handle index registers */ ++ if (reg <= 0xff) { ++ rt286_hw_write(client, RT286_COEF_INDEX, reg); ++ reg = RT286_PROC_COEF; ++ } ++ ++ reg = reg | 0x80000; ++ vid = (reg >> 8) & 0xfff; ++ ++ if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) { ++ index = (reg >> 8) & 0xf; ++ reg = (reg & ~0xf0f) | index; ++ } ++ be_reg = cpu_to_be32(reg); ++ ++ /* Write register */ ++ xfer[0].addr = client->addr; ++ xfer[0].flags = 0; ++ xfer[0].len = 4; ++ xfer[0].buf = (u8 *)&be_reg; ++ ++ /* Read data */ ++ xfer[1].addr = client->addr; ++ xfer[1].flags = I2C_M_RD; ++ xfer[1].len = 4; ++ xfer[1].buf = (u8 *)&buf; ++ ++ ret = i2c_transfer(client->adapter, xfer, 2); ++ if (ret < 0) ++ return ret; ++ else if (ret != 2) ++ return -EIO; ++ ++ *value = be32_to_cpu(buf); ++ ++ return 0; ++} ++ + #ifdef CONFIG_PM + static void rt286_index_sync(struct snd_soc_codec *codec) + { +@@ -272,6 +360,15 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) + *hp = buf & 0x80000000; + regmap_read(rt286->regmap, RT286_GET_MIC1_SENSE, &buf); + *mic = buf & 0x80000000; ++ if (*mic) { ++ regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24); ++ msleep(50); ++ ++ regmap_update_bits(rt286->regmap, ++ RT286_CBJ_CTRL1, ++ 0xfcc0, 0xd400); ++ msleep(300); ++ } + } + + snd_soc_dapm_disable_pin(dapm, "HV"); +@@ -695,6 +792,7 @@ static int rt286_hw_params(struct snd_pcm_substream *substream, + unsigned int val = 0; + int d_len_code; + ++ pr_err("%s : rate : %d clk %d ch %d width %d\n",__func__,params_rate(params),rt286->sys_clk, params_channels(params), params_width(params)); + switch (params_rate(params)) { + /* bit 14 0:48K 1:44.1K */ + case 44100: +@@ -763,7 +861,8 @@ static int rt286_hw_params(struct snd_pcm_substream *substream, + + snd_soc_update_bits(codec, + RT286_I2S_CTRL1, 0x0018, d_len_code << 3); +- dev_dbg(codec->dev, "format val = 0x%x\n", val); ++ //dev_dbg(codec->dev, "format val = 0x%x\n", val); ++ pr_err("format val = 0x%x\n", val); + + snd_soc_update_bits(codec, RT286_DAC_FORMAT, 0x407f, val); + snd_soc_update_bits(codec, RT286_ADC_FORMAT, 0x407f, val); +@@ -927,6 +1026,7 @@ static int rt286_set_bias_level(struct snd_soc_codec *codec, + default: + break; + } ++ //codec->dapm.bias_level = level; + + return 0; + } +@@ -992,7 +1092,6 @@ static int rt286_suspend(struct snd_soc_codec *codec) + + regcache_cache_only(rt286->regmap, true); + regcache_mark_dirty(rt286->regmap); +- + return 0; + } + +@@ -1003,7 +1102,6 @@ static int rt286_resume(struct snd_soc_codec *codec) + regcache_cache_only(rt286->regmap, false); + rt286_index_sync(codec); + regcache_sync(rt286->regmap); +- + return 0; + } + #else +@@ -1013,7 +1111,8 @@ static int rt286_resume(struct snd_soc_codec *codec) + + #define RT286_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) + #define RT286_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ +- SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) ++ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) | \ ++ SNDRV_PCM_FMTBIT_S32_LE + + static const struct snd_soc_dai_ops rt286_aif_dai_ops = { + .hw_params = rt286_hw_params, +@@ -1087,8 +1186,8 @@ static const struct regmap_config rt286_regmap = { + .max_register = 0x02370100, + .volatile_reg = rt286_volatile_register, + .readable_reg = rt286_readable_register, +- .reg_write = rl6347a_hw_write, +- .reg_read = rl6347a_hw_read, ++ .reg_write = rt286_hw_write, ++ .reg_read = rt286_hw_read, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt286_reg, + .num_reg_defaults = ARRAY_SIZE(rt286_reg), +@@ -1103,11 +1202,12 @@ MODULE_DEVICE_TABLE(i2c, rt286_i2c_id); + + static const struct acpi_device_id rt286_acpi_match[] = { + { "INT343A", 0 }, ++ { "RTK0000", 0}, + {}, + }; + MODULE_DEVICE_TABLE(acpi, rt286_acpi_match); + +-static const struct dmi_system_id force_combo_jack_table[] = { ++static struct dmi_system_id force_combo_jack_table[] = { + { + .ident = "Intel Wilson Beach", + .matches = { +@@ -1117,7 +1217,7 @@ static const struct dmi_system_id force_combo_jack_table[] = { + { } + }; + +-static const struct dmi_system_id dmi_dell_dino[] = { ++static struct dmi_system_id dmi_dell_dino[] = { + { + .ident = "Dell Dino", + .matches = { +@@ -1128,13 +1228,53 @@ static const struct dmi_system_id dmi_dell_dino[] = { + { } + }; + ++static struct rt286_platform_data rt286_acpi_data = { ++ .cbj_en = false, ++ .gpio2_en = false, ++}; ++ ++#if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB) ++ ++static int get_gpio_irq(struct acpi_resource *ares, void *data) ++{ ++ if ((ares->type == ACPI_RESOURCE_GPIO_TYPE_INT) || ++ (ares->type == ACPI_RESOURCE_TYPE_GPIO)) { ++ int *irq = data; ++ *irq = gpio_to_irq(ares->data.gpio.pin_table[0]); ++ } ++ return 1; ++} ++ ++static int acpi_get_gpio_irq_res(struct device *idev) ++{ ++ int irq; ++ struct acpi_device *adev; ++ struct list_head resource_list; ++ acpi_handle handle; ++ ++ INIT_LIST_HEAD(&resource_list); ++ handle = ACPI_HANDLE(idev); ++ ++ if (!handle || acpi_bus_get_device(handle, &adev)) ++ return -ENODEV; ++ ++ acpi_dev_get_resources(adev, &resource_list, ++ get_gpio_irq, &irq); ++ acpi_dev_free_resource_list(&resource_list); ++ ++ return irq; ++} ++ ++#endif ++ + static int rt286_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) + { +- struct rt286_platform_data *pdata = dev_get_platdata(&i2c->dev); ++ struct rt286_platform_data *pdata = &rt286_acpi_data; + struct rt286_priv *rt286; + int i, ret, val; + ++ pr_err("%s : called\n",__func__); + rt286 = devm_kzalloc(&i2c->dev, sizeof(*rt286), + GFP_KERNEL); + if (NULL == rt286) +@@ -1156,16 +1296,11 @@ static int rt286_i2c_probe(struct i2c_client *i2c, + } + if (val != RT286_VENDOR_ID && val != RT288_VENDOR_ID) { + dev_err(&i2c->dev, +- "Device with ID register %#x is not rt286\n", val); ++ "Device with ID register %x is not rt286\n", val); + return -ENODEV; + } + +- rt286->index_cache = devm_kmemdup(&i2c->dev, rt286_index_def, +- sizeof(rt286_index_def), GFP_KERNEL); +- if (!rt286->index_cache) +- return -ENOMEM; +- +- rt286->index_cache_size = INDEX_CACHE_SIZE; ++ rt286->index_cache = rt286_index_def; + rt286->i2c = i2c; + i2c_set_clientdata(i2c, rt286); + +@@ -1231,19 +1366,24 @@ static int rt286_i2c_probe(struct i2c_client *i2c, + RT286_GPIO_CTRL, 0xc, 0x8); + } + +- if (rt286->i2c->irq) { +- ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq, +- IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286); +- if (ret != 0) { +- dev_err(&i2c->dev, +- "Failed to reguest IRQ: %d\n", ret); +- return ret; +- } ++ if (rt286->i2c->irq < 0) { ++ rt286->i2c->irq = acpi_get_gpio_irq_res(&rt286->i2c->dev); ++ if (rt286->i2c->irq < 0) ++ return -ENODEV; ++ } ++ ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq, ++ IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rt286", rt286); ++ if (ret != 0) { ++ dev_err(&i2c->dev, ++ "Failed to reguest IRQ: %d\n", ret); ++ return ret; + } + + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt286, + rt286_dai, ARRAY_SIZE(rt286_dai)); + ++ pr_err("%s : ret = %d\n",__func__,ret); ++ + return ret; + } + +@@ -1262,6 +1402,7 @@ static int rt286_i2c_remove(struct i2c_client *i2c) + static struct i2c_driver rt286_i2c_driver = { + .driver = { + .name = "rt286", ++ .owner = THIS_MODULE, + .acpi_match_table = ACPI_PTR(rt286_acpi_match), + }, + .probe = rt286_i2c_probe, +-- +2.7.4 + |