0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #ifndef __NOUVEAU_CONNECTOR_H__
0028 #define __NOUVEAU_CONNECTOR_H__
0029 #include <nvif/conn.h>
0030 #include <nvif/notify.h>
0031
0032 #include <nvhw/class/cl507d.h>
0033 #include <nvhw/class/cl907d.h>
0034 #include <nvhw/drf.h>
0035
0036 #include <drm/display/drm_dp_helper.h>
0037 #include <drm/drm_crtc.h>
0038 #include <drm/drm_edid.h>
0039 #include <drm/drm_encoder.h>
0040 #include <drm/drm_util.h>
0041
0042 #include "nouveau_crtc.h"
0043 #include "nouveau_encoder.h"
0044
0045 struct nvkm_i2c_port;
0046 struct dcb_output;
0047
0048 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
0049 struct nouveau_backlight {
0050 struct backlight_device *dev;
0051
0052 struct drm_edp_backlight_info edp_info;
0053 bool uses_dpcd : 1;
0054
0055 int id;
0056 };
0057 #endif
0058
0059 #define nouveau_conn_atom(p) \
0060 container_of((p), struct nouveau_conn_atom, state)
0061
0062 struct nouveau_conn_atom {
0063 struct drm_connector_state state;
0064
0065 struct {
0066
0067
0068
0069 enum {
0070 DITHERING_MODE_OFF =
0071 NVDEF(NV507D, HEAD_SET_DITHER_CONTROL, ENABLE, DISABLE),
0072 DITHERING_MODE_ON =
0073 NVDEF(NV507D, HEAD_SET_DITHER_CONTROL, ENABLE, ENABLE),
0074 DITHERING_MODE_DYNAMIC2X2 = DITHERING_MODE_ON |
0075 NVDEF(NV507D, HEAD_SET_DITHER_CONTROL, MODE, DYNAMIC_2X2),
0076 DITHERING_MODE_STATIC2X2 = DITHERING_MODE_ON |
0077 NVDEF(NV507D, HEAD_SET_DITHER_CONTROL, MODE, STATIC_2X2),
0078 DITHERING_MODE_TEMPORAL = DITHERING_MODE_ON |
0079 NVDEF(NV907D, HEAD_SET_DITHER_CONTROL, MODE, TEMPORAL),
0080 DITHERING_MODE_AUTO
0081 } mode;
0082 enum {
0083 DITHERING_DEPTH_6BPC =
0084 NVDEF(NV507D, HEAD_SET_DITHER_CONTROL, BITS, DITHER_TO_6_BITS),
0085 DITHERING_DEPTH_8BPC =
0086 NVDEF(NV507D, HEAD_SET_DITHER_CONTROL, BITS, DITHER_TO_8_BITS),
0087 DITHERING_DEPTH_AUTO
0088 } depth;
0089 } dither;
0090
0091 struct {
0092 int mode;
0093 struct {
0094 enum {
0095 UNDERSCAN_OFF,
0096 UNDERSCAN_ON,
0097 UNDERSCAN_AUTO,
0098 } mode;
0099 u32 hborder;
0100 u32 vborder;
0101 } underscan;
0102 bool full;
0103 } scaler;
0104
0105 struct {
0106 int color_vibrance;
0107 int vibrant_hue;
0108 } procamp;
0109
0110 union {
0111 struct {
0112 bool dither:1;
0113 bool scaler:1;
0114 bool procamp:1;
0115 };
0116 u8 mask;
0117 } set;
0118 };
0119
0120 struct nouveau_connector {
0121 struct drm_connector base;
0122 enum dcb_connector_type type;
0123 u8 index;
0124 u8 *dcb;
0125
0126 struct nvif_conn conn;
0127 struct nvif_notify hpd;
0128
0129 struct drm_dp_aux aux;
0130
0131 int dithering_mode;
0132 int scaling_mode;
0133
0134 struct nouveau_encoder *detected_encoder;
0135 struct edid *edid;
0136 struct drm_display_mode *native_mode;
0137 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
0138 struct nouveau_backlight *backlight;
0139 #endif
0140
0141
0142
0143
0144
0145 struct nouveau_conn_atom properties_state;
0146 };
0147
0148 static inline struct nouveau_connector *nouveau_connector(
0149 struct drm_connector *con)
0150 {
0151 return container_of(con, struct nouveau_connector, base);
0152 }
0153
0154 static inline bool
0155 nouveau_connector_is_mst(struct drm_connector *connector)
0156 {
0157 const struct nouveau_encoder *nv_encoder;
0158 const struct drm_encoder *encoder;
0159
0160 if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
0161 return false;
0162
0163 nv_encoder = find_encoder(connector, DCB_OUTPUT_ANY);
0164 if (!nv_encoder)
0165 return false;
0166
0167 encoder = &nv_encoder->base.base;
0168 return encoder->encoder_type == DRM_MODE_ENCODER_DPMST;
0169 }
0170
0171 #define nouveau_for_each_non_mst_connector_iter(connector, iter) \
0172 drm_for_each_connector_iter(connector, iter) \
0173 for_each_if(!nouveau_connector_is_mst(connector))
0174
0175 static inline struct nouveau_connector *
0176 nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
0177 {
0178 struct drm_device *dev = nv_crtc->base.dev;
0179 struct drm_connector *connector;
0180 struct drm_connector_list_iter conn_iter;
0181 struct nouveau_connector *nv_connector = NULL;
0182 struct drm_crtc *crtc = to_drm_crtc(nv_crtc);
0183
0184 drm_connector_list_iter_begin(dev, &conn_iter);
0185 nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
0186 if (connector->encoder && connector->encoder->crtc == crtc) {
0187 nv_connector = nouveau_connector(connector);
0188 break;
0189 }
0190 }
0191 drm_connector_list_iter_end(&conn_iter);
0192
0193 return nv_connector;
0194 }
0195
0196 struct drm_connector *
0197 nouveau_connector_create(struct drm_device *, const struct dcb_output *);
0198 void nouveau_connector_hpd(struct drm_connector *connector);
0199
0200 extern int nouveau_tv_disable;
0201 extern int nouveau_ignorelid;
0202 extern int nouveau_duallink;
0203 extern int nouveau_hdmimhz;
0204
0205 void nouveau_conn_attach_properties(struct drm_connector *);
0206 void nouveau_conn_reset(struct drm_connector *);
0207 struct drm_connector_state *
0208 nouveau_conn_atomic_duplicate_state(struct drm_connector *);
0209 void nouveau_conn_atomic_destroy_state(struct drm_connector *,
0210 struct drm_connector_state *);
0211 int nouveau_conn_atomic_set_property(struct drm_connector *,
0212 struct drm_connector_state *,
0213 struct drm_property *, u64);
0214 int nouveau_conn_atomic_get_property(struct drm_connector *,
0215 const struct drm_connector_state *,
0216 struct drm_property *, u64 *);
0217 struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *);
0218 enum drm_mode_status
0219 nouveau_conn_mode_clock_valid(const struct drm_display_mode *,
0220 const unsigned min_clock,
0221 const unsigned max_clock,
0222 unsigned *clock);
0223
0224 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
0225 extern int nouveau_backlight_init(struct drm_connector *);
0226 extern void nouveau_backlight_fini(struct drm_connector *);
0227 extern void nouveau_backlight_ctor(void);
0228 extern void nouveau_backlight_dtor(void);
0229 #else
0230 static inline int
0231 nouveau_backlight_init(struct drm_connector *connector)
0232 {
0233 return 0;
0234 }
0235
0236 static inline void
0237 nouveau_backlight_fini(struct drm_connector *connector) {
0238 }
0239
0240 static inline void
0241 nouveau_backlight_ctor(void) {
0242 }
0243
0244 static inline void
0245 nouveau_backlight_dtor(void) {
0246 }
0247 #endif
0248
0249 #endif