Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (C) 2008 Maarten Maathuis.
0003  * All Rights Reserved.
0004  *
0005  * Permission is hereby granted, free of charge, to any person obtaining
0006  * a copy of this software and associated documentation files (the
0007  * "Software"), to deal in the Software without restriction, including
0008  * without limitation the rights to use, copy, modify, merge, publish,
0009  * distribute, sublicense, and/or sell copies of the Software, and to
0010  * permit persons to whom the Software is furnished to do so, subject to
0011  * the following conditions:
0012  *
0013  * The above copyright notice and this permission notice (including the
0014  * next paragraph) shall be included in all copies or substantial
0015  * portions of the Software.
0016  *
0017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0018  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
0020  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
0021  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
0022  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
0023  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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         /* The enum values specifically defined here match nv50/gf119
0067          * hw values, and the code relies on this.
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;   /* DRM_MODE_SCALE_* */
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      * Our connector property code expects a nouveau_conn_atom struct
0142      * even on pre-nv50 where we do not support atomic. This embedded
0143      * version gets used in the non atomic modeset case.
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 /* __NOUVEAU_CONNECTOR_H__ */