1 1.3 riastrad /* $NetBSD: ch7006_drv.c,v 1.3 2021/12/18 23:45:27 riastradh Exp $ */ 2 1.3 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright (C) 2009 Francisco Jerez. 5 1.1 riastrad * All Rights Reserved. 6 1.1 riastrad * 7 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining 8 1.1 riastrad * a copy of this software and associated documentation files (the 9 1.1 riastrad * "Software"), to deal in the Software without restriction, including 10 1.1 riastrad * without limitation the rights to use, copy, modify, merge, publish, 11 1.1 riastrad * distribute, sublicense, and/or sell copies of the Software, and to 12 1.1 riastrad * permit persons to whom the Software is furnished to do so, subject to 13 1.1 riastrad * the following conditions: 14 1.1 riastrad * 15 1.1 riastrad * The above copyright notice and this permission notice (including the 16 1.1 riastrad * next paragraph) shall be included in all copies or substantial 17 1.1 riastrad * portions of the Software. 18 1.1 riastrad * 19 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 1.1 riastrad * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 1.1 riastrad * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 1.1 riastrad * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 23 1.1 riastrad * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 1.1 riastrad * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 1.1 riastrad * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 1.1 riastrad * 27 1.1 riastrad */ 28 1.1 riastrad 29 1.3 riastrad #include <sys/cdefs.h> 30 1.3 riastrad __KERNEL_RCSID(0, "$NetBSD: ch7006_drv.c,v 1.3 2021/12/18 23:45:27 riastradh Exp $"); 31 1.3 riastrad 32 1.1 riastrad #include <linux/module.h> 33 1.1 riastrad 34 1.1 riastrad #include "ch7006_priv.h" 35 1.1 riastrad 36 1.1 riastrad /* DRM encoder functions */ 37 1.1 riastrad 38 1.1 riastrad static void ch7006_encoder_set_config(struct drm_encoder *encoder, 39 1.1 riastrad void *params) 40 1.1 riastrad { 41 1.1 riastrad struct ch7006_priv *priv = to_ch7006_priv(encoder); 42 1.1 riastrad 43 1.1 riastrad priv->params = *(struct ch7006_encoder_params *)params; 44 1.1 riastrad } 45 1.1 riastrad 46 1.1 riastrad static void ch7006_encoder_destroy(struct drm_encoder *encoder) 47 1.1 riastrad { 48 1.1 riastrad struct ch7006_priv *priv = to_ch7006_priv(encoder); 49 1.1 riastrad 50 1.1 riastrad drm_property_destroy(encoder->dev, priv->scale_property); 51 1.1 riastrad 52 1.1 riastrad kfree(priv); 53 1.1 riastrad to_encoder_slave(encoder)->slave_priv = NULL; 54 1.1 riastrad 55 1.1 riastrad drm_i2c_encoder_destroy(encoder); 56 1.1 riastrad } 57 1.1 riastrad 58 1.1 riastrad static void ch7006_encoder_dpms(struct drm_encoder *encoder, int mode) 59 1.1 riastrad { 60 1.1 riastrad struct i2c_client *client = drm_i2c_encoder_get_client(encoder); 61 1.1 riastrad struct ch7006_priv *priv = to_ch7006_priv(encoder); 62 1.1 riastrad struct ch7006_state *state = &priv->state; 63 1.1 riastrad 64 1.1 riastrad ch7006_dbg(client, "\n"); 65 1.1 riastrad 66 1.1 riastrad if (mode == priv->last_dpms) 67 1.1 riastrad return; 68 1.1 riastrad priv->last_dpms = mode; 69 1.1 riastrad 70 1.1 riastrad ch7006_setup_power_state(encoder); 71 1.1 riastrad 72 1.1 riastrad ch7006_load_reg(client, state, CH7006_POWER); 73 1.1 riastrad } 74 1.1 riastrad 75 1.1 riastrad static void ch7006_encoder_save(struct drm_encoder *encoder) 76 1.1 riastrad { 77 1.1 riastrad struct i2c_client *client = drm_i2c_encoder_get_client(encoder); 78 1.1 riastrad struct ch7006_priv *priv = to_ch7006_priv(encoder); 79 1.1 riastrad 80 1.1 riastrad ch7006_dbg(client, "\n"); 81 1.1 riastrad 82 1.1 riastrad ch7006_state_save(client, &priv->saved_state); 83 1.1 riastrad } 84 1.1 riastrad 85 1.1 riastrad static void ch7006_encoder_restore(struct drm_encoder *encoder) 86 1.1 riastrad { 87 1.1 riastrad struct i2c_client *client = drm_i2c_encoder_get_client(encoder); 88 1.1 riastrad struct ch7006_priv *priv = to_ch7006_priv(encoder); 89 1.1 riastrad 90 1.1 riastrad ch7006_dbg(client, "\n"); 91 1.1 riastrad 92 1.1 riastrad ch7006_state_load(client, &priv->saved_state); 93 1.1 riastrad } 94 1.1 riastrad 95 1.1 riastrad static bool ch7006_encoder_mode_fixup(struct drm_encoder *encoder, 96 1.1 riastrad const struct drm_display_mode *mode, 97 1.1 riastrad struct drm_display_mode *adjusted_mode) 98 1.1 riastrad { 99 1.1 riastrad struct ch7006_priv *priv = to_ch7006_priv(encoder); 100 1.1 riastrad 101 1.1 riastrad /* The ch7006 is painfully picky with the input timings so no 102 1.1 riastrad * custom modes for now... */ 103 1.1 riastrad 104 1.1 riastrad priv->mode = ch7006_lookup_mode(encoder, mode); 105 1.1 riastrad 106 1.1 riastrad return !!priv->mode; 107 1.1 riastrad } 108 1.1 riastrad 109 1.1 riastrad static int ch7006_encoder_mode_valid(struct drm_encoder *encoder, 110 1.1 riastrad struct drm_display_mode *mode) 111 1.1 riastrad { 112 1.1 riastrad if (ch7006_lookup_mode(encoder, mode)) 113 1.1 riastrad return MODE_OK; 114 1.1 riastrad else 115 1.1 riastrad return MODE_BAD; 116 1.1 riastrad } 117 1.1 riastrad 118 1.1 riastrad static void ch7006_encoder_mode_set(struct drm_encoder *encoder, 119 1.1 riastrad struct drm_display_mode *drm_mode, 120 1.1 riastrad struct drm_display_mode *adjusted_mode) 121 1.1 riastrad { 122 1.1 riastrad struct i2c_client *client = drm_i2c_encoder_get_client(encoder); 123 1.1 riastrad struct ch7006_priv *priv = to_ch7006_priv(encoder); 124 1.1 riastrad struct ch7006_encoder_params *params = &priv->params; 125 1.1 riastrad struct ch7006_state *state = &priv->state; 126 1.1 riastrad uint8_t *regs = state->regs; 127 1.3 riastrad const struct ch7006_mode *mode = priv->mode; 128 1.3 riastrad const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm]; 129 1.1 riastrad int start_active; 130 1.1 riastrad 131 1.1 riastrad ch7006_dbg(client, "\n"); 132 1.1 riastrad 133 1.1 riastrad regs[CH7006_DISPMODE] = norm->dispmode | mode->dispmode; 134 1.1 riastrad regs[CH7006_BWIDTH] = 0; 135 1.1 riastrad regs[CH7006_INPUT_FORMAT] = bitf(CH7006_INPUT_FORMAT_FORMAT, 136 1.1 riastrad params->input_format); 137 1.1 riastrad 138 1.1 riastrad regs[CH7006_CLKMODE] = CH7006_CLKMODE_SUBC_LOCK 139 1.1 riastrad | bitf(CH7006_CLKMODE_XCM, params->xcm) 140 1.1 riastrad | bitf(CH7006_CLKMODE_PCM, params->pcm); 141 1.1 riastrad if (params->clock_mode) 142 1.1 riastrad regs[CH7006_CLKMODE] |= CH7006_CLKMODE_MASTER; 143 1.1 riastrad if (params->clock_edge) 144 1.1 riastrad regs[CH7006_CLKMODE] |= CH7006_CLKMODE_POS_EDGE; 145 1.1 riastrad 146 1.1 riastrad start_active = (drm_mode->htotal & ~0x7) - (drm_mode->hsync_start & ~0x7); 147 1.1 riastrad regs[CH7006_POV] = bitf(CH7006_POV_START_ACTIVE_8, start_active); 148 1.1 riastrad regs[CH7006_START_ACTIVE] = bitf(CH7006_START_ACTIVE_0, start_active); 149 1.1 riastrad 150 1.1 riastrad regs[CH7006_INPUT_SYNC] = 0; 151 1.1 riastrad if (params->sync_direction) 152 1.1 riastrad regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_OUTPUT; 153 1.1 riastrad if (params->sync_encoding) 154 1.1 riastrad regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_EMBEDDED; 155 1.1 riastrad if (drm_mode->flags & DRM_MODE_FLAG_PVSYNC) 156 1.1 riastrad regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_PVSYNC; 157 1.1 riastrad if (drm_mode->flags & DRM_MODE_FLAG_PHSYNC) 158 1.1 riastrad regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_PHSYNC; 159 1.1 riastrad 160 1.1 riastrad regs[CH7006_DETECT] = 0; 161 1.1 riastrad regs[CH7006_BCLKOUT] = 0; 162 1.1 riastrad 163 1.1 riastrad regs[CH7006_SUBC_INC3] = 0; 164 1.1 riastrad if (params->pout_level) 165 1.1 riastrad regs[CH7006_SUBC_INC3] |= CH7006_SUBC_INC3_POUT_3_3V; 166 1.1 riastrad 167 1.1 riastrad regs[CH7006_SUBC_INC4] = 0; 168 1.1 riastrad if (params->active_detect) 169 1.1 riastrad regs[CH7006_SUBC_INC4] |= CH7006_SUBC_INC4_DS_INPUT; 170 1.1 riastrad 171 1.1 riastrad regs[CH7006_PLL_CONTROL] = priv->saved_state.regs[CH7006_PLL_CONTROL]; 172 1.1 riastrad 173 1.1 riastrad ch7006_setup_levels(encoder); 174 1.1 riastrad ch7006_setup_subcarrier(encoder); 175 1.1 riastrad ch7006_setup_pll(encoder); 176 1.1 riastrad ch7006_setup_power_state(encoder); 177 1.1 riastrad ch7006_setup_properties(encoder); 178 1.1 riastrad 179 1.1 riastrad ch7006_state_load(client, state); 180 1.1 riastrad } 181 1.1 riastrad 182 1.1 riastrad static enum drm_connector_status ch7006_encoder_detect(struct drm_encoder *encoder, 183 1.1 riastrad struct drm_connector *connector) 184 1.1 riastrad { 185 1.1 riastrad struct i2c_client *client = drm_i2c_encoder_get_client(encoder); 186 1.1 riastrad struct ch7006_priv *priv = to_ch7006_priv(encoder); 187 1.1 riastrad struct ch7006_state *state = &priv->state; 188 1.1 riastrad int det; 189 1.1 riastrad 190 1.1 riastrad ch7006_dbg(client, "\n"); 191 1.1 riastrad 192 1.1 riastrad ch7006_save_reg(client, state, CH7006_DETECT); 193 1.1 riastrad ch7006_save_reg(client, state, CH7006_POWER); 194 1.1 riastrad ch7006_save_reg(client, state, CH7006_CLKMODE); 195 1.1 riastrad 196 1.1 riastrad ch7006_write(client, CH7006_POWER, CH7006_POWER_RESET | 197 1.1 riastrad bitfs(CH7006_POWER_LEVEL, NORMAL)); 198 1.1 riastrad ch7006_write(client, CH7006_CLKMODE, CH7006_CLKMODE_MASTER); 199 1.1 riastrad 200 1.1 riastrad ch7006_write(client, CH7006_DETECT, CH7006_DETECT_SENSE); 201 1.1 riastrad 202 1.1 riastrad ch7006_write(client, CH7006_DETECT, 0); 203 1.1 riastrad 204 1.1 riastrad det = ch7006_read(client, CH7006_DETECT); 205 1.1 riastrad 206 1.1 riastrad ch7006_load_reg(client, state, CH7006_CLKMODE); 207 1.1 riastrad ch7006_load_reg(client, state, CH7006_POWER); 208 1.1 riastrad ch7006_load_reg(client, state, CH7006_DETECT); 209 1.1 riastrad 210 1.1 riastrad if ((det & (CH7006_DETECT_SVIDEO_Y_TEST| 211 1.1 riastrad CH7006_DETECT_SVIDEO_C_TEST| 212 1.1 riastrad CH7006_DETECT_CVBS_TEST)) == 0) 213 1.1 riastrad priv->subconnector = DRM_MODE_SUBCONNECTOR_SCART; 214 1.1 riastrad else if ((det & (CH7006_DETECT_SVIDEO_Y_TEST| 215 1.1 riastrad CH7006_DETECT_SVIDEO_C_TEST)) == 0) 216 1.1 riastrad priv->subconnector = DRM_MODE_SUBCONNECTOR_SVIDEO; 217 1.1 riastrad else if ((det & CH7006_DETECT_CVBS_TEST) == 0) 218 1.1 riastrad priv->subconnector = DRM_MODE_SUBCONNECTOR_Composite; 219 1.1 riastrad else 220 1.1 riastrad priv->subconnector = DRM_MODE_SUBCONNECTOR_Unknown; 221 1.1 riastrad 222 1.1 riastrad drm_object_property_set_value(&connector->base, 223 1.1 riastrad encoder->dev->mode_config.tv_subconnector_property, 224 1.1 riastrad priv->subconnector); 225 1.1 riastrad 226 1.1 riastrad return priv->subconnector ? connector_status_connected : 227 1.1 riastrad connector_status_disconnected; 228 1.1 riastrad } 229 1.1 riastrad 230 1.1 riastrad static int ch7006_encoder_get_modes(struct drm_encoder *encoder, 231 1.1 riastrad struct drm_connector *connector) 232 1.1 riastrad { 233 1.1 riastrad struct ch7006_priv *priv = to_ch7006_priv(encoder); 234 1.3 riastrad const struct ch7006_mode *mode; 235 1.1 riastrad int n = 0; 236 1.1 riastrad 237 1.1 riastrad for (mode = ch7006_modes; mode->mode.clock; mode++) { 238 1.1 riastrad if (~mode->valid_scales & 1<<priv->scale || 239 1.1 riastrad ~mode->valid_norms & 1<<priv->norm) 240 1.1 riastrad continue; 241 1.1 riastrad 242 1.1 riastrad drm_mode_probed_add(connector, 243 1.1 riastrad drm_mode_duplicate(encoder->dev, &mode->mode)); 244 1.1 riastrad 245 1.1 riastrad n++; 246 1.1 riastrad } 247 1.1 riastrad 248 1.1 riastrad return n; 249 1.1 riastrad } 250 1.1 riastrad 251 1.1 riastrad static int ch7006_encoder_create_resources(struct drm_encoder *encoder, 252 1.1 riastrad struct drm_connector *connector) 253 1.1 riastrad { 254 1.1 riastrad struct ch7006_priv *priv = to_ch7006_priv(encoder); 255 1.1 riastrad struct drm_device *dev = encoder->dev; 256 1.1 riastrad struct drm_mode_config *conf = &dev->mode_config; 257 1.1 riastrad 258 1.1 riastrad drm_mode_create_tv_properties(dev, NUM_TV_NORMS, ch7006_tv_norm_names); 259 1.1 riastrad 260 1.1 riastrad priv->scale_property = drm_property_create_range(dev, 0, "scale", 0, 2); 261 1.3 riastrad if (!priv->scale_property) 262 1.3 riastrad return -ENOMEM; 263 1.1 riastrad 264 1.1 riastrad drm_object_attach_property(&connector->base, conf->tv_select_subconnector_property, 265 1.1 riastrad priv->select_subconnector); 266 1.1 riastrad drm_object_attach_property(&connector->base, conf->tv_subconnector_property, 267 1.1 riastrad priv->subconnector); 268 1.1 riastrad drm_object_attach_property(&connector->base, conf->tv_left_margin_property, 269 1.1 riastrad priv->hmargin); 270 1.1 riastrad drm_object_attach_property(&connector->base, conf->tv_bottom_margin_property, 271 1.1 riastrad priv->vmargin); 272 1.1 riastrad drm_object_attach_property(&connector->base, conf->tv_mode_property, 273 1.1 riastrad priv->norm); 274 1.1 riastrad drm_object_attach_property(&connector->base, conf->tv_brightness_property, 275 1.1 riastrad priv->brightness); 276 1.1 riastrad drm_object_attach_property(&connector->base, conf->tv_contrast_property, 277 1.1 riastrad priv->contrast); 278 1.1 riastrad drm_object_attach_property(&connector->base, conf->tv_flicker_reduction_property, 279 1.1 riastrad priv->flicker); 280 1.1 riastrad drm_object_attach_property(&connector->base, priv->scale_property, 281 1.1 riastrad priv->scale); 282 1.1 riastrad 283 1.1 riastrad return 0; 284 1.1 riastrad } 285 1.1 riastrad 286 1.1 riastrad static int ch7006_encoder_set_property(struct drm_encoder *encoder, 287 1.1 riastrad struct drm_connector *connector, 288 1.1 riastrad struct drm_property *property, 289 1.1 riastrad uint64_t val) 290 1.1 riastrad { 291 1.1 riastrad struct i2c_client *client = drm_i2c_encoder_get_client(encoder); 292 1.1 riastrad struct ch7006_priv *priv = to_ch7006_priv(encoder); 293 1.1 riastrad struct ch7006_state *state = &priv->state; 294 1.1 riastrad struct drm_mode_config *conf = &encoder->dev->mode_config; 295 1.1 riastrad struct drm_crtc *crtc = encoder->crtc; 296 1.1 riastrad bool modes_changed = false; 297 1.1 riastrad 298 1.1 riastrad ch7006_dbg(client, "\n"); 299 1.1 riastrad 300 1.1 riastrad if (property == conf->tv_select_subconnector_property) { 301 1.1 riastrad priv->select_subconnector = val; 302 1.1 riastrad 303 1.1 riastrad ch7006_setup_power_state(encoder); 304 1.1 riastrad 305 1.1 riastrad ch7006_load_reg(client, state, CH7006_POWER); 306 1.1 riastrad 307 1.1 riastrad } else if (property == conf->tv_left_margin_property) { 308 1.1 riastrad priv->hmargin = val; 309 1.1 riastrad 310 1.1 riastrad ch7006_setup_properties(encoder); 311 1.1 riastrad 312 1.1 riastrad ch7006_load_reg(client, state, CH7006_POV); 313 1.1 riastrad ch7006_load_reg(client, state, CH7006_HPOS); 314 1.1 riastrad 315 1.1 riastrad } else if (property == conf->tv_bottom_margin_property) { 316 1.1 riastrad priv->vmargin = val; 317 1.1 riastrad 318 1.1 riastrad ch7006_setup_properties(encoder); 319 1.1 riastrad 320 1.1 riastrad ch7006_load_reg(client, state, CH7006_POV); 321 1.1 riastrad ch7006_load_reg(client, state, CH7006_VPOS); 322 1.1 riastrad 323 1.1 riastrad } else if (property == conf->tv_mode_property) { 324 1.1 riastrad if (connector->dpms != DRM_MODE_DPMS_OFF) 325 1.1 riastrad return -EINVAL; 326 1.1 riastrad 327 1.1 riastrad priv->norm = val; 328 1.1 riastrad 329 1.1 riastrad modes_changed = true; 330 1.1 riastrad 331 1.1 riastrad } else if (property == conf->tv_brightness_property) { 332 1.1 riastrad priv->brightness = val; 333 1.1 riastrad 334 1.1 riastrad ch7006_setup_levels(encoder); 335 1.1 riastrad 336 1.1 riastrad ch7006_load_reg(client, state, CH7006_BLACK_LEVEL); 337 1.1 riastrad 338 1.1 riastrad } else if (property == conf->tv_contrast_property) { 339 1.1 riastrad priv->contrast = val; 340 1.1 riastrad 341 1.1 riastrad ch7006_setup_properties(encoder); 342 1.1 riastrad 343 1.1 riastrad ch7006_load_reg(client, state, CH7006_CONTRAST); 344 1.1 riastrad 345 1.1 riastrad } else if (property == conf->tv_flicker_reduction_property) { 346 1.1 riastrad priv->flicker = val; 347 1.1 riastrad 348 1.1 riastrad ch7006_setup_properties(encoder); 349 1.1 riastrad 350 1.1 riastrad ch7006_load_reg(client, state, CH7006_FFILTER); 351 1.1 riastrad 352 1.1 riastrad } else if (property == priv->scale_property) { 353 1.1 riastrad if (connector->dpms != DRM_MODE_DPMS_OFF) 354 1.1 riastrad return -EINVAL; 355 1.1 riastrad 356 1.1 riastrad priv->scale = val; 357 1.1 riastrad 358 1.1 riastrad modes_changed = true; 359 1.1 riastrad 360 1.1 riastrad } else { 361 1.1 riastrad return -EINVAL; 362 1.1 riastrad } 363 1.1 riastrad 364 1.1 riastrad if (modes_changed) { 365 1.1 riastrad drm_helper_probe_single_connector_modes(connector, 0, 0); 366 1.1 riastrad 367 1.3 riastrad if (crtc) 368 1.3 riastrad drm_crtc_helper_set_mode(crtc, &crtc->mode, 369 1.3 riastrad crtc->x, crtc->y, 370 1.3 riastrad crtc->primary->fb); 371 1.1 riastrad } 372 1.1 riastrad 373 1.1 riastrad return 0; 374 1.1 riastrad } 375 1.1 riastrad 376 1.3 riastrad static const struct drm_encoder_slave_funcs ch7006_encoder_funcs = { 377 1.1 riastrad .set_config = ch7006_encoder_set_config, 378 1.1 riastrad .destroy = ch7006_encoder_destroy, 379 1.1 riastrad .dpms = ch7006_encoder_dpms, 380 1.1 riastrad .save = ch7006_encoder_save, 381 1.1 riastrad .restore = ch7006_encoder_restore, 382 1.1 riastrad .mode_fixup = ch7006_encoder_mode_fixup, 383 1.1 riastrad .mode_valid = ch7006_encoder_mode_valid, 384 1.1 riastrad .mode_set = ch7006_encoder_mode_set, 385 1.1 riastrad .detect = ch7006_encoder_detect, 386 1.1 riastrad .get_modes = ch7006_encoder_get_modes, 387 1.1 riastrad .create_resources = ch7006_encoder_create_resources, 388 1.1 riastrad .set_property = ch7006_encoder_set_property, 389 1.1 riastrad }; 390 1.1 riastrad 391 1.1 riastrad 392 1.1 riastrad /* I2C driver functions */ 393 1.1 riastrad 394 1.1 riastrad static int ch7006_probe(struct i2c_client *client, const struct i2c_device_id *id) 395 1.1 riastrad { 396 1.1 riastrad uint8_t addr = CH7006_VERSION_ID; 397 1.1 riastrad uint8_t val; 398 1.1 riastrad int ret; 399 1.1 riastrad 400 1.1 riastrad ch7006_dbg(client, "\n"); 401 1.1 riastrad 402 1.1 riastrad ret = i2c_master_send(client, &addr, sizeof(addr)); 403 1.1 riastrad if (ret < 0) 404 1.1 riastrad goto fail; 405 1.1 riastrad 406 1.1 riastrad ret = i2c_master_recv(client, &val, sizeof(val)); 407 1.1 riastrad if (ret < 0) 408 1.1 riastrad goto fail; 409 1.1 riastrad 410 1.1 riastrad ch7006_info(client, "Detected version ID: %x\n", val); 411 1.1 riastrad 412 1.1 riastrad /* I don't know what this is for, but otherwise I get no 413 1.1 riastrad * signal. 414 1.1 riastrad */ 415 1.1 riastrad ch7006_write(client, 0x3d, 0x0); 416 1.1 riastrad 417 1.1 riastrad return 0; 418 1.1 riastrad 419 1.1 riastrad fail: 420 1.1 riastrad ch7006_err(client, "Error %d reading version ID\n", ret); 421 1.1 riastrad 422 1.1 riastrad return -ENODEV; 423 1.1 riastrad } 424 1.1 riastrad 425 1.1 riastrad static int ch7006_remove(struct i2c_client *client) 426 1.1 riastrad { 427 1.1 riastrad ch7006_dbg(client, "\n"); 428 1.1 riastrad 429 1.1 riastrad return 0; 430 1.1 riastrad } 431 1.1 riastrad 432 1.1 riastrad static int ch7006_resume(struct device *dev) 433 1.1 riastrad { 434 1.1 riastrad struct i2c_client *client = to_i2c_client(dev); 435 1.1 riastrad 436 1.1 riastrad ch7006_dbg(client, "\n"); 437 1.1 riastrad 438 1.1 riastrad ch7006_write(client, 0x3d, 0x0); 439 1.1 riastrad 440 1.1 riastrad return 0; 441 1.1 riastrad } 442 1.1 riastrad 443 1.1 riastrad static int ch7006_encoder_init(struct i2c_client *client, 444 1.1 riastrad struct drm_device *dev, 445 1.1 riastrad struct drm_encoder_slave *encoder) 446 1.1 riastrad { 447 1.1 riastrad struct ch7006_priv *priv; 448 1.1 riastrad int i; 449 1.1 riastrad 450 1.1 riastrad ch7006_dbg(client, "\n"); 451 1.1 riastrad 452 1.1 riastrad priv = kzalloc(sizeof(*priv), GFP_KERNEL); 453 1.1 riastrad if (!priv) 454 1.1 riastrad return -ENOMEM; 455 1.1 riastrad 456 1.1 riastrad encoder->slave_priv = priv; 457 1.1 riastrad encoder->slave_funcs = &ch7006_encoder_funcs; 458 1.1 riastrad 459 1.1 riastrad priv->norm = TV_NORM_PAL; 460 1.1 riastrad priv->select_subconnector = DRM_MODE_SUBCONNECTOR_Automatic; 461 1.1 riastrad priv->subconnector = DRM_MODE_SUBCONNECTOR_Unknown; 462 1.1 riastrad priv->scale = 1; 463 1.1 riastrad priv->contrast = 50; 464 1.1 riastrad priv->brightness = 50; 465 1.1 riastrad priv->flicker = 50; 466 1.1 riastrad priv->hmargin = 50; 467 1.1 riastrad priv->vmargin = 50; 468 1.1 riastrad priv->last_dpms = -1; 469 1.1 riastrad priv->chip_version = ch7006_read(client, CH7006_VERSION_ID); 470 1.1 riastrad 471 1.1 riastrad if (ch7006_tv_norm) { 472 1.1 riastrad for (i = 0; i < NUM_TV_NORMS; i++) { 473 1.1 riastrad if (!strcmp(ch7006_tv_norm_names[i], ch7006_tv_norm)) { 474 1.1 riastrad priv->norm = i; 475 1.1 riastrad break; 476 1.1 riastrad } 477 1.1 riastrad } 478 1.1 riastrad 479 1.1 riastrad if (i == NUM_TV_NORMS) 480 1.1 riastrad ch7006_err(client, "Invalid TV norm setting \"%s\".\n", 481 1.1 riastrad ch7006_tv_norm); 482 1.1 riastrad } 483 1.1 riastrad 484 1.1 riastrad if (ch7006_scale >= 0 && ch7006_scale <= 2) 485 1.1 riastrad priv->scale = ch7006_scale; 486 1.1 riastrad else 487 1.1 riastrad ch7006_err(client, "Invalid scale setting \"%d\".\n", 488 1.1 riastrad ch7006_scale); 489 1.1 riastrad 490 1.1 riastrad return 0; 491 1.1 riastrad } 492 1.1 riastrad 493 1.3 riastrad static const struct i2c_device_id ch7006_ids[] = { 494 1.1 riastrad { "ch7006", 0 }, 495 1.1 riastrad { } 496 1.1 riastrad }; 497 1.1 riastrad MODULE_DEVICE_TABLE(i2c, ch7006_ids); 498 1.1 riastrad 499 1.1 riastrad static const struct dev_pm_ops ch7006_pm_ops = { 500 1.1 riastrad .resume = ch7006_resume, 501 1.1 riastrad }; 502 1.1 riastrad 503 1.1 riastrad static struct drm_i2c_encoder_driver ch7006_driver = { 504 1.1 riastrad .i2c_driver = { 505 1.1 riastrad .probe = ch7006_probe, 506 1.1 riastrad .remove = ch7006_remove, 507 1.1 riastrad 508 1.1 riastrad .driver = { 509 1.1 riastrad .name = "ch7006", 510 1.1 riastrad .pm = &ch7006_pm_ops, 511 1.1 riastrad }, 512 1.1 riastrad 513 1.1 riastrad .id_table = ch7006_ids, 514 1.1 riastrad }, 515 1.1 riastrad 516 1.1 riastrad .encoder_init = ch7006_encoder_init, 517 1.1 riastrad }; 518 1.1 riastrad 519 1.1 riastrad 520 1.1 riastrad /* Module initialization */ 521 1.1 riastrad 522 1.1 riastrad static int __init ch7006_init(void) 523 1.1 riastrad { 524 1.1 riastrad return drm_i2c_encoder_register(THIS_MODULE, &ch7006_driver); 525 1.1 riastrad } 526 1.1 riastrad 527 1.1 riastrad static void __exit ch7006_exit(void) 528 1.1 riastrad { 529 1.1 riastrad drm_i2c_encoder_unregister(&ch7006_driver); 530 1.1 riastrad } 531 1.1 riastrad 532 1.1 riastrad int ch7006_debug; 533 1.1 riastrad module_param_named(debug, ch7006_debug, int, 0600); 534 1.1 riastrad MODULE_PARM_DESC(debug, "Enable debug output."); 535 1.1 riastrad 536 1.1 riastrad char *ch7006_tv_norm; 537 1.1 riastrad module_param_named(tv_norm, ch7006_tv_norm, charp, 0600); 538 1.1 riastrad MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" 539 1.1 riastrad "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, PAL-60, NTSC-M, NTSC-J.\n" 540 1.1 riastrad "\t\tDefault: PAL"); 541 1.1 riastrad 542 1.1 riastrad int ch7006_scale = 1; 543 1.1 riastrad module_param_named(scale, ch7006_scale, int, 0600); 544 1.1 riastrad MODULE_PARM_DESC(scale, "Default scale.\n" 545 1.1 riastrad "\t\tSupported: 0 -> Select video modes with a higher blanking ratio.\n" 546 1.1 riastrad "\t\t\t1 -> Select default video modes.\n" 547 1.1 riastrad "\t\t\t2 -> Select video modes with a lower blanking ratio."); 548 1.1 riastrad 549 1.1 riastrad MODULE_AUTHOR("Francisco Jerez <currojerez (at) riseup.net>"); 550 1.1 riastrad MODULE_DESCRIPTION("Chrontel ch7006 TV encoder driver"); 551 1.1 riastrad MODULE_LICENSE("GPL and additional rights"); 552 1.1 riastrad 553 1.1 riastrad module_init(ch7006_init); 554 1.1 riastrad module_exit(ch7006_exit); 555