Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit abaaf3e1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
parents 71ea4efe 2bd05db7
Loading
Loading
Loading
Loading
+77 −51
Original line number Diff line number Diff line
@@ -282,6 +282,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
		/* Default PLL configuration after power up */
		twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
		twl6040->sysclk = 19200000;
		twl6040->mclk = 32768;
	} else {
		/* already powered-down */
		if (!twl6040->power_count) {
@@ -305,6 +306,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
			twl6040_power_down(twl6040);
		}
		twl6040->sysclk = 0;
		twl6040->mclk = 0;
	}

out:
@@ -324,9 +326,17 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
	hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
	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) {
	case TWL6040_SYSCLK_SEL_LPPLL:
		/* low-power PLL divider */
		/* Change the sysclk configuration only if it has been canged */
		if (twl6040->sysclk != freq_out) {
			switch (freq_out) {
			case 17640000:
				lppllctl |= TWL6040_LPLLFIN;
@@ -336,11 +346,18 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
				break;
			default:
				dev_err(twl6040->dev,
				"freq_out %d not supported\n", freq_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) {
		case 32768:
@@ -371,6 +388,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
			goto pll_out;
		}

		if (twl6040->mclk != freq_in) {
			hppllctl &= ~TWL6040_MCLK_MSK;

			switch (freq_in) {
@@ -404,15 +422,22 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
				goto pll_out;
			}

		/* enable clock slicer to ensure input waveform is square */
			/*
			 * enable clock slicer to ensure input waveform is
			 * square
			 */
			hppllctl |= TWL6040_HPLLSQRENA;

		twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl);
			twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
					  hppllctl);
			usleep_range(500, 700);
			lppllctl |= TWL6040_HPLLSEL;
		twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
					  lppllctl);
			lppllctl &= ~TWL6040_LPLLENA;
		twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
					  lppllctl);
		}
		break;
	default:
		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->mclk = freq_in;
	twl6040->pll = pll_id;

pll_out:
+2 −0
Original line number Diff line number Diff line
@@ -187,8 +187,10 @@ struct twl6040 {
	int rev;
	u8 vibra_ctrl_cache[2];

	/* PLL configuration */
	int pll;
	unsigned int sysclk;
	unsigned int mclk;

	unsigned int irq;
	unsigned int irq_base;