aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2018-10-10 20:23:11 -0400
committerDave Airlie <airlied@redhat.com>2018-10-10 20:24:28 -0400
commit7e6191d4360a2df6cf2a2613dcb79680cb943df8 (patch)
treee07605113d5028f3dd825d6e259f63cdb3f1d161
parent62e681f7dcab746412dce22d4b75b32c5ea38cdb (diff)
parent74a07c0a59fa372b069d879971ba4d9e341979cf (diff)
Merge branch 'linux-4.20' of git://github.com/skeggsb/linux into drm-next
Just initial HDMI 2.0 support, and a bunch of other cleanups. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/CABDvA=mgEm9JxP7AX7Sff-AEs7a75M4SqwFHmLPZhJojm4k=OA@mail.gmail.com
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c40
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl5070.h5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_backlight.c220
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c54
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.h33
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.h25
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c179
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c36
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c11
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c1
17 files changed, 401 insertions, 236 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 1dbd1dcdcf15..5f163a025e89 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -36,6 +36,7 @@
36#include <drm/drm_dp_helper.h> 36#include <drm/drm_dp_helper.h>
37#include <drm/drm_fb_helper.h> 37#include <drm/drm_fb_helper.h>
38#include <drm/drm_plane_helper.h> 38#include <drm/drm_plane_helper.h>
39#include <drm/drm_scdc_helper.h>
39#include <drm/drm_edid.h> 40#include <drm/drm_edid.h>
40 41
41#include <nvif/class.h> 42#include <nvif/class.h>
@@ -531,6 +532,7 @@ nv50_hdmi_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
531static void 532static void
532nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) 533nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
533{ 534{
535 struct nouveau_drm *drm = nouveau_drm(encoder->dev);
534 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 536 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
535 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); 537 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
536 struct nv50_disp *disp = nv50_disp(encoder->dev); 538 struct nv50_disp *disp = nv50_disp(encoder->dev);
@@ -548,9 +550,12 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
548 .pwr.rekey = 56, /* binary driver, and tegra, constant */ 550 .pwr.rekey = 56, /* binary driver, and tegra, constant */
549 }; 551 };
550 struct nouveau_connector *nv_connector; 552 struct nouveau_connector *nv_connector;
553 struct drm_hdmi_info *hdmi;
551 u32 max_ac_packet; 554 u32 max_ac_packet;
552 union hdmi_infoframe avi_frame; 555 union hdmi_infoframe avi_frame;
553 union hdmi_infoframe vendor_frame; 556 union hdmi_infoframe vendor_frame;
557 bool scdc_supported, high_tmds_clock_ratio = false, scrambling = false;
558 u8 config;
554 int ret; 559 int ret;
555 int size; 560 int size;
556 561
@@ -558,8 +563,11 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
558 if (!drm_detect_hdmi_monitor(nv_connector->edid)) 563 if (!drm_detect_hdmi_monitor(nv_connector->edid))
559 return; 564 return;
560 565
566 hdmi = &nv_connector->base.display_info.hdmi;
567 scdc_supported = hdmi->scdc.supported;
568
561 ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode, 569 ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode,
562 false); 570 scdc_supported);
563 if (!ret) { 571 if (!ret) {
564 /* We have an AVI InfoFrame, populate it to the display */ 572 /* We have an AVI InfoFrame, populate it to the display */
565 args.pwr.avi_infoframe_length 573 args.pwr.avi_infoframe_length
@@ -582,12 +590,42 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
582 max_ac_packet -= 18; /* constant from tegra */ 590 max_ac_packet -= 18; /* constant from tegra */
583 args.pwr.max_ac_packet = max_ac_packet / 32; 591 args.pwr.max_ac_packet = max_ac_packet / 32;
584 592
593 if (hdmi->scdc.scrambling.supported) {
594 high_tmds_clock_ratio = mode->clock > 340000;
595 scrambling = high_tmds_clock_ratio ||
596 hdmi->scdc.scrambling.low_rates;
597 }
598
599 args.pwr.scdc =
600 NV50_DISP_SOR_HDMI_PWR_V0_SCDC_SCRAMBLE * scrambling |
601 NV50_DISP_SOR_HDMI_PWR_V0_SCDC_DIV_BY_4 * high_tmds_clock_ratio;
602
585 size = sizeof(args.base) 603 size = sizeof(args.base)
586 + sizeof(args.pwr) 604 + sizeof(args.pwr)
587 + args.pwr.avi_infoframe_length 605 + args.pwr.avi_infoframe_length
588 + args.pwr.vendor_infoframe_length; 606 + args.pwr.vendor_infoframe_length;
589 nvif_mthd(&disp->disp->object, 0, &args, size); 607 nvif_mthd(&disp->disp->object, 0, &args, size);
608
590 nv50_audio_enable(encoder, mode); 609 nv50_audio_enable(encoder, mode);
610
611 /* If SCDC is supported by the downstream monitor, update
612 * divider / scrambling settings to what we programmed above.
613 */
614 if (!hdmi->scdc.scrambling.supported)
615 return;
616
617 ret = drm_scdc_readb(nv_encoder->i2c, SCDC_TMDS_CONFIG, &config);
618 if (ret < 0) {
619 NV_ERROR(drm, "Failure to read SCDC_TMDS_CONFIG: %d\n", ret);
620 return;
621 }
622 config &= ~(SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 | SCDC_SCRAMBLING_ENABLE);
623 config |= SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 * high_tmds_clock_ratio;
624 config |= SCDC_SCRAMBLING_ENABLE * scrambling;
625 ret = drm_scdc_writeb(nv_encoder->i2c, SCDC_TMDS_CONFIG, config);
626 if (ret < 0)
627 NV_ERROR(drm, "Failure to write SCDC_TMDS_CONFIG = 0x%02x: %d\n",
628 config, ret);
591} 629}
592 630
593/****************************************************************************** 631/******************************************************************************
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
index 7cdf53615d7b..bced81987269 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
@@ -69,7 +69,10 @@ struct nv50_disp_sor_hdmi_pwr_v0 {
69 __u8 rekey; 69 __u8 rekey;
70 __u8 avi_infoframe_length; 70 __u8 avi_infoframe_length;
71 __u8 vendor_infoframe_length; 71 __u8 vendor_infoframe_length;
72 __u8 pad06[2]; 72#define NV50_DISP_SOR_HDMI_PWR_V0_SCDC_SCRAMBLE (1 << 0)
73#define NV50_DISP_SOR_HDMI_PWR_V0_SCDC_DIV_BY_4 (1 << 1)
74 __u8 scdc;
75 __u8 pad07[1];
73}; 76};
74 77
75struct nv50_disp_sor_lvds_script_v0 { 78struct nv50_disp_sor_lvds_script_v0 {
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 408b955e5c39..5f5be6368aed 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -37,18 +37,19 @@
37#include "nouveau_drv.h" 37#include "nouveau_drv.h"
38#include "nouveau_reg.h" 38#include "nouveau_reg.h"
39#include "nouveau_encoder.h" 39#include "nouveau_encoder.h"
40#include "nouveau_connector.h"
40 41
41static struct ida bl_ida; 42static struct ida bl_ida;
42#define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0' 43#define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0'
43 44
44struct backlight_connector { 45struct nouveau_backlight {
45 struct list_head head; 46 struct backlight_device *dev;
46 int id; 47 int id;
47}; 48};
48 49
49static bool 50static bool
50nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], struct backlight_connector 51nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE],
51 *connector) 52 struct nouveau_backlight *bl)
52{ 53{
53 const int nb = ida_simple_get(&bl_ida, 0, 0, GFP_KERNEL); 54 const int nb = ida_simple_get(&bl_ida, 0, 0, GFP_KERNEL);
54 if (nb < 0 || nb >= 100) 55 if (nb < 0 || nb >= 100)
@@ -57,17 +58,18 @@ nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], struct backlight_c
57 snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb); 58 snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb);
58 else 59 else
59 snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight"); 60 snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight");
60 connector->id = nb; 61 bl->id = nb;
61 return true; 62 return true;
62} 63}
63 64
64static int 65static int
65nv40_get_intensity(struct backlight_device *bd) 66nv40_get_intensity(struct backlight_device *bd)
66{ 67{
67 struct nouveau_drm *drm = bl_get_data(bd); 68 struct nouveau_encoder *nv_encoder = bl_get_data(bd);
69 struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
68 struct nvif_object *device = &drm->client.device.object; 70 struct nvif_object *device = &drm->client.device.object;
69 int val = (nvif_rd32(device, NV40_PMC_BACKLIGHT) & 71 int val = (nvif_rd32(device, NV40_PMC_BACKLIGHT) &
70 NV40_PMC_BACKLIGHT_MASK) >> 16; 72 NV40_PMC_BACKLIGHT_MASK) >> 16;
71 73
72 return val; 74 return val;
73} 75}
@@ -75,13 +77,14 @@ nv40_get_intensity(struct backlight_device *bd)
75static int 77static int
76nv40_set_intensity(struct backlight_device *bd) 78nv40_set_intensity(struct backlight_device *bd)
77{ 79{
78 struct nouveau_drm *drm = bl_get_data(bd); 80 struct nouveau_encoder *nv_encoder = bl_get_data(bd);
81 struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
79 struct nvif_object *device = &drm->client.device.object; 82 struct nvif_object *device = &drm->client.device.object;
80 int val = bd->props.brightness; 83 int val = bd->props.brightness;
81 int reg = nvif_rd32(device, NV40_PMC_BACKLIGHT); 84 int reg = nvif_rd32(device, NV40_PMC_BACKLIGHT);
82 85
83 nvif_wr32(device, NV40_PMC_BACKLIGHT, 86 nvif_wr32(device, NV40_PMC_BACKLIGHT,
84 (val << 16) | (reg & ~NV40_PMC_BACKLIGHT_MASK)); 87 (val << 16) | (reg & ~NV40_PMC_BACKLIGHT_MASK));
85 88
86 return 0; 89 return 0;
87} 90}
@@ -93,38 +96,19 @@ static const struct backlight_ops nv40_bl_ops = {
93}; 96};
94 97
95static int 98static int
96nv40_backlight_init(struct drm_connector *connector) 99nv40_backlight_init(struct nouveau_encoder *encoder,
100 struct backlight_properties *props,
101 const struct backlight_ops **ops)
97{ 102{
98 struct nouveau_drm *drm = nouveau_drm(connector->dev); 103 struct nouveau_drm *drm = nouveau_drm(encoder->base.base.dev);
99 struct nvif_object *device = &drm->client.device.object; 104 struct nvif_object *device = &drm->client.device.object;
100 struct backlight_properties props;
101 struct backlight_device *bd;
102 struct backlight_connector bl_connector;
103 char backlight_name[BL_NAME_SIZE];
104 105
105 if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK)) 106 if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
106 return 0; 107 return -ENODEV;
107
108 memset(&props, 0, sizeof(struct backlight_properties));
109 props.type = BACKLIGHT_RAW;
110 props.max_brightness = 31;
111 if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) {
112 NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
113 return 0;
114 }
115 bd = backlight_device_register(backlight_name , connector->kdev, drm,
116 &nv40_bl_ops, &props);
117
118 if (IS_ERR(bd)) {
119 if (bl_connector.id > 0)
120 ida_simple_remove(&bl_ida, bl_connector.id);
121 return PTR_ERR(bd);
122 }
123 list_add(&bl_connector.head, &drm->bl_connectors);
124 drm->backlight = bd;
125 bd->props.brightness = nv40_get_intensity(bd);
126 backlight_update_status(bd);
127 108
109 props->type = BACKLIGHT_RAW;
110 props->max_brightness = 31;
111 *ops = &nv40_bl_ops;
128 return 0; 112 return 0;
129} 113}
130 114
@@ -154,7 +138,7 @@ nv50_set_intensity(struct backlight_device *bd)
154 u32 val = (bd->props.brightness * div) / 100; 138 u32 val = (bd->props.brightness * div) / 100;
155 139
156 nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or), 140 nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
157 NV50_PDISP_SOR_PWM_CTL_NEW | val); 141 NV50_PDISP_SOR_PWM_CTL_NEW | val);
158 return 0; 142 return 0;
159} 143}
160 144
@@ -194,9 +178,10 @@ nva3_set_intensity(struct backlight_device *bd)
194 div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or)); 178 div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
195 val = (bd->props.brightness * div) / 100; 179 val = (bd->props.brightness * div) / 100;
196 if (div) { 180 if (div) {
197 nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or), val | 181 nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
198 NV50_PDISP_SOR_PWM_CTL_NEW | 182 val |
199 NVA3_PDISP_SOR_PWM_CTL_UNK); 183 NV50_PDISP_SOR_PWM_CTL_NEW |
184 NVA3_PDISP_SOR_PWM_CTL_UNK);
200 return 0; 185 return 0;
201 } 186 }
202 187
@@ -210,110 +195,119 @@ static const struct backlight_ops nva3_bl_ops = {
210}; 195};
211 196
212static int 197static int
213nv50_backlight_init(struct drm_connector *connector) 198nv50_backlight_init(struct nouveau_encoder *nv_encoder,
199 struct backlight_properties *props,
200 const struct backlight_ops **ops)
214{ 201{
215 struct nouveau_drm *drm = nouveau_drm(connector->dev); 202 struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
216 struct nvif_object *device = &drm->client.device.object; 203 struct nvif_object *device = &drm->client.device.object;
217 struct nouveau_encoder *nv_encoder;
218 struct backlight_properties props;
219 struct backlight_device *bd;
220 const struct backlight_ops *ops;
221 struct backlight_connector bl_connector;
222 char backlight_name[BL_NAME_SIZE];
223
224 nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
225 if (!nv_encoder) {
226 nv_encoder = find_encoder(connector, DCB_OUTPUT_DP);
227 if (!nv_encoder)
228 return -ENODEV;
229 }
230 204
231 if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1))) 205 if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1)))
232 return 0; 206 return -ENODEV;
233 207
234 if (drm->client.device.info.chipset <= 0xa0 || 208 if (drm->client.device.info.chipset <= 0xa0 ||
235 drm->client.device.info.chipset == 0xaa || 209 drm->client.device.info.chipset == 0xaa ||
236 drm->client.device.info.chipset == 0xac) 210 drm->client.device.info.chipset == 0xac)
237 ops = &nv50_bl_ops; 211 *ops = &nv50_bl_ops;
238 else 212 else
239 ops = &nva3_bl_ops; 213 *ops = &nva3_bl_ops;
240
241 memset(&props, 0, sizeof(struct backlight_properties));
242 props.type = BACKLIGHT_RAW;
243 props.max_brightness = 100;
244 if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) {
245 NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
246 return 0;
247 }
248 bd = backlight_device_register(backlight_name , connector->kdev,
249 nv_encoder, ops, &props);
250 214
251 if (IS_ERR(bd)) { 215 props->type = BACKLIGHT_RAW;
252 if (bl_connector.id > 0) 216 props->max_brightness = 100;
253 ida_simple_remove(&bl_ida, bl_connector.id);
254 return PTR_ERR(bd);
255 }
256 217
257 list_add(&bl_connector.head, &drm->bl_connectors);
258 drm->backlight = bd;
259 bd->props.brightness = bd->ops->get_brightness(bd);
260 backlight_update_status(bd);
261 return 0; 218 return 0;
262} 219}
263 220
264int 221int
265nouveau_backlight_init(struct drm_device *dev) 222nouveau_backlight_init(struct drm_connector *connector)
266{ 223{
267 struct nouveau_drm *drm = nouveau_drm(dev); 224 struct nouveau_drm *drm = nouveau_drm(connector->dev);
225 struct nouveau_backlight *bl;
226 struct nouveau_encoder *nv_encoder = NULL;
268 struct nvif_device *device = &drm->client.device; 227 struct nvif_device *device = &drm->client.device;
269 struct drm_connector *connector; 228 char backlight_name[BL_NAME_SIZE];
270 struct drm_connector_list_iter conn_iter; 229 struct backlight_properties props = {0};
271 230 const struct backlight_ops *ops;
272 INIT_LIST_HEAD(&drm->bl_connectors); 231 int ret;
273 232
274 if (apple_gmux_present()) { 233 if (apple_gmux_present()) {
275 NV_INFO(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n"); 234 NV_INFO_ONCE(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n");
276 return 0; 235 return 0;
277 } 236 }
278 237
279 drm_connector_list_iter_begin(dev, &conn_iter); 238 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
280 drm_for_each_connector_iter(connector, &conn_iter) { 239 nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
281 if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && 240 else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
282 connector->connector_type != DRM_MODE_CONNECTOR_eDP) 241 nv_encoder = find_encoder(connector, DCB_OUTPUT_DP);
283 continue; 242 else
284 243 return 0;
285 switch (device->info.family) { 244
286 case NV_DEVICE_INFO_V0_CURIE: 245 if (!nv_encoder)
287 return nv40_backlight_init(connector); 246 return 0;
288 case NV_DEVICE_INFO_V0_TESLA: 247
289 case NV_DEVICE_INFO_V0_FERMI: 248 switch (device->info.family) {
290 case NV_DEVICE_INFO_V0_KEPLER: 249 case NV_DEVICE_INFO_V0_CURIE:
291 case NV_DEVICE_INFO_V0_MAXWELL: 250 ret = nv40_backlight_init(nv_encoder, &props, &ops);
292 return nv50_backlight_init(connector); 251 break;
293 default: 252 case NV_DEVICE_INFO_V0_TESLA:
294 break; 253 case NV_DEVICE_INFO_V0_FERMI:
295 } 254 case NV_DEVICE_INFO_V0_KEPLER:
255 case NV_DEVICE_INFO_V0_MAXWELL:
256 ret = nv50_backlight_init(nv_encoder, &props, &ops);
257 break;
258 default:
259 return 0;
296 } 260 }
297 drm_connector_list_iter_end(&conn_iter); 261
262 if (ret == -ENODEV)
263 return 0;
264 else if (ret)
265 return ret;
266
267 bl = kzalloc(sizeof(*bl), GFP_KERNEL);
268 if (!bl)
269 return -ENOMEM;
270
271 if (!nouveau_get_backlight_name(backlight_name, bl)) {
272 NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
273 goto fail_alloc;
274 }
275
276 bl->dev = backlight_device_register(backlight_name, connector->kdev,
277 nv_encoder, ops, &props);
278 if (IS_ERR(bl->dev)) {
279 if (bl->id >= 0)
280 ida_simple_remove(&bl_ida, bl->id);
281 ret = PTR_ERR(bl->dev);
282 goto fail_alloc;
283 }
284
285 nouveau_connector(connector)->backlight = bl;
286 bl->dev->props.brightness = bl->dev->ops->get_brightness(bl->dev);
287 backlight_update_status(bl->dev);
298 288
299 return 0; 289 return 0;
290
291fail_alloc:
292 kfree(bl);
293 return ret;
300} 294}
301 295
302void 296void
303nouveau_backlight_exit(struct drm_device *dev) 297nouveau_backlight_fini(struct drm_connector *connector)
304{ 298{
305 struct nouveau_drm *drm = nouveau_drm(dev); 299 struct nouveau_connector *nv_conn = nouveau_connector(connector);
306 struct backlight_connector *connector; 300 struct nouveau_backlight *bl = nv_conn->backlight;
307 301
308 list_for_each_entry(connector, &drm->bl_connectors, head) { 302 if (!bl)
309 if (connector->id >= 0) 303 return;
310 ida_simple_remove(&bl_ida, connector->id);
311 }
312 304
313 if (drm->backlight) { 305 if (bl->id >= 0)
314 backlight_device_unregister(drm->backlight); 306 ida_simple_remove(&bl_ida, bl->id);
315 drm->backlight = NULL; 307
316 } 308 backlight_device_unregister(bl->dev);
309 nv_conn->backlight = NULL;
310 kfree(bl);
317} 311}
318 312
319void 313void
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index dde8724aa8f5..fd80661dff92 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -886,6 +886,22 @@ nouveau_connector_detect_depth(struct drm_connector *connector)
886} 886}
887 887
888static int 888static int
889nouveau_connector_late_register(struct drm_connector *connector)
890{
891 int ret;
892
893 ret = nouveau_backlight_init(connector);
894
895 return ret;
896}
897
898static void
899nouveau_connector_early_unregister(struct drm_connector *connector)
900{
901 nouveau_backlight_fini(connector);
902}
903
904static int
889nouveau_connector_get_modes(struct drm_connector *connector) 905nouveau_connector_get_modes(struct drm_connector *connector)
890{ 906{
891 struct drm_device *dev = connector->dev; 907 struct drm_device *dev = connector->dev;
@@ -953,18 +969,33 @@ nouveau_connector_get_modes(struct drm_connector *connector)
953} 969}
954 970
955static unsigned 971static unsigned
956get_tmds_link_bandwidth(struct drm_connector *connector, bool hdmi) 972get_tmds_link_bandwidth(struct drm_connector *connector)
957{ 973{
958 struct nouveau_connector *nv_connector = nouveau_connector(connector); 974 struct nouveau_connector *nv_connector = nouveau_connector(connector);
975 struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
959 struct nouveau_drm *drm = nouveau_drm(connector->dev); 976 struct nouveau_drm *drm = nouveau_drm(connector->dev);
960 struct dcb_output *dcb = nv_connector->detected_encoder->dcb; 977 struct dcb_output *dcb = nv_connector->detected_encoder->dcb;
978 struct drm_display_info *info = NULL;
979 const unsigned duallink_scale =
980 nouveau_duallink && nv_encoder->dcb->duallink_possible ? 2 : 1;
981
982 if (drm_detect_hdmi_monitor(nv_connector->edid))
983 info = &nv_connector->base.display_info;
961 984
962 if (hdmi) { 985 if (info) {
963 if (nouveau_hdmimhz > 0) 986 if (nouveau_hdmimhz > 0)
964 return nouveau_hdmimhz * 1000; 987 return nouveau_hdmimhz * 1000;
965 /* Note: these limits are conservative, some Fermi's 988 /* Note: these limits are conservative, some Fermi's
966 * can do 297 MHz. Unclear how this can be determined. 989 * can do 297 MHz. Unclear how this can be determined.
967 */ 990 */
991 if (drm->client.device.info.chipset >= 0x120) {
992 const int max_tmds_clock =
993 info->hdmi.scdc.scrambling.supported ?
994 594000 : 340000;
995 return info->max_tmds_clock ?
996 min(info->max_tmds_clock, max_tmds_clock) :
997 max_tmds_clock;
998 }
968 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_KEPLER) 999 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_KEPLER)
969 return 297000; 1000 return 297000;
970 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_FERMI) 1001 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_FERMI)
@@ -972,13 +1003,13 @@ get_tmds_link_bandwidth(struct drm_connector *connector, bool hdmi)
972 } 1003 }
973 if (dcb->location != DCB_LOC_ON_CHIP || 1004 if (dcb->location != DCB_LOC_ON_CHIP ||
974 drm->client.device.info.chipset >= 0x46) 1005 drm->client.device.info.chipset >= 0x46)
975 return 165000; 1006 return 165000 * duallink_scale;
976 else if (drm->client.device.info.chipset >= 0x40) 1007 else if (drm->client.device.info.chipset >= 0x40)
977 return 155000; 1008 return 155000 * duallink_scale;
978 else if (drm->client.device.info.chipset >= 0x18) 1009 else if (drm->client.device.info.chipset >= 0x18)
979 return 135000; 1010 return 135000 * duallink_scale;
980 else 1011 else
981 return 112000; 1012 return 112000 * duallink_scale;
982} 1013}
983 1014
984static enum drm_mode_status 1015static enum drm_mode_status
@@ -990,7 +1021,6 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
990 struct drm_encoder *encoder = to_drm_encoder(nv_encoder); 1021 struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
991 unsigned min_clock = 25000, max_clock = min_clock; 1022 unsigned min_clock = 25000, max_clock = min_clock;
992 unsigned clock = mode->clock; 1023 unsigned clock = mode->clock;
993 bool hdmi;
994 1024
995 switch (nv_encoder->dcb->type) { 1025 switch (nv_encoder->dcb->type) {
996 case DCB_OUTPUT_LVDS: 1026 case DCB_OUTPUT_LVDS:
@@ -1003,11 +1033,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
1003 max_clock = 400000; 1033 max_clock = 400000;
1004 break; 1034 break;
1005 case DCB_OUTPUT_TMDS: 1035 case DCB_OUTPUT_TMDS:
1006 hdmi = drm_detect_hdmi_monitor(nv_connector->edid); 1036 max_clock = get_tmds_link_bandwidth(connector);
1007 max_clock = get_tmds_link_bandwidth(connector, hdmi);
1008 if (!hdmi && nouveau_duallink &&
1009 nv_encoder->dcb->duallink_possible)
1010 max_clock *= 2;
1011 break; 1037 break;
1012 case DCB_OUTPUT_ANALOG: 1038 case DCB_OUTPUT_ANALOG:
1013 max_clock = nv_encoder->dcb->crtconf.maxfreq; 1039 max_clock = nv_encoder->dcb->crtconf.maxfreq;
@@ -1069,6 +1095,8 @@ nouveau_connector_funcs = {
1069 .atomic_destroy_state = nouveau_conn_atomic_destroy_state, 1095 .atomic_destroy_state = nouveau_conn_atomic_destroy_state,
1070 .atomic_set_property = nouveau_conn_atomic_set_property, 1096 .atomic_set_property = nouveau_conn_atomic_set_property,
1071 .atomic_get_property = nouveau_conn_atomic_get_property, 1097 .atomic_get_property = nouveau_conn_atomic_get_property,
1098 .late_register = nouveau_connector_late_register,
1099 .early_unregister = nouveau_connector_early_unregister,
1072}; 1100};
1073 1101
1074static const struct drm_connector_funcs 1102static const struct drm_connector_funcs
@@ -1084,6 +1112,8 @@ nouveau_connector_funcs_lvds = {
1084 .atomic_destroy_state = nouveau_conn_atomic_destroy_state, 1112 .atomic_destroy_state = nouveau_conn_atomic_destroy_state,
1085 .atomic_set_property = nouveau_conn_atomic_set_property, 1113 .atomic_set_property = nouveau_conn_atomic_set_property,
1086 .atomic_get_property = nouveau_conn_atomic_get_property, 1114 .atomic_get_property = nouveau_conn_atomic_get_property,
1115 .late_register = nouveau_connector_late_register,
1116 .early_unregister = nouveau_connector_early_unregister,
1087}; 1117};
1088 1118
1089static int 1119static int
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index 0acc07555bcd..f57ef35b1e5e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -39,6 +39,10 @@
39 39
40struct nvkm_i2c_port; 40struct nvkm_i2c_port;
41 41
42#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
43struct nouveau_backlight;
44#endif
45
42struct nouveau_connector { 46struct nouveau_connector {
43 struct drm_connector base; 47 struct drm_connector base;
44 enum dcb_connector_type type; 48 enum dcb_connector_type type;
@@ -55,6 +59,9 @@ struct nouveau_connector {
55 struct nouveau_encoder *detected_encoder; 59 struct nouveau_encoder *detected_encoder;
56 struct edid *edid; 60 struct edid *edid;
57 struct drm_display_mode *native_mode; 61 struct drm_display_mode *native_mode;
62#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
63 struct nouveau_backlight *backlight;
64#endif
58}; 65};
59 66
60static inline struct nouveau_connector *nouveau_connector( 67static inline struct nouveau_connector *nouveau_connector(
@@ -181,4 +188,30 @@ int nouveau_conn_atomic_get_property(struct drm_connector *,
181 const struct drm_connector_state *, 188 const struct drm_connector_state *,
182 struct drm_property *, u64 *); 189 struct drm_property *, u64 *);
183struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *); 190struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *);
191
192#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
193extern int nouveau_backlight_init(struct drm_connector *);
194extern void nouveau_backlight_fini(struct drm_connector *);
195extern void nouveau_backlight_ctor(void);
196extern void nouveau_backlight_dtor(void);
197#else
198static inline int
199nouveau_backlight_init(struct drm_connector *connector)
200{
201 return 0;
202}
203
204static inline void
205nouveau_backlight_fini(struct drm_connector *connector) {
206}
207
208static inline void
209nouveau_backlight_ctor(void) {
210}
211
212static inline void
213nouveau_backlight_dtor(void) {
214}
215#endif
216
184#endif /* __NOUVEAU_CONNECTOR_H__ */ 217#endif /* __NOUVEAU_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 540c0cbbfcee..f326ffd86766 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -582,7 +582,6 @@ nouveau_display_create(struct drm_device *dev)
582 goto vblank_err; 582 goto vblank_err;
583 } 583 }
584 584
585 nouveau_backlight_init(dev);
586 INIT_WORK(&drm->hpd_work, nouveau_display_hpd_work); 585 INIT_WORK(&drm->hpd_work, nouveau_display_hpd_work);
587#ifdef CONFIG_ACPI 586#ifdef CONFIG_ACPI
588 drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy; 587 drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy;
@@ -607,7 +606,6 @@ nouveau_display_destroy(struct drm_device *dev)
607#ifdef CONFIG_ACPI 606#ifdef CONFIG_ACPI
608 unregister_acpi_notifier(&nouveau_drm(dev)->acpi_nb); 607 unregister_acpi_notifier(&nouveau_drm(dev)->acpi_nb);
609#endif 608#endif
610 nouveau_backlight_exit(dev);
611 nouveau_display_vblank_fini(dev); 609 nouveau_display_vblank_fini(dev);
612 610
613 drm_kms_helper_poll_fini(dev); 611 drm_kms_helper_poll_fini(dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index ff92b54ce448..eb77e41c2d4e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -85,31 +85,6 @@ int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *,
85 85
86void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); 86void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *);
87 87
88#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
89extern int nouveau_backlight_init(struct drm_device *);
90extern void nouveau_backlight_exit(struct drm_device *);
91extern void nouveau_backlight_ctor(void);
92extern void nouveau_backlight_dtor(void);
93#else
94static inline int
95nouveau_backlight_init(struct drm_device *dev)
96{
97 return 0;
98}
99
100static inline void
101nouveau_backlight_exit(struct drm_device *dev) {
102}
103
104static inline void
105nouveau_backlight_ctor(void) {
106}
107
108static inline void
109nouveau_backlight_dtor(void) {
110}
111#endif
112
113struct drm_framebuffer * 88struct drm_framebuffer *
114nouveau_user_framebuffer_create(struct drm_device *, struct drm_file *, 89nouveau_user_framebuffer_create(struct drm_device *, struct drm_file *,
115 const struct drm_mode_fb_cmd2 *); 90 const struct drm_mode_fb_cmd2 *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 74d2283f2c28..2b2baf6e0e0d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -458,75 +458,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
458 nouveau_bo_move_init(drm); 458 nouveau_bo_move_init(drm);
459} 459}
460 460
461static int nouveau_drm_probe(struct pci_dev *pdev,
462 const struct pci_device_id *pent)
463{
464 struct nvkm_device *device;
465 struct apertures_struct *aper;
466 bool boot = false;
467 int ret;
468
469 if (vga_switcheroo_client_probe_defer(pdev))
470 return -EPROBE_DEFER;
471
472 /* We need to check that the chipset is supported before booting
473 * fbdev off the hardware, as there's no way to put it back.
474 */
475 ret = nvkm_device_pci_new(pdev, NULL, "error", true, false, 0, &device);
476 if (ret)
477 return ret;
478
479 nvkm_device_del(&device);
480
481 /* Remove conflicting drivers (vesafb, efifb etc). */
482 aper = alloc_apertures(3);
483 if (!aper)
484 return -ENOMEM;
485
486 aper->ranges[0].base = pci_resource_start(pdev, 1);
487 aper->ranges[0].size = pci_resource_len(pdev, 1);
488 aper->count = 1;
489
490 if (pci_resource_len(pdev, 2)) {
491 aper->ranges[aper->count].base = pci_resource_start(pdev, 2);
492 aper->ranges[aper->count].size = pci_resource_len(pdev, 2);
493 aper->count++;
494 }
495
496 if (pci_resource_len(pdev, 3)) {
497 aper->ranges[aper->count].base = pci_resource_start(pdev, 3);
498 aper->ranges[aper->count].size = pci_resource_len(pdev, 3);
499 aper->count++;
500 }
501
502#ifdef CONFIG_X86
503 boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
504#endif
505 if (nouveau_modeset != 2)
506 drm_fb_helper_remove_conflicting_framebuffers(aper, "nouveaufb", boot);
507 kfree(aper);
508
509 ret = nvkm_device_pci_new(pdev, nouveau_config, nouveau_debug,
510 true, true, ~0ULL, &device);
511 if (ret)
512 return ret;
513
514 pci_set_master(pdev);
515
516 if (nouveau_atomic)
517 driver_pci.driver_features |= DRIVER_ATOMIC;
518
519 ret = drm_get_pci_dev(pdev, pent, &driver_pci);
520 if (ret) {
521 nvkm_device_del(&device);
522 return ret;
523 }
524
525 return 0;
526}
527
528static int 461static int
529nouveau_drm_load(struct drm_device *dev, unsigned long flags) 462nouveau_drm_device_init(struct drm_device *dev)
530{ 463{
531 struct nouveau_drm *drm; 464 struct nouveau_drm *drm;
532 int ret; 465 int ret;
@@ -538,11 +471,11 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
538 471
539 ret = nouveau_cli_init(drm, "DRM-master", &drm->master); 472 ret = nouveau_cli_init(drm, "DRM-master", &drm->master);
540 if (ret) 473 if (ret)
541 return ret; 474 goto fail_alloc;
542 475
543 ret = nouveau_cli_init(drm, "DRM", &drm->client); 476 ret = nouveau_cli_init(drm, "DRM", &drm->client);
544 if (ret) 477 if (ret)
545 return ret; 478 goto fail_master;
546 479
547 dev->irq_enabled = true; 480 dev->irq_enabled = true;
548 481
@@ -605,13 +538,15 @@ fail_bios:
605fail_ttm: 538fail_ttm:
606 nouveau_vga_fini(drm); 539 nouveau_vga_fini(drm);
607 nouveau_cli_fini(&drm->client); 540 nouveau_cli_fini(&drm->client);
541fail_master:
608 nouveau_cli_fini(&drm->master); 542 nouveau_cli_fini(&drm->master);
543fail_alloc:
609 kfree(drm); 544 kfree(drm);
610 return ret; 545 return ret;
611} 546}
612 547
613static void 548static void
614nouveau_drm_unload(struct drm_device *dev) 549nouveau_drm_device_fini(struct drm_device *dev)
615{ 550{
616 struct nouveau_drm *drm = nouveau_drm(dev); 551 struct nouveau_drm *drm = nouveau_drm(dev);
617 552
@@ -640,18 +575,116 @@ nouveau_drm_unload(struct drm_device *dev)
640 kfree(drm); 575 kfree(drm);
641} 576}
642 577
578static int nouveau_drm_probe(struct pci_dev *pdev,
579 const struct pci_device_id *pent)
580{
581 struct nvkm_device *device;
582 struct drm_device *drm_dev;
583 struct apertures_struct *aper;
584 bool boot = false;
585 int ret;
586
587 if (vga_switcheroo_client_probe_defer(pdev))
588 return -EPROBE_DEFER;
589
590 /* We need to check that the chipset is supported before booting
591 * fbdev off the hardware, as there's no way to put it back.
592 */
593 ret = nvkm_device_pci_new(pdev, NULL, "error", true, false, 0, &device);
594 if (ret)
595 return ret;
596
597 nvkm_device_del(&device);
598
599 /* Remove conflicting drivers (vesafb, efifb etc). */
600 aper = alloc_apertures(3);
601 if (!aper)
602 return -ENOMEM;
603
604 aper->ranges[0].base = pci_resource_start(pdev, 1);
605 aper->ranges[0].size = pci_resource_len(pdev, 1);
606 aper->count = 1;
607
608 if (pci_resource_len(pdev, 2)) {
609 aper->ranges[aper->count].base = pci_resource_start(pdev, 2);
610 aper->ranges[aper->count].size = pci_resource_len(pdev, 2);
611 aper->count++;
612 }
613
614 if (pci_resource_len(pdev, 3)) {
615 aper->ranges[aper->count].base = pci_resource_start(pdev, 3);
616 aper->ranges[aper->count].size = pci_resource_len(pdev, 3);
617 aper->count++;
618 }
619
620#ifdef CONFIG_X86
621 boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
622#endif
623 if (nouveau_modeset != 2)
624 drm_fb_helper_remove_conflicting_framebuffers(aper, "nouveaufb", boot);
625 kfree(aper);
626
627 ret = nvkm_device_pci_new(pdev, nouveau_config, nouveau_debug,
628 true, true, ~0ULL, &device);
629 if (ret)
630 return ret;
631
632 pci_set_master(pdev);
633
634 if (nouveau_atomic)
635 driver_pci.driver_features |= DRIVER_ATOMIC;
636
637 drm_dev = drm_dev_alloc(&driver_pci, &pdev->dev);
638 if (IS_ERR(drm_dev)) {
639 ret = PTR_ERR(drm_dev);
640 goto fail_nvkm;
641 }
642
643 ret = pci_enable_device(pdev);
644 if (ret)
645 goto fail_drm;
646
647 drm_dev->pdev = pdev;
648 pci_set_drvdata(pdev, drm_dev);
649
650 ret = nouveau_drm_device_init(drm_dev);
651 if (ret)
652 goto fail_pci;
653
654 ret = drm_dev_register(drm_dev, pent->driver_data);
655 if (ret)
656 goto fail_drm_dev_init;
657
658 return 0;
659
660fail_drm_dev_init:
661 nouveau_drm_device_fini(drm_dev);
662fail_pci:
663 pci_disable_device(pdev);
664fail_drm:
665 drm_dev_put(drm_dev);
666fail_nvkm:
667 nvkm_device_del(&device);
668 return ret;
669}
670
643void 671void
644nouveau_drm_device_remove(struct drm_device *dev) 672nouveau_drm_device_remove(struct drm_device *dev)
645{ 673{
674 struct pci_dev *pdev = dev->pdev;
646 struct nouveau_drm *drm = nouveau_drm(dev); 675 struct nouveau_drm *drm = nouveau_drm(dev);
647 struct nvkm_client *client; 676 struct nvkm_client *client;
648 struct nvkm_device *device; 677 struct nvkm_device *device;
649 678
679 drm_dev_unregister(dev);
680
650 dev->irq_enabled = false; 681 dev->irq_enabled = false;
651 client = nvxx_client(&drm->client.base); 682 client = nvxx_client(&drm->client.base);
652 device = nvkm_device_find(client->device); 683 device = nvkm_device_find(client->device);
653 drm_put_dev(dev);
654 684
685 nouveau_drm_device_fini(dev);
686 pci_disable_device(pdev);
687 drm_dev_put(dev);
655 nvkm_device_del(&device); 688 nvkm_device_del(&device);
656} 689}
657 690
@@ -1018,8 +1051,6 @@ driver_stub = {
1018 DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER | 1051 DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER |
1019 DRIVER_KMS_LEGACY_CONTEXT, 1052 DRIVER_KMS_LEGACY_CONTEXT,
1020 1053
1021 .load = nouveau_drm_load,
1022 .unload = nouveau_drm_unload,
1023 .open = nouveau_drm_open, 1054 .open = nouveau_drm_open,
1024 .postclose = nouveau_drm_postclose, 1055 .postclose = nouveau_drm_postclose,
1025 .lastclose = nouveau_vga_lastclose, 1056 .lastclose = nouveau_vga_lastclose,
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 6e1acaec3400..0b2191fa96f7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -194,8 +194,6 @@ struct nouveau_drm {
194 /* modesetting */ 194 /* modesetting */
195 struct nvbios vbios; 195 struct nvbios vbios;
196 struct nouveau_display *display; 196 struct nouveau_display *display;
197 struct backlight_device *backlight;
198 struct list_head bl_connectors;
199 struct work_struct hpd_work; 197 struct work_struct hpd_work;
200 struct work_struct fbcon_work; 198 struct work_struct fbcon_work;
201 int fbcon_new_state; 199 int fbcon_new_state;
@@ -244,10 +242,12 @@ void nouveau_drm_device_remove(struct drm_device *dev);
244 struct nouveau_cli *_cli = (c); \ 242 struct nouveau_cli *_cli = (c); \
245 dev_##l(_cli->drm->dev->dev, "%s: "f, _cli->name, ##a); \ 243 dev_##l(_cli->drm->dev->dev, "%s: "f, _cli->name, ##a); \
246} while(0) 244} while(0)
245
247#define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a) 246#define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a)
248#define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a) 247#define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a)
249#define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a) 248#define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a)
250#define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a) 249#define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a)
250
251#define NV_DEBUG(drm,f,a...) do { \ 251#define NV_DEBUG(drm,f,a...) do { \
252 if (unlikely(drm_debug & DRM_UT_DRIVER)) \ 252 if (unlikely(drm_debug & DRM_UT_DRIVER)) \
253 NV_PRINTK(info, &(drm)->client, f, ##a); \ 253 NV_PRINTK(info, &(drm)->client, f, ##a); \
@@ -257,6 +257,12 @@ void nouveau_drm_device_remove(struct drm_device *dev);
257 NV_PRINTK(info, &(drm)->client, f, ##a); \ 257 NV_PRINTK(info, &(drm)->client, f, ##a); \
258} while(0) 258} while(0)
259 259
260#define NV_PRINTK_ONCE(l,c,f,a...) NV_PRINTK(l##_once,c,f, ##a)
261
262#define NV_ERROR_ONCE(drm,f,a...) NV_PRINTK_ONCE(err, &(drm)->client, f, ##a)
263#define NV_WARN_ONCE(drm,f,a...) NV_PRINTK_ONCE(warn, &(drm)->client, f, ##a)
264#define NV_INFO_ONCE(drm,f,a...) NV_PRINTK_ONCE(info, &(drm)->client, f, ##a)
265
260extern int nouveau_modeset; 266extern int nouveau_modeset;
261 267
262#endif 268#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
index 3d485dbf310a..8089ac9a12e2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
@@ -50,6 +50,7 @@ nvkm-y += nvkm/engine/disp/hdmig84.o
50nvkm-y += nvkm/engine/disp/hdmigt215.o 50nvkm-y += nvkm/engine/disp/hdmigt215.o
51nvkm-y += nvkm/engine/disp/hdmigf119.o 51nvkm-y += nvkm/engine/disp/hdmigf119.o
52nvkm-y += nvkm/engine/disp/hdmigk104.o 52nvkm-y += nvkm/engine/disp/hdmigk104.o
53nvkm-y += nvkm/engine/disp/hdmigm200.o
53nvkm-y += nvkm/engine/disp/hdmigv100.o 54nvkm-y += nvkm/engine/disp/hdmigv100.o
54 55
55nvkm-y += nvkm/engine/disp/conn.o 56nvkm-y += nvkm/engine/disp/conn.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c
new file mode 100644
index 000000000000..9b16a08eb4d9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c
@@ -0,0 +1,36 @@
1/*
2 * Copyright 2018 Ilia Mirkin
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ilia Mirkin
23 */
24#include "hdmi.h"
25
26void
27gm200_hdmi_scdc(struct nvkm_ior *ior, int head, u8 scdc)
28{
29 struct nvkm_device *device = ior->disp->engine.subdev.device;
30 const u32 hoff = head * 0x800;
31 const u32 ctrl = scdc & 0x3;
32
33 nvkm_mask(device, 0x61c5bc + hoff, 0x00000003, ctrl);
34
35 ior->tmds.high_speed = !!(scdc & 0x2);
36}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
index 19911211a12a..0f0c86c32ec3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
@@ -41,6 +41,11 @@ struct nvkm_ior {
41 u8 nr; 41 u8 nr;
42 u8 bw; 42 u8 bw;
43 } dp; 43 } dp;
44
45 /* Armed TMDS state. */
46 struct {
47 bool high_speed;
48 } tmds;
44}; 49};
45 50
46struct nvkm_ior_func { 51struct nvkm_ior_func {
@@ -61,6 +66,7 @@ struct nvkm_ior_func {
61 void (*ctrl)(struct nvkm_ior *, int head, bool enable, 66 void (*ctrl)(struct nvkm_ior *, int head, bool enable,
62 u8 max_ac_packet, u8 rekey, u8 *avi, u8 avi_size, 67 u8 max_ac_packet, u8 rekey, u8 *avi, u8 avi_size,
63 u8 *vendor, u8 vendor_size); 68 u8 *vendor, u8 vendor_size);
69 void (*scdc)(struct nvkm_ior *, int head, u8 scdc);
64 } hdmi; 70 } hdmi;
65 71
66 struct { 72 struct {
@@ -144,6 +150,8 @@ void gf119_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
144void gk104_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); 150void gk104_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
145void gv100_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); 151void gv100_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
146 152
153void gm200_hdmi_scdc(struct nvkm_ior *, int, u8);
154
147void gt215_hda_hpd(struct nvkm_ior *, int, bool); 155void gt215_hda_hpd(struct nvkm_ior *, int, bool);
148void gt215_hda_eld(struct nvkm_ior *, u8 *, u8); 156void gt215_hda_eld(struct nvkm_ior *, u8 *, u8);
149 157
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
index 3aa5a2879239..5f758948d6e1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
@@ -176,9 +176,10 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
176 nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size); 176 nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
177 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { 177 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
178 nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d " 178 nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
179 "max_ac_packet %d rekey %d\n", 179 "max_ac_packet %d rekey %d scdc %d\n",
180 args->v0.version, args->v0.state, 180 args->v0.version, args->v0.state,
181 args->v0.max_ac_packet, args->v0.rekey); 181 args->v0.max_ac_packet, args->v0.rekey,
182 args->v0.scdc);
182 if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f) 183 if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
183 return -EINVAL; 184 return -EINVAL;
184 if ((args->v0.avi_infoframe_length 185 if ((args->v0.avi_infoframe_length
@@ -202,6 +203,11 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
202 args->v0.max_ac_packet, 203 args->v0.max_ac_packet,
203 args->v0.rekey, avi, avi_size, 204 args->v0.rekey, avi, avi_size,
204 vendor, vendor_size); 205 vendor, vendor_size);
206
207 if (outp->ior->func->hdmi.scdc)
208 outp->ior->func->hdmi.scdc(
209 outp->ior, hidx, args->v0.scdc);
210
205 return 0; 211 return 0;
206 } 212 }
207 break; 213 break;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
index e6e6dfbb1283..456a5a143522 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
@@ -120,13 +120,16 @@ void
120gf119_sor_clock(struct nvkm_ior *sor) 120gf119_sor_clock(struct nvkm_ior *sor)
121{ 121{
122 struct nvkm_device *device = sor->disp->engine.subdev.device; 122 struct nvkm_device *device = sor->disp->engine.subdev.device;
123 const int div = sor->asy.link == 3;
124 const u32 soff = nv50_ior_base(sor); 123 const u32 soff = nv50_ior_base(sor);
124 u32 div1 = sor->asy.link == 3;
125 u32 div2 = sor->asy.link == 3;
125 if (sor->asy.proto == TMDS) { 126 if (sor->asy.proto == TMDS) {
126 /* NFI why, but this sets DP_LINK_BW_2_7 when using TMDS. */ 127 const u32 speed = sor->tmds.high_speed ? 0x14 : 0x0a;
127 nvkm_mask(device, 0x612300 + soff, 0x007c0000, 0x0a << 18); 128 nvkm_mask(device, 0x612300 + soff, 0x007c0000, speed << 18);
129 if (sor->tmds.high_speed)
130 div2 = 1;
128 } 131 }
129 nvkm_mask(device, 0x612300 + soff, 0x00000707, (div << 8) | div); 132 nvkm_mask(device, 0x612300 + soff, 0x00000707, (div2 << 8) | div1);
130} 133}
131 134
132void 135void
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
index d892bdf04034..384f82652bec 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
@@ -99,6 +99,7 @@ gm200_sor = {
99 .clock = gf119_sor_clock, 99 .clock = gf119_sor_clock,
100 .hdmi = { 100 .hdmi = {
101 .ctrl = gk104_hdmi_ctrl, 101 .ctrl = gk104_hdmi_ctrl,
102 .scdc = gm200_hdmi_scdc,
102 }, 103 },
103 .dp = { 104 .dp = {
104 .lanes = { 0, 1, 2, 3 }, 105 .lanes = { 0, 1, 2, 3 },
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c
index 040db8a338de..8ba881a729ee 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c
@@ -88,6 +88,7 @@ gv100_sor = {
88 .clock = gf119_sor_clock, 88 .clock = gf119_sor_clock,
89 .hdmi = { 89 .hdmi = {
90 .ctrl = gv100_hdmi_ctrl, 90 .ctrl = gv100_hdmi_ctrl,
91 .scdc = gm200_hdmi_scdc,
91 }, 92 },
92 .dp = { 93 .dp = {
93 .lanes = { 0, 1, 2, 3 }, 94 .lanes = { 0, 1, 2, 3 },
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
index d02e183717dc..5c14d6ac855d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
@@ -801,6 +801,7 @@ acr_r352_load(struct nvkm_acr *_acr, struct nvkm_falcon *falcon,
801 bl = acr->hsbl_unload_blob; 801 bl = acr->hsbl_unload_blob;
802 } else { 802 } else {
803 nvkm_error(_acr->subdev, "invalid secure boot blob!\n"); 803 nvkm_error(_acr->subdev, "invalid secure boot blob!\n");
804 kfree(bl_desc);
804 return -EINVAL; 805 return -EINVAL;
805 } 806 }
806 807