diff options
author | Dave Airlie <airlied@redhat.com> | 2018-10-10 20:23:11 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-10-10 20:24:28 -0400 |
commit | 7e6191d4360a2df6cf2a2613dcb79680cb943df8 (patch) | |
tree | e07605113d5028f3dd825d6e259f63cdb3f1d161 | |
parent | 62e681f7dcab746412dce22d4b75b32c5ea38cdb (diff) | |
parent | 74a07c0a59fa372b069d879971ba4d9e341979cf (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.c | 40 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvif/cl5070.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_backlight.c | 220 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.c | 54 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.h | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_display.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_display.h | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drm.c | 179 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c | 36 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c | 1 |
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) | |||
531 | static void | 532 | static void |
532 | nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) | 533 | nv50_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 | ||
75 | struct nv50_disp_sor_lvds_script_v0 { | 78 | struct 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 | ||
41 | static struct ida bl_ida; | 42 | static 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 | ||
44 | struct backlight_connector { | 45 | struct nouveau_backlight { |
45 | struct list_head head; | 46 | struct backlight_device *dev; |
46 | int id; | 47 | int id; |
47 | }; | 48 | }; |
48 | 49 | ||
49 | static bool | 50 | static bool |
50 | nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], struct backlight_connector | 51 | nouveau_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 | ||
64 | static int | 65 | static int |
65 | nv40_get_intensity(struct backlight_device *bd) | 66 | nv40_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) | |||
75 | static int | 77 | static int |
76 | nv40_set_intensity(struct backlight_device *bd) | 78 | nv40_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 | ||
95 | static int | 98 | static int |
96 | nv40_backlight_init(struct drm_connector *connector) | 99 | nv40_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 | ||
212 | static int | 197 | static int |
213 | nv50_backlight_init(struct drm_connector *connector) | 198 | nv50_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 | ||
264 | int | 221 | int |
265 | nouveau_backlight_init(struct drm_device *dev) | 222 | nouveau_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 | |||
291 | fail_alloc: | ||
292 | kfree(bl); | ||
293 | return ret; | ||
300 | } | 294 | } |
301 | 295 | ||
302 | void | 296 | void |
303 | nouveau_backlight_exit(struct drm_device *dev) | 297 | nouveau_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 | ||
319 | void | 313 | void |
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 | ||
888 | static int | 888 | static int |
889 | nouveau_connector_late_register(struct drm_connector *connector) | ||
890 | { | ||
891 | int ret; | ||
892 | |||
893 | ret = nouveau_backlight_init(connector); | ||
894 | |||
895 | return ret; | ||
896 | } | ||
897 | |||
898 | static void | ||
899 | nouveau_connector_early_unregister(struct drm_connector *connector) | ||
900 | { | ||
901 | nouveau_backlight_fini(connector); | ||
902 | } | ||
903 | |||
904 | static int | ||
889 | nouveau_connector_get_modes(struct drm_connector *connector) | 905 | nouveau_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 | ||
955 | static unsigned | 971 | static unsigned |
956 | get_tmds_link_bandwidth(struct drm_connector *connector, bool hdmi) | 972 | get_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 | ||
984 | static enum drm_mode_status | 1015 | static 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 | ||
1074 | static const struct drm_connector_funcs | 1102 | static 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 | ||
1089 | static int | 1119 | static 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 | ||
40 | struct nvkm_i2c_port; | 40 | struct nvkm_i2c_port; |
41 | 41 | ||
42 | #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT | ||
43 | struct nouveau_backlight; | ||
44 | #endif | ||
45 | |||
42 | struct nouveau_connector { | 46 | struct 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 | ||
60 | static inline struct nouveau_connector *nouveau_connector( | 67 | static 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 *); |
183 | struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *); | 190 | struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *); |
191 | |||
192 | #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT | ||
193 | extern int nouveau_backlight_init(struct drm_connector *); | ||
194 | extern void nouveau_backlight_fini(struct drm_connector *); | ||
195 | extern void nouveau_backlight_ctor(void); | ||
196 | extern void nouveau_backlight_dtor(void); | ||
197 | #else | ||
198 | static inline int | ||
199 | nouveau_backlight_init(struct drm_connector *connector) | ||
200 | { | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static inline void | ||
205 | nouveau_backlight_fini(struct drm_connector *connector) { | ||
206 | } | ||
207 | |||
208 | static inline void | ||
209 | nouveau_backlight_ctor(void) { | ||
210 | } | ||
211 | |||
212 | static inline void | ||
213 | nouveau_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 | ||
86 | void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); | 86 | void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); |
87 | 87 | ||
88 | #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT | ||
89 | extern int nouveau_backlight_init(struct drm_device *); | ||
90 | extern void nouveau_backlight_exit(struct drm_device *); | ||
91 | extern void nouveau_backlight_ctor(void); | ||
92 | extern void nouveau_backlight_dtor(void); | ||
93 | #else | ||
94 | static inline int | ||
95 | nouveau_backlight_init(struct drm_device *dev) | ||
96 | { | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static inline void | ||
101 | nouveau_backlight_exit(struct drm_device *dev) { | ||
102 | } | ||
103 | |||
104 | static inline void | ||
105 | nouveau_backlight_ctor(void) { | ||
106 | } | ||
107 | |||
108 | static inline void | ||
109 | nouveau_backlight_dtor(void) { | ||
110 | } | ||
111 | #endif | ||
112 | |||
113 | struct drm_framebuffer * | 88 | struct drm_framebuffer * |
114 | nouveau_user_framebuffer_create(struct drm_device *, struct drm_file *, | 89 | nouveau_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 | ||
461 | static 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 | |||
528 | static int | 461 | static int |
529 | nouveau_drm_load(struct drm_device *dev, unsigned long flags) | 462 | nouveau_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: | |||
605 | fail_ttm: | 538 | fail_ttm: |
606 | nouveau_vga_fini(drm); | 539 | nouveau_vga_fini(drm); |
607 | nouveau_cli_fini(&drm->client); | 540 | nouveau_cli_fini(&drm->client); |
541 | fail_master: | ||
608 | nouveau_cli_fini(&drm->master); | 542 | nouveau_cli_fini(&drm->master); |
543 | fail_alloc: | ||
609 | kfree(drm); | 544 | kfree(drm); |
610 | return ret; | 545 | return ret; |
611 | } | 546 | } |
612 | 547 | ||
613 | static void | 548 | static void |
614 | nouveau_drm_unload(struct drm_device *dev) | 549 | nouveau_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 | ||
578 | static 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 | |||
660 | fail_drm_dev_init: | ||
661 | nouveau_drm_device_fini(drm_dev); | ||
662 | fail_pci: | ||
663 | pci_disable_device(pdev); | ||
664 | fail_drm: | ||
665 | drm_dev_put(drm_dev); | ||
666 | fail_nvkm: | ||
667 | nvkm_device_del(&device); | ||
668 | return ret; | ||
669 | } | ||
670 | |||
643 | void | 671 | void |
644 | nouveau_drm_device_remove(struct drm_device *dev) | 672 | nouveau_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 | |||
260 | extern int nouveau_modeset; | 266 | extern 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 | |||
50 | nvkm-y += nvkm/engine/disp/hdmigt215.o | 50 | nvkm-y += nvkm/engine/disp/hdmigt215.o |
51 | nvkm-y += nvkm/engine/disp/hdmigf119.o | 51 | nvkm-y += nvkm/engine/disp/hdmigf119.o |
52 | nvkm-y += nvkm/engine/disp/hdmigk104.o | 52 | nvkm-y += nvkm/engine/disp/hdmigk104.o |
53 | nvkm-y += nvkm/engine/disp/hdmigm200.o | ||
53 | nvkm-y += nvkm/engine/disp/hdmigv100.o | 54 | nvkm-y += nvkm/engine/disp/hdmigv100.o |
54 | 55 | ||
55 | nvkm-y += nvkm/engine/disp/conn.o | 56 | nvkm-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 | |||
26 | void | ||
27 | gm200_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 | ||
46 | struct nvkm_ior_func { | 51 | struct 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); | |||
144 | void gk104_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); | 150 | void gk104_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); |
145 | void gv100_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); | 151 | void gv100_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); |
146 | 152 | ||
153 | void gm200_hdmi_scdc(struct nvkm_ior *, int, u8); | ||
154 | |||
147 | void gt215_hda_hpd(struct nvkm_ior *, int, bool); | 155 | void gt215_hda_hpd(struct nvkm_ior *, int, bool); |
148 | void gt215_hda_eld(struct nvkm_ior *, u8 *, u8); | 156 | void 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 | |||
120 | gf119_sor_clock(struct nvkm_ior *sor) | 120 | gf119_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 | ||
132 | void | 135 | void |
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 | ||