Commit a18d5151 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'asoc/topic/arizona' into asoc-next

parents 0680fa6c b6ed61cf
...@@ -100,6 +100,55 @@ static const char *arizona_cable[] = { ...@@ -100,6 +100,55 @@ static const char *arizona_cable[] = {
NULL, NULL,
}; };
static void arizona_extcon_do_magic(struct arizona_extcon_info *info,
unsigned int magic)
{
struct arizona *arizona = info->arizona;
int ret;
mutex_lock(&arizona->dapm->card->dapm_mutex);
arizona->hpdet_magic = magic;
/* Keep the HP output stages disabled while doing the magic */
if (magic) {
ret = regmap_update_bits(arizona->regmap,
ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT1L_ENA |
ARIZONA_OUT1R_ENA, 0);
if (ret != 0)
dev_warn(arizona->dev,
"Failed to disable headphone outputs: %d\n",
ret);
}
ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000,
magic);
if (ret != 0)
dev_warn(arizona->dev, "Failed to do magic: %d\n",
ret);
ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000,
magic);
if (ret != 0)
dev_warn(arizona->dev, "Failed to do magic: %d\n",
ret);
/* Restore the desired state while not doing the magic */
if (!magic) {
ret = regmap_update_bits(arizona->regmap,
ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT1L_ENA |
ARIZONA_OUT1R_ENA, arizona->hp_ena);
if (ret != 0)
dev_warn(arizona->dev,
"Failed to restore headphone outputs: %d\n",
ret);
}
mutex_unlock(&arizona->dapm->card->dapm_mutex);
}
static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode) static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
{ {
struct arizona *arizona = info->arizona; struct arizona *arizona = info->arizona;
...@@ -484,7 +533,6 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) ...@@ -484,7 +533,6 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
struct arizona *arizona = info->arizona; struct arizona *arizona = info->arizona;
int id_gpio = arizona->pdata.hpdet_id_gpio; int id_gpio = arizona->pdata.hpdet_id_gpio;
int report = ARIZONA_CABLE_HEADPHONE; int report = ARIZONA_CABLE_HEADPHONE;
unsigned int val;
int ret, reading; int ret, reading;
mutex_lock(&info->lock); mutex_lock(&info->lock);
...@@ -539,28 +587,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) ...@@ -539,28 +587,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
dev_err(arizona->dev, "Failed to report HP/line: %d\n", dev_err(arizona->dev, "Failed to report HP/line: %d\n",
ret); ret);
mutex_lock(&arizona->dapm->card->dapm_mutex); arizona_extcon_do_magic(info, 0);
ret = regmap_read(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1, &val);
if (ret != 0) {
dev_err(arizona->dev, "Failed to read output enables: %d\n",
ret);
val = 0;
}
if (!(val & (ARIZONA_OUT1L_ENA | ARIZONA_OUT1R_ENA))) {
ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 0);
if (ret != 0)
dev_warn(arizona->dev, "Failed to undo magic: %d\n",
ret);
ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, 0);
if (ret != 0)
dev_warn(arizona->dev, "Failed to undo magic: %d\n",
ret);
}
mutex_unlock(&arizona->dapm->card->dapm_mutex);
done: done:
if (id_gpio) if (id_gpio)
...@@ -606,13 +633,7 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info) ...@@ -606,13 +633,7 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)
if (info->mic) if (info->mic)
arizona_stop_mic(info); arizona_stop_mic(info);
ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 0x4000); arizona_extcon_do_magic(info, 0x4000);
if (ret != 0)
dev_warn(arizona->dev, "Failed to do magic: %d\n", ret);
ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, 0x4000);
if (ret != 0)
dev_warn(arizona->dev, "Failed to do magic: %d\n", ret);
ret = regmap_update_bits(arizona->regmap, ret = regmap_update_bits(arizona->regmap,
ARIZONA_ACCESSORY_DETECT_MODE_1, ARIZONA_ACCESSORY_DETECT_MODE_1,
...@@ -653,7 +674,6 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info) ...@@ -653,7 +674,6 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)
static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info) static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
{ {
struct arizona *arizona = info->arizona; struct arizona *arizona = info->arizona;
unsigned int val;
int ret; int ret;
dev_dbg(arizona->dev, "Starting identification via HPDET\n"); dev_dbg(arizona->dev, "Starting identification via HPDET\n");
...@@ -665,30 +685,7 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info) ...@@ -665,30 +685,7 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
arizona_extcon_pulse_micbias(info); arizona_extcon_pulse_micbias(info);
mutex_lock(&arizona->dapm->card->dapm_mutex); arizona_extcon_do_magic(info, 0x4000);
ret = regmap_read(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1, &val);
if (ret != 0) {
dev_err(arizona->dev, "Failed to read output enables: %d\n",
ret);
val = 0;
}
if (!(val & (ARIZONA_OUT1L_ENA | ARIZONA_OUT1R_ENA))) {
ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000,
0x4000);
if (ret != 0)
dev_warn(arizona->dev, "Failed to do magic: %d\n",
ret);
ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000,
0x4000);
if (ret != 0)
dev_warn(arizona->dev, "Failed to do magic: %d\n",
ret);
}
mutex_unlock(&arizona->dapm->card->dapm_mutex);
ret = regmap_update_bits(arizona->regmap, ret = regmap_update_bits(arizona->regmap,
ARIZONA_ACCESSORY_DETECT_MODE_1, ARIZONA_ACCESSORY_DETECT_MODE_1,
......
...@@ -290,12 +290,14 @@ static const struct reg_default wm5102_reg_default[] = { ...@@ -290,12 +290,14 @@ static const struct reg_default wm5102_reg_default[] = {
{ 0x00000176, 0x0000 }, /* R374 - FLL1 Control 6 */ { 0x00000176, 0x0000 }, /* R374 - FLL1 Control 6 */
{ 0x00000177, 0x0181 }, /* R375 - FLL1 Loop Filter Test 1 */ { 0x00000177, 0x0181 }, /* R375 - FLL1 Loop Filter Test 1 */
{ 0x00000178, 0x0000 }, /* R376 - FLL1 NCO Test 0 */ { 0x00000178, 0x0000 }, /* R376 - FLL1 NCO Test 0 */
{ 0x00000179, 0x0000 }, /* R377 - FLL1 Control 7 */
{ 0x00000181, 0x0000 }, /* R385 - FLL1 Synchroniser 1 */ { 0x00000181, 0x0000 }, /* R385 - FLL1 Synchroniser 1 */
{ 0x00000182, 0x0000 }, /* R386 - FLL1 Synchroniser 2 */ { 0x00000182, 0x0000 }, /* R386 - FLL1 Synchroniser 2 */
{ 0x00000183, 0x0000 }, /* R387 - FLL1 Synchroniser 3 */ { 0x00000183, 0x0000 }, /* R387 - FLL1 Synchroniser 3 */
{ 0x00000184, 0x0000 }, /* R388 - FLL1 Synchroniser 4 */ { 0x00000184, 0x0000 }, /* R388 - FLL1 Synchroniser 4 */
{ 0x00000185, 0x0000 }, /* R389 - FLL1 Synchroniser 5 */ { 0x00000185, 0x0000 }, /* R389 - FLL1 Synchroniser 5 */
{ 0x00000186, 0x0000 }, /* R390 - FLL1 Synchroniser 6 */ { 0x00000186, 0x0000 }, /* R390 - FLL1 Synchroniser 6 */
{ 0x00000187, 0x0001 }, /* R391 - FLL1 Synchroniser 7 */
{ 0x00000189, 0x0000 }, /* R393 - FLL1 Spread Spectrum */ { 0x00000189, 0x0000 }, /* R393 - FLL1 Spread Spectrum */
{ 0x0000018A, 0x0004 }, /* R394 - FLL1 GPIO Clock */ { 0x0000018A, 0x0004 }, /* R394 - FLL1 GPIO Clock */
{ 0x00000191, 0x0000 }, /* R401 - FLL2 Control 1 */ { 0x00000191, 0x0000 }, /* R401 - FLL2 Control 1 */
...@@ -306,12 +308,14 @@ static const struct reg_default wm5102_reg_default[] = { ...@@ -306,12 +308,14 @@ static const struct reg_default wm5102_reg_default[] = {
{ 0x00000196, 0x0000 }, /* R406 - FLL2 Control 6 */ { 0x00000196, 0x0000 }, /* R406 - FLL2 Control 6 */
{ 0x00000197, 0x0000 }, /* R407 - FLL2 Loop Filter Test 1 */ { 0x00000197, 0x0000 }, /* R407 - FLL2 Loop Filter Test 1 */
{ 0x00000198, 0x0000 }, /* R408 - FLL2 NCO Test 0 */ { 0x00000198, 0x0000 }, /* R408 - FLL2 NCO Test 0 */
{ 0x00000199, 0x0000 }, /* R409 - FLL2 Control 7 */
{ 0x000001A1, 0x0000 }, /* R417 - FLL2 Synchroniser 1 */ { 0x000001A1, 0x0000 }, /* R417 - FLL2 Synchroniser 1 */
{ 0x000001A2, 0x0000 }, /* R418 - FLL2 Synchroniser 2 */ { 0x000001A2, 0x0000 }, /* R418 - FLL2 Synchroniser 2 */
{ 0x000001A3, 0x0000 }, /* R419 - FLL2 Synchroniser 3 */ { 0x000001A3, 0x0000 }, /* R419 - FLL2 Synchroniser 3 */
{ 0x000001A4, 0x0000 }, /* R420 - FLL2 Synchroniser 4 */ { 0x000001A4, 0x0000 }, /* R420 - FLL2 Synchroniser 4 */
{ 0x000001A5, 0x0000 }, /* R421 - FLL2 Synchroniser 5 */ { 0x000001A5, 0x0000 }, /* R421 - FLL2 Synchroniser 5 */
{ 0x000001A6, 0x0000 }, /* R422 - FLL2 Synchroniser 6 */ { 0x000001A6, 0x0000 }, /* R422 - FLL2 Synchroniser 6 */
{ 0x000001A7, 0x0001 }, /* R423 - FLL2 Synchroniser 7 */
{ 0x000001A9, 0x0000 }, /* R425 - FLL2 Spread Spectrum */ { 0x000001A9, 0x0000 }, /* R425 - FLL2 Spread Spectrum */
{ 0x000001AA, 0x0004 }, /* R426 - FLL2 GPIO Clock */ { 0x000001AA, 0x0004 }, /* R426 - FLL2 GPIO Clock */
{ 0x00000200, 0x0006 }, /* R512 - Mic Charge Pump 1 */ { 0x00000200, 0x0006 }, /* R512 - Mic Charge Pump 1 */
...@@ -1051,12 +1055,14 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg) ...@@ -1051,12 +1055,14 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_FLL1_CONTROL_6: case ARIZONA_FLL1_CONTROL_6:
case ARIZONA_FLL1_LOOP_FILTER_TEST_1: case ARIZONA_FLL1_LOOP_FILTER_TEST_1:
case ARIZONA_FLL1_NCO_TEST_0: case ARIZONA_FLL1_NCO_TEST_0:
case ARIZONA_FLL1_CONTROL_7:
case ARIZONA_FLL1_SYNCHRONISER_1: case ARIZONA_FLL1_SYNCHRONISER_1:
case ARIZONA_FLL1_SYNCHRONISER_2: case ARIZONA_FLL1_SYNCHRONISER_2:
case ARIZONA_FLL1_SYNCHRONISER_3: case ARIZONA_FLL1_SYNCHRONISER_3:
case ARIZONA_FLL1_SYNCHRONISER_4: case ARIZONA_FLL1_SYNCHRONISER_4:
case ARIZONA_FLL1_SYNCHRONISER_5: case ARIZONA_FLL1_SYNCHRONISER_5:
case ARIZONA_FLL1_SYNCHRONISER_6: case ARIZONA_FLL1_SYNCHRONISER_6:
case ARIZONA_FLL1_SYNCHRONISER_7:
case ARIZONA_FLL1_SPREAD_SPECTRUM: case ARIZONA_FLL1_SPREAD_SPECTRUM:
case ARIZONA_FLL1_GPIO_CLOCK: case ARIZONA_FLL1_GPIO_CLOCK:
case ARIZONA_FLL2_CONTROL_1: case ARIZONA_FLL2_CONTROL_1:
...@@ -1067,12 +1073,14 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg) ...@@ -1067,12 +1073,14 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_FLL2_CONTROL_6: case ARIZONA_FLL2_CONTROL_6:
case ARIZONA_FLL2_LOOP_FILTER_TEST_1: case ARIZONA_FLL2_LOOP_FILTER_TEST_1:
case ARIZONA_FLL2_NCO_TEST_0: case ARIZONA_FLL2_NCO_TEST_0:
case ARIZONA_FLL2_CONTROL_7:
case ARIZONA_FLL2_SYNCHRONISER_1: case ARIZONA_FLL2_SYNCHRONISER_1:
case ARIZONA_FLL2_SYNCHRONISER_2: case ARIZONA_FLL2_SYNCHRONISER_2:
case ARIZONA_FLL2_SYNCHRONISER_3: case ARIZONA_FLL2_SYNCHRONISER_3:
case ARIZONA_FLL2_SYNCHRONISER_4: case ARIZONA_FLL2_SYNCHRONISER_4:
case ARIZONA_FLL2_SYNCHRONISER_5: case ARIZONA_FLL2_SYNCHRONISER_5:
case ARIZONA_FLL2_SYNCHRONISER_6: case ARIZONA_FLL2_SYNCHRONISER_6:
case ARIZONA_FLL2_SYNCHRONISER_7:
case ARIZONA_FLL2_SPREAD_SPECTRUM: case ARIZONA_FLL2_SPREAD_SPECTRUM:
case ARIZONA_FLL2_GPIO_CLOCK: case ARIZONA_FLL2_GPIO_CLOCK:
case ARIZONA_MIC_CHARGE_PUMP_1: case ARIZONA_MIC_CHARGE_PUMP_1:
...@@ -1161,6 +1169,8 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg) ...@@ -1161,6 +1169,8 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_NOISE_GATE_CONTROL: case ARIZONA_NOISE_GATE_CONTROL:
case ARIZONA_PDM_SPK1_CTRL_1: case ARIZONA_PDM_SPK1_CTRL_1:
case ARIZONA_PDM_SPK1_CTRL_2: case ARIZONA_PDM_SPK1_CTRL_2:
case ARIZONA_SPK_CTRL_2:
case ARIZONA_SPK_CTRL_3:
case ARIZONA_DAC_COMP_1: case ARIZONA_DAC_COMP_1:
case ARIZONA_DAC_COMP_2: case ARIZONA_DAC_COMP_2:
case ARIZONA_DAC_COMP_3: case ARIZONA_DAC_COMP_3:
......
...@@ -100,6 +100,9 @@ struct arizona { ...@@ -100,6 +100,9 @@ struct arizona {
struct regmap_irq_chip_data *aod_irq_chip; struct regmap_irq_chip_data *aod_irq_chip;
struct regmap_irq_chip_data *irq_chip; struct regmap_irq_chip_data *irq_chip;
bool hpdet_magic;
unsigned int hp_ena;
struct mutex clk_lock; struct mutex clk_lock;
int clk32k_ref; int clk32k_ref;
......
...@@ -85,12 +85,14 @@ ...@@ -85,12 +85,14 @@
#define ARIZONA_FLL1_CONTROL_6 0x176 #define ARIZONA_FLL1_CONTROL_6 0x176
#define ARIZONA_FLL1_LOOP_FILTER_TEST_1 0x177 #define ARIZONA_FLL1_LOOP_FILTER_TEST_1 0x177
#define ARIZONA_FLL1_NCO_TEST_0 0x178 #define ARIZONA_FLL1_NCO_TEST_0 0x178
#define ARIZONA_FLL1_CONTROL_7 0x179
#define ARIZONA_FLL1_SYNCHRONISER_1 0x181 #define ARIZONA_FLL1_SYNCHRONISER_1 0x181
#define ARIZONA_FLL1_SYNCHRONISER_2 0x182 #define ARIZONA_FLL1_SYNCHRONISER_2 0x182
#define ARIZONA_FLL1_SYNCHRONISER_3 0x183 #define ARIZONA_FLL1_SYNCHRONISER_3 0x183
#define ARIZONA_FLL1_SYNCHRONISER_4 0x184 #define ARIZONA_FLL1_SYNCHRONISER_4 0x184
#define ARIZONA_FLL1_SYNCHRONISER_5 0x185 #define ARIZONA_FLL1_SYNCHRONISER_5 0x185
#define ARIZONA_FLL1_SYNCHRONISER_6 0x186 #define ARIZONA_FLL1_SYNCHRONISER_6 0x186
#define ARIZONA_FLL1_SYNCHRONISER_7 0x187
#define ARIZONA_FLL1_SPREAD_SPECTRUM 0x189 #define ARIZONA_FLL1_SPREAD_SPECTRUM 0x189
#define ARIZONA_FLL1_GPIO_CLOCK 0x18A #define ARIZONA_FLL1_GPIO_CLOCK 0x18A
#define ARIZONA_FLL2_CONTROL_1 0x191 #define ARIZONA_FLL2_CONTROL_1 0x191
...@@ -101,12 +103,14 @@ ...@@ -101,12 +103,14 @@
#define ARIZONA_FLL2_CONTROL_6 0x196 #define ARIZONA_FLL2_CONTROL_6 0x196
#define ARIZONA_FLL2_LOOP_FILTER_TEST_1 0x197 #define ARIZONA_FLL2_LOOP_FILTER_TEST_1 0x197
#define ARIZONA_FLL2_NCO_TEST_0 0x198 #define ARIZONA_FLL2_NCO_TEST_0 0x198
#define ARIZONA_FLL2_CONTROL_7 0x199
#define ARIZONA_FLL2_SYNCHRONISER_1 0x1A1 #define ARIZONA_FLL2_SYNCHRONISER_1 0x1A1
#define ARIZONA_FLL2_SYNCHRONISER_2 0x1A2 #define ARIZONA_FLL2_SYNCHRONISER_2 0x1A2
#define ARIZONA_FLL2_SYNCHRONISER_3 0x1A3 #define ARIZONA_FLL2_SYNCHRONISER_3 0x1A3
#define ARIZONA_FLL2_SYNCHRONISER_4 0x1A4 #define ARIZONA_FLL2_SYNCHRONISER_4 0x1A4
#define ARIZONA_FLL2_SYNCHRONISER_5 0x1A5 #define ARIZONA_FLL2_SYNCHRONISER_5 0x1A5
#define ARIZONA_FLL2_SYNCHRONISER_6 0x1A6 #define ARIZONA_FLL2_SYNCHRONISER_6 0x1A6
#define ARIZONA_FLL2_SYNCHRONISER_7 0x1A7
#define ARIZONA_FLL2_SPREAD_SPECTRUM 0x1A9 #define ARIZONA_FLL2_SPREAD_SPECTRUM 0x1A9
#define ARIZONA_FLL2_GPIO_CLOCK 0x1AA #define ARIZONA_FLL2_GPIO_CLOCK 0x1AA
#define ARIZONA_MIC_CHARGE_PUMP_1 0x200 #define ARIZONA_MIC_CHARGE_PUMP_1 0x200
...@@ -213,6 +217,8 @@ ...@@ -213,6 +217,8 @@
#define ARIZONA_PDM_SPK1_CTRL_2 0x491 #define ARIZONA_PDM_SPK1_CTRL_2 0x491
#define ARIZONA_PDM_SPK2_CTRL_1 0x492 #define ARIZONA_PDM_SPK2_CTRL_1 0x492
#define ARIZONA_PDM_SPK2_CTRL_2 0x493 #define ARIZONA_PDM_SPK2_CTRL_2 0x493
#define ARIZONA_SPK_CTRL_2 0x4B5
#define ARIZONA_SPK_CTRL_3 0x4B6
#define ARIZONA_DAC_COMP_1 0x4DC #define ARIZONA_DAC_COMP_1 0x4DC
#define ARIZONA_DAC_COMP_2 0x4DD #define ARIZONA_DAC_COMP_2 0x4DD
#define ARIZONA_DAC_COMP_3 0x4DE #define ARIZONA_DAC_COMP_3 0x4DE
...@@ -1677,6 +1683,13 @@ ...@@ -1677,6 +1683,13 @@
#define ARIZONA_FLL1_FRC_INTEG_VAL_SHIFT 0 /* FLL1_FRC_INTEG_VAL - [11:0] */ #define ARIZONA_FLL1_FRC_INTEG_VAL_SHIFT 0 /* FLL1_FRC_INTEG_VAL - [11:0] */
#define ARIZONA_FLL1_FRC_INTEG_VAL_WIDTH 12 /* FLL1_FRC_INTEG_VAL - [11:0] */ #define ARIZONA_FLL1_FRC_INTEG_VAL_WIDTH 12 /* FLL1_FRC_INTEG_VAL - [11:0] */
/*
* R377 (0x179) - FLL1 Control 7
*/
#define ARIZONA_FLL1_GAIN_MASK 0x003c /* FLL1_GAIN */
#define ARIZONA_FLL1_GAIN_SHIFT 2 /* FLL1_GAIN */
#define ARIZONA_FLL1_GAIN_WIDTH 4 /* FLL1_GAIN */
/* /*
* R385 (0x181) - FLL1 Synchroniser 1 * R385 (0x181) - FLL1 Synchroniser 1
*/ */
...@@ -1723,6 +1736,17 @@ ...@@ -1723,6 +1736,17 @@
#define ARIZONA_FLL1_CLK_SYNC_SRC_SHIFT 0 /* FLL1_CLK_SYNC_SRC - [3:0] */ #define ARIZONA_FLL1_CLK_SYNC_SRC_SHIFT 0 /* FLL1_CLK_SYNC_SRC - [3:0] */
#define ARIZONA_FLL1_CLK_SYNC_SRC_WIDTH 4 /* FLL1_CLK_SYNC_SRC - [3:0] */ #define ARIZONA_FLL1_CLK_SYNC_SRC_WIDTH 4 /* FLL1_CLK_SYNC_SRC - [3:0] */
/*
* R391 (0x187) - FLL1 Synchroniser 7
*/
#define ARIZONA_FLL1_SYNC_GAIN_MASK 0x003c /* FLL1_SYNC_GAIN */
#define ARIZONA_FLL1_SYNC_GAIN_SHIFT 2 /* FLL1_SYNC_GAIN */
#define ARIZONA_FLL1_SYNC_GAIN_WIDTH 4 /* FLL1_SYNC_GAIN */
#define ARIZONA_FLL1_SYNC_BW 0x0001 /* FLL1_SYNC_BW */
#define ARIZONA_FLL1_SYNC_BW_MASK 0x0001 /* FLL1_SYNC_BW */
#define ARIZONA_FLL1_SYNC_BW_SHIFT 0 /* FLL1_SYNC_BW */
#define ARIZONA_FLL1_SYNC_BW_WIDTH 1 /* FLL1_SYNC_BW */
/* /*
* R393 (0x189) - FLL1 Spread Spectrum * R393 (0x189) - FLL1 Spread Spectrum
*/ */
...@@ -1815,6 +1839,13 @@ ...@@ -1815,6 +1839,13 @@
#define ARIZONA_FLL2_FRC_INTEG_VAL_SHIFT 0 /* FLL2_FRC_INTEG_VAL - [11:0] */ #define ARIZONA_FLL2_FRC_INTEG_VAL_SHIFT 0 /* FLL2_FRC_INTEG_VAL - [11:0] */
#define ARIZONA_FLL2_FRC_INTEG_VAL_WIDTH 12 /* FLL2_FRC_INTEG_VAL - [11:0] */ #define ARIZONA_FLL2_FRC_INTEG_VAL_WIDTH 12 /* FLL2_FRC_INTEG_VAL - [11:0] */
/*
* R409 (0x199) - FLL2 Control 7
*/
#define ARIZONA_FLL2_GAIN_MASK 0x003c /* FLL2_GAIN */
#define ARIZONA_FLL2_GAIN_SHIFT 2 /* FLL2_GAIN */
#define ARIZONA_FLL2_GAIN_WIDTH 4 /* FLL2_GAIN */
/* /*
* R417 (0x1A1) - FLL2 Synchroniser 1 * R417 (0x1A1) - FLL2 Synchroniser 1
*/ */
...@@ -1861,6 +1892,17 @@ ...@@ -1861,6 +1892,17 @@
#define ARIZONA_FLL2_CLK_SYNC_SRC_SHIFT 0 /* FLL2_CLK_SYNC_SRC - [3:0] */ #define ARIZONA_FLL2_CLK_SYNC_SRC_SHIFT 0 /* FLL2_CLK_SYNC_SRC - [3:0] */
#define ARIZONA_FLL2_CLK_SYNC_SRC_WIDTH 4 /* FLL2_CLK_SYNC_SRC - [3:0] */ #define ARIZONA_FLL2_CLK_SYNC_SRC_WIDTH 4 /* FLL2_CLK_SYNC_SRC - [3:0] */
/*
* R423 (0x1A7) - FLL2 Synchroniser 7
*/
#define ARIZONA_FLL2_SYNC_GAIN_MASK 0x003c /* FLL2_SYNC_GAIN */
#define ARIZONA_FLL2_SYNC_GAIN_SHIFT 2 /* FLL2_SYNC_GAIN */
#define ARIZONA_FLL2_SYNC_GAIN_WIDTH 4 /* FLL2_SYNC_GAIN */
#define ARIZONA_FLL2_SYNC_BW_MASK 0x0001 /* FLL2_SYNC_BW */
#define ARIZONA_FLL2_SYNC_BW_MASK 0x0001 /* FLL2_SYNC_BW */
#define ARIZONA_FLL2_SYNC_BW_SHIFT 0 /* FLL2_SYNC_BW */
#define ARIZONA_FLL2_SYNC_BW_WIDTH 1 /* FLL2_SYNC_BW */
/* /*
* R425 (0x1A9) - FLL2 Spread Spectrum * R425 (0x1A9) - FLL2 Spread Spectrum
*/ */
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/delay.h>
#include <linux/gcd.h> #include <linux/gcd.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
...@@ -65,6 +66,163 @@ ...@@ -65,6 +66,163 @@
#define arizona_aif_dbg(_dai, fmt, ...) \ #define arizona_aif_dbg(_dai, fmt, ...) \
dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = w->codec;
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
bool manual_ena = false;
int val;
switch (arizona->type) {
case WM5102:
switch (arizona->rev) {
case 0:
break;
default:
manual_ena = true;
break;
}
default:
break;
}
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (!priv->spk_ena && manual_ena) {
snd_soc_write(codec, 0x4f5, 0x25a);
priv->spk_ena_pending = true;
}
break;
case SND_SOC_DAPM_POST_PMU:
val = snd_soc_read(codec, ARIZONA_INTERRUPT_RAW_STATUS_3);
if (val & ARIZONA_SPK_SHUTDOWN_STS) {
dev_crit(arizona->dev,
"Speaker not enabled due to temperature\n");
return -EBUSY;
}
snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1,
1 << w->shift, 1 << w->shift);
if (priv->spk_ena_pending) {
msleep(75);
snd_soc_write(codec, 0x4f5, 0xda);
priv->spk_ena_pending = false;
priv->spk_ena++;
}
break;
case SND_SOC_DAPM_PRE_PMD:
if (manual_ena) {
priv->spk_ena--;
if (!priv->spk_ena)
snd_soc_write(codec, 0x4f5, 0x25a);
}
snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1,
1 << w->shift, 0);
break;
case SND_SOC_DAPM_POST_PMD:
if (manual_ena) {
if (!priv->spk_ena)
snd_soc_write(codec, 0x4f5, 0x0da);
}
break;
}
return 0;
}
static irqreturn_t arizona_thermal_warn(int irq, void *data)
{
struct arizona *arizona = data;
unsigned int val;
int ret;
ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
&val);
if (ret != 0) {
dev_err(arizona->dev, "Failed to read thermal status: %d\n",
ret);
} else if (val & ARIZONA_SPK_SHUTDOWN_WARN_STS) {
dev_crit(arizona->dev, "Thermal warning\n");
}
return IRQ_HANDLED;
}
static irqreturn_t arizona_thermal_shutdown(int irq, void *data)
{
struct arizona *arizona = data;
unsigned int val;
int ret;
ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
&val);
if (ret != 0) {
dev_err(arizona->dev, "Failed to read thermal status: %d\n",
ret);
} else if (val & ARIZONA_SPK_SHUTDOWN_STS) {
dev_crit(arizona->dev, "Thermal shutdown\n");
ret = regmap_update_bits(arizona->regmap,
ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT4L_ENA |
ARIZONA_OUT4R_ENA, 0);
if (ret != 0)
dev_crit(arizona->dev,
"Failed to disable speaker outputs: %d\n",
ret);
}
return IRQ_HANDLED;
}
static const struct snd_soc_dapm_widget arizona_spkl =
SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM,
ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
static const struct snd_soc_dapm_widget arizona_spkr =
SND_SOC_DAPM_PGA_E("OUT4R", SND_SOC_NOPM,
ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
int arizona_init_spk(struct snd_soc_codec *codec)
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->arizona;
int ret;
ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkl, 1);
if (ret != 0)
return ret;
ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkr, 1);
if (ret != 0)
return ret;
ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN_WARN,
"Thermal warning", arizona_thermal_warn,
arizona);
if (ret != 0)
dev_err(arizona->dev,
"Failed to get thermal warning IRQ: %d\n",
ret);
ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN,
"Thermal shutdown", arizona_thermal_shutdown,
arizona);
if (ret != 0)
dev_err(arizona->dev,
"Failed to get thermal shutdown IRQ: %d\n",
ret);
return 0;
}
EXPORT_SYMBOL_GPL(arizona_init_spk);
const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
"None", "None",
"Tone Generator 1", "Tone Generator 1",
...@@ -274,6 +432,33 @@ EXPORT_SYMBOL_GPL(arizona_mixer_values); ...@@ -274,6 +432,33 @@ EXPORT_SYMBOL_GPL(arizona_mixer_values);
const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0); const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
EXPORT_SYMBOL_GPL(arizona_mixer_tlv); EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = {
"SYNCCLK rate", "8kHz", "16kHz", "ASYNCCLK rate",
};
EXPORT_SYMBOL_GPL(arizona_rate_text);
const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = {
0, 1, 2, 8,
};
EXPORT_SYMBOL_GPL(arizona_rate_val);
const struct soc_enum arizona_isrc_fsl[] = {
SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_2,
ARIZONA_ISRC1_FSL_SHIFT, 0xf,
ARIZONA_RATE_ENUM_SIZE,
arizona_rate_text, arizona_rate_val),
SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_2_CTRL_2,
ARIZONA_ISRC2_FSL_SHIFT, 0xf,
ARIZONA_RATE_ENUM_SIZE,
arizona_rate_text, arizona_rate_val),
SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_3_CTRL_2,
ARIZONA_ISRC3_FSL_SHIFT, 0xf,
ARIZONA_RATE_ENUM_SIZE,
arizona_rate_text, arizona_rate_val),
};
EXPORT_SYMBOL_GPL(arizona_isrc_fsl);
static const char *arizona_vol_ramp_text[] = { static const char *arizona_vol_ramp_text[] = {
"0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB", "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
"15ms/6dB", "30ms/6dB", "15ms/6dB", "30ms/6dB",
...@@ -332,9 +517,27 @@ const struct soc_enum arizona_ng_hold = ...@@ -332,9 +517,27 @@ const struct soc_enum arizona_ng_hold =
4, arizona_ng_hold_text); 4, arizona_ng_hold_text);
EXPORT_SYMBOL_GPL(arizona_ng_hold); EXPORT_SYMBOL_GPL(arizona_ng_hold);
static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
unsigned int val;
int i;
if (ena)
val = ARIZONA_IN_VU;
else
val = 0;
for (i = 0; i < priv->num_inputs; i++)
snd_soc_update_bits(codec,
ARIZONA_ADC_DIGITAL_VOLUME_1L + (i * 4),
ARIZONA_IN_VU, val);
}
int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
int event) int event)
{ {
struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
unsigned int reg; unsigned int reg;
if (w->shift % 2) if (w->shift % 2)
...@@ -343,13 +546,29 @@ int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, ...@@ -343,13 +546,29 @@ int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8); reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
switch (event) { switch (event) {
case SND_SOC_DAPM_PRE_PMU:
priv->in_pending++;
break;
case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_POST_PMU:
snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0); snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0);
/* If this is the last input pending then allow VU */
priv->in_pending--;
if (priv->in_pending == 0) {
msleep(1);
arizona_in_set_vu(w->codec, 1);
}
break; break;
case SND_SOC_DAPM_PRE_PMD: case SND_SOC_DAPM_PRE_PMD:
snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, snd_soc_update_bits(w->codec, reg,
ARIZONA_IN1L_MUTE); ARIZONA_IN1L_MUTE | ARIZONA_IN_VU,
ARIZONA_IN1L_MUTE | ARIZONA_IN_VU);
break; break;
case SND_SOC_DAPM_POST_PMD:
/* Disable volume updates if no inputs are enabled */
reg = snd_soc_read(w->codec, ARIZONA_INPUT_ENABLES);
if (reg == 0)
arizona_in_set_vu(w->codec, 0);
} }
return 0; return 0;
...@@ -360,10 +579,61 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, ...@@ -360,10 +579,61 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, struct snd_kcontrol *kcontrol,
int event) int event)
{ {
switch (event) {
case SND_SOC_DAPM_POST_PMU:
switch (w->shift) {
case ARIZONA_OUT1L_ENA_SHIFT:
case ARIZONA_OUT1R_ENA_SHIFT:
case ARIZONA_OUT2L_ENA_SHIFT:
case ARIZONA_OUT2R_ENA_SHIFT:
case ARIZONA_OUT3L_ENA_SHIFT:
case ARIZONA_OUT3R_ENA_SHIFT:
msleep(17);
break;
default:
break;
}
break;
}
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(arizona_out_ev); EXPORT_SYMBOL_GPL(arizona_out_ev);
int arizona_hp_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
unsigned int mask = 1 << w->shift;
unsigned int val;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
val = mask;
break;
case SND_SOC_DAPM_PRE_PMD:
val = 0;
break;
default:
return -EINVAL;
}
/* Store the desired state for the HP outputs */
priv->arizona->hp_ena &= ~mask;
priv->arizona->hp_ena |= val;
/* Force off if HPDET magic is active */
if (priv->arizona->hpdet_magic)
val = 0;
snd_soc_update_bits(w->codec, ARIZONA_OUTPUT_ENABLES_1, mask, val);
return arizona_out_ev(w, kcontrol, event);
}
EXPORT_SYMBOL_GPL(arizona_hp_ev);
static unsigned int arizona_sysclk_48k_rates[] = { static unsigned int arizona_sysclk_48k_rates[] = {
6144000, 6144000,
12288000, 12288000,
...@@ -469,27 +739,27 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, ...@@ -469,27 +739,27 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
break; break;
case 11289600: case 11289600:
case 12288000: case 12288000:
val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT; val |= ARIZONA_CLK_12MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
break; break;
case 22579200: case 22579200:
case 24576000: case 24576000:
val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT; val |= ARIZONA_CLK_24MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
break; break;
case 45158400: case 45158400:
case 49152000: case 49152000:
val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT; val |= ARIZONA_CLK_49MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
break; break;
case 67737600: case 67737600:
case 73728000: case 73728000:
val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT; val |= ARIZONA_CLK_73MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
break; break;
case 90316800: case 90316800:
case 98304000: case 98304000:
val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT; val |= ARIZONA_CLK_98MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
break; break;
case 135475200: case 135475200:
case 147456000: case 147456000:
val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT; val |= ARIZONA_CLK_147MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
break; break;
case 0: case 0:
dev_dbg(arizona->dev, "%s cleared\n", name); dev_dbg(arizona->dev, "%s cleared\n", name);
...@@ -783,7 +1053,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, ...@@ -783,7 +1053,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
struct arizona *arizona = priv->arizona; struct arizona *arizona = priv->arizona;
int base = dai->driver->base; int base = dai->driver->base;
const int *rates; const int *rates;
int i, ret; int i, ret, val;
int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1]; int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
int bclk, lrclk, wl, frame, bclk_target; int bclk, lrclk, wl, frame, bclk_target;
...@@ -799,6 +1069,13 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, ...@@ -799,6 +1069,13 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
bclk_target *= chan_limit; bclk_target *= chan_limit;
} }
/* Force stereo for I2S mode */
val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) {
arizona_aif_dbg(dai, "Forcing stereo mode\n");
bclk_target *= 2;
}
for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
if (rates[i] >= bclk_target && if (rates[i] >= bclk_target &&
rates[i] % params_rate(params) == 0) { rates[i] % params_rate(params) == 0) {
...@@ -955,6 +1232,16 @@ static struct { ...@@ -955,6 +1232,16 @@ static struct {
{ 1000000, 13500000, 0, 1 }, { 1000000, 13500000, 0, 1 },
}; };
static struct {
unsigned int min;
unsigned int max;
u16 gain;
} fll_gains[] = {
{ 0, 256000, 0 },
{ 256000, 1000000, 2 },
{ 1000000, 13500000, 4 },
};
struct arizona_fll_cfg { struct arizona_fll_cfg {
int n; int n;
int theta; int theta;
...@@ -962,6 +1249,7 @@ struct arizona_fll_cfg { ...@@ -962,6 +1249,7 @@ struct arizona_fll_cfg {
int refdiv; int refdiv;
int outdiv; int outdiv;
int fratio; int fratio;
int gain;
}; };
static int arizona_calc_fll(struct arizona_fll *fll, static int arizona_calc_fll(struct arizona_fll *fll,
...@@ -1021,6 +1309,18 @@ static int arizona_calc_fll(struct arizona_fll *fll, ...@@ -1021,6 +1309,18 @@ static int arizona_calc_fll(struct arizona_fll *fll,
return -EINVAL; return -EINVAL;
} }
for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
cfg->gain = fll_gains[i].gain;
break;
}
}
if (i == ARRAY_SIZE(fll_gains)) {
arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
Fref);
return -EINVAL;
}
cfg->n = target / (ratio * Fref); cfg->n = target / (ratio * Fref);
if (target % (ratio * Fref)) { if (target % (ratio * Fref)) {
...@@ -1048,13 +1348,15 @@ static int arizona_calc_fll(struct arizona_fll *fll, ...@@ -1048,13 +1348,15 @@ static int arizona_calc_fll(struct arizona_fll *fll,
cfg->n, cfg->theta, cfg->lambda); cfg->n, cfg->theta, cfg->lambda);
arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n", arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv); cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
arizona_fll_dbg(fll, "GAIN=%d\n", cfg->gain);
return 0; return 0;
} }
static void arizona_apply_fll(struct arizona *arizona, unsigned int base, static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
struct arizona_fll_cfg *cfg, int source) struct arizona_fll_cfg *cfg, int source,
bool sync)
{ {
regmap_update_bits(arizona->regmap, base + 3, regmap_update_bits(arizona->regmap, base + 3,
ARIZONA_FLL1_THETA_MASK, cfg->theta); ARIZONA_FLL1_THETA_MASK, cfg->theta);
...@@ -1069,87 +1371,84 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base, ...@@ -1069,87 +1371,84 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
if (sync)
regmap_update_bits(arizona->regmap, base + 0x7,
ARIZONA_FLL1_GAIN_MASK,
cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
else
regmap_update_bits(arizona->regmap, base + 0x9,
ARIZONA_FLL1_GAIN_MASK,
cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
regmap_update_bits(arizona->regmap, base + 2, regmap_update_bits(arizona->regmap, base + 2,
ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
ARIZONA_FLL1_CTRL_UPD | cfg->n); ARIZONA_FLL1_CTRL_UPD | cfg->n);
} }
int arizona_set_fll(struct arizona_fll *fll, int source, static bool arizona_is_enabled_fll(struct arizona_fll *fll)
unsigned int Fref, unsigned int Fout)
{ {
struct arizona *arizona = fll->arizona; struct arizona *arizona = fll->arizona;
struct arizona_fll_cfg cfg, sync; unsigned int reg;
unsigned int reg, val;
int syncsrc;
bool ena;
int ret; int ret;
if (fll->fref == Fref && fll->fout == Fout)
return 0;
ret = regmap_read(arizona->regmap, fll->base + 1, &reg); ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
if (ret != 0) { if (ret != 0) {
arizona_fll_err(fll, "Failed to read current state: %d\n", arizona_fll_err(fll, "Failed to read current state: %d\n",
ret); ret);
return ret; return ret;
} }
ena = reg & ARIZONA_FLL1_ENA;
if (Fout) {
/* Do we have a 32kHz reference? */
regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
switch (val & ARIZONA_CLK_32K_SRC_MASK) {
case ARIZONA_CLK_SRC_MCLK1:
case ARIZONA_CLK_SRC_MCLK2:
syncsrc = val & ARIZONA_CLK_32K_SRC_MASK;
break;
default:
syncsrc = -1;
}
if (source == syncsrc)
syncsrc = -1;
if (syncsrc >= 0) {
ret = arizona_calc_fll(fll, &sync, Fref, Fout);
if (ret != 0)
return ret;
ret = arizona_calc_fll(fll, &cfg, 32768, Fout);
if (ret != 0)
return ret;
} else {
ret = arizona_calc_fll(fll, &cfg, Fref, Fout);
if (ret != 0)
return ret;
}
} else {
regmap_update_bits(arizona->regmap, fll->base + 1,
ARIZONA_FLL1_ENA, 0);
regmap_update_bits(arizona->regmap, fll->base + 0x11,
ARIZONA_FLL1_SYNC_ENA, 0);
if (ena)
pm_runtime_put_autosuspend(arizona->dev);
fll->fref = Fref; return reg & ARIZONA_FLL1_ENA;
fll->fout = Fout; }
return 0; static void arizona_enable_fll(struct arizona_fll *fll,
} struct arizona_fll_cfg *ref,
struct arizona_fll_cfg *sync)
{
struct arizona *arizona = fll->arizona;
int ret;
/*
* If we have both REFCLK and SYNCCLK then enable both,
* otherwise apply the SYNCCLK settings to REFCLK.
*/
if (fll->ref_src >= 0 && fll->ref_src != fll->sync_src) {
regmap_update_bits(arizona->regmap, fll->base + 5,
ARIZONA_FLL1_OUTDIV_MASK,
ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
arizona_apply_fll(arizona, fll->base, ref, fll->ref_src,
false);
if (fll->sync_src >= 0)
arizona_apply_fll(arizona, fll->base + 0x10, sync,
fll->sync_src, true);
} else if (fll->sync_src >= 0) {
regmap_update_bits(arizona->regmap, fll->base + 5, regmap_update_bits(arizona->regmap, fll->base + 5,
ARIZONA_FLL1_OUTDIV_MASK, ARIZONA_FLL1_OUTDIV_MASK,
cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
if (syncsrc >= 0) { arizona_apply_fll(arizona, fll->base, sync,
arizona_apply_fll(arizona, fll->base, &cfg, syncsrc); fll->sync_src, false);
arizona_apply_fll(arizona, fll->base + 0x10, &sync, source);
regmap_update_bits(arizona->regmap, fll->base + 0x11,
ARIZONA_FLL1_SYNC_ENA, 0);
} else { } else {
arizona_apply_fll(arizona, fll->base, &cfg, source); arizona_fll_err(fll, "No clocks provided\n");
return;
} }
if (!ena) /*
* Increase the bandwidth if we're not using a low frequency
* sync source.
*/
if (fll->sync_src >= 0 && fll->sync_freq > 100000)
regmap_update_bits(arizona->regmap, fll->base + 0x17,
ARIZONA_FLL1_SYNC_BW, 0);
else
regmap_update_bits(arizona->regmap, fll->base + 0x17,
ARIZONA_FLL1_SYNC_BW, ARIZONA_FLL1_SYNC_BW);
if (!arizona_is_enabled_fll(fll))
pm_runtime_get(arizona->dev); pm_runtime_get(arizona->dev);
/* Clear any pending completions */ /* Clear any pending completions */
...@@ -1157,7 +1456,8 @@ int arizona_set_fll(struct arizona_fll *fll, int source, ...@@ -1157,7 +1456,8 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
regmap_update_bits(arizona->regmap, fll->base + 1, regmap_update_bits(arizona->regmap, fll->base + 1,
ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
if (syncsrc >= 0) if (fll->ref_src >= 0 && fll->sync_src >= 0 &&
fll->ref_src != fll->sync_src)
regmap_update_bits(arizona->regmap, fll->base + 0x11, regmap_update_bits(arizona->regmap, fll->base + 0x11,
ARIZONA_FLL1_SYNC_ENA, ARIZONA_FLL1_SYNC_ENA,
ARIZONA_FLL1_SYNC_ENA); ARIZONA_FLL1_SYNC_ENA);
...@@ -1166,10 +1466,88 @@ int arizona_set_fll(struct arizona_fll *fll, int source, ...@@ -1166,10 +1466,88 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
msecs_to_jiffies(250)); msecs_to_jiffies(250));
if (ret == 0) if (ret == 0)
arizona_fll_warn(fll, "Timed out waiting for lock\n"); arizona_fll_warn(fll, "Timed out waiting for lock\n");
}
static void arizona_disable_fll(struct arizona_fll *fll)
{
struct arizona *arizona = fll->arizona;
bool change;
regmap_update_bits_check(arizona->regmap, fll->base + 1,
ARIZONA_FLL1_ENA, 0, &change);
regmap_update_bits(arizona->regmap, fll->base + 0x11,
ARIZONA_FLL1_SYNC_ENA, 0);
if (change)
pm_runtime_put_autosuspend(arizona->dev);
}
int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
unsigned int Fref, unsigned int Fout)
{
struct arizona_fll_cfg ref, sync;
int ret;
if (fll->ref_src == source && fll->ref_freq == Fref)
return 0;
if (fll->fout && Fref > 0) {
ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
if (ret != 0)
return ret;
if (fll->sync_src >= 0) {
ret = arizona_calc_fll(fll, &sync, fll->sync_freq,
fll->fout);
if (ret != 0)
return ret;
}
}
fll->ref_src = source;
fll->ref_freq = Fref;
fll->fref = Fref; if (fll->fout && Fref > 0) {
arizona_enable_fll(fll, &ref, &sync);
}
return 0;
}
EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
int arizona_set_fll(struct arizona_fll *fll, int source,
unsigned int Fref, unsigned int Fout)
{
struct arizona_fll_cfg ref, sync;
int ret;
if (fll->sync_src == source &&
fll->sync_freq == Fref && fll->fout == Fout)
return 0;
if (Fout) {
if (fll->ref_src >= 0) {
ret = arizona_calc_fll(fll, &ref, fll->ref_freq,
Fout);
if (ret != 0)
return ret;
}
ret = arizona_calc_fll(fll, &sync, Fref, Fout);
if (ret != 0)
return ret;
}
fll->sync_src = source;
fll->sync_freq = Fref;
fll->fout = Fout; fll->fout = Fout;
if (Fout) {
arizona_enable_fll(fll, &ref, &sync);
} else {
arizona_disable_fll(fll);
}
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(arizona_set_fll); EXPORT_SYMBOL_GPL(arizona_set_fll);
...@@ -1178,12 +1556,26 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq, ...@@ -1178,12 +1556,26 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
int ok_irq, struct arizona_fll *fll) int ok_irq, struct arizona_fll *fll)
{ {
int ret; int ret;
unsigned int val;
init_completion(&fll->ok); init_completion(&fll->ok);
fll->id = id; fll->id = id;
fll->base = base; fll->base = base;
fll->arizona = arizona; fll->arizona = arizona;
fll->sync_src = ARIZONA_FLL_SRC_NONE;
/* Configure default refclk to 32kHz if we have one */
regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
switch (val & ARIZONA_CLK_32K_SRC_MASK) {
case ARIZONA_CLK_SRC_MCLK1:
case ARIZONA_CLK_SRC_MCLK2:
fll->ref_src = val & ARIZONA_CLK_32K_SRC_MASK;
break;
default:
fll->ref_src = ARIZONA_FLL_SRC_NONE;
}
fll->ref_freq = 32768;
snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id); snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name), snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#define ARIZONA_CLK_SRC_AIF2BCLK 0x9 #define ARIZONA_CLK_SRC_AIF2BCLK 0x9
#define ARIZONA_CLK_SRC_AIF3BCLK 0xa #define ARIZONA_CLK_SRC_AIF3BCLK 0xa
#define ARIZONA_FLL_SRC_NONE -1
#define ARIZONA_FLL_SRC_MCLK1 0 #define ARIZONA_FLL_SRC_MCLK1 0
#define ARIZONA_FLL_SRC_MCLK2 1 #define ARIZONA_FLL_SRC_MCLK2 1
#define ARIZONA_FLL_SRC_SLIMCLK 3 #define ARIZONA_FLL_SRC_SLIMCLK 3
...@@ -48,6 +49,14 @@ ...@@ -48,6 +49,14 @@
#define ARIZONA_MIXER_VOL_SHIFT 1 #define ARIZONA_MIXER_VOL_SHIFT 1
#define ARIZONA_MIXER_VOL_WIDTH 7 #define ARIZONA_MIXER_VOL_WIDTH 7
#define ARIZONA_CLK_6MHZ 0
#define ARIZONA_CLK_12MHZ 1
#define ARIZONA_CLK_24MHZ 2
#define ARIZONA_CLK_49MHZ 3
#define ARIZONA_CLK_73MHZ 4
#define ARIZONA_CLK_98MHZ 5
#define ARIZONA_CLK_147MHZ 6
#define ARIZONA_MAX_DAI 4 #define ARIZONA_MAX_DAI 4
#define ARIZONA_MAX_ADSP 4 #define ARIZONA_MAX_ADSP 4
...@@ -64,6 +73,12 @@ struct arizona_priv { ...@@ -64,6 +73,12 @@ struct arizona_priv {
int sysclk; int sysclk;
int asyncclk; int asyncclk;
struct arizona_dai_priv dai[ARIZONA_MAX_DAI]; struct arizona_dai_priv dai[ARIZONA_MAX_DAI];
int num_inputs;
unsigned int in_pending;
unsigned int spk_ena:2;
unsigned int spk_ena_pending:1;
}; };
#define ARIZONA_NUM_MIXER_INPUTS 99 #define ARIZONA_NUM_MIXER_INPUTS 99
...@@ -165,6 +180,12 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; ...@@ -165,6 +180,12 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
ARIZONA_MIXER_ROUTES(name, name "L"), \ ARIZONA_MIXER_ROUTES(name, name "L"), \
ARIZONA_MIXER_ROUTES(name, name "R") ARIZONA_MIXER_ROUTES(name, name "R")
#define ARIZONA_RATE_ENUM_SIZE 4
extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE];
extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE];
extern const struct soc_enum arizona_isrc_fsl[];
extern const struct soc_enum arizona_in_vi_ramp; extern const struct soc_enum arizona_in_vi_ramp;
extern const struct soc_enum arizona_in_vd_ramp; extern const struct soc_enum arizona_in_vd_ramp;
...@@ -184,6 +205,9 @@ extern int arizona_in_ev(struct snd_soc_dapm_widget *w, ...@@ -184,6 +205,9 @@ extern int arizona_in_ev(struct snd_soc_dapm_widget *w,
extern int arizona_out_ev(struct snd_soc_dapm_widget *w, extern int arizona_out_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, struct snd_kcontrol *kcontrol,
int event); int event);
extern int arizona_hp_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir); int source, unsigned int freq, int dir);
...@@ -198,8 +222,12 @@ struct arizona_fll { ...@@ -198,8 +222,12 @@ struct arizona_fll {
unsigned int base; unsigned int base;
unsigned int vco_mult; unsigned int vco_mult;
struct completion ok; struct completion ok;
unsigned int fref;
unsigned int fout; unsigned int fout;
int sync_src;
unsigned int sync_freq;
int ref_src;
unsigned int ref_freq;
char lock_name[ARIZONA_FLL_NAME_LEN]; char lock_name[ARIZONA_FLL_NAME_LEN];
char clock_ok_name[ARIZONA_FLL_NAME_LEN]; char clock_ok_name[ARIZONA_FLL_NAME_LEN];
...@@ -207,9 +235,13 @@ struct arizona_fll { ...@@ -207,9 +235,13 @@ struct arizona_fll {
extern int arizona_init_fll(struct arizona *arizona, int id, int base, extern int arizona_init_fll(struct arizona *arizona, int id, int base,
int lock_irq, int ok_irq, struct arizona_fll *fll); int lock_irq, int ok_irq, struct arizona_fll *fll);
extern int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
unsigned int Fref, unsigned int Fout);
extern int arizona_set_fll(struct arizona_fll *fll, int source, extern int arizona_set_fll(struct arizona_fll *fll, int source,
unsigned int Fref, unsigned int Fout); unsigned int Fref, unsigned int Fout);
extern int arizona_init_spk(struct snd_soc_codec *codec);
extern int arizona_init_dai(struct arizona_priv *priv, int dai); extern int arizona_init_dai(struct arizona_priv *priv, int dai);
int arizona_set_output_mode(struct snd_soc_codec *codec, int output, int arizona_set_output_mode(struct snd_soc_codec *codec, int output,
......
...@@ -1565,7 +1565,7 @@ static int wm2200_probe(struct snd_soc_codec *codec) ...@@ -1565,7 +1565,7 @@ static int wm2200_probe(struct snd_soc_codec *codec)
return ret; return ret;
} }
ret = snd_soc_add_codec_controls(codec, wm_adsp_fw_controls, 2); ret = snd_soc_add_codec_controls(codec, wm_adsp1_fw_controls, 2);
if (ret != 0) if (ret != 0)
return ret; return ret;
......
...@@ -36,9 +36,6 @@ ...@@ -36,9 +36,6 @@
struct wm5102_priv { struct wm5102_priv {
struct arizona_priv core; struct arizona_priv core;
struct arizona_fll fll[2]; struct arizona_fll fll[2];
unsigned int spk_ena:2;
unsigned int spk_ena_pending:1;
}; };
static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0);
...@@ -615,6 +612,26 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, ...@@ -615,6 +612,26 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
return 0; return 0;
} }
static const char *wm5102_osr_text[] = {
"Low power", "Normal", "High performance",
};
static const unsigned int wm5102_osr_val[] = {
0x0, 0x3, 0x5,
};
static const struct soc_enum wm5102_hpout_osr[] = {
SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L,
ARIZONA_OUT1_OSR_SHIFT, 0x7, 3,
wm5102_osr_text, wm5102_osr_val),
SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L,
ARIZONA_OUT2_OSR_SHIFT, 0x7, 3,
wm5102_osr_text, wm5102_osr_val),
SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L,
ARIZONA_OUT3_OSR_SHIFT, 0x7, 3,
wm5102_osr_text, wm5102_osr_val),
};
#define WM5102_NG_SRC(name, base) \ #define WM5102_NG_SRC(name, base) \
SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \ SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \
SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \ SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \
...@@ -745,6 +762,9 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), ...@@ -745,6 +762,9 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
SOC_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE),
...@@ -761,6 +781,8 @@ ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE), ...@@ -761,6 +781,8 @@ ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
ARIZONA_OUT4_OSR_SHIFT, 1, 0),
SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L, SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
ARIZONA_OUT5_OSR_SHIFT, 1, 0), ARIZONA_OUT5_OSR_SHIFT, 1, 0),
...@@ -790,6 +812,10 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L, ...@@ -790,6 +812,10 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT, ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
0xbf, 0, digital_tlv), 0xbf, 0, digital_tlv),
SOC_VALUE_ENUM("HPOUT1 OSR", wm5102_hpout_osr[0]),
SOC_VALUE_ENUM("HPOUT2 OSR", wm5102_hpout_osr[1]),
SOC_VALUE_ENUM("HPOUT3 OSR", wm5102_hpout_osr[2]),
SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
...@@ -828,47 +854,6 @@ ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), ...@@ -828,47 +854,6 @@ ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
}; };
static int wm5102_spk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = w->codec;
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
struct wm5102_priv *wm5102 = snd_soc_codec_get_drvdata(codec);
if (arizona->rev < 1)
return 0;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (!wm5102->spk_ena) {
snd_soc_write(codec, 0x4f5, 0x25a);
wm5102->spk_ena_pending = true;
}
break;
case SND_SOC_DAPM_POST_PMU:
if (wm5102->spk_ena_pending) {
msleep(75);
snd_soc_write(codec, 0x4f5, 0xda);
wm5102->spk_ena_pending = false;
wm5102->spk_ena++;
}
break;
case SND_SOC_DAPM_PRE_PMD:
wm5102->spk_ena--;
if (!wm5102->spk_ena)
snd_soc_write(codec, 0x4f5, 0x25a);
break;
case SND_SOC_DAPM_POST_PMD:
if (!wm5102->spk_ena)
snd_soc_write(codec, 0x4f5, 0x0da);
break;
}
return 0;
}
ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE);
...@@ -984,22 +969,28 @@ SND_SOC_DAPM_INPUT("IN3R"), ...@@ -984,22 +969,28 @@ SND_SOC_DAPM_INPUT("IN3R"),
SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
0, NULL, 0, arizona_in_ev, 0, NULL, 0, arizona_in_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT,
0, NULL, 0, arizona_in_ev, 0, NULL, 0, arizona_in_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT,
0, NULL, 0, arizona_in_ev, 0, NULL, 0, arizona_in_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT,
0, NULL, 0, arizona_in_ev, 0, NULL, 0, arizona_in_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT,
0, NULL, 0, arizona_in_ev, 0, NULL, 0, arizona_in_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
0, NULL, 0, arizona_in_ev, 0, NULL, 0, arizona_in_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
...@@ -1131,11 +1122,11 @@ ARIZONA_DSP_WIDGETS(DSP1, "DSP1"), ...@@ -1131,11 +1122,11 @@ ARIZONA_DSP_WIDGETS(DSP1, "DSP1"),
SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux), ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux),
SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM,
ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1, SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM,
ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1, SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
...@@ -1146,12 +1137,6 @@ SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1, ...@@ -1146,12 +1137,6 @@ SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1,
SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
...@@ -1494,6 +1479,12 @@ static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source, ...@@ -1494,6 +1479,12 @@ static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
return arizona_set_fll(&wm5102->fll[0], source, Fref, Fout); return arizona_set_fll(&wm5102->fll[0], source, Fref, Fout);
case WM5102_FLL2: case WM5102_FLL2:
return arizona_set_fll(&wm5102->fll[1], source, Fref, Fout); return arizona_set_fll(&wm5102->fll[1], source, Fref, Fout);
case WM5102_FLL1_REFCLK:
return arizona_set_fll_refclk(&wm5102->fll[0], source, Fref,
Fout);
case WM5102_FLL2_REFCLK:
return arizona_set_fll_refclk(&wm5102->fll[1], source, Fref,
Fout);
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -1581,10 +1572,12 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec) ...@@ -1581,10 +1572,12 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec)
if (ret != 0) if (ret != 0)
return ret; return ret;
ret = snd_soc_add_codec_controls(codec, wm_adsp_fw_controls, 1); ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 2);
if (ret != 0) if (ret != 0)
return ret; return ret;
arizona_init_spk(codec);
snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
priv->core.arizona->dapm = &codec->dapm; priv->core.arizona->dapm = &codec->dapm;
...@@ -1604,13 +1597,6 @@ static int wm5102_codec_remove(struct snd_soc_codec *codec) ...@@ -1604,13 +1597,6 @@ static int wm5102_codec_remove(struct snd_soc_codec *codec)
#define WM5102_DIG_VU 0x0200 #define WM5102_DIG_VU 0x0200
static unsigned int wm5102_digital_vu[] = { static unsigned int wm5102_digital_vu[] = {
ARIZONA_ADC_DIGITAL_VOLUME_1L,
ARIZONA_ADC_DIGITAL_VOLUME_1R,
ARIZONA_ADC_DIGITAL_VOLUME_2L,
ARIZONA_ADC_DIGITAL_VOLUME_2R,
ARIZONA_ADC_DIGITAL_VOLUME_3L,
ARIZONA_ADC_DIGITAL_VOLUME_3R,
ARIZONA_DAC_DIGITAL_VOLUME_1L, ARIZONA_DAC_DIGITAL_VOLUME_1L,
ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_DAC_DIGITAL_VOLUME_1R,
ARIZONA_DAC_DIGITAL_VOLUME_2L, ARIZONA_DAC_DIGITAL_VOLUME_2L,
...@@ -1653,6 +1639,7 @@ static int wm5102_probe(struct platform_device *pdev) ...@@ -1653,6 +1639,7 @@ static int wm5102_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, wm5102); platform_set_drvdata(pdev, wm5102);
wm5102->core.arizona = arizona; wm5102->core.arizona = arizona;
wm5102->core.num_inputs = 6;
wm5102->core.adsp[0].part = "wm5102"; wm5102->core.adsp[0].part = "wm5102";
wm5102->core.adsp[0].num = 1; wm5102->core.adsp[0].num = 1;
...@@ -1677,6 +1664,12 @@ static int wm5102_probe(struct platform_device *pdev) ...@@ -1677,6 +1664,12 @@ static int wm5102_probe(struct platform_device *pdev)
ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK,
&wm5102->fll[1]); &wm5102->fll[1]);
/* SR2 fixed at 8kHz, SR3 fixed at 16kHz */
regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_2,
ARIZONA_SAMPLE_RATE_2_MASK, 0x11);
regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_3,
ARIZONA_SAMPLE_RATE_3_MASK, 0x12);
for (i = 0; i < ARRAY_SIZE(wm5102_dai); i++) for (i = 0; i < ARRAY_SIZE(wm5102_dai); i++)
arizona_init_dai(&wm5102->core, i); arizona_init_dai(&wm5102->core, i);
......
...@@ -17,5 +17,7 @@ ...@@ -17,5 +17,7 @@
#define WM5102_FLL1 1 #define WM5102_FLL1 1
#define WM5102_FLL2 2 #define WM5102_FLL2 2
#define WM5102_FLL1_REFCLK 3
#define WM5102_FLL2_REFCLK 4
#endif #endif
...@@ -416,28 +416,36 @@ SND_SOC_DAPM_INPUT("IN4R"), ...@@ -416,28 +416,36 @@ SND_SOC_DAPM_INPUT("IN4R"),
SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
0, NULL, 0, arizona_in_ev, 0, NULL, 0, arizona_in_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT,
0, NULL, 0, arizona_in_ev, 0, NULL, 0, arizona_in_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT,
0, NULL, 0, arizona_in_ev, 0, NULL, 0, arizona_in_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT,
0, NULL, 0, arizona_in_ev, 0, NULL, 0, arizona_in_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT,
0, NULL, 0, arizona_in_ev, 0, NULL, 0, arizona_in_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
0, NULL, 0, arizona_in_ev, 0, NULL, 0, arizona_in_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT, SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT,
0, NULL, 0, arizona_in_ev, 0, NULL, 0, arizona_in_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("IN4R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4R_ENA_SHIFT, SND_SOC_DAPM_PGA_E("IN4R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4R_ENA_SHIFT,
0, NULL, 0, arizona_in_ev, 0, NULL, 0, arizona_in_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
...@@ -551,11 +559,11 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, ...@@ -551,11 +559,11 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM,
ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1, SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM,
ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1, SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
...@@ -569,12 +577,6 @@ SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, ...@@ -569,12 +577,6 @@ SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
SND_SOC_DAPM_PGA_E("OUT3R", ARIZONA_OUTPUT_ENABLES_1, SND_SOC_DAPM_PGA_E("OUT3R", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT3R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, ARIZONA_OUT3R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
...@@ -880,6 +882,12 @@ static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source, ...@@ -880,6 +882,12 @@ static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
return arizona_set_fll(&wm5110->fll[0], source, Fref, Fout); return arizona_set_fll(&wm5110->fll[0], source, Fref, Fout);
case WM5110_FLL2: case WM5110_FLL2:
return arizona_set_fll(&wm5110->fll[1], source, Fref, Fout); return arizona_set_fll(&wm5110->fll[1], source, Fref, Fout);
case WM5110_FLL1_REFCLK:
return arizona_set_fll_refclk(&wm5110->fll[0], source, Fref,
Fout);
case WM5110_FLL2_REFCLK:
return arizona_set_fll_refclk(&wm5110->fll[1], source, Fref,
Fout);
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -987,15 +995,6 @@ static int wm5110_codec_remove(struct snd_soc_codec *codec) ...@@ -987,15 +995,6 @@ static int wm5110_codec_remove(struct snd_soc_codec *codec)
#define WM5110_DIG_VU 0x0200 #define WM5110_DIG_VU 0x0200
static unsigned int wm5110_digital_vu[] = { static unsigned int wm5110_digital_vu[] = {
ARIZONA_ADC_DIGITAL_VOLUME_1L,
ARIZONA_ADC_DIGITAL_VOLUME_1R,
ARIZONA_ADC_DIGITAL_VOLUME_2L,
ARIZONA_ADC_DIGITAL_VOLUME_2R,
ARIZONA_ADC_DIGITAL_VOLUME_3L,
ARIZONA_ADC_DIGITAL_VOLUME_3R,
ARIZONA_ADC_DIGITAL_VOLUME_4L,
ARIZONA_ADC_DIGITAL_VOLUME_4R,
ARIZONA_DAC_DIGITAL_VOLUME_1L, ARIZONA_DAC_DIGITAL_VOLUME_1L,
ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_DAC_DIGITAL_VOLUME_1R,
ARIZONA_DAC_DIGITAL_VOLUME_2L, ARIZONA_DAC_DIGITAL_VOLUME_2L,
...@@ -1040,6 +1039,7 @@ static int wm5110_probe(struct platform_device *pdev) ...@@ -1040,6 +1039,7 @@ static int wm5110_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, wm5110); platform_set_drvdata(pdev, wm5110);
wm5110->core.arizona = arizona; wm5110->core.arizona = arizona;
wm5110->core.num_inputs = 8;
for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++) for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++)
wm5110->fll[i].vco_mult = 3; wm5110->fll[i].vco_mult = 3;
......
...@@ -17,5 +17,7 @@ ...@@ -17,5 +17,7 @@
#define WM5110_FLL1 1 #define WM5110_FLL1 1
#define WM5110_FLL2 2 #define WM5110_FLL2 2
#define WM5110_FLL1_REFCLK 3
#define WM5110_FLL2_REFCLK 4
#endif #endif
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/mfd/arizona/registers.h> #include <linux/mfd/arizona/registers.h>
#include "arizona.h"
#include "wm_adsp.h" #include "wm_adsp.h"
#define adsp_crit(_dsp, fmt, ...) \ #define adsp_crit(_dsp, fmt, ...) \
...@@ -254,17 +255,52 @@ static const struct soc_enum wm_adsp_fw_enum[] = { ...@@ -254,17 +255,52 @@ static const struct soc_enum wm_adsp_fw_enum[] = {
SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text), SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
}; };
const struct snd_kcontrol_new wm_adsp_fw_controls[] = { const struct snd_kcontrol_new wm_adsp1_fw_controls[] = {
SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
wm_adsp_fw_get, wm_adsp_fw_put), wm_adsp_fw_get, wm_adsp_fw_put),
SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
wm_adsp_fw_get, wm_adsp_fw_put), wm_adsp_fw_get, wm_adsp_fw_put),
SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
wm_adsp_fw_get, wm_adsp_fw_put), wm_adsp_fw_get, wm_adsp_fw_put),
};
EXPORT_SYMBOL_GPL(wm_adsp1_fw_controls);
#if IS_ENABLED(CONFIG_SND_SOC_ARIZONA)
static const struct soc_enum wm_adsp2_rate_enum[] = {
SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1,
ARIZONA_DSP1_RATE_SHIFT, 0xf,
ARIZONA_RATE_ENUM_SIZE,
arizona_rate_text, arizona_rate_val),
SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1,
ARIZONA_DSP1_RATE_SHIFT, 0xf,
ARIZONA_RATE_ENUM_SIZE,
arizona_rate_text, arizona_rate_val),
SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
ARIZONA_DSP1_RATE_SHIFT, 0xf,
ARIZONA_RATE_ENUM_SIZE,
arizona_rate_text, arizona_rate_val),
SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
ARIZONA_DSP1_RATE_SHIFT, 0xf,
ARIZONA_RATE_ENUM_SIZE,
arizona_rate_text, arizona_rate_val),
};
const struct snd_kcontrol_new wm_adsp2_fw_controls[] = {
SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
wm_adsp_fw_get, wm_adsp_fw_put),
SOC_ENUM("DSP1 Rate", wm_adsp2_rate_enum[0]),
SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
wm_adsp_fw_get, wm_adsp_fw_put),
SOC_ENUM("DSP2 Rate", wm_adsp2_rate_enum[1]),
SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
wm_adsp_fw_get, wm_adsp_fw_put),
SOC_ENUM("DSP3 Rate", wm_adsp2_rate_enum[2]),
SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3], SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3],
wm_adsp_fw_get, wm_adsp_fw_put), wm_adsp_fw_get, wm_adsp_fw_put),
SOC_ENUM("DSP4 Rate", wm_adsp2_rate_enum[3]),
}; };
EXPORT_SYMBOL_GPL(wm_adsp_fw_controls); EXPORT_SYMBOL_GPL(wm_adsp2_fw_controls);
#endif
static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
int type) int type)
......
...@@ -67,7 +67,8 @@ struct wm_adsp { ...@@ -67,7 +67,8 @@ struct wm_adsp {
.shift = num, .event = wm_adsp2_event, \ .shift = num, .event = wm_adsp2_event, \
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
extern const struct snd_kcontrol_new wm_adsp_fw_controls[]; extern const struct snd_kcontrol_new wm_adsp1_fw_controls[];
extern const struct snd_kcontrol_new wm_adsp2_fw_controls[];
int wm_adsp1_init(struct wm_adsp *adsp); int wm_adsp1_init(struct wm_adsp *adsp);
int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs); int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment