aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-06-04 20:59:55 -0400
committerBen Skeggs <bskeggs@redhat.com>2014-06-11 02:11:29 -0400
commite84a35a8054397b0a4efc86ba82d9bc8b3895c75 (patch)
tree3681db98f5efa125772b664e4ab0a233b0a02d01 /drivers/gpu
parente32d68c9c799dbe90450b94146624d04aa25aa47 (diff)
drm/nv50-: prepare for attaching a SOR to multiple heads
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_crtc.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h1
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c85
3 files changed, 46 insertions, 42 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h
index d1e5890784d7..a0534489d23f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h
+++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h
@@ -74,7 +74,7 @@ struct nouveau_crtc {
74 74
75static inline struct nouveau_crtc *nouveau_crtc(struct drm_crtc *crtc) 75static inline struct nouveau_crtc *nouveau_crtc(struct drm_crtc *crtc)
76{ 76{
77 return container_of(crtc, struct nouveau_crtc, base); 77 return crtc ? container_of(crtc, struct nouveau_crtc, base) : NULL;
78} 78}
79 79
80static inline struct drm_crtc *to_drm_crtc(struct nouveau_crtc *crtc) 80static inline struct drm_crtc *to_drm_crtc(struct nouveau_crtc *crtc)
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index 24660c0f713d..fcf89c8c67b7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -46,6 +46,7 @@ struct nouveau_encoder {
46 /* different to drm_encoder.crtc, this reflects what's 46 /* different to drm_encoder.crtc, this reflects what's
47 * actually programmed on the hw, not the proposed crtc */ 47 * actually programmed on the hw, not the proposed crtc */
48 struct drm_crtc *crtc; 48 struct drm_crtc *crtc;
49 u32 ctrl;
49 50
50 struct drm_display_mode mode; 51 struct drm_display_mode mode;
51 int last_dpms; 52 int last_dpms;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 21c72480df82..765cf68545ae 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1701,10 +1701,9 @@ nv50_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode)
1701} 1701}
1702 1702
1703static void 1703static void
1704nv50_hdmi_disconnect(struct drm_encoder *encoder) 1704nv50_hdmi_disconnect(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
1705{ 1705{
1706 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 1706 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
1707 struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc);
1708 struct nv50_disp *disp = nv50_disp(encoder->dev); 1707 struct nv50_disp *disp = nv50_disp(encoder->dev);
1709 const u32 moff = (nv_crtc->index << 3) | nv_encoder->or; 1708 const u32 moff = (nv_crtc->index << 3) | nv_encoder->or;
1710 1709
@@ -1775,33 +1774,36 @@ nv50_sor_mode_fixup(struct drm_encoder *encoder,
1775} 1774}
1776 1775
1777static void 1776static void
1778nv50_sor_disconnect(struct drm_encoder *encoder) 1777nv50_sor_ctrl(struct nouveau_encoder *nv_encoder, u32 mask, u32 data)
1779{ 1778{
1780 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 1779 struct nv50_mast *mast = nv50_mast(nv_encoder->base.base.dev);
1781 struct nv50_mast *mast = nv50_mast(encoder->dev); 1780 u32 temp = (nv_encoder->ctrl & ~mask) | (data & mask), *push;
1782 const int or = nv_encoder->or; 1781 if (temp != nv_encoder->ctrl && (push = evo_wait(mast, 2))) {
1783 u32 *push; 1782 if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
1784 1783 evo_mthd(push, 0x0600 + (nv_encoder->or * 0x40), 1);
1785 if (nv_encoder->crtc) { 1784 evo_data(push, (nv_encoder->ctrl = temp));
1786 nv50_crtc_prepare(nv_encoder->crtc); 1785 } else {
1787 1786 evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1);
1788 push = evo_wait(mast, 4); 1787 evo_data(push, (nv_encoder->ctrl = temp));
1789 if (push) {
1790 if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
1791 evo_mthd(push, 0x0600 + (or * 0x40), 1);
1792 evo_data(push, 0x00000000);
1793 } else {
1794 evo_mthd(push, 0x0200 + (or * 0x20), 1);
1795 evo_data(push, 0x00000000);
1796 }
1797 evo_kick(push, mast);
1798 } 1788 }
1799 1789 evo_kick(push, mast);
1800 nv50_hdmi_disconnect(encoder);
1801 } 1790 }
1791}
1792
1793static void
1794nv50_sor_disconnect(struct drm_encoder *encoder)
1795{
1796 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
1797 struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc);
1802 1798
1803 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; 1799 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
1804 nv_encoder->crtc = NULL; 1800 nv_encoder->crtc = NULL;
1801
1802 if (nv_crtc) {
1803 nv50_crtc_prepare(&nv_crtc->base);
1804 nv50_sor_ctrl(nv_encoder, 1 << nv_crtc->index, 0);
1805 nv50_hdmi_disconnect(&nv_encoder->base.base, nv_crtc);
1806 }
1805} 1807}
1806 1808
1807static void 1809static void
@@ -1821,12 +1823,14 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
1821 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); 1823 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
1822 struct nouveau_connector *nv_connector; 1824 struct nouveau_connector *nv_connector;
1823 struct nvbios *bios = &drm->vbios; 1825 struct nvbios *bios = &drm->vbios;
1824 u32 *push, lvds = 0; 1826 u32 lvds = 0, mask, ctrl;
1825 u8 owner = 1 << nv_crtc->index; 1827 u8 owner = 1 << nv_crtc->index;
1826 u8 proto = 0xf; 1828 u8 proto = 0xf;
1827 u8 depth = 0x0; 1829 u8 depth = 0x0;
1828 1830
1829 nv_connector = nouveau_encoder_connector_get(nv_encoder); 1831 nv_connector = nouveau_encoder_connector_get(nv_encoder);
1832 nv_encoder->crtc = encoder->crtc;
1833
1830 switch (nv_encoder->dcb->type) { 1834 switch (nv_encoder->dcb->type) {
1831 case DCB_OUTPUT_TMDS: 1835 case DCB_OUTPUT_TMDS:
1832 if (nv_encoder->dcb->sorconf.link & 1) { 1836 if (nv_encoder->dcb->sorconf.link & 1) {
@@ -1838,7 +1842,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
1838 proto = 0x2; 1842 proto = 0x2;
1839 } 1843 }
1840 1844
1841 nv50_hdmi_mode_set(encoder, mode); 1845 nv50_hdmi_mode_set(&nv_encoder->base.base, mode);
1842 break; 1846 break;
1843 case DCB_OUTPUT_LVDS: 1847 case DCB_OUTPUT_LVDS:
1844 proto = 0x0; 1848 proto = 0x0;
@@ -1894,19 +1898,11 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
1894 break; 1898 break;
1895 } 1899 }
1896 1900
1897 nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); 1901 nv50_sor_dpms(&nv_encoder->base.base, DRM_MODE_DPMS_ON);
1898 1902
1899 push = evo_wait(nv50_mast(dev), 8); 1903 if (nv50_vers(mast) >= NVD0_DISP_CLASS) {
1900 if (push) { 1904 u32 *push = evo_wait(mast, 3);
1901 if (nv50_vers(mast) < NVD0_DISP_CLASS) { 1905 if (push) {
1902 u32 ctrl = (depth << 16) | (proto << 8) | owner;
1903 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
1904 ctrl |= 0x00001000;
1905 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
1906 ctrl |= 0x00002000;
1907 evo_mthd(push, 0x0600 + (nv_encoder->or * 0x040), 1);
1908 evo_data(push, ctrl);
1909 } else {
1910 u32 magic = 0x31ec6000 | (nv_crtc->index << 25); 1906 u32 magic = 0x31ec6000 | (nv_crtc->index << 25);
1911 u32 syncs = 0x00000001; 1907 u32 syncs = 0x00000001;
1912 1908
@@ -1921,14 +1917,21 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
1921 evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2); 1917 evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2);
1922 evo_data(push, syncs | (depth << 6)); 1918 evo_data(push, syncs | (depth << 6));
1923 evo_data(push, magic); 1919 evo_data(push, magic);
1924 evo_mthd(push, 0x0200 + (nv_encoder->or * 0x020), 1); 1920 evo_kick(push, mast);
1925 evo_data(push, owner | (proto << 8));
1926 } 1921 }
1927 1922
1928 evo_kick(push, mast); 1923 ctrl = proto << 8;
1924 mask = 0x00000f00;
1925 } else {
1926 ctrl = (depth << 16) | (proto << 8);
1927 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
1928 ctrl |= 0x00001000;
1929 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
1930 ctrl |= 0x00002000;
1931 mask = 0x000f3f00;
1929 } 1932 }
1930 1933
1931 nv_encoder->crtc = encoder->crtc; 1934 nv50_sor_ctrl(nv_encoder, mask | owner, ctrl | owner);
1932} 1935}
1933 1936
1934static void 1937static void