diff options
Diffstat (limited to 'sound/soc/codecs/arizona.c')
-rw-r--r-- | sound/soc/codecs/arizona.c | 325 |
1 files changed, 208 insertions, 117 deletions
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index e4295fee8f13..29e198f57d4c 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -53,6 +53,14 @@ | |||
53 | #define ARIZONA_AIF_RX_ENABLES 0x1A | 53 | #define ARIZONA_AIF_RX_ENABLES 0x1A |
54 | #define ARIZONA_AIF_FORCE_WRITE 0x1B | 54 | #define ARIZONA_AIF_FORCE_WRITE 0x1B |
55 | 55 | ||
56 | #define ARIZONA_FLL_VCO_CORNER 141900000 | ||
57 | #define ARIZONA_FLL_MAX_FREF 13500000 | ||
58 | #define ARIZONA_FLL_MIN_FVCO 90000000 | ||
59 | #define ARIZONA_FLL_MAX_FRATIO 16 | ||
60 | #define ARIZONA_FLL_MAX_REFDIV 8 | ||
61 | #define ARIZONA_FLL_MIN_OUTDIV 2 | ||
62 | #define ARIZONA_FLL_MAX_OUTDIV 7 | ||
63 | |||
56 | #define arizona_fll_err(_fll, fmt, ...) \ | 64 | #define arizona_fll_err(_fll, fmt, ...) \ |
57 | dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) | 65 | dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) |
58 | #define arizona_fll_warn(_fll, fmt, ...) \ | 66 | #define arizona_fll_warn(_fll, fmt, ...) \ |
@@ -542,67 +550,76 @@ static const char *arizona_vol_ramp_text[] = { | |||
542 | "15ms/6dB", "30ms/6dB", | 550 | "15ms/6dB", "30ms/6dB", |
543 | }; | 551 | }; |
544 | 552 | ||
545 | const struct soc_enum arizona_in_vd_ramp = | 553 | SOC_ENUM_SINGLE_DECL(arizona_in_vd_ramp, |
546 | SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP, | 554 | ARIZONA_INPUT_VOLUME_RAMP, |
547 | ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text); | 555 | ARIZONA_IN_VD_RAMP_SHIFT, |
556 | arizona_vol_ramp_text); | ||
548 | EXPORT_SYMBOL_GPL(arizona_in_vd_ramp); | 557 | EXPORT_SYMBOL_GPL(arizona_in_vd_ramp); |
549 | 558 | ||
550 | const struct soc_enum arizona_in_vi_ramp = | 559 | SOC_ENUM_SINGLE_DECL(arizona_in_vi_ramp, |
551 | SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP, | 560 | ARIZONA_INPUT_VOLUME_RAMP, |
552 | ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text); | 561 | ARIZONA_IN_VI_RAMP_SHIFT, |
562 | arizona_vol_ramp_text); | ||
553 | EXPORT_SYMBOL_GPL(arizona_in_vi_ramp); | 563 | EXPORT_SYMBOL_GPL(arizona_in_vi_ramp); |
554 | 564 | ||
555 | const struct soc_enum arizona_out_vd_ramp = | 565 | SOC_ENUM_SINGLE_DECL(arizona_out_vd_ramp, |
556 | SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP, | 566 | ARIZONA_OUTPUT_VOLUME_RAMP, |
557 | ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text); | 567 | ARIZONA_OUT_VD_RAMP_SHIFT, |
568 | arizona_vol_ramp_text); | ||
558 | EXPORT_SYMBOL_GPL(arizona_out_vd_ramp); | 569 | EXPORT_SYMBOL_GPL(arizona_out_vd_ramp); |
559 | 570 | ||
560 | const struct soc_enum arizona_out_vi_ramp = | 571 | SOC_ENUM_SINGLE_DECL(arizona_out_vi_ramp, |
561 | SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP, | 572 | ARIZONA_OUTPUT_VOLUME_RAMP, |
562 | ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text); | 573 | ARIZONA_OUT_VI_RAMP_SHIFT, |
574 | arizona_vol_ramp_text); | ||
563 | EXPORT_SYMBOL_GPL(arizona_out_vi_ramp); | 575 | EXPORT_SYMBOL_GPL(arizona_out_vi_ramp); |
564 | 576 | ||
565 | static const char *arizona_lhpf_mode_text[] = { | 577 | static const char *arizona_lhpf_mode_text[] = { |
566 | "Low-pass", "High-pass" | 578 | "Low-pass", "High-pass" |
567 | }; | 579 | }; |
568 | 580 | ||
569 | const struct soc_enum arizona_lhpf1_mode = | 581 | SOC_ENUM_SINGLE_DECL(arizona_lhpf1_mode, |
570 | SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2, | 582 | ARIZONA_HPLPF1_1, |
571 | arizona_lhpf_mode_text); | 583 | ARIZONA_LHPF1_MODE_SHIFT, |
584 | arizona_lhpf_mode_text); | ||
572 | EXPORT_SYMBOL_GPL(arizona_lhpf1_mode); | 585 | EXPORT_SYMBOL_GPL(arizona_lhpf1_mode); |
573 | 586 | ||
574 | const struct soc_enum arizona_lhpf2_mode = | 587 | SOC_ENUM_SINGLE_DECL(arizona_lhpf2_mode, |
575 | SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2, | 588 | ARIZONA_HPLPF2_1, |
576 | arizona_lhpf_mode_text); | 589 | ARIZONA_LHPF2_MODE_SHIFT, |
590 | arizona_lhpf_mode_text); | ||
577 | EXPORT_SYMBOL_GPL(arizona_lhpf2_mode); | 591 | EXPORT_SYMBOL_GPL(arizona_lhpf2_mode); |
578 | 592 | ||
579 | const struct soc_enum arizona_lhpf3_mode = | 593 | SOC_ENUM_SINGLE_DECL(arizona_lhpf3_mode, |
580 | SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2, | 594 | ARIZONA_HPLPF3_1, |
581 | arizona_lhpf_mode_text); | 595 | ARIZONA_LHPF3_MODE_SHIFT, |
596 | arizona_lhpf_mode_text); | ||
582 | EXPORT_SYMBOL_GPL(arizona_lhpf3_mode); | 597 | EXPORT_SYMBOL_GPL(arizona_lhpf3_mode); |
583 | 598 | ||
584 | const struct soc_enum arizona_lhpf4_mode = | 599 | SOC_ENUM_SINGLE_DECL(arizona_lhpf4_mode, |
585 | SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2, | 600 | ARIZONA_HPLPF4_1, |
586 | arizona_lhpf_mode_text); | 601 | ARIZONA_LHPF4_MODE_SHIFT, |
602 | arizona_lhpf_mode_text); | ||
587 | EXPORT_SYMBOL_GPL(arizona_lhpf4_mode); | 603 | EXPORT_SYMBOL_GPL(arizona_lhpf4_mode); |
588 | 604 | ||
589 | static const char *arizona_ng_hold_text[] = { | 605 | static const char *arizona_ng_hold_text[] = { |
590 | "30ms", "120ms", "250ms", "500ms", | 606 | "30ms", "120ms", "250ms", "500ms", |
591 | }; | 607 | }; |
592 | 608 | ||
593 | const struct soc_enum arizona_ng_hold = | 609 | SOC_ENUM_SINGLE_DECL(arizona_ng_hold, |
594 | SOC_ENUM_SINGLE(ARIZONA_NOISE_GATE_CONTROL, ARIZONA_NGATE_HOLD_SHIFT, | 610 | ARIZONA_NOISE_GATE_CONTROL, |
595 | 4, arizona_ng_hold_text); | 611 | ARIZONA_NGATE_HOLD_SHIFT, |
612 | arizona_ng_hold_text); | ||
596 | EXPORT_SYMBOL_GPL(arizona_ng_hold); | 613 | EXPORT_SYMBOL_GPL(arizona_ng_hold); |
597 | 614 | ||
598 | static const char * const arizona_in_hpf_cut_text[] = { | 615 | static const char * const arizona_in_hpf_cut_text[] = { |
599 | "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz" | 616 | "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz" |
600 | }; | 617 | }; |
601 | 618 | ||
602 | const struct soc_enum arizona_in_hpf_cut_enum = | 619 | SOC_ENUM_SINGLE_DECL(arizona_in_hpf_cut_enum, |
603 | SOC_ENUM_SINGLE(ARIZONA_HPF_CONTROL, ARIZONA_IN_HPF_CUT_SHIFT, | 620 | ARIZONA_HPF_CONTROL, |
604 | ARRAY_SIZE(arizona_in_hpf_cut_text), | 621 | ARIZONA_IN_HPF_CUT_SHIFT, |
605 | arizona_in_hpf_cut_text); | 622 | arizona_in_hpf_cut_text); |
606 | EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum); | 623 | EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum); |
607 | 624 | ||
608 | static const char * const arizona_in_dmic_osr_text[] = { | 625 | static const char * const arizona_in_dmic_osr_text[] = { |
@@ -1377,74 +1394,147 @@ struct arizona_fll_cfg { | |||
1377 | int gain; | 1394 | int gain; |
1378 | }; | 1395 | }; |
1379 | 1396 | ||
1380 | static int arizona_calc_fll(struct arizona_fll *fll, | 1397 | static int arizona_validate_fll(struct arizona_fll *fll, |
1381 | struct arizona_fll_cfg *cfg, | 1398 | unsigned int Fref, |
1382 | unsigned int Fref, | 1399 | unsigned int Fout) |
1383 | unsigned int Fout) | ||
1384 | { | 1400 | { |
1385 | unsigned int target, div, gcd_fll; | 1401 | unsigned int Fvco_min; |
1386 | int i, ratio; | 1402 | |
1403 | if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) { | ||
1404 | arizona_fll_err(fll, | ||
1405 | "Can't scale %dMHz in to <=13.5MHz\n", | ||
1406 | Fref); | ||
1407 | return -EINVAL; | ||
1408 | } | ||
1387 | 1409 | ||
1388 | arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout); | 1410 | Fvco_min = ARIZONA_FLL_MIN_FVCO * fll->vco_mult; |
1411 | if (Fout * ARIZONA_FLL_MAX_OUTDIV < Fvco_min) { | ||
1412 | arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", | ||
1413 | Fout); | ||
1414 | return -EINVAL; | ||
1415 | } | ||
1416 | |||
1417 | return 0; | ||
1418 | } | ||
1419 | |||
1420 | static int arizona_find_fratio(unsigned int Fref, int *fratio) | ||
1421 | { | ||
1422 | int i; | ||
1423 | |||
1424 | /* Find an appropriate FLL_FRATIO */ | ||
1425 | for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { | ||
1426 | if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { | ||
1427 | if (fratio) | ||
1428 | *fratio = fll_fratios[i].fratio; | ||
1429 | return fll_fratios[i].ratio; | ||
1430 | } | ||
1431 | } | ||
1432 | |||
1433 | return -EINVAL; | ||
1434 | } | ||
1435 | |||
1436 | static int arizona_calc_fratio(struct arizona_fll *fll, | ||
1437 | struct arizona_fll_cfg *cfg, | ||
1438 | unsigned int target, | ||
1439 | unsigned int Fref, bool sync) | ||
1440 | { | ||
1441 | int init_ratio, ratio; | ||
1442 | int refdiv, div; | ||
1389 | 1443 | ||
1390 | /* Fref must be <=13.5MHz */ | 1444 | /* Fref must be <=13.5MHz, find initial refdiv */ |
1391 | div = 1; | 1445 | div = 1; |
1392 | cfg->refdiv = 0; | 1446 | cfg->refdiv = 0; |
1393 | while ((Fref / div) > 13500000) { | 1447 | while (Fref > ARIZONA_FLL_MAX_FREF) { |
1394 | div *= 2; | 1448 | div *= 2; |
1449 | Fref /= 2; | ||
1395 | cfg->refdiv++; | 1450 | cfg->refdiv++; |
1396 | 1451 | ||
1397 | if (div > 8) { | 1452 | if (div > ARIZONA_FLL_MAX_REFDIV) |
1398 | arizona_fll_err(fll, | ||
1399 | "Can't scale %dMHz in to <=13.5MHz\n", | ||
1400 | Fref); | ||
1401 | return -EINVAL; | 1453 | return -EINVAL; |
1454 | } | ||
1455 | |||
1456 | /* Find an appropriate FLL_FRATIO */ | ||
1457 | init_ratio = arizona_find_fratio(Fref, &cfg->fratio); | ||
1458 | if (init_ratio < 0) { | ||
1459 | arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n", | ||
1460 | Fref); | ||
1461 | return init_ratio; | ||
1462 | } | ||
1463 | |||
1464 | switch (fll->arizona->type) { | ||
1465 | case WM5110: | ||
1466 | if (fll->arizona->rev < 3 || sync) | ||
1467 | return init_ratio; | ||
1468 | break; | ||
1469 | default: | ||
1470 | return init_ratio; | ||
1471 | } | ||
1472 | |||
1473 | cfg->fratio = init_ratio - 1; | ||
1474 | |||
1475 | /* Adjust FRATIO/refdiv to avoid integer mode if possible */ | ||
1476 | refdiv = cfg->refdiv; | ||
1477 | |||
1478 | while (div <= ARIZONA_FLL_MAX_REFDIV) { | ||
1479 | for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO; | ||
1480 | ratio++) { | ||
1481 | if (target % (ratio * Fref)) { | ||
1482 | cfg->refdiv = refdiv; | ||
1483 | cfg->fratio = ratio - 1; | ||
1484 | return ratio; | ||
1485 | } | ||
1402 | } | 1486 | } |
1487 | |||
1488 | for (ratio = init_ratio - 1; ratio >= 0; ratio--) { | ||
1489 | if (ARIZONA_FLL_VCO_CORNER / (fll->vco_mult * ratio) < | ||
1490 | Fref) | ||
1491 | break; | ||
1492 | |||
1493 | if (target % (ratio * Fref)) { | ||
1494 | cfg->refdiv = refdiv; | ||
1495 | cfg->fratio = ratio - 1; | ||
1496 | return ratio; | ||
1497 | } | ||
1498 | } | ||
1499 | |||
1500 | div *= 2; | ||
1501 | Fref /= 2; | ||
1502 | refdiv++; | ||
1503 | init_ratio = arizona_find_fratio(Fref, NULL); | ||
1403 | } | 1504 | } |
1404 | 1505 | ||
1405 | /* Apply the division for our remaining calculations */ | 1506 | arizona_fll_warn(fll, "Falling back to integer mode operation\n"); |
1406 | Fref /= div; | 1507 | return cfg->fratio + 1; |
1508 | } | ||
1509 | |||
1510 | static int arizona_calc_fll(struct arizona_fll *fll, | ||
1511 | struct arizona_fll_cfg *cfg, | ||
1512 | unsigned int Fref, bool sync) | ||
1513 | { | ||
1514 | unsigned int target, div, gcd_fll; | ||
1515 | int i, ratio; | ||
1516 | |||
1517 | arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout); | ||
1407 | 1518 | ||
1408 | /* Fvco should be over the targt; don't check the upper bound */ | 1519 | /* Fvco should be over the targt; don't check the upper bound */ |
1409 | div = 1; | 1520 | div = ARIZONA_FLL_MIN_OUTDIV; |
1410 | while (Fout * div < 90000000 * fll->vco_mult) { | 1521 | while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { |
1411 | div++; | 1522 | div++; |
1412 | if (div > 7) { | 1523 | if (div > ARIZONA_FLL_MAX_OUTDIV) |
1413 | arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", | ||
1414 | Fout); | ||
1415 | return -EINVAL; | 1524 | return -EINVAL; |
1416 | } | ||
1417 | } | 1525 | } |
1418 | target = Fout * div / fll->vco_mult; | 1526 | target = fll->fout * div / fll->vco_mult; |
1419 | cfg->outdiv = div; | 1527 | cfg->outdiv = div; |
1420 | 1528 | ||
1421 | arizona_fll_dbg(fll, "Fvco=%dHz\n", target); | 1529 | arizona_fll_dbg(fll, "Fvco=%dHz\n", target); |
1422 | 1530 | ||
1423 | /* Find an appropraite FLL_FRATIO and factor it out of the target */ | 1531 | /* Find an appropriate FLL_FRATIO and refdiv */ |
1424 | for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { | 1532 | ratio = arizona_calc_fratio(fll, cfg, target, Fref, sync); |
1425 | if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { | 1533 | if (ratio < 0) |
1426 | cfg->fratio = fll_fratios[i].fratio; | 1534 | return ratio; |
1427 | ratio = fll_fratios[i].ratio; | ||
1428 | break; | ||
1429 | } | ||
1430 | } | ||
1431 | if (i == ARRAY_SIZE(fll_fratios)) { | ||
1432 | arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n", | ||
1433 | Fref); | ||
1434 | return -EINVAL; | ||
1435 | } | ||
1436 | 1535 | ||
1437 | for (i = 0; i < ARRAY_SIZE(fll_gains); i++) { | 1536 | /* Apply the division for our remaining calculations */ |
1438 | if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) { | 1537 | Fref = Fref / (1 << cfg->refdiv); |
1439 | cfg->gain = fll_gains[i].gain; | ||
1440 | break; | ||
1441 | } | ||
1442 | } | ||
1443 | if (i == ARRAY_SIZE(fll_gains)) { | ||
1444 | arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n", | ||
1445 | Fref); | ||
1446 | return -EINVAL; | ||
1447 | } | ||
1448 | 1538 | ||
1449 | cfg->n = target / (ratio * Fref); | 1539 | cfg->n = target / (ratio * Fref); |
1450 | 1540 | ||
@@ -1469,6 +1559,18 @@ static int arizona_calc_fll(struct arizona_fll *fll, | |||
1469 | cfg->lambda >>= 1; | 1559 | cfg->lambda >>= 1; |
1470 | } | 1560 | } |
1471 | 1561 | ||
1562 | for (i = 0; i < ARRAY_SIZE(fll_gains); i++) { | ||
1563 | if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) { | ||
1564 | cfg->gain = fll_gains[i].gain; | ||
1565 | break; | ||
1566 | } | ||
1567 | } | ||
1568 | if (i == ARRAY_SIZE(fll_gains)) { | ||
1569 | arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n", | ||
1570 | Fref); | ||
1571 | return -EINVAL; | ||
1572 | } | ||
1573 | |||
1472 | arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n", | 1574 | arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n", |
1473 | cfg->n, cfg->theta, cfg->lambda); | 1575 | cfg->n, cfg->theta, cfg->lambda); |
1474 | arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n", | 1576 | arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n", |
@@ -1496,14 +1598,18 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base, | |||
1496 | cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | | 1598 | cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | |
1497 | source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); | 1599 | source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); |
1498 | 1600 | ||
1499 | if (sync) | 1601 | if (sync) { |
1500 | regmap_update_bits_async(arizona->regmap, base + 0x7, | 1602 | regmap_update_bits(arizona->regmap, base + 0x7, |
1501 | ARIZONA_FLL1_GAIN_MASK, | 1603 | ARIZONA_FLL1_GAIN_MASK, |
1502 | cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); | 1604 | cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); |
1503 | else | 1605 | } else { |
1504 | regmap_update_bits_async(arizona->regmap, base + 0x9, | 1606 | regmap_update_bits(arizona->regmap, base + 0x5, |
1505 | ARIZONA_FLL1_GAIN_MASK, | 1607 | ARIZONA_FLL1_OUTDIV_MASK, |
1506 | cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); | 1608 | cfg->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); |
1609 | regmap_update_bits(arizona->regmap, base + 0x9, | ||
1610 | ARIZONA_FLL1_GAIN_MASK, | ||
1611 | cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); | ||
1612 | } | ||
1507 | 1613 | ||
1508 | regmap_update_bits_async(arizona->regmap, base + 2, | 1614 | regmap_update_bits_async(arizona->regmap, base + 2, |
1509 | ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, | 1615 | ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, |
@@ -1526,13 +1632,12 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll) | |||
1526 | return reg & ARIZONA_FLL1_ENA; | 1632 | return reg & ARIZONA_FLL1_ENA; |
1527 | } | 1633 | } |
1528 | 1634 | ||
1529 | static void arizona_enable_fll(struct arizona_fll *fll, | 1635 | static void arizona_enable_fll(struct arizona_fll *fll) |
1530 | struct arizona_fll_cfg *ref, | ||
1531 | struct arizona_fll_cfg *sync) | ||
1532 | { | 1636 | { |
1533 | struct arizona *arizona = fll->arizona; | 1637 | struct arizona *arizona = fll->arizona; |
1534 | int ret; | 1638 | int ret; |
1535 | bool use_sync = false; | 1639 | bool use_sync = false; |
1640 | struct arizona_fll_cfg cfg; | ||
1536 | 1641 | ||
1537 | /* | 1642 | /* |
1538 | * If we have both REFCLK and SYNCCLK then enable both, | 1643 | * If we have both REFCLK and SYNCCLK then enable both, |
@@ -1540,23 +1645,21 @@ static void arizona_enable_fll(struct arizona_fll *fll, | |||
1540 | */ | 1645 | */ |
1541 | if (fll->ref_src >= 0 && fll->ref_freq && | 1646 | if (fll->ref_src >= 0 && fll->ref_freq && |
1542 | fll->ref_src != fll->sync_src) { | 1647 | fll->ref_src != fll->sync_src) { |
1543 | regmap_update_bits_async(arizona->regmap, fll->base + 5, | 1648 | arizona_calc_fll(fll, &cfg, fll->ref_freq, false); |
1544 | ARIZONA_FLL1_OUTDIV_MASK, | ||
1545 | ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); | ||
1546 | 1649 | ||
1547 | arizona_apply_fll(arizona, fll->base, ref, fll->ref_src, | 1650 | arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src, |
1548 | false); | 1651 | false); |
1549 | if (fll->sync_src >= 0) { | 1652 | if (fll->sync_src >= 0) { |
1550 | arizona_apply_fll(arizona, fll->base + 0x10, sync, | 1653 | arizona_calc_fll(fll, &cfg, fll->sync_freq, true); |
1654 | |||
1655 | arizona_apply_fll(arizona, fll->base + 0x10, &cfg, | ||
1551 | fll->sync_src, true); | 1656 | fll->sync_src, true); |
1552 | use_sync = true; | 1657 | use_sync = true; |
1553 | } | 1658 | } |
1554 | } else if (fll->sync_src >= 0) { | 1659 | } else if (fll->sync_src >= 0) { |
1555 | regmap_update_bits_async(arizona->regmap, fll->base + 5, | 1660 | arizona_calc_fll(fll, &cfg, fll->sync_freq, false); |
1556 | ARIZONA_FLL1_OUTDIV_MASK, | ||
1557 | sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); | ||
1558 | 1661 | ||
1559 | arizona_apply_fll(arizona, fll->base, sync, | 1662 | arizona_apply_fll(arizona, fll->base, &cfg, |
1560 | fll->sync_src, false); | 1663 | fll->sync_src, false); |
1561 | 1664 | ||
1562 | regmap_update_bits_async(arizona->regmap, fll->base + 0x11, | 1665 | regmap_update_bits_async(arizona->regmap, fll->base + 0x11, |
@@ -1618,32 +1721,22 @@ static void arizona_disable_fll(struct arizona_fll *fll) | |||
1618 | int arizona_set_fll_refclk(struct arizona_fll *fll, int source, | 1721 | int arizona_set_fll_refclk(struct arizona_fll *fll, int source, |
1619 | unsigned int Fref, unsigned int Fout) | 1722 | unsigned int Fref, unsigned int Fout) |
1620 | { | 1723 | { |
1621 | struct arizona_fll_cfg ref, sync; | ||
1622 | int ret; | 1724 | int ret; |
1623 | 1725 | ||
1624 | if (fll->ref_src == source && fll->ref_freq == Fref) | 1726 | if (fll->ref_src == source && fll->ref_freq == Fref) |
1625 | return 0; | 1727 | return 0; |
1626 | 1728 | ||
1627 | if (fll->fout) { | 1729 | if (fll->fout && Fref > 0) { |
1628 | if (Fref > 0) { | 1730 | ret = arizona_validate_fll(fll, Fref, fll->fout); |
1629 | ret = arizona_calc_fll(fll, &ref, Fref, fll->fout); | 1731 | if (ret != 0) |
1630 | if (ret != 0) | 1732 | return ret; |
1631 | return ret; | ||
1632 | } | ||
1633 | |||
1634 | if (fll->sync_src >= 0) { | ||
1635 | ret = arizona_calc_fll(fll, &sync, fll->sync_freq, | ||
1636 | fll->fout); | ||
1637 | if (ret != 0) | ||
1638 | return ret; | ||
1639 | } | ||
1640 | } | 1733 | } |
1641 | 1734 | ||
1642 | fll->ref_src = source; | 1735 | fll->ref_src = source; |
1643 | fll->ref_freq = Fref; | 1736 | fll->ref_freq = Fref; |
1644 | 1737 | ||
1645 | if (fll->fout && Fref > 0) { | 1738 | if (fll->fout && Fref > 0) { |
1646 | arizona_enable_fll(fll, &ref, &sync); | 1739 | arizona_enable_fll(fll); |
1647 | } | 1740 | } |
1648 | 1741 | ||
1649 | return 0; | 1742 | return 0; |
@@ -1653,7 +1746,6 @@ EXPORT_SYMBOL_GPL(arizona_set_fll_refclk); | |||
1653 | int arizona_set_fll(struct arizona_fll *fll, int source, | 1746 | int arizona_set_fll(struct arizona_fll *fll, int source, |
1654 | unsigned int Fref, unsigned int Fout) | 1747 | unsigned int Fref, unsigned int Fout) |
1655 | { | 1748 | { |
1656 | struct arizona_fll_cfg ref, sync; | ||
1657 | int ret; | 1749 | int ret; |
1658 | 1750 | ||
1659 | if (fll->sync_src == source && | 1751 | if (fll->sync_src == source && |
@@ -1662,13 +1754,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source, | |||
1662 | 1754 | ||
1663 | if (Fout) { | 1755 | if (Fout) { |
1664 | if (fll->ref_src >= 0) { | 1756 | if (fll->ref_src >= 0) { |
1665 | ret = arizona_calc_fll(fll, &ref, fll->ref_freq, | 1757 | ret = arizona_validate_fll(fll, fll->ref_freq, Fout); |
1666 | Fout); | ||
1667 | if (ret != 0) | 1758 | if (ret != 0) |
1668 | return ret; | 1759 | return ret; |
1669 | } | 1760 | } |
1670 | 1761 | ||
1671 | ret = arizona_calc_fll(fll, &sync, Fref, Fout); | 1762 | ret = arizona_validate_fll(fll, Fref, Fout); |
1672 | if (ret != 0) | 1763 | if (ret != 0) |
1673 | return ret; | 1764 | return ret; |
1674 | } | 1765 | } |
@@ -1678,7 +1769,7 @@ int arizona_set_fll(struct arizona_fll *fll, int source, | |||
1678 | fll->fout = Fout; | 1769 | fll->fout = Fout; |
1679 | 1770 | ||
1680 | if (Fout) { | 1771 | if (Fout) { |
1681 | arizona_enable_fll(fll, &ref, &sync); | 1772 | arizona_enable_fll(fll); |
1682 | } else { | 1773 | } else { |
1683 | arizona_disable_fll(fll); | 1774 | arizona_disable_fll(fll); |
1684 | } | 1775 | } |