diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_bios.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.c | 136 |
1 files changed, 104 insertions, 32 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 974b0f8ae04..2319390b200 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -4675,6 +4675,92 @@ int run_tmds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, i | |||
4675 | return 0; | 4675 | return 0; |
4676 | } | 4676 | } |
4677 | 4677 | ||
4678 | struct pll_mapping { | ||
4679 | u8 type; | ||
4680 | u32 reg; | ||
4681 | }; | ||
4682 | |||
4683 | static struct pll_mapping nv04_pll_mapping[] = { | ||
4684 | { PLL_CORE , NV_PRAMDAC_NVPLL_COEFF }, | ||
4685 | { PLL_MEMORY, NV_PRAMDAC_MPLL_COEFF }, | ||
4686 | { PLL_VPLL0 , NV_PRAMDAC_VPLL_COEFF }, | ||
4687 | { PLL_VPLL1 , NV_RAMDAC_VPLL2 }, | ||
4688 | {} | ||
4689 | }; | ||
4690 | |||
4691 | static struct pll_mapping nv40_pll_mapping[] = { | ||
4692 | { PLL_CORE , 0x004000 }, | ||
4693 | { PLL_MEMORY, 0x004020 }, | ||
4694 | { PLL_VPLL0 , NV_PRAMDAC_VPLL_COEFF }, | ||
4695 | { PLL_VPLL1 , NV_RAMDAC_VPLL2 }, | ||
4696 | {} | ||
4697 | }; | ||
4698 | |||
4699 | static struct pll_mapping nv50_pll_mapping[] = { | ||
4700 | { PLL_CORE , 0x004028 }, | ||
4701 | { PLL_SHADER, 0x004020 }, | ||
4702 | { PLL_UNK03 , 0x004000 }, | ||
4703 | { PLL_MEMORY, 0x004008 }, | ||
4704 | { PLL_UNK40 , 0x00e810 }, | ||
4705 | { PLL_UNK41 , 0x00e818 }, | ||
4706 | { PLL_UNK42 , 0x00e824 }, | ||
4707 | { PLL_VPLL0 , 0x614100 }, | ||
4708 | { PLL_VPLL1 , 0x614900 }, | ||
4709 | {} | ||
4710 | }; | ||
4711 | |||
4712 | static struct pll_mapping nv84_pll_mapping[] = { | ||
4713 | { PLL_CORE , 0x004028 }, | ||
4714 | { PLL_SHADER, 0x004020 }, | ||
4715 | { PLL_MEMORY, 0x004008 }, | ||
4716 | { PLL_UNK05 , 0x004030 }, | ||
4717 | { PLL_UNK41 , 0x00e818 }, | ||
4718 | { PLL_VPLL0 , 0x614100 }, | ||
4719 | { PLL_VPLL1 , 0x614900 }, | ||
4720 | {} | ||
4721 | }; | ||
4722 | |||
4723 | u32 | ||
4724 | get_pll_register(struct drm_device *dev, enum pll_types type) | ||
4725 | { | ||
4726 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
4727 | struct nvbios *bios = &dev_priv->vbios; | ||
4728 | struct pll_mapping *map; | ||
4729 | int i; | ||
4730 | |||
4731 | if (dev_priv->card_type < NV_40) | ||
4732 | map = nv04_pll_mapping; | ||
4733 | else | ||
4734 | if (dev_priv->card_type < NV_50) | ||
4735 | map = nv40_pll_mapping; | ||
4736 | else { | ||
4737 | u8 *plim = &bios->data[bios->pll_limit_tbl_ptr]; | ||
4738 | |||
4739 | if (plim[0] >= 0x40) { | ||
4740 | u8 *entry = plim + plim[1]; | ||
4741 | for (i = 0; i < plim[3]; i++, entry += plim[2]) { | ||
4742 | if (entry[0] == type) | ||
4743 | return ROM32(entry[3]); | ||
4744 | } | ||
4745 | |||
4746 | return 0; | ||
4747 | } | ||
4748 | |||
4749 | if (dev_priv->chipset == 0x50) | ||
4750 | map = nv50_pll_mapping; | ||
4751 | else | ||
4752 | map = nv84_pll_mapping; | ||
4753 | } | ||
4754 | |||
4755 | while (map->reg) { | ||
4756 | if (map->type == type) | ||
4757 | return map->reg; | ||
4758 | map++; | ||
4759 | } | ||
4760 | |||
4761 | return 0; | ||
4762 | } | ||
4763 | |||
4678 | int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims *pll_lim) | 4764 | int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims *pll_lim) |
4679 | { | 4765 | { |
4680 | /* | 4766 | /* |
@@ -4750,6 +4836,14 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4750 | /* initialize all members to zero */ | 4836 | /* initialize all members to zero */ |
4751 | memset(pll_lim, 0, sizeof(struct pll_lims)); | 4837 | memset(pll_lim, 0, sizeof(struct pll_lims)); |
4752 | 4838 | ||
4839 | /* if we were passed a type rather than a register, figure | ||
4840 | * out the register and store it | ||
4841 | */ | ||
4842 | if (limit_match > PLL_MAX) | ||
4843 | pll_lim->reg = limit_match; | ||
4844 | else | ||
4845 | pll_lim->reg = get_pll_register(dev, limit_match); | ||
4846 | |||
4753 | if (pll_lim_ver == 0x10 || pll_lim_ver == 0x11) { | 4847 | if (pll_lim_ver == 0x10 || pll_lim_ver == 0x11) { |
4754 | uint8_t *pll_rec = &bios->data[bios->pll_limit_tbl_ptr + headerlen + recordlen * pllindex]; | 4848 | uint8_t *pll_rec = &bios->data[bios->pll_limit_tbl_ptr + headerlen + recordlen * pllindex]; |
4755 | 4849 | ||
@@ -4785,7 +4879,6 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4785 | pll_lim->max_usable_log2p = 0x6; | 4879 | pll_lim->max_usable_log2p = 0x6; |
4786 | } else if (pll_lim_ver == 0x20 || pll_lim_ver == 0x21) { | 4880 | } else if (pll_lim_ver == 0x20 || pll_lim_ver == 0x21) { |
4787 | uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen; | 4881 | uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen; |
4788 | uint32_t reg = 0; /* default match */ | ||
4789 | uint8_t *pll_rec; | 4882 | uint8_t *pll_rec; |
4790 | int i; | 4883 | int i; |
4791 | 4884 | ||
@@ -4797,29 +4890,8 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4797 | NV_WARN(dev, "Default PLL limit entry has non-zero " | 4890 | NV_WARN(dev, "Default PLL limit entry has non-zero " |
4798 | "register field\n"); | 4891 | "register field\n"); |
4799 | 4892 | ||
4800 | if (limit_match > MAX_PLL_TYPES) | ||
4801 | /* we've been passed a reg as the match */ | ||
4802 | reg = limit_match; | ||
4803 | else /* limit match is a pll type */ | ||
4804 | for (i = 1; i < entries && !reg; i++) { | ||
4805 | uint32_t cmpreg = ROM32(bios->data[plloffs + recordlen * i]); | ||
4806 | |||
4807 | if (limit_match == NVPLL && | ||
4808 | (cmpreg == NV_PRAMDAC_NVPLL_COEFF || cmpreg == 0x4000)) | ||
4809 | reg = cmpreg; | ||
4810 | if (limit_match == MPLL && | ||
4811 | (cmpreg == NV_PRAMDAC_MPLL_COEFF || cmpreg == 0x4020)) | ||
4812 | reg = cmpreg; | ||
4813 | if (limit_match == VPLL1 && | ||
4814 | (cmpreg == NV_PRAMDAC_VPLL_COEFF || cmpreg == 0x4010)) | ||
4815 | reg = cmpreg; | ||
4816 | if (limit_match == VPLL2 && | ||
4817 | (cmpreg == NV_RAMDAC_VPLL2 || cmpreg == 0x4018)) | ||
4818 | reg = cmpreg; | ||
4819 | } | ||
4820 | |||
4821 | for (i = 1; i < entries; i++) | 4893 | for (i = 1; i < entries; i++) |
4822 | if (ROM32(bios->data[plloffs + recordlen * i]) == reg) { | 4894 | if (ROM32(bios->data[plloffs + recordlen * i]) == pll_lim->reg) { |
4823 | pllindex = i; | 4895 | pllindex = i; |
4824 | break; | 4896 | break; |
4825 | } | 4897 | } |
@@ -4827,7 +4899,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4827 | pll_rec = &bios->data[plloffs + recordlen * pllindex]; | 4899 | pll_rec = &bios->data[plloffs + recordlen * pllindex]; |
4828 | 4900 | ||
4829 | BIOSLOG(bios, "Loading PLL limits for reg 0x%08x\n", | 4901 | BIOSLOG(bios, "Loading PLL limits for reg 0x%08x\n", |
4830 | pllindex ? reg : 0); | 4902 | pllindex ? pll_lim->reg : 0); |
4831 | 4903 | ||
4832 | /* | 4904 | /* |
4833 | * Frequencies are stored in tables in MHz, kHz are more | 4905 | * Frequencies are stored in tables in MHz, kHz are more |
@@ -4877,8 +4949,8 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4877 | if (cv == 0x51 && !pll_lim->refclk) { | 4949 | if (cv == 0x51 && !pll_lim->refclk) { |
4878 | uint32_t sel_clk = bios_rd32(bios, NV_PRAMDAC_SEL_CLK); | 4950 | uint32_t sel_clk = bios_rd32(bios, NV_PRAMDAC_SEL_CLK); |
4879 | 4951 | ||
4880 | if (((limit_match == NV_PRAMDAC_VPLL_COEFF || limit_match == VPLL1) && sel_clk & 0x20) || | 4952 | if ((pll_lim->reg == NV_PRAMDAC_VPLL_COEFF && sel_clk & 0x20) || |
4881 | ((limit_match == NV_RAMDAC_VPLL2 || limit_match == VPLL2) && sel_clk & 0x80)) { | 4953 | (pll_lim->reg == NV_RAMDAC_VPLL2 && sel_clk & 0x80)) { |
4882 | if (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_CHIP_ID_INDEX) < 0xa3) | 4954 | if (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_CHIP_ID_INDEX) < 0xa3) |
4883 | pll_lim->refclk = 200000; | 4955 | pll_lim->refclk = 200000; |
4884 | else | 4956 | else |
@@ -4891,10 +4963,10 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4891 | int i; | 4963 | int i; |
4892 | 4964 | ||
4893 | BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", | 4965 | BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", |
4894 | limit_match); | 4966 | pll_lim->reg); |
4895 | 4967 | ||
4896 | for (i = 0; i < entries; i++, entry += recordlen) { | 4968 | for (i = 0; i < entries; i++, entry += recordlen) { |
4897 | if (ROM32(entry[3]) == limit_match) { | 4969 | if (ROM32(entry[3]) == pll_lim->reg) { |
4898 | record = &bios->data[ROM16(entry[1])]; | 4970 | record = &bios->data[ROM16(entry[1])]; |
4899 | break; | 4971 | break; |
4900 | } | 4972 | } |
@@ -4902,7 +4974,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4902 | 4974 | ||
4903 | if (!record) { | 4975 | if (!record) { |
4904 | NV_ERROR(dev, "Register 0x%08x not found in PLL " | 4976 | NV_ERROR(dev, "Register 0x%08x not found in PLL " |
4905 | "limits table", limit_match); | 4977 | "limits table", pll_lim->reg); |
4906 | return -ENOENT; | 4978 | return -ENOENT; |
4907 | } | 4979 | } |
4908 | 4980 | ||
@@ -4931,10 +5003,10 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4931 | int i; | 5003 | int i; |
4932 | 5004 | ||
4933 | BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", | 5005 | BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", |
4934 | limit_match); | 5006 | pll_lim->reg); |
4935 | 5007 | ||
4936 | for (i = 0; i < entries; i++, entry += recordlen) { | 5008 | for (i = 0; i < entries; i++, entry += recordlen) { |
4937 | if (ROM32(entry[3]) == limit_match) { | 5009 | if (ROM32(entry[3]) == pll_lim->reg) { |
4938 | record = &bios->data[ROM16(entry[1])]; | 5010 | record = &bios->data[ROM16(entry[1])]; |
4939 | break; | 5011 | break; |
4940 | } | 5012 | } |
@@ -4942,7 +5014,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4942 | 5014 | ||
4943 | if (!record) { | 5015 | if (!record) { |
4944 | NV_ERROR(dev, "Register 0x%08x not found in PLL " | 5016 | NV_ERROR(dev, "Register 0x%08x not found in PLL " |
4945 | "limits table", limit_match); | 5017 | "limits table", pll_lim->reg); |
4946 | return -ENOENT; | 5018 | return -ENOENT; |
4947 | } | 5019 | } |
4948 | 5020 | ||