1 /* 2 * Copyright (c) 2015 NVIDIA Corporation. All rights reserved. 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, sub license, 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 (including the 12 * next paragraph) shall be included in all copies or substantial portions 13 * of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 #ifndef DRM_SCDC_HELPER_H 25 #define DRM_SCDC_HELPER_H 26 27 #include <linux/errno.h> 28 #include <linux/types.h> 29 30 #include <drm/display/drm_scdc.h> 31 32 struct drm_connector; 33 struct i2c_adapter; 34 struct dentry; 35 36 struct drm_scdc_status_flags { 37 /* Status Register 0 */ 38 bool clock_detected; 39 bool ch0_locked; 40 bool ch1_locked; 41 bool ch2_locked; 42 bool ln3_locked; 43 bool flt_ready; 44 bool dsc_fail; 45 46 /* Status Register 1 */ 47 u8 ln0_training_pattern : 4; 48 u8 ln1_training_pattern : 4; 49 50 /* Status Register 2 */ 51 u8 ln2_training_pattern : 4; 52 u8 ln3_training_pattern : 4; 53 }; 54 55 enum drm_scdc_frl_rate { 56 SCDC_FRL_RATE_OFF = 0, 57 SCDC_FRL_RATE_3X3 = 1, 58 SCDC_FRL_RATE_6X3 = 2, 59 SCDC_FRL_RATE_6X4 = 3, 60 SCDC_FRL_RATE_8X4 = 4, 61 SCDC_FRL_RATE_10X4 = 5, 62 SCDC_FRL_RATE_12X4 = 6, 63 SCDC_FRL_RATE_RESV_7 = 7, 64 SCDC_FRL_RATE_RESV_8 = 8, 65 SCDC_FRL_RATE_RESV_9 = 9, 66 SCDC_FRL_RATE_RESV_10 = 10, 67 SCDC_FRL_RATE_RESV_11 = 11, 68 SCDC_FRL_RATE_RESV_12 = 12, 69 SCDC_FRL_RATE_RESV_13 = 13, 70 SCDC_FRL_RATE_RESV_14 = 14, 71 SCDC_FRL_RATE_RESV_15 = 15 72 }; 73 74 /** 75 * drm_scdc_num_frl_lanes - get number of lanes for a given FRL rate 76 * @rate: one of &enum drm_scdc_frl_rate 77 * 78 * For a given @rate, return the number of lanes it uses. 79 * 80 * Returns: %-EINVAL if @rate is not a valid FRL rate, or the number of lanes 81 * for a given &enum drm_scdc_frl_rate on success (including %0 for "off") 82 */ 83 static inline __pure int drm_scdc_num_frl_lanes(enum drm_scdc_frl_rate rate) 84 { 85 switch (rate) { 86 case SCDC_FRL_RATE_OFF: 87 return 0; 88 case SCDC_FRL_RATE_3X3: 89 case SCDC_FRL_RATE_6X3: 90 return 3; 91 case SCDC_FRL_RATE_6X4: 92 case SCDC_FRL_RATE_8X4: 93 case SCDC_FRL_RATE_10X4: 94 case SCDC_FRL_RATE_12X4: 95 return 4; 96 default: 97 return -EINVAL; 98 } 99 } 100 101 struct drm_scdc_state { 102 /** @stf: contents of the status flag registers */ 103 struct drm_scdc_status_flags stf; 104 /** @scramling_enabled: true if TMDS scrambling is on */ 105 bool scrambling_enabled; 106 /** @scrambling_detected: true if the sink actually detected scrambling */ 107 bool scrambling_detected; 108 /** 109 * @tmds_bclk_x40: true if TMDS bit period is 1/40th of the TMDS 110 * clock period, false if it's 1/10th of the clock period. 111 */ 112 bool tmds_bclk_x40; 113 /** @rate: FRL rate set by the source */ 114 enum drm_scdc_frl_rate rate : 4; 115 /** @ffe_levels: The FFE levels for @rate set by the source */ 116 u8 ffe_levels : 4; 117 /** @error_count: character error counts for each channel/link */ 118 u16 error_count[4]; 119 /** @rs_corrections: number of Reed-Solomon Corrections */ 120 u16 rs_corrections; 121 /** @scdc: raw SCDC data buffer */ 122 u8 scdc[256]; 123 }; 124 125 int drm_scdc_read(struct i2c_adapter *adapter, u8 offset, void *buffer, 126 size_t size); 127 int drm_scdc_write(struct i2c_adapter *adapter, u8 offset, const void *buffer, 128 size_t size); 129 130 /** 131 * drm_scdc_readb - read a single byte from SCDC 132 * @adapter: I2C adapter 133 * @offset: offset of register to read 134 * @value: return location for the register value 135 * 136 * Reads a single byte from SCDC. This is a convenience wrapper around the 137 * drm_scdc_read() function. 138 * 139 * Returns: 140 * 0 on success or a negative error code on failure. 141 */ 142 static inline int drm_scdc_readb(struct i2c_adapter *adapter, u8 offset, 143 u8 *value) 144 { 145 return drm_scdc_read(adapter, offset, value, sizeof(*value)); 146 } 147 148 /** 149 * drm_scdc_writeb - write a single byte to SCDC 150 * @adapter: I2C adapter 151 * @offset: offset of register to read 152 * @value: return location for the register value 153 * 154 * Writes a single byte to SCDC. This is a convenience wrapper around the 155 * drm_scdc_write() function. 156 * 157 * Returns: 158 * 0 on success or a negative error code on failure. 159 */ 160 static inline int drm_scdc_writeb(struct i2c_adapter *adapter, u8 offset, 161 u8 value) 162 { 163 return drm_scdc_write(adapter, offset, &value, sizeof(value)); 164 } 165 166 bool drm_scdc_get_scrambling_status(struct drm_connector *connector); 167 168 bool drm_scdc_set_scrambling(struct drm_connector *connector, bool enable); 169 bool drm_scdc_set_high_tmds_clock_ratio(struct drm_connector *connector, bool set); 170 171 int drm_scdc_set_source_version(struct drm_connector *connector, u8 ver); 172 173 int drm_scdc_read_state(struct drm_connector *connector, 174 struct drm_scdc_state *state); 175 void drm_scdc_debugfs_init(struct drm_connector *connector, struct dentry *root); 176 177 #endif 178