Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: mfd: Avoid twl6040-codec PLL reconfiguration when not needed mfd: Store twl6040-codec mclk configuration
This commit is contained in:
@@ -282,6 +282,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
|
|||||||
/* Default PLL configuration after power up */
|
/* Default PLL configuration after power up */
|
||||||
twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
|
twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
|
||||||
twl6040->sysclk = 19200000;
|
twl6040->sysclk = 19200000;
|
||||||
|
twl6040->mclk = 32768;
|
||||||
} else {
|
} else {
|
||||||
/* already powered-down */
|
/* already powered-down */
|
||||||
if (!twl6040->power_count) {
|
if (!twl6040->power_count) {
|
||||||
@@ -305,6 +306,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
|
|||||||
twl6040_power_down(twl6040);
|
twl6040_power_down(twl6040);
|
||||||
}
|
}
|
||||||
twl6040->sysclk = 0;
|
twl6040->sysclk = 0;
|
||||||
|
twl6040->mclk = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@@ -324,23 +326,38 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
|
|||||||
hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
|
hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
|
||||||
lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
|
lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
|
||||||
|
|
||||||
|
/* Force full reconfiguration when switching between PLL */
|
||||||
|
if (pll_id != twl6040->pll) {
|
||||||
|
twl6040->sysclk = 0;
|
||||||
|
twl6040->mclk = 0;
|
||||||
|
}
|
||||||
|
|
||||||
switch (pll_id) {
|
switch (pll_id) {
|
||||||
case TWL6040_SYSCLK_SEL_LPPLL:
|
case TWL6040_SYSCLK_SEL_LPPLL:
|
||||||
/* low-power PLL divider */
|
/* low-power PLL divider */
|
||||||
switch (freq_out) {
|
/* Change the sysclk configuration only if it has been canged */
|
||||||
case 17640000:
|
if (twl6040->sysclk != freq_out) {
|
||||||
lppllctl |= TWL6040_LPLLFIN;
|
switch (freq_out) {
|
||||||
break;
|
case 17640000:
|
||||||
case 19200000:
|
lppllctl |= TWL6040_LPLLFIN;
|
||||||
lppllctl &= ~TWL6040_LPLLFIN;
|
break;
|
||||||
break;
|
case 19200000:
|
||||||
default:
|
lppllctl &= ~TWL6040_LPLLFIN;
|
||||||
dev_err(twl6040->dev,
|
break;
|
||||||
"freq_out %d not supported\n", freq_out);
|
default:
|
||||||
ret = -EINVAL;
|
dev_err(twl6040->dev,
|
||||||
goto pll_out;
|
"freq_out %d not supported\n",
|
||||||
|
freq_out);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto pll_out;
|
||||||
|
}
|
||||||
|
twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
|
||||||
|
lppllctl);
|
||||||
}
|
}
|
||||||
twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
|
|
||||||
|
/* The PLL in use has not been change, we can exit */
|
||||||
|
if (twl6040->pll == pll_id)
|
||||||
|
break;
|
||||||
|
|
||||||
switch (freq_in) {
|
switch (freq_in) {
|
||||||
case 32768:
|
case 32768:
|
||||||
@@ -371,48 +388,56 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
|
|||||||
goto pll_out;
|
goto pll_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
hppllctl &= ~TWL6040_MCLK_MSK;
|
if (twl6040->mclk != freq_in) {
|
||||||
|
hppllctl &= ~TWL6040_MCLK_MSK;
|
||||||
|
|
||||||
|
switch (freq_in) {
|
||||||
|
case 12000000:
|
||||||
|
/* PLL enabled, active mode */
|
||||||
|
hppllctl |= TWL6040_MCLK_12000KHZ |
|
||||||
|
TWL6040_HPLLENA;
|
||||||
|
break;
|
||||||
|
case 19200000:
|
||||||
|
/*
|
||||||
|
* PLL disabled
|
||||||
|
* (enable PLL if MCLK jitter quality
|
||||||
|
* doesn't meet specification)
|
||||||
|
*/
|
||||||
|
hppllctl |= TWL6040_MCLK_19200KHZ;
|
||||||
|
break;
|
||||||
|
case 26000000:
|
||||||
|
/* PLL enabled, active mode */
|
||||||
|
hppllctl |= TWL6040_MCLK_26000KHZ |
|
||||||
|
TWL6040_HPLLENA;
|
||||||
|
break;
|
||||||
|
case 38400000:
|
||||||
|
/* PLL enabled, active mode */
|
||||||
|
hppllctl |= TWL6040_MCLK_38400KHZ |
|
||||||
|
TWL6040_HPLLENA;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(twl6040->dev,
|
||||||
|
"freq_in %d not supported\n", freq_in);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto pll_out;
|
||||||
|
}
|
||||||
|
|
||||||
switch (freq_in) {
|
|
||||||
case 12000000:
|
|
||||||
/* PLL enabled, active mode */
|
|
||||||
hppllctl |= TWL6040_MCLK_12000KHZ |
|
|
||||||
TWL6040_HPLLENA;
|
|
||||||
break;
|
|
||||||
case 19200000:
|
|
||||||
/*
|
/*
|
||||||
* PLL disabled
|
* enable clock slicer to ensure input waveform is
|
||||||
* (enable PLL if MCLK jitter quality
|
* square
|
||||||
* doesn't meet specification)
|
|
||||||
*/
|
*/
|
||||||
hppllctl |= TWL6040_MCLK_19200KHZ;
|
hppllctl |= TWL6040_HPLLSQRENA;
|
||||||
break;
|
|
||||||
case 26000000:
|
twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
|
||||||
/* PLL enabled, active mode */
|
hppllctl);
|
||||||
hppllctl |= TWL6040_MCLK_26000KHZ |
|
usleep_range(500, 700);
|
||||||
TWL6040_HPLLENA;
|
lppllctl |= TWL6040_HPLLSEL;
|
||||||
break;
|
twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
|
||||||
case 38400000:
|
lppllctl);
|
||||||
/* PLL enabled, active mode */
|
lppllctl &= ~TWL6040_LPLLENA;
|
||||||
hppllctl |= TWL6040_MCLK_38400KHZ |
|
twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
|
||||||
TWL6040_HPLLENA;
|
lppllctl);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dev_err(twl6040->dev,
|
|
||||||
"freq_in %d not supported\n", freq_in);
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto pll_out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enable clock slicer to ensure input waveform is square */
|
|
||||||
hppllctl |= TWL6040_HPLLSQRENA;
|
|
||||||
|
|
||||||
twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl);
|
|
||||||
usleep_range(500, 700);
|
|
||||||
lppllctl |= TWL6040_HPLLSEL;
|
|
||||||
twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
|
|
||||||
lppllctl &= ~TWL6040_LPLLENA;
|
|
||||||
twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(twl6040->dev, "unknown pll id %d\n", pll_id);
|
dev_err(twl6040->dev, "unknown pll id %d\n", pll_id);
|
||||||
@@ -421,6 +446,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
twl6040->sysclk = freq_out;
|
twl6040->sysclk = freq_out;
|
||||||
|
twl6040->mclk = freq_in;
|
||||||
twl6040->pll = pll_id;
|
twl6040->pll = pll_id;
|
||||||
|
|
||||||
pll_out:
|
pll_out:
|
||||||
|
@@ -187,8 +187,10 @@ struct twl6040 {
|
|||||||
int rev;
|
int rev;
|
||||||
u8 vibra_ctrl_cache[2];
|
u8 vibra_ctrl_cache[2];
|
||||||
|
|
||||||
|
/* PLL configuration */
|
||||||
int pll;
|
int pll;
|
||||||
unsigned int sysclk;
|
unsigned int sysclk;
|
||||||
|
unsigned int mclk;
|
||||||
|
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
unsigned int irq_base;
|
unsigned int irq_base;
|
||||||
|
Reference in New Issue
Block a user