aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-02-10 18:52:58 -0500
committerBen Skeggs <bskeggs@redhat.com>2013-02-20 01:01:05 -0500
commiteb6313add6dddf07ea3e50c4caa33a9c3b2379f1 (patch)
treedb60f5990aa58a2c1279f19057e67b9d3867c6d0 /drivers/gpu/drm
parent476e84e126171d809f9c0b5d97137f5055f95ca8 (diff)
drm/nv50: initial kms support for off-chip TMDS/DP encoders
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c5
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c215
2 files changed, 202 insertions, 18 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index b64065781a4a..50a6dd02f7c5 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -1469,6 +1469,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
1469 } 1469 }
1470 case DCB_OUTPUT_DP: 1470 case DCB_OUTPUT_DP:
1471 entry->dpconf.sor.link = (conf & 0x00000030) >> 4; 1471 entry->dpconf.sor.link = (conf & 0x00000030) >> 4;
1472 entry->extdev = (conf & 0x0000ff00) >> 8;
1472 switch ((conf & 0x00e00000) >> 21) { 1473 switch ((conf & 0x00e00000) >> 21) {
1473 case 0: 1474 case 0:
1474 entry->dpconf.link_bw = 162000; 1475 entry->dpconf.link_bw = 162000;
@@ -1490,8 +1491,10 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
1490 } 1491 }
1491 break; 1492 break;
1492 case DCB_OUTPUT_TMDS: 1493 case DCB_OUTPUT_TMDS:
1493 if (dcb->version >= 0x40) 1494 if (dcb->version >= 0x40) {
1494 entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4; 1495 entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4;
1496 entry->extdev = (conf & 0x0000ff00) >> 8;
1497 }
1495 else if (dcb->version >= 0x30) 1498 else if (dcb->version >= 0x30)
1496 entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8; 1499 entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8;
1497 else if (dcb->version >= 0x22) 1500 else if (dcb->version >= 0x22)
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 5c56575729be..49f26cd86013 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1923,6 +1923,184 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
1923} 1923}
1924 1924
1925/****************************************************************************** 1925/******************************************************************************
1926 * PIOR
1927 *****************************************************************************/
1928
1929static void
1930nv50_pior_dpms(struct drm_encoder *encoder, int mode)
1931{
1932 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
1933 struct nv50_disp *disp = nv50_disp(encoder->dev);
1934 u32 mthd = (nv_encoder->dcb->type << 12) | nv_encoder->or;
1935 u32 ctrl = (mode == DRM_MODE_DPMS_ON);
1936 nv_call(disp->core, NV50_DISP_PIOR_PWR + mthd, ctrl);
1937}
1938
1939static bool
1940nv50_pior_mode_fixup(struct drm_encoder *encoder,
1941 const struct drm_display_mode *mode,
1942 struct drm_display_mode *adjusted_mode)
1943{
1944 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
1945 struct nouveau_connector *nv_connector;
1946
1947 nv_connector = nouveau_encoder_connector_get(nv_encoder);
1948 if (nv_connector && nv_connector->native_mode) {
1949 if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) {
1950 int id = adjusted_mode->base.id;
1951 *adjusted_mode = *nv_connector->native_mode;
1952 adjusted_mode->base.id = id;
1953 }
1954 }
1955
1956 adjusted_mode->clock *= 2;
1957 return true;
1958}
1959
1960static void
1961nv50_pior_commit(struct drm_encoder *encoder)
1962{
1963}
1964
1965static void
1966nv50_pior_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
1967 struct drm_display_mode *adjusted_mode)
1968{
1969 struct nv50_mast *mast = nv50_mast(encoder->dev);
1970 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
1971 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
1972 struct nouveau_connector *nv_connector;
1973 u8 owner = 1 << nv_crtc->index;
1974 u8 proto, depth;
1975 u32 *push;
1976
1977 nv_connector = nouveau_encoder_connector_get(nv_encoder);
1978 switch (nv_connector->base.display_info.bpc) {
1979 case 10: depth = 0x6; break;
1980 case 8: depth = 0x5; break;
1981 case 6: depth = 0x2; break;
1982 default: depth = 0x0; break;
1983 }
1984
1985 switch (nv_encoder->dcb->type) {
1986 case DCB_OUTPUT_TMDS:
1987 case DCB_OUTPUT_DP:
1988 proto = 0x0;
1989 break;
1990 default:
1991 BUG_ON(1);
1992 break;
1993 }
1994
1995 nv50_pior_dpms(encoder, DRM_MODE_DPMS_ON);
1996
1997 push = evo_wait(mast, 8);
1998 if (push) {
1999 if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
2000 u32 ctrl = (depth << 16) | (proto << 8) | owner;
2001 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
2002 ctrl |= 0x00001000;
2003 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
2004 ctrl |= 0x00002000;
2005 evo_mthd(push, 0x0700 + (nv_encoder->or * 0x040), 1);
2006 evo_data(push, ctrl);
2007 }
2008
2009 evo_kick(push, mast);
2010 }
2011
2012 nv_encoder->crtc = encoder->crtc;
2013}
2014
2015static void
2016nv50_pior_disconnect(struct drm_encoder *encoder)
2017{
2018 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
2019 struct nv50_mast *mast = nv50_mast(encoder->dev);
2020 const int or = nv_encoder->or;
2021 u32 *push;
2022
2023 if (nv_encoder->crtc) {
2024 nv50_crtc_prepare(nv_encoder->crtc);
2025
2026 push = evo_wait(mast, 4);
2027 if (push) {
2028 if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
2029 evo_mthd(push, 0x0700 + (or * 0x040), 1);
2030 evo_data(push, 0x00000000);
2031 }
2032
2033 evo_mthd(push, 0x0080, 1);
2034 evo_data(push, 0x00000000);
2035 evo_kick(push, mast);
2036 }
2037 }
2038
2039 nv_encoder->crtc = NULL;
2040}
2041
2042static void
2043nv50_pior_destroy(struct drm_encoder *encoder)
2044{
2045 drm_encoder_cleanup(encoder);
2046 kfree(encoder);
2047}
2048
2049static const struct drm_encoder_helper_funcs nv50_pior_hfunc = {
2050 .dpms = nv50_pior_dpms,
2051 .mode_fixup = nv50_pior_mode_fixup,
2052 .prepare = nv50_pior_disconnect,
2053 .commit = nv50_pior_commit,
2054 .mode_set = nv50_pior_mode_set,
2055 .disable = nv50_pior_disconnect,
2056 .get_crtc = nv50_display_crtc_get,
2057};
2058
2059static const struct drm_encoder_funcs nv50_pior_func = {
2060 .destroy = nv50_pior_destroy,
2061};
2062
2063static int
2064nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
2065{
2066 struct nouveau_drm *drm = nouveau_drm(connector->dev);
2067 struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
2068 struct nouveau_i2c_port *ddc = NULL;
2069 struct nouveau_encoder *nv_encoder;
2070 struct drm_encoder *encoder;
2071 int type;
2072
2073 switch (dcbe->type) {
2074 case DCB_OUTPUT_TMDS:
2075 ddc = i2c->find_type(i2c, NV_I2C_TYPE_EXTDDC(dcbe->extdev));
2076 type = DRM_MODE_ENCODER_TMDS;
2077 break;
2078 case DCB_OUTPUT_DP:
2079 ddc = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(dcbe->extdev));
2080 type = DRM_MODE_ENCODER_TMDS;
2081 break;
2082 default:
2083 return -ENODEV;
2084 }
2085
2086 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
2087 if (!nv_encoder)
2088 return -ENOMEM;
2089 nv_encoder->dcb = dcbe;
2090 nv_encoder->or = ffs(dcbe->or) - 1;
2091 nv_encoder->i2c = ddc;
2092
2093 encoder = to_drm_encoder(nv_encoder);
2094 encoder->possible_crtcs = dcbe->heads;
2095 encoder->possible_clones = 0;
2096 drm_encoder_init(connector->dev, encoder, &nv50_pior_func, type);
2097 drm_encoder_helper_add(encoder, &nv50_pior_hfunc);
2098
2099 drm_mode_connector_attach_encoder(connector, encoder);
2100 return 0;
2101}
2102
2103/******************************************************************************
1926 * Init 2104 * Init
1927 *****************************************************************************/ 2105 *****************************************************************************/
1928void 2106void
@@ -2044,25 +2222,28 @@ nv50_display_create(struct drm_device *dev)
2044 if (IS_ERR(connector)) 2222 if (IS_ERR(connector))
2045 continue; 2223 continue;
2046 2224
2047 if (dcbe->location != DCB_LOC_ON_CHIP) { 2225 if (dcbe->location == DCB_LOC_ON_CHIP) {
2048 NV_WARN(drm, "skipping off-chip encoder %d/%d\n", 2226 switch (dcbe->type) {
2049 dcbe->type, ffs(dcbe->or) - 1); 2227 case DCB_OUTPUT_TMDS:
2050 continue; 2228 case DCB_OUTPUT_LVDS:
2229 case DCB_OUTPUT_DP:
2230 ret = nv50_sor_create(connector, dcbe);
2231 break;
2232 case DCB_OUTPUT_ANALOG:
2233 ret = nv50_dac_create(connector, dcbe);
2234 break;
2235 default:
2236 ret = -ENODEV;
2237 break;
2238 }
2239 } else {
2240 ret = nv50_pior_create(connector, dcbe);
2051 } 2241 }
2052 2242
2053 switch (dcbe->type) { 2243 if (ret) {
2054 case DCB_OUTPUT_TMDS: 2244 NV_WARN(drm, "failed to create encoder %d/%d/%d: %d\n",
2055 case DCB_OUTPUT_LVDS: 2245 dcbe->location, dcbe->type,
2056 case DCB_OUTPUT_DP: 2246 ffs(dcbe->or) - 1, ret);
2057 nv50_sor_create(connector, dcbe);
2058 break;
2059 case DCB_OUTPUT_ANALOG:
2060 nv50_dac_create(connector, dcbe);
2061 break;
2062 default:
2063 NV_WARN(drm, "skipping unsupported encoder %d/%d\n",
2064 dcbe->type, ffs(dcbe->or) - 1);
2065 continue;
2066 } 2247 }
2067 } 2248 }
2068 2249