drm/nouveau/disp: add output backlight control methods
authorBen Skeggs <bskeggs@redhat.com>
Tue, 19 Sep 2023 21:56:18 +0000 (17:56 -0400)
committerLyude Paul <lyude@redhat.com>
Tue, 19 Sep 2023 22:22:06 +0000 (18:22 -0400)
- preparation for GSP-RM

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
Acked-by: Danilo Krummrich <me@dakr.org>
Signed-off-by: Lyude Paul <lyude@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230919220442.202488-24-lyude@redhat.com
22 files changed:
drivers/gpu/drm/nouveau/include/nvif/if0012.h
drivers/gpu/drm/nouveau/include/nvif/outp.h
drivers/gpu/drm/nouveau/nouveau_backlight.c
drivers/gpu/drm/nouveau/nvif/outp.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c

index 230084d675ec24bd7153d7dab7253f777b711a34..f878784593b439a3ae39a863a2e8eb3fee0fad30 100644 (file)
@@ -21,6 +21,9 @@ union nvif_outp_args {
 
 #define NVIF_OUTP_V0_LOAD_DETECT   0x20
 
+#define NVIF_OUTP_V0_BL_GET        0x30
+#define NVIF_OUTP_V0_BL_SET        0x31
+
 #define NVIF_OUTP_V0_HDMI          0x50
 
 #define NVIF_OUTP_V0_INFOFRAME     0x60
@@ -118,6 +121,20 @@ union nvif_outp_release_args {
        } vn;
 };
 
+union nvif_outp_bl_get_args {
+       struct nvif_outp_bl_get_v0 {
+               __u8  version;
+               __u8  level;
+       } v0;
+};
+
+union nvif_outp_bl_set_args {
+       struct nvif_outp_bl_set_v0 {
+               __u8  version;
+               __u8  level;
+       } v0;
+};
+
 union nvif_outp_hdmi_args {
        struct nvif_outp_hdmi_v0 {
                __u8 version;
index ea60d418d7f09c6b05f0e6d3c1f4d881c469343b..ef63d22b62f848f2e23d6cf5f36327e7f1093cd9 100644 (file)
@@ -47,6 +47,9 @@ nvif_outp_acquired(struct nvif_outp *outp)
        return outp->or.id >= 0;
 }
 
+int nvif_outp_bl_get(struct nvif_outp *);
+int nvif_outp_bl_set(struct nvif_outp *, int level);
+
 int nvif_outp_hdmi(struct nvif_outp *, int head, bool enable, u8 max_ac_packet, u8 rekey, u32 khz,
                   bool scdc, bool scdc_scrambling, bool scdc_low_rates);
 
index 91b5ecc57538083f7be573fbc25ec3a91ce0c9dd..d47442125fa183146135f3725eae161c68e2a900 100644 (file)
@@ -109,42 +109,6 @@ nv40_backlight_init(struct nouveau_encoder *encoder,
        return 0;
 }
 
-static int
-nv50_get_intensity(struct backlight_device *bd)
-{
-       struct nouveau_encoder *nv_encoder = bl_get_data(bd);
-       struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
-       struct nvif_object *device = &drm->client.device.object;
-       int or = ffs(nv_encoder->dcb->or) - 1;
-       u32 div = 1025;
-       u32 val;
-
-       val  = nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
-       val &= NV50_PDISP_SOR_PWM_CTL_VAL;
-       return ((val * 100) + (div / 2)) / div;
-}
-
-static int
-nv50_set_intensity(struct backlight_device *bd)
-{
-       struct nouveau_encoder *nv_encoder = bl_get_data(bd);
-       struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
-       struct nvif_object *device = &drm->client.device.object;
-       int or = ffs(nv_encoder->dcb->or) - 1;
-       u32 div = 1025;
-       u32 val = (bd->props.brightness * div) / 100;
-
-       nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
-                 NV50_PDISP_SOR_PWM_CTL_NEW | val);
-       return 0;
-}
-
-static const struct backlight_ops nv50_bl_ops = {
-       .options = BL_CORE_SUSPENDRESUME,
-       .get_brightness = nv50_get_intensity,
-       .update_status = nv50_set_intensity,
-};
-
 /*
  * eDP brightness callbacks need to happen under lock, since we need to
  * enable/disable the backlight ourselves for modesets
@@ -238,53 +202,25 @@ static const struct backlight_ops nv50_edp_bl_ops = {
 };
 
 static int
-nva3_get_intensity(struct backlight_device *bd)
+nv50_get_intensity(struct backlight_device *bd)
 {
        struct nouveau_encoder *nv_encoder = bl_get_data(bd);
-       struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
-       struct nvif_object *device = &drm->client.device.object;
-       int or = ffs(nv_encoder->dcb->or) - 1;
-       u32 div, val;
 
-       div  = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
-       val  = nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
-       val &= NVA3_PDISP_SOR_PWM_CTL_VAL;
-       if (div && div >= val)
-               return ((val * 100) + (div / 2)) / div;
-
-       return 100;
+       return nvif_outp_bl_get(&nv_encoder->outp);
 }
 
 static int
-nva3_set_intensity(struct backlight_device *bd)
+nv50_set_intensity(struct backlight_device *bd)
 {
        struct nouveau_encoder *nv_encoder = bl_get_data(bd);
-       struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
-       struct nvif_object *device = &drm->client.device.object;
-       int or = ffs(nv_encoder->dcb->or) - 1;
-       u32 div, val;
-
-       div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
 
-       val = backlight_get_brightness(bd);
-       if (val)
-               val = (val * div) / 100;
-
-       if (div) {
-               nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
-                         val |
-                         NV50_PDISP_SOR_PWM_CTL_NEW |
-                         NVA3_PDISP_SOR_PWM_CTL_UNK);
-               return 0;
-       }
-
-       return -EINVAL;
+       return nvif_outp_bl_set(&nv_encoder->outp, backlight_get_brightness(bd));
 }
 
-static const struct backlight_ops nva3_bl_ops = {
+static const struct backlight_ops nv50_bl_ops = {
        .options = BL_CORE_SUSPENDRESUME,
-       .get_brightness = nva3_get_intensity,
-       .update_status = nva3_set_intensity,
+       .get_brightness = nv50_get_intensity,
+       .update_status = nv50_set_intensity,
 };
 
 /* FIXME: perform backlight probing for eDP _before_ this, this only gets called after connector
@@ -298,13 +234,12 @@ nv50_backlight_init(struct nouveau_backlight *bl,
                    const struct backlight_ops **ops)
 {
        struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
-       struct nvif_object *device = &drm->client.device.object;
 
        /*
         * Note when this runs the connectors have not been probed yet,
         * so nv_conn->base.status is not set yet.
         */
-       if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1)) ||
+       if (nvif_outp_bl_get(&nv_encoder->outp) < 0 ||
            drm_helper_probe_detect(&nv_conn->base, NULL, false) != connector_status_connected)
                return -ENODEV;
 
@@ -346,15 +281,8 @@ nv50_backlight_init(struct nouveau_backlight *bl,
                }
        }
 
-       if (drm->client.device.info.chipset <= 0xa0 ||
-           drm->client.device.info.chipset == 0xaa ||
-           drm->client.device.info.chipset == 0xac)
-               *ops = &nv50_bl_ops;
-       else
-               *ops = &nva3_bl_ops;
-
+       *ops = &nv50_bl_ops;
        props->max_brightness = 100;
-
        return 0;
 }
 
index 6e1bcc265d07fd35fe5136aa367560e18d4c467d..5a3c0dd7d53249283c6946788f9c65041b93a013 100644 (file)
@@ -165,6 +165,33 @@ nvif_outp_acquire_lvds(struct nvif_outp *outp, bool dual, bool bpc8)
        return ret;
 }
 
+int
+nvif_outp_bl_set(struct nvif_outp *outp, int level)
+{
+       struct nvif_outp_bl_set_v0 args;
+       int ret;
+
+       args.version = 0;
+       args.level = level;
+
+       ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_BL_SET, &args, sizeof(args));
+       NVIF_ERRON(ret, &outp->object, "[BL_SET level:%d]", args.level);
+       return ret;
+}
+
+int
+nvif_outp_bl_get(struct nvif_outp *outp)
+{
+       struct nvif_outp_bl_get_v0 args;
+       int ret;
+
+       args.version = 0;
+
+       ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_BL_GET, &args, sizeof(args));
+       NVIF_ERRON(ret, &outp->object, "[BL_GET level:%d]", args.level);
+       return ret ? ret : args.level;
+}
+
 void
 nvif_outp_release(struct nvif_outp *outp)
 {
index 3b6d58c15452105bc953c88c33963d11a6d418d8..0e6e388003765880da0ae130a7fc72006244b839 100644 (file)
@@ -812,6 +812,8 @@ nvkm_dp_func = {
        .acquire = nvkm_dp_acquire,
        .release = nvkm_dp_release,
        .disable = nvkm_dp_disable,
+       .bl.get = nvkm_outp_bl_get,
+       .bl.set = nvkm_outp_bl_set,
 };
 
 int
index 23ae451ba473da75c85dca885e571327d65e460c..1be97a68a83ee5834be50ee68cb350e67721bcad 100644 (file)
@@ -124,6 +124,7 @@ g84_sor = {
        .state = nv50_sor_state,
        .power = nv50_sor_power,
        .clock = nv50_sor_clock,
+       .bl = &nv50_sor_bl,
        .hdmi = &g84_sor_hdmi,
 };
 
index 67ef889a0c5f4728d62d80be74357b13881acebc..843a2661ce9d8ee5826e6c8b8cb65e3268619b16 100644 (file)
@@ -295,6 +295,7 @@ g94_sor = {
        .clock = nv50_sor_clock,
        .war_2 = g94_sor_war_2,
        .war_3 = g94_sor_war_3,
+       .bl = &nv50_sor_bl,
        .hdmi = &g84_sor_hdmi,
        .dp = &g94_sor_dp,
 };
index 52099b75f52ae850269300a3f039497197ba734a..efe66ba3c61f8e49c6ce920298e8f884ee194044 100644 (file)
@@ -105,6 +105,7 @@ ga102_sor = {
        .state = gv100_sor_state,
        .power = nv50_sor_power,
        .clock = ga102_sor_clock,
+       .bl = &gt215_sor_bl,
        .hdmi = &gv100_sor_hdmi,
        .dp = &ga102_sor_dp,
        .hda = &gv100_sor_hda,
index 937baae6a3ebbfd4aee2420794f086ef9ae535fc..b48ead31da30e2617b6a82096f80fd8e59a7f6b3 100644 (file)
@@ -328,6 +328,7 @@ gf119_sor = {
        .state = gf119_sor_state,
        .power = nv50_sor_power,
        .clock = gf119_sor_clock,
+       .bl = &gt215_sor_bl,
        .hdmi = &gf119_sor_hdmi,
        .dp = &gf119_sor_dp,
        .hda = &gf119_sor_hda,
index 876a21a0cebb79ceb633726d57d8147c482fcd88..a3e2fbadade492da6605b3257d17d40598c304c5 100644 (file)
@@ -115,6 +115,7 @@ gk104_sor = {
        .state = gf119_sor_state,
        .power = nv50_sor_power,
        .clock = gf119_sor_clock,
+       .bl = &gt215_sor_bl,
        .hdmi = &gk104_sor_hdmi,
        .dp = &gf119_sor_dp,
        .hda = &gf119_sor_hda,
index b4d8e868616fa067078b60e7f0ad33aa14b674c2..688e123ad4829c82bdbe43ddba653c3e5e0cd0aa 100644 (file)
@@ -70,6 +70,7 @@ gm107_sor = {
        .state = gf119_sor_state,
        .power = nv50_sor_power,
        .clock = gf119_sor_clock,
+       .bl = &gt215_sor_bl,
        .hdmi = &gk104_sor_hdmi,
        .dp = &gm107_sor_dp,
        .hda = &gf119_sor_hda,
index 126a90805dee0b76483d2a8ba78d4df94d85f9c5..511e7831b2f582eb496554503a8028ea44903a7a 100644 (file)
@@ -147,6 +147,7 @@ gm200_sor = {
        .state = gf119_sor_state,
        .power = nv50_sor_power,
        .clock = gf119_sor_clock,
+       .bl = &gt215_sor_bl,
        .hdmi = &gm200_sor_hdmi,
        .dp = &gm200_sor_dp,
        .hda = &gf119_sor_hda,
index 7f1eb4332040bc5bd074f49a500e4ddc9fcf0af3..4070447bd800cee14ffef076d2ccdbd21382ed67 100644 (file)
@@ -37,6 +37,7 @@ gp100_sor = {
        .state = gf119_sor_state,
        .power = nv50_sor_power,
        .clock = gf119_sor_clock,
+       .bl = &gt215_sor_bl,
        .hdmi = &gm200_sor_hdmi,
        .dp = &gm200_sor_dp,
        .hda = &gf119_sor_hda,
index 506ffbe7b84216fd7045a759e68648c9c8c6f3a5..6318721b66f6ee34955a5b0081519a91f236fdbf 100644 (file)
@@ -182,11 +182,49 @@ gt215_sor_hdmi = {
        .infoframe_vsi = gt215_sor_hdmi_infoframe_vsi,
 };
 
+static int
+gt215_sor_bl_set(struct nvkm_ior *ior, int lvl)
+{
+       struct nvkm_device *device = ior->disp->engine.subdev.device;
+       const u32 soff = nv50_ior_base(ior);
+       u32 div, val;
+
+       div = nvkm_rd32(device, 0x61c080 + soff);
+       val = (lvl * div) / 100;
+       if (div)
+               nvkm_wr32(device, 0x61c084 + soff, 0xc0000000 | val);
+
+       return 0;
+}
+
+static int
+gt215_sor_bl_get(struct nvkm_ior *ior)
+{
+       struct nvkm_device *device = ior->disp->engine.subdev.device;
+       const u32 soff = nv50_ior_base(ior);
+       u32 div, val;
+
+       div  = nvkm_rd32(device, 0x61c080 + soff);
+       val  = nvkm_rd32(device, 0x61c084 + soff);
+       val &= 0x00ffffff;
+       if (div && div >= val)
+               return ((val * 100) + (div / 2)) / div;
+
+       return 100;
+}
+
+const struct nvkm_ior_func_bl
+gt215_sor_bl = {
+       .get = gt215_sor_bl_get,
+       .set = gt215_sor_bl_set,
+};
+
 static const struct nvkm_ior_func
 gt215_sor = {
        .state = g94_sor_state,
        .power = nv50_sor_power,
        .clock = nv50_sor_clock,
+       .bl = &gt215_sor_bl,
        .hdmi = &gt215_sor_hdmi,
        .dp = &gt215_sor_dp,
        .hda = &gt215_sor_hda,
index 7ac59bab6309fdd06148d182a46cb57105485c6e..e1634f7bca56f6b0df1f1320f657614876826d27 100644 (file)
@@ -212,6 +212,7 @@ gv100_sor = {
        .state = gv100_sor_state,
        .power = nv50_sor_power,
        .clock = gf119_sor_clock,
+       .bl = &gt215_sor_bl,
        .hdmi = &gv100_sor_hdmi,
        .dp = &gv100_sor_dp,
        .hda = &gv100_sor_hda,
index f8b9d16304e99e8a35082b46568348370ebc1460..6e750890bcc936c6e019c2c9814ac9600e93b42f 100644 (file)
@@ -63,6 +63,11 @@ struct nvkm_ior_func {
        void (*war_2)(struct nvkm_ior *);
        void (*war_3)(struct nvkm_ior *);
 
+       const struct nvkm_ior_func_bl {
+               int (*get)(struct nvkm_ior *);
+               int (*set)(struct nvkm_ior *, int lvl);
+       } *bl;
+
        const struct nvkm_ior_func_hdmi {
                void (*ctrl)(struct nvkm_ior *, int head, bool enable, u8 max_ac_packet, u8 rekey);
                void (*scdc)(struct nvkm_ior *, u32 khz, bool support, bool scrambling,
@@ -123,6 +128,7 @@ int nv50_sor_cnt(struct nvkm_disp *, unsigned long *);
 void nv50_sor_state(struct nvkm_ior *, struct nvkm_ior_state *);
 void nv50_sor_power(struct nvkm_ior *, bool, bool, bool, bool, bool);
 void nv50_sor_clock(struct nvkm_ior *);
+extern const struct nvkm_ior_func_bl nv50_sor_bl;
 
 int g84_sor_new(struct nvkm_disp *, int);
 extern const struct nvkm_ior_func_hdmi g84_sor_hdmi;
@@ -139,6 +145,7 @@ void g94_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32);
 void g94_sor_dp_activesym(struct nvkm_ior *, int, u8, u8, u8, u8);
 void g94_sor_dp_watermark(struct nvkm_ior *, int, u8);
 
+extern const struct nvkm_ior_func_bl gt215_sor_bl;
 extern const struct nvkm_ior_func_hdmi gt215_sor_hdmi;
 void gt215_sor_dp_audio(struct nvkm_ior *, int, bool);
 extern const struct nvkm_ior_func_hda gt215_sor_hda;
index f96ba4752655c00d0d2f8f9702a6d1b359a1db33..e0c5fb6df3d729fbade884345b49dd87dc6b1f40 100644 (file)
@@ -44,6 +44,7 @@ mcp89_sor = {
        .state = g94_sor_state,
        .power = nv50_sor_power,
        .clock = nv50_sor_clock,
+       .bl = &gt215_sor_bl,
        .hdmi = &gt215_sor_hdmi,
        .dp = &mcp89_sor_dp,
        .hda = &gt215_sor_hda,
index a4ce60517789563057c42b581c8a8345bfeffb63..948a46f3a1bdfdd8ae496ac04e8db568e289b200 100644 (file)
@@ -156,6 +156,37 @@ nv50_pior_cnt(struct nvkm_disp *disp, unsigned long *pmask)
        return 3;
 }
 
+static int
+nv50_sor_bl_set(struct nvkm_ior *ior, int lvl)
+{
+       struct nvkm_device *device = ior->disp->engine.subdev.device;
+       const u32 soff = nv50_ior_base(ior);
+       u32 div = 1025;
+       u32 val = (lvl * div) / 100;
+
+       nvkm_wr32(device, 0x61c084 + soff, 0x80000000 | val);
+       return 0;
+}
+
+static int
+nv50_sor_bl_get(struct nvkm_ior *ior)
+{
+       struct nvkm_device *device = ior->disp->engine.subdev.device;
+       const u32 soff = nv50_ior_base(ior);
+       u32 div = 1025;
+       u32 val;
+
+       val  = nvkm_rd32(device, 0x61c084 + soff);
+       val &= 0x000007ff;
+       return ((val * 100) + (div / 2)) / div;
+}
+
+const struct nvkm_ior_func_bl
+nv50_sor_bl = {
+       .get = nv50_sor_bl_get,
+       .set = nv50_sor_bl_set,
+};
+
 void
 nv50_sor_clock(struct nvkm_ior *sor)
 {
@@ -220,6 +251,7 @@ nv50_sor = {
        .state = nv50_sor_state,
        .power = nv50_sor_power,
        .clock = nv50_sor_clock,
+       .bl = &nv50_sor_bl,
 };
 
 static int
index 20a013f1bbbacc07327feea14a8dd94a64d1f51a..28ec7b37851304290dbc351b6d9913056c6fa7aa 100644 (file)
@@ -209,6 +209,42 @@ nvkm_outp_acquire_or(struct nvkm_outp *outp, u8 user, bool hda)
        return nvkm_outp_acquire_hda(outp, type, user, false);
 }
 
+int
+nvkm_outp_bl_set(struct nvkm_outp *outp, int level)
+{
+       int ret;
+
+       ret = nvkm_outp_acquire_or(outp, NVKM_OUTP_PRIV, false);
+       if (ret)
+               return ret;
+
+       if (outp->ior->func->bl)
+               ret = outp->ior->func->bl->set(outp->ior, level);
+       else
+               ret = -EINVAL;
+
+       nvkm_outp_release_or(outp, NVKM_OUTP_PRIV);
+       return ret;
+}
+
+int
+nvkm_outp_bl_get(struct nvkm_outp *outp)
+{
+       int ret;
+
+       ret = nvkm_outp_acquire_or(outp, NVKM_OUTP_PRIV, false);
+       if (ret)
+               return ret;
+
+       if (outp->ior->func->bl)
+               ret = outp->ior->func->bl->get(outp->ior);
+       else
+               ret = -EINVAL;
+
+       nvkm_outp_release_or(outp, NVKM_OUTP_PRIV);
+       return ret;
+}
+
 int
 nvkm_outp_detect(struct nvkm_outp *outp)
 {
@@ -376,6 +412,8 @@ static const struct nvkm_outp_func
 nvkm_outp = {
        .detect = nvkm_outp_detect,
        .inherit = nvkm_outp_inherit,
+       .bl.get = nvkm_outp_bl_get,
+       .bl.set = nvkm_outp_bl_set,
 };
 
 int
index ab1699b07acc6ffd0a896bf8f589011dbd58e134..38b6b43a9f2003c7603a7c0855ece52abc2677ac 100644 (file)
@@ -84,6 +84,9 @@ void nvkm_outp_release(struct nvkm_outp *);
 void nvkm_outp_release_or(struct nvkm_outp *, u8 user);
 void nvkm_outp_route(struct nvkm_disp *);
 
+int nvkm_outp_bl_get(struct nvkm_outp *);
+int nvkm_outp_bl_set(struct nvkm_outp *, int level);
+
 struct nvkm_outp_func {
        void *(*dtor)(struct nvkm_outp *);
        void (*init)(struct nvkm_outp *);
@@ -96,6 +99,11 @@ struct nvkm_outp_func {
        int (*acquire)(struct nvkm_outp *);
        void (*release)(struct nvkm_outp *);
        void (*disable)(struct nvkm_outp *, struct nvkm_ior *);
+
+       struct {
+               int (*get)(struct nvkm_outp *);
+               int (*set)(struct nvkm_outp *, int level);
+       } bl;
 };
 
 #define OUTP_MSG(o,l,f,a...) do {                                              \
index f5242a6722794487307e00f41a59e13c147824bc..19f5d3a6035eb3cc900eb58c7fb33a7c571b2ce2 100644 (file)
@@ -88,6 +88,7 @@ tu102_sor = {
        .state = gv100_sor_state,
        .power = nv50_sor_power,
        .clock = gf119_sor_clock,
+       .bl = &gt215_sor_bl,
        .hdmi = &gv100_sor_hdmi,
        .dp = &tu102_sor_dp,
        .hda = &gv100_sor_hda,
index 40cbb4ddc0378b325be9b2266c8d83e68bcbe296..c1775524919fd39551cafce40e8f62d21814bb05 100644 (file)
@@ -181,6 +181,45 @@ nvkm_uoutp_mthd_acquire_lvds(struct nvkm_outp *outp, bool dual, bool bpc8)
        return 0;
 }
 
+static int
+nvkm_uoutp_mthd_bl_set(struct nvkm_outp *outp, void *argv, u32 argc)
+{
+       union nvif_outp_bl_get_args *args = argv;
+       int ret;
+
+       if (argc != sizeof(args->v0) || args->v0.version != 0)
+               return -ENOSYS;
+
+       if (outp->func->bl.set)
+               ret = outp->func->bl.set(outp, args->v0.level);
+       else
+               ret = -EINVAL;
+
+       return ret;
+}
+
+static int
+nvkm_uoutp_mthd_bl_get(struct nvkm_outp *outp, void *argv, u32 argc)
+{
+       union nvif_outp_bl_get_args *args = argv;
+       int ret;
+
+       if (argc != sizeof(args->v0) || args->v0.version != 0)
+               return -ENOSYS;
+
+       if (outp->func->bl.get) {
+               ret = outp->func->bl.get(outp);
+               if (ret >= 0) {
+                       args->v0.level = ret;
+                       ret = 0;
+               }
+       } else {
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
 static int
 nvkm_uoutp_mthd_release(struct nvkm_outp *outp, void *argv, u32 argc)
 {
@@ -388,6 +427,8 @@ nvkm_uoutp_mthd_noacquire(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc
        case NVIF_OUTP_V0_INHERIT    : return nvkm_uoutp_mthd_inherit    (outp, argv, argc);
        case NVIF_OUTP_V0_ACQUIRE    : return nvkm_uoutp_mthd_acquire    (outp, argv, argc);
        case NVIF_OUTP_V0_LOAD_DETECT: return nvkm_uoutp_mthd_load_detect(outp, argv, argc);
+       case NVIF_OUTP_V0_BL_GET     : return nvkm_uoutp_mthd_bl_get     (outp, argv, argc);
+       case NVIF_OUTP_V0_BL_SET     : return nvkm_uoutp_mthd_bl_set     (outp, argv, argc);
        case NVIF_OUTP_V0_DP_AUX_PWR : return nvkm_uoutp_mthd_dp_aux_pwr (outp, argv, argc);
        default:
                break;