diff options
| author | Ben Skeggs <bskeggs@redhat.com> | 2016-11-04 03:20:36 -0400 |
|---|---|---|
| committer | Ben Skeggs <bskeggs@redhat.com> | 2016-11-06 23:05:03 -0500 |
| commit | d665c7e91458e19f413ea89d99d89f4743be95e3 (patch) | |
| tree | 40ece02034a182cd9106ac4d9782141a98a383cb /drivers | |
| parent | 9bfdee9a08bbe550598fc4098c85470c63b46ff6 (diff) | |
drm/nouveau/kms/nv50: allow encoder update to be called from other modules
MST encoders will make use of this to share code with SOR>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_encoder.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 86 |
2 files changed, 44 insertions, 44 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index 2cd4a2dab835..848982bd18e9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h | |||
| @@ -66,6 +66,8 @@ struct nouveau_encoder { | |||
| 66 | 66 | ||
| 67 | void (*enc_save)(struct drm_encoder *encoder); | 67 | void (*enc_save)(struct drm_encoder *encoder); |
| 68 | void (*enc_restore)(struct drm_encoder *encoder); | 68 | void (*enc_restore)(struct drm_encoder *encoder); |
| 69 | void (*update)(struct nouveau_encoder *, u8 head, | ||
| 70 | struct drm_display_mode *, u8 proto, u8 depth); | ||
| 69 | }; | 71 | }; |
| 70 | 72 | ||
| 71 | struct nouveau_encoder * | 73 | struct nouveau_encoder * |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 45379f90acc8..854fa31eddb6 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
| @@ -2926,19 +2926,50 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) | |||
| 2926 | } | 2926 | } |
| 2927 | 2927 | ||
| 2928 | static void | 2928 | static void |
| 2929 | nv50_sor_ctrl(struct nouveau_encoder *nv_encoder, u32 mask, u32 data) | 2929 | nv50_sor_update(struct nouveau_encoder *nv_encoder, u8 head, |
| 2930 | struct drm_display_mode *mode, u8 proto, u8 depth) | ||
| 2930 | { | 2931 | { |
| 2931 | struct nv50_mast *mast = nv50_mast(nv_encoder->base.base.dev); | 2932 | struct nv50_dmac *core = &nv50_mast(nv_encoder->base.base.dev)->base; |
| 2932 | u32 temp = (nv_encoder->ctrl & ~mask) | (data & mask), *push; | 2933 | u32 *push; |
| 2933 | if (temp != nv_encoder->ctrl && (push = evo_wait(mast, 2))) { | 2934 | |
| 2934 | if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) { | 2935 | if (!mode) { |
| 2936 | nv_encoder->ctrl &= ~BIT(head); | ||
| 2937 | if (!(nv_encoder->ctrl & 0x0000000f)) | ||
| 2938 | nv_encoder->ctrl = 0; | ||
| 2939 | } else { | ||
| 2940 | nv_encoder->ctrl |= proto << 8; | ||
| 2941 | nv_encoder->ctrl |= BIT(head); | ||
| 2942 | } | ||
| 2943 | |||
| 2944 | if ((push = evo_wait(core, 6))) { | ||
| 2945 | if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) { | ||
| 2946 | if (mode) { | ||
| 2947 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
| 2948 | nv_encoder->ctrl |= 0x00001000; | ||
| 2949 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
| 2950 | nv_encoder->ctrl |= 0x00002000; | ||
| 2951 | nv_encoder->ctrl |= depth << 16; | ||
| 2952 | } | ||
| 2935 | evo_mthd(push, 0x0600 + (nv_encoder->or * 0x40), 1); | 2953 | evo_mthd(push, 0x0600 + (nv_encoder->or * 0x40), 1); |
| 2936 | evo_data(push, (nv_encoder->ctrl = temp)); | ||
| 2937 | } else { | 2954 | } else { |
| 2955 | if (mode) { | ||
| 2956 | u32 magic = 0x31ec6000 | (head << 25); | ||
| 2957 | u32 syncs = 0x00000001; | ||
| 2958 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
| 2959 | syncs |= 0x00000008; | ||
| 2960 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
| 2961 | syncs |= 0x00000010; | ||
| 2962 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) | ||
| 2963 | magic |= 0x00000001; | ||
| 2964 | |||
| 2965 | evo_mthd(push, 0x0404 + (head * 0x300), 2); | ||
| 2966 | evo_data(push, syncs | (depth << 6)); | ||
| 2967 | evo_data(push, magic); | ||
| 2968 | } | ||
| 2938 | evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1); | 2969 | evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1); |
| 2939 | evo_data(push, (nv_encoder->ctrl = temp)); | ||
| 2940 | } | 2970 | } |
| 2941 | evo_kick(push, mast); | 2971 | evo_data(push, nv_encoder->ctrl); |
| 2972 | evo_kick(push, core); | ||
| 2942 | } | 2973 | } |
| 2943 | } | 2974 | } |
| 2944 | 2975 | ||
| @@ -2963,7 +2994,7 @@ nv50_sor_disable(struct drm_encoder *encoder) | |||
| 2963 | } | 2994 | } |
| 2964 | } | 2995 | } |
| 2965 | 2996 | ||
| 2966 | nv50_sor_ctrl(nv_encoder, 1 << nv_crtc->index, 0); | 2997 | nv_encoder->update(nv_encoder, nv_crtc->index, NULL, 0, 0); |
| 2967 | nv50_audio_disable(encoder, nv_crtc); | 2998 | nv50_audio_disable(encoder, nv_crtc); |
| 2968 | nv50_hdmi_disable(&nv_encoder->base.base, nv_crtc); | 2999 | nv50_hdmi_disable(&nv_encoder->base.base, nv_crtc); |
| 2969 | } | 3000 | } |
| @@ -2985,13 +3016,10 @@ nv50_sor_enable(struct drm_encoder *encoder) | |||
| 2985 | .base.hashm = nv_encoder->dcb->hashm, | 3016 | .base.hashm = nv_encoder->dcb->hashm, |
| 2986 | }; | 3017 | }; |
| 2987 | struct nv50_disp *disp = nv50_disp(encoder->dev); | 3018 | struct nv50_disp *disp = nv50_disp(encoder->dev); |
| 2988 | struct nv50_mast *mast = nv50_mast(encoder->dev); | ||
| 2989 | struct drm_device *dev = encoder->dev; | 3019 | struct drm_device *dev = encoder->dev; |
| 2990 | struct nouveau_drm *drm = nouveau_drm(dev); | 3020 | struct nouveau_drm *drm = nouveau_drm(dev); |
| 2991 | struct nouveau_connector *nv_connector; | 3021 | struct nouveau_connector *nv_connector; |
| 2992 | struct nvbios *bios = &drm->vbios; | 3022 | struct nvbios *bios = &drm->vbios; |
| 2993 | u32 mask, ctrl; | ||
| 2994 | u8 owner = 1 << nv_crtc->index; | ||
| 2995 | u8 proto = 0xf; | 3023 | u8 proto = 0xf; |
| 2996 | u8 depth = 0x0; | 3024 | u8 depth = 0x0; |
| 2997 | 3025 | ||
| @@ -3070,38 +3098,7 @@ nv50_sor_enable(struct drm_encoder *encoder) | |||
| 3070 | break; | 3098 | break; |
| 3071 | } | 3099 | } |
| 3072 | 3100 | ||
| 3073 | if (nv50_vers(mast) >= GF110_DISP) { | 3101 | nv_encoder->update(nv_encoder, nv_crtc->index, mode, proto, depth); |
| 3074 | u32 *push = evo_wait(mast, 3); | ||
| 3075 | if (push) { | ||
| 3076 | u32 magic = 0x31ec6000 | (nv_crtc->index << 25); | ||
| 3077 | u32 syncs = 0x00000001; | ||
| 3078 | |||
| 3079 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
| 3080 | syncs |= 0x00000008; | ||
| 3081 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
| 3082 | syncs |= 0x00000010; | ||
| 3083 | |||
| 3084 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) | ||
| 3085 | magic |= 0x00000001; | ||
| 3086 | |||
| 3087 | evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2); | ||
| 3088 | evo_data(push, syncs | (depth << 6)); | ||
| 3089 | evo_data(push, magic); | ||
| 3090 | evo_kick(push, mast); | ||
| 3091 | } | ||
| 3092 | |||
| 3093 | ctrl = proto << 8; | ||
| 3094 | mask = 0x00000f00; | ||
| 3095 | } else { | ||
| 3096 | ctrl = (depth << 16) | (proto << 8); | ||
| 3097 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
| 3098 | ctrl |= 0x00001000; | ||
| 3099 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
| 3100 | ctrl |= 0x00002000; | ||
| 3101 | mask = 0x000f3f00; | ||
| 3102 | } | ||
| 3103 | |||
| 3104 | nv50_sor_ctrl(nv_encoder, mask | owner, ctrl | owner); | ||
| 3105 | } | 3102 | } |
| 3106 | 3103 | ||
| 3107 | static const struct drm_encoder_helper_funcs | 3104 | static const struct drm_encoder_helper_funcs |
| @@ -3150,6 +3147,7 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) | |||
| 3150 | return -ENOMEM; | 3147 | return -ENOMEM; |
| 3151 | nv_encoder->dcb = dcbe; | 3148 | nv_encoder->dcb = dcbe; |
| 3152 | nv_encoder->or = ffs(dcbe->or) - 1; | 3149 | nv_encoder->or = ffs(dcbe->or) - 1; |
| 3150 | nv_encoder->update = nv50_sor_update; | ||
| 3153 | 3151 | ||
| 3154 | encoder = to_drm_encoder(nv_encoder); | 3152 | encoder = to_drm_encoder(nv_encoder); |
| 3155 | encoder->possible_crtcs = dcbe->heads; | 3153 | encoder->possible_crtcs = dcbe->heads; |
